1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-16 14:55:50 +00:00

Merge branch 'retry_hidden_no_stuck_last_networks_visible' into fix_scan_failing_after_restart

This commit is contained in:
J. Nick Koston
2025-11-11 16:05:01 -06:00
committed by GitHub
8 changed files with 69 additions and 35 deletions

View File

@@ -49,9 +49,9 @@ void DebugComponent::dump_config() {
} }
#endif // USE_TEXT_SENSOR #endif // USE_TEXT_SENSOR
#ifdef USE_ESP32 #if defined(USE_ESP32) || defined(USE_ZEPHYR)
this->log_partition_info_(); // Log partition information for ESP32 this->log_partition_info_(); // Log partition information
#endif // USE_ESP32 #endif
} }
void DebugComponent::loop() { void DebugComponent::loop() {

View File

@@ -62,19 +62,19 @@ class DebugComponent : public PollingComponent {
sensor::Sensor *cpu_frequency_sensor_{nullptr}; sensor::Sensor *cpu_frequency_sensor_{nullptr};
#endif // USE_SENSOR #endif // USE_SENSOR
#ifdef USE_ESP32 #if defined(USE_ESP32) || defined(USE_ZEPHYR)
/** /**
* @brief Logs information about the device's partition table. * @brief Logs information about the device's partition table.
* *
* This function iterates through the ESP32's partition table and logs details * This function iterates through the partition table and logs details
* about each partition, including its name, type, subtype, starting address, * about each partition, including its name, type, subtype, starting address,
* and size. The information is useful for diagnosing issues related to flash * and size. The information is useful for diagnosing issues related to flash
* memory or verifying the partition configuration dynamically at runtime. * memory or verifying the partition configuration dynamically at runtime.
* *
* Only available when compiled for ESP32 platforms. * Only available when compiled for ESP32 and ZEPHYR platforms.
*/ */
void log_partition_info_(); void log_partition_info_();
#endif // USE_ESP32 #endif
#ifdef USE_TEXT_SENSOR #ifdef USE_TEXT_SENSOR
text_sensor::TextSensor *device_info_{nullptr}; text_sensor::TextSensor *device_info_{nullptr};

View File

@@ -5,6 +5,7 @@
#include <zephyr/drivers/hwinfo.h> #include <zephyr/drivers/hwinfo.h>
#include <hal/nrf_power.h> #include <hal/nrf_power.h>
#include <cstdint> #include <cstdint>
#include <zephyr/storage/flash_map.h>
#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0] #define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
@@ -86,6 +87,37 @@ std::string DebugComponent::get_reset_reason_() {
uint32_t DebugComponent::get_free_heap_() { return INT_MAX; } uint32_t DebugComponent::get_free_heap_() { return INT_MAX; }
static void fa_cb(const struct flash_area *fa, void *user_data) {
#if CONFIG_FLASH_MAP_LABELS
const char *fa_label = flash_area_label(fa);
if (fa_label == nullptr) {
fa_label = "-";
}
ESP_LOGCONFIG(TAG, "%2d 0x%0*" PRIxPTR " %-26s %-24.24s 0x%-10x 0x%-12x", (int) fa->fa_id,
sizeof(uintptr_t) * 2, (uintptr_t) fa->fa_dev, fa->fa_dev->name, fa_label, (uint32_t) fa->fa_off,
fa->fa_size);
#else
ESP_LOGCONFIG(TAG, "%2d 0x%0*" PRIxPTR " %-26s 0x%-10x 0x%-12x", (int) fa->fa_id, sizeof(uintptr_t) * 2,
(uintptr_t) fa->fa_dev, fa->fa_dev->name, (uint32_t) fa->fa_off, fa->fa_size);
#endif
}
void DebugComponent::log_partition_info_() {
#if CONFIG_FLASH_MAP_LABELS
ESP_LOGCONFIG(TAG, "ID | Device | Device Name "
"| Label | Offset | Size");
ESP_LOGCONFIG(TAG, "--------------------------------------------"
"-----------------------------------------------");
#else
ESP_LOGCONFIG(TAG, "ID | Device | Device Name "
"| Offset | Size");
ESP_LOGCONFIG(TAG, "-----------------------------------------"
"------------------------------");
#endif
flash_area_foreach(fa_cb, nullptr);
}
void DebugComponent::get_device_info_(std::string &device_info) { void DebugComponent::get_device_info_(std::string &device_info) {
std::string supply = "Main supply status: "; std::string supply = "Main supply status: ";
if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_NORMAL) { if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_NORMAL) {

View File

@@ -107,7 +107,6 @@ CONF_REG0 = "reg0"
CONF_UICR_ERASE = "uicr_erase" CONF_UICR_ERASE = "uicr_erase"
VOLTAGE_LEVELS = [1.8, 2.1, 2.4, 2.7, 3.0, 3.3] VOLTAGE_LEVELS = [1.8, 2.1, 2.4, 2.7, 3.0, 3.3]
DEFAULT_VOLTAGE_LEVEL = "default"
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
_detect_bootloader, _detect_bootloader,
@@ -124,12 +123,9 @@ CONFIG_SCHEMA = cv.All(
), ),
cv.Optional(CONF_REG0): cv.Schema( cv.Optional(CONF_REG0): cv.Schema(
{ {
cv.Required(CONF_VOLTAGE): cv.Any( cv.Required(CONF_VOLTAGE): cv.All(
cv.All( cv.voltage,
cv.voltage, cv.one_of(*VOLTAGE_LEVELS, float=True),
cv.one_of(*VOLTAGE_LEVELS, float=True),
),
cv.one_of(*[DEFAULT_VOLTAGE_LEVEL], lower=True),
), ),
cv.Optional(CONF_UICR_ERASE, default=False): cv.boolean, cv.Optional(CONF_UICR_ERASE, default=False): cv.boolean,
} }
@@ -202,9 +198,7 @@ async def to_code(config: ConfigType) -> None:
CORE.add_job(_dfu_to_code, dfu_config) CORE.add_job(_dfu_to_code, dfu_config)
if reg0_config := config.get(CONF_REG0): if reg0_config := config.get(CONF_REG0):
value = 7 # DEFAULT_VOLTAGE_LEVEL value = VOLTAGE_LEVELS.index(reg0_config[CONF_VOLTAGE])
if reg0_config[CONF_VOLTAGE] in VOLTAGE_LEVELS:
value = VOLTAGE_LEVELS.index(reg0_config[CONF_VOLTAGE])
cg.add_define("USE_NRF52_REG0_VOUT", value) cg.add_define("USE_NRF52_REG0_VOUT", value)
if reg0_config[CONF_UICR_ERASE]: if reg0_config[CONF_UICR_ERASE]:
cg.add_define("USE_NRF52_UICR_ERASE") cg.add_define("USE_NRF52_UICR_ERASE")

View File

@@ -69,9 +69,20 @@ static StatusFlags fix_bootloader() {
} }
#endif #endif
#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
static StatusFlags set_uicr() { static StatusFlags set_uicr() {
StatusFlags status = StatusFlags::OK; StatusFlags status = StatusFlags::OK;
status |= set_regout0(); #ifndef USE_BOOTLOADER_MCUBOOT
if (BOOTLOADER_VERSION_REGISTER <= 0x902) {
#ifdef CONFIG_PRINTK
printk("cannot control regout0 for %#x\n", BOOTLOADER_VERSION_REGISTER);
#endif
} else
#endif
{
status |= set_regout0();
}
#ifndef USE_BOOTLOADER_MCUBOOT #ifndef USE_BOOTLOADER_MCUBOOT
status |= fix_bootloader(); status |= fix_bootloader();
#endif #endif

View File

@@ -1167,11 +1167,9 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() {
if (this->find_next_hidden_sta_(-1) >= 0) { if (this->find_next_hidden_sta_(-1) >= 0) {
return WiFiRetryPhase::RETRY_HIDDEN; // Found hidden networks to try return WiFiRetryPhase::RETRY_HIDDEN; // Found hidden networks to try
} }
// No hidden networks - skip directly to restart/rescan // No hidden networks - always go through RESTARTING_ADAPTER phase
if (this->is_captive_portal_active_() || this->is_esp32_improv_active_()) { // This ensures num_retried_ gets reset and a fresh scan is triggered
return this->went_through_explicit_hidden_phase_() ? WiFiRetryPhase::EXPLICIT_HIDDEN // The actual adapter restart will be skipped if captive portal/improv is active
: WiFiRetryPhase::SCAN_CONNECTING;
}
return WiFiRetryPhase::RESTARTING_ADAPTER; return WiFiRetryPhase::RESTARTING_ADAPTER;
case WiFiRetryPhase::RETRY_HIDDEN: case WiFiRetryPhase::RETRY_HIDDEN:
@@ -1192,16 +1190,9 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() {
} }
} }
} }
// Exhausted all potentially hidden SSIDs - rescan to try next BSSID // Exhausted all potentially hidden SSIDs - always go through RESTARTING_ADAPTER
// If captive portal/improv is active, skip adapter restart and go back to start // This ensures num_retried_ gets reset and a fresh scan is triggered
// Otherwise restart adapter to clear any stuck state // The actual adapter restart will be skipped if captive portal/improv is active
if (this->is_captive_portal_active_() || this->is_esp32_improv_active_()) {
// Go back to explicit hidden if we went through it initially, otherwise scan
return this->went_through_explicit_hidden_phase_() ? WiFiRetryPhase::EXPLICIT_HIDDEN
: WiFiRetryPhase::SCAN_CONNECTING;
}
// Restart adapter
return WiFiRetryPhase::RESTARTING_ADAPTER; return WiFiRetryPhase::RESTARTING_ADAPTER;
case WiFiRetryPhase::RESTARTING_ADAPTER: case WiFiRetryPhase::RESTARTING_ADAPTER:
@@ -1289,7 +1280,12 @@ bool WiFiComponent::transition_to_phase_(WiFiRetryPhase new_phase) {
break; break;
case WiFiRetryPhase::RESTARTING_ADAPTER: case WiFiRetryPhase::RESTARTING_ADAPTER:
this->restart_adapter(); // Skip actual adapter restart if captive portal/improv is active
// This allows state machine to reset num_retried_ and trigger fresh scan
// without disrupting the captive portal/improv connection
if (!this->is_captive_portal_active_() && !this->is_esp32_improv_active_()) {
this->restart_adapter();
}
// Return true to indicate we should wait (go to COOLDOWN) instead of immediately connecting // Return true to indicate we should wait (go to COOLDOWN) instead of immediately connecting
return true; return true;

View File

@@ -0,0 +1 @@
<<: !include common.yaml

View File

@@ -6,4 +6,4 @@ nrf52:
mode: mode:
output: true output: true
reg0: reg0:
voltage: default voltage: 1.8V