From 4160157457c86b01ae52b37bf7edf9ac535d4807 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Nov 2025 08:26:15 -0600 Subject: [PATCH] [wifi] Restore two-attempt BSSID filtering for mesh networks --- esphome/components/wifi/wifi_component.cpp | 24 +++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 7279e0c783..cba7267aae 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1304,6 +1304,11 @@ bool WiFiComponent::transition_to_phase_(WiFiRetryPhase new_phase) { /// - Other phases: Uses BSSID from config if explicitly specified by user or fast_connect /// /// If no BSSID is available (SSID-only connection), priority adjustment is skipped. +/// +/// IMPORTANT: Priority is only decreased on the LAST attempt for a BSSID in SCAN_CONNECTING phase. +/// This prevents false positives from transient WiFi stack state issues after scanning. +/// Single failures don't necessarily mean the AP is bad - two genuine failures provide +/// higher confidence before degrading priority and skipping the BSSID in future scans. void WiFiComponent::log_and_adjust_priority_for_failed_connect_() { // Determine which BSSID we tried to connect to optional failed_bssid; @@ -1320,11 +1325,6 @@ void WiFiComponent::log_and_adjust_priority_for_failed_connect_() { return; // No BSSID to penalize } - // Decrease priority to avoid repeatedly trying the same failed BSSID - float old_priority = this->get_sta_priority(failed_bssid.value()); - float new_priority = old_priority - 1.0f; - this->set_sta_priority(failed_bssid.value(), new_priority); - // Get SSID for logging std::string ssid; if (this->retry_phase_ == WiFiRetryPhase::SCAN_CONNECTING && !this->scan_result_.empty()) { @@ -1333,6 +1333,20 @@ void WiFiComponent::log_and_adjust_priority_for_failed_connect_() { ssid = config->get_ssid(); } + // Only decrease priority on the last attempt for this phase + // This prevents false positives from transient WiFi stack issues + uint8_t max_retries = get_max_retries_for_phase(this->retry_phase_); + bool is_last_attempt = (this->num_retried_ + 1 >= max_retries); + + // Decrease priority only on last attempt to avoid false positives from transient failures + float old_priority = this->get_sta_priority(failed_bssid.value()); + float new_priority = old_priority; + + if (is_last_attempt) { + new_priority -= 1.0f; // Decrease priority on failure + this->set_sta_priority(failed_bssid.value(), new_priority); + } + ESP_LOGD(TAG, "Failed " LOG_SECRET("'%s'") " " LOG_SECRET("(%s)") ", priority %.1f → %.1f", ssid.c_str(), format_mac_address_pretty(failed_bssid.value().data()).c_str(), old_priority, new_priority); }