From 93f8e40111da66b8d1e9c6561c612c92e7c99d35 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Nov 2025 13:12:10 -0600 Subject: [PATCH 1/5] Fix scan failing after restart --- esphome/components/wifi/wifi_component.cpp | 34 ++++++---------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 7454361319..88e60c4523 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -413,8 +413,10 @@ void WiFiComponent::start() { void WiFiComponent::restart_adapter() { ESP_LOGW(TAG, "Restarting adapter"); this->wifi_mode_(false, {}); - delay(100); // NOLINT + // Enter cooldown state to allow WiFi hardware to stabilize after restart // Don't set retry_phase_ or num_retried_ here - state machine handles transitions + this->state_ = WIFI_COMPONENT_STATE_COOLDOWN; + this->action_started_ = millis(); } void WiFiComponent::loop() { @@ -435,19 +437,8 @@ void WiFiComponent::loop() { case WIFI_COMPONENT_STATE_COOLDOWN: { this->status_set_warning(LOG_STR("waiting to reconnect")); if (millis() - this->action_started_ > 5000) { - // After cooldown, connect based on current retry phase - this->reset_selected_ap_to_first_if_invalid_(); - - // Check if we need to trigger a scan first - if (this->needs_scan_results_() && !this->all_networks_hidden_()) { - // Need scan results or no matching networks found - scan/rescan - ESP_LOGD(TAG, "Scanning required for phase %s", LOG_STR_ARG(retry_phase_to_log_string(this->retry_phase_))); - this->start_scanning(); - } else { - // Have everything we need to connect (or all networks are hidden, skip scanning) - WiFiAP params = this->build_params_for_current_phase_(); - this->start_connecting(params, false); - } + // After cooldown, let retry_connect handle phase transitions and connection logic + this->retry_connect(); } break; } @@ -1007,8 +998,6 @@ void WiFiComponent::check_scanning_finished() { this->transition_to_phase_(WiFiRetryPhase::RETRY_HIDDEN); // If no hidden networks to try, skip connection attempt (will be handled on next loop) if (this->selected_sta_index_ == -1) { - this->state_ = WIFI_COMPONENT_STATE_COOLDOWN; - this->action_started_ = millis(); return; } // Now start connection attempt in hidden mode @@ -1425,15 +1414,13 @@ void WiFiComponent::advance_to_next_target_or_increment_retry_() { void WiFiComponent::retry_connect() { this->log_and_adjust_priority_for_failed_connect_(); - delay(10); - // Determine next retry phase based on current state WiFiRetryPhase current_phase = this->retry_phase_; WiFiRetryPhase next_phase = this->determine_next_phase_(); // Handle phase transitions (transition_to_phase_ handles same-phase no-op internally) if (this->transition_to_phase_(next_phase)) { - return; // Wait for scan to complete + return; // Scan started or adapter restarted (which sets its own state) } if (next_phase == current_phase) { @@ -1442,7 +1429,7 @@ void WiFiComponent::retry_connect() { this->error_from_callback_ = false; - if (this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING) { + if (this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING || this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING_2) { yield(); // Check if we have a valid target before building params // After exhausting all networks in a phase, selected_sta_index_ may be -1 @@ -1451,13 +1438,10 @@ void WiFiComponent::retry_connect() { this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING_2; WiFiAP params = this->build_params_for_current_phase_(); this->start_connecting(params, true); - return; } - // No valid target - fall through to set state to allow phase transition + } else { + ESP_LOGW(TAG, "Retry called in invalid state %d", (int) this->state_); } - - this->state_ = WIFI_COMPONENT_STATE_COOLDOWN; - this->action_started_ = millis(); } void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; } From 7a92565a0c4d0290f55a63f3cfdad9da9ec5fe17 Mon Sep 17 00:00:00 2001 From: CzBiX Date: Wed, 12 Nov 2025 03:24:52 +0800 Subject: [PATCH 2/5] [lvgl] Fix compile when using transform_zoom (#11845) --- esphome/components/lvgl/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 4df68a6386..2a24f343c3 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -331,7 +331,7 @@ async def to_code(configs): # This must be done after all widgets are created for comp in helpers.lvgl_components_required: cg.add_define(f"USE_LVGL_{comp.upper()}") - if "transform_angle" in styles_used: + if {"transform_angle", "transform_zoom"} & styles_used: add_define("LV_COLOR_SCREEN_TRANSP", "1") for use in helpers.lv_uses: add_define(f"LV_USE_{use.upper()}") From f6ac916bb2904f461fc1e4ce30ab547b0e6c926b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Nov 2025 13:55:29 -0600 Subject: [PATCH 3/5] cleanups --- esphome/components/wifi/wifi_component.cpp | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 88e60c4523..3b68d299b0 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -437,8 +437,14 @@ void WiFiComponent::loop() { case WIFI_COMPONENT_STATE_COOLDOWN: { this->status_set_warning(LOG_STR("waiting to reconnect")); if (millis() - this->action_started_ > 5000) { - // After cooldown, let retry_connect handle phase transitions and connection logic - this->retry_connect(); + // After cooldown we either restarted the adapter because of + // a failure, or something tried to connect over and over + // so we entered cooldown. In both cases we call + // check_connecting_finished to continue the state machine. + // If we just restarted the adapter because we failed to connect, + // this->error_from_callback_ will be true and we will move to the + // next retry phase. + this->check_connecting_finished(); } break; } @@ -1076,12 +1082,18 @@ void WiFiComponent::check_connecting_finished() { uint32_t now = millis(); if (now - this->action_started_ > 30000) { ESP_LOGW(TAG, "Connection timeout"); + // Move from STA_CONNECTING_2 back to STA_CONNECTING state + // since we know the connection attempt has failed + this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING; this->retry_connect(); return; } if (this->error_from_callback_) { - ESP_LOGW(TAG, "Connecting to network failed"); + ESP_LOGW(TAG, "Connecting to network failed (callback)"); + // Move from STA_CONNECTING_2 back to STA_CONNECTING state + // since we know the connection attempt is finished + this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING; this->retry_connect(); return; } @@ -1090,6 +1102,9 @@ void WiFiComponent::check_connecting_finished() { return; } + // Move from STA_CONNECTING_2 back to STA_CONNECTING state + // since we know the connection attempt is finished + this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING; if (status == WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND) { ESP_LOGW(TAG, "Network no longer found"); this->retry_connect(); @@ -1429,7 +1444,7 @@ void WiFiComponent::retry_connect() { this->error_from_callback_ = false; - if (this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING || this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING_2) { + if (this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING) { yield(); // Check if we have a valid target before building params // After exhausting all networks in a phase, selected_sta_index_ may be -1 @@ -1438,10 +1453,14 @@ void WiFiComponent::retry_connect() { this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING_2; WiFiAP params = this->build_params_for_current_phase_(); this->start_connecting(params, true); + return; } - } else { - ESP_LOGW(TAG, "Retry called in invalid state %d", (int) this->state_); } + + ESP_LOGD(TAG, "Entering cooldown from state %d and phase %s", this->state_, + LOG_STR_ARG(retry_phase_to_log_string(this->retry_phase_))); + this->state_ = WIFI_COMPONENT_STATE_COOLDOWN; + this->action_started_ = millis(); } void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; } From db9af4a8623e3b5db8fb9bab8f60c970020c98a8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Nov 2025 14:00:25 -0600 Subject: [PATCH 4/5] cleanup --- esphome/components/wifi/wifi_component.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 3b68d299b0..e6560e8670 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -441,9 +441,6 @@ void WiFiComponent::loop() { // a failure, or something tried to connect over and over // so we entered cooldown. In both cases we call // check_connecting_finished to continue the state machine. - // If we just restarted the adapter because we failed to connect, - // this->error_from_callback_ will be true and we will move to the - // next retry phase. this->check_connecting_finished(); } break; @@ -1455,6 +1452,7 @@ void WiFiComponent::retry_connect() { this->start_connecting(params, true); return; } + // No valid target - fall through to set state to allow phase transition } ESP_LOGD(TAG, "Entering cooldown from state %d and phase %s", this->state_, From 1bde521380bef0f4c4a50f5bb144e7eb51bc7738 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Nov 2025 14:05:44 -0600 Subject: [PATCH 5/5] cleanups --- esphome/components/wifi/wifi_component.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index e6560e8670..bd94d9392c 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1450,11 +1450,14 @@ void WiFiComponent::retry_connect() { this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING_2; WiFiAP params = this->build_params_for_current_phase_(); this->start_connecting(params, true); - return; } - // No valid target - fall through to set state to allow phase transition + return; } + // If we can't progress forward its likely because scanning failed + // or the stack is in a bad state after restart so we cooldown first + // and once it finishes, cooldown will call check_connecting_finished() + // which will progress the state machine ESP_LOGD(TAG, "Entering cooldown from state %d and phase %s", this->state_, LOG_STR_ARG(retry_phase_to_log_string(this->retry_phase_))); this->state_ = WIFI_COMPONENT_STATE_COOLDOWN;