diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index d2db78ae006..e3f2e50d208 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -112,8 +112,7 @@ void WiFiComponent::start() { this->trying_loaded_ap_ = this->load_fast_connect_settings_(); if (!this->trying_loaded_ap_) { // FAST CONNECT FALLBACK: No saved settings available - // Set selected_sta_index_ to first config without any scan result - // build_selected_ap_() will use config data only (no SSID/BSSID/channel from scan) + // Use first config without any scan result (config data only, no SSID/BSSID/channel) this->selected_sta_index_ = 0; } this->start_connecting_to_selected_(false); @@ -689,29 +688,16 @@ void WiFiComponent::check_scanning_finished() { log_scan_result(res); } - // Find matching config for on-demand connection params building // SYNCHRONIZATION POINT: Establish link between scan_result_[0] and selected_sta_index_ // After sorting, scan_result_[0] contains the best network. Now find which sta_[i] config // matches that network and record it in selected_sta_index_. This keeps the two indices // synchronized so build_selected_ap_() can safely use both to build connection parameters. - const WiFiScanResult &scan_res = this->scan_result_[0]; - - if (!scan_res.get_matches()) { + if (!this->sync_selected_sta_to_best_scan_result_()) { ESP_LOGW(TAG, "No matching network found"); this->retry_connect(); return; } - for (size_t i = 0; i < this->sta_.size(); i++) { - // search for matching STA config, at least one will match (from checks before) - if (!scan_res.matches(this->sta_[i])) { - continue; - } - - this->selected_sta_index_ = i; // Links scan_result_[0] with sta_[i] - break; - } - yield(); this->start_connecting_to_selected_(false); @@ -894,15 +880,11 @@ bool WiFiComponent::load_fast_connect_settings_() { std::copy(fast_connect_save.bssid, fast_connect_save.bssid + 6, bssid.begin()); // FAST CONNECT SUCCESS: Restore saved settings without scanning - // Create a temporary scan result with the fast connect BSSID and channel - this->scan_result_.init(1); - WiFiScanResult fast_connect_scan(bssid, "", fast_connect_save.channel, 0, false, false); - this->scan_result_.push_back(fast_connect_scan); - - // SYNCHRONIZATION: Link scan_result_[0] (temporary) with sta_[saved_index] + // SYNCHRONIZATION: Link temporary scan result with sta_[saved_index] // Unlike wifi_scan_done() which sorts then finds the match, here we know exactly // which config was used before and create a matching temporary scan result - this->selected_sta_index_ = fast_connect_save.ap_index; + WiFiScanResult fast_connect_scan(bssid, "", fast_connect_save.channel, 0, false, false); + this->set_selected_sta_with_scan_(fast_connect_save.ap_index, fast_connect_scan); ESP_LOGD(TAG, "Loaded fast_connect settings"); return true; diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index ae8dafe14b1..a89c1fb4304 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -352,6 +352,34 @@ class WiFiComponent : public Component { } } + // SYNCHRONIZATION HELPERS: Encapsulate the relationship between selected_sta_index_ and scan_result_ + + // Set selected sta with a temporary scan result (fast connect path) + void set_selected_sta_with_scan_(int8_t sta_index, const WiFiScanResult &scan) { + this->scan_result_.init(1); + this->scan_result_.push_back(scan); + this->selected_sta_index_ = sta_index; + } + + // Find which sta_[i] matches scan_result_[0] and set selected_sta_index_ (scan done path) + // Returns true if match found, false otherwise + bool sync_selected_sta_to_best_scan_result_() { + if (this->scan_result_.empty()) + return false; + + const WiFiScanResult &scan_res = this->scan_result_[0]; + if (!scan_res.get_matches()) + return false; + + for (size_t i = 0; i < this->sta_.size(); i++) { + if (scan_res.matches(this->sta_[i])) { + this->selected_sta_index_ = i; // Links scan_result_[0] with sta_[i] + return true; + } + } + return false; + } + void start_connecting_to_selected_(bool two) { WiFiAP connection_params = this->build_selected_ap_(); this->start_connecting(connection_params, two);