From 72a6051f0d5cf7581e8bc3d3a4776eefc48a9c2e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Nov 2025 09:16:31 -0600 Subject: [PATCH] [wifi] Fix infinite loop in RETRY_HIDDEN when remaining networks are visible --- esphome/components/wifi/wifi_component.cpp | 19 ++++++++++++------- esphome/components/wifi/wifi_component.h | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 7279e0c783..0fef3fe661 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -253,8 +253,9 @@ bool WiFiComponent::ssid_was_seen_in_scan_(const std::string &ssid) const { return false; } -int8_t WiFiComponent::find_next_hidden_sta_(int8_t start_index, bool include_explicit_hidden) { +int8_t WiFiComponent::find_next_hidden_sta_(int8_t start_index) { // Find next SSID that wasn't in scan results (might be hidden) + bool include_explicit_hidden = !this->went_through_explicit_hidden_phase_(); // Start searching from start_index + 1 for (size_t i = start_index + 1; i < this->sta_.size(); i++) { const auto &sta = this->sta_[i]; @@ -1160,7 +1161,7 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() { // Its priority has been decreased, so on next scan it will be sorted lower // and we'll try the next best BSSID. // Check if there are any potentially hidden networks to try - if (this->find_next_hidden_sta_(-1, !this->went_through_explicit_hidden_phase_()) >= 0) { + if (this->find_next_hidden_sta_(-1) >= 0) { return WiFiRetryPhase::RETRY_HIDDEN; // Found hidden networks to try } // No hidden networks - skip directly to restart/rescan @@ -1179,8 +1180,13 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() { // Exhausted retries on current SSID - check if there are more potentially hidden SSIDs to try if (this->selected_sta_index_ < static_cast(this->sta_.size()) - 1) { - // More SSIDs available - stay in RETRY_HIDDEN, advance will happen in retry_connect() - return WiFiRetryPhase::RETRY_HIDDEN; + // Check if find_next_hidden_sta_() would actually find another hidden SSID + // as it might have been seen in the scan results and we want to skip those + // otherwise we will get stuck in RETRY_HIDDEN phase + if (this->find_next_hidden_sta_(this->selected_sta_index_) != -1) { + // More hidden SSIDs available - stay in RETRY_HIDDEN, advance will happen in retry_connect() + return WiFiRetryPhase::RETRY_HIDDEN; + } } } // Exhausted all potentially hidden SSIDs - rescan to try next BSSID @@ -1271,7 +1277,7 @@ bool WiFiComponent::transition_to_phase_(WiFiRetryPhase new_phase) { // If first network is marked hidden, we went through EXPLICIT_HIDDEN phase // In that case, skip networks marked hidden:true (already tried) // Otherwise, include them (they haven't been tried yet) - this->selected_sta_index_ = this->find_next_hidden_sta_(-1, !this->went_through_explicit_hidden_phase_()); + this->selected_sta_index_ = this->find_next_hidden_sta_(-1); if (this->selected_sta_index_ == -1) { ESP_LOGD(TAG, "All SSIDs visible or already tried, skipping hidden mode"); @@ -1379,8 +1385,7 @@ void WiFiComponent::advance_to_next_target_or_increment_retry_() { // If first network is marked hidden, we went through EXPLICIT_HIDDEN phase // In that case, skip networks marked hidden:true (already tried) // Otherwise, include them (they haven't been tried yet) - int8_t next_index = - this->find_next_hidden_sta_(this->selected_sta_index_, !this->went_through_explicit_hidden_phase_()); + int8_t next_index = this->find_next_hidden_sta_(this->selected_sta_index_); if (next_index != -1) { // Found another potentially hidden SSID this->selected_sta_index_ = next_index; diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index ed049544cf..df8bac5728 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -380,7 +380,7 @@ class WiFiComponent : public Component { /// Returns index of next potentially hidden SSID, or -1 if none found /// @param start_index Start searching from index after this (-1 to start from beginning) /// @param include_explicit_hidden If true, include SSIDs marked hidden:true. If false, only find truly hidden SSIDs. - int8_t find_next_hidden_sta_(int8_t start_index, bool include_explicit_hidden = true); + int8_t find_next_hidden_sta_(int8_t start_index); /// Log failed connection and decrease BSSID priority to avoid repeated attempts void log_and_adjust_priority_for_failed_connect_(); /// Advance to next target (AP/SSID) within current phase, or increment retry counter