mirror of
https://github.com/esphome/esphome.git
synced 2026-03-24 06:53:07 +08:00
[wifi] Fix roaming attempt counter reset on disconnect during scan
When WiFi disconnects while a roaming scan is in progress, the SCANNING state was transitioning to IDLE in retry_connect(). When the device then reconnected, check_connecting_finished() treated the IDLE state as a normal connection and reset roaming_attempts_ to 0. This caused the roaming counter to perpetually restart at 1/3 instead of progressing to 2/3, 3/3, creating an infinite loop of roaming scans every 5 minutes. This is most likely to occur on ESP8266 where disconnect callbacks run immediately in SDK system context (setting error_from_callback_ before the main loop can process scan results), compared to ESP32 IDF where events are queued and the scan-done event is typically processed before the disconnect. Fix by transitioning to RECONNECTING instead of IDLE when a disconnect occurs during SCANNING. This preserves the attempts counter on successful reconnection, allowing the device to reach the 3-attempt limit and stop scanning.
This commit is contained in:
@@ -269,11 +269,11 @@ bool CompactString::operator==(const StringRef &other) const {
|
||||
/// │ │ │
|
||||
/// │ ┌──────────────┼──────────────┐ │
|
||||
/// │ ↓ ↓ ↓ │
|
||||
/// │ scan error no better AP +10 dB better AP │
|
||||
/// │ disconnect no better AP +10 dB better AP │
|
||||
/// │ │ │ │ │
|
||||
/// │ ↓ ↓ ↓ │
|
||||
/// │ ┌──────────────────────────────┐ ┌──────────────────────────┐ │
|
||||
/// │ │ → IDLE │ │ CONNECTING │ │
|
||||
/// │ │ → RECONNECTING │ │ CONNECTING │ │
|
||||
/// │ │ (counter preserved) │ │ (process_roaming_scan_) │ │
|
||||
/// │ └──────────────────────────────┘ └────────────┬─────────────┘ │
|
||||
/// │ │ │
|
||||
@@ -296,7 +296,7 @@ bool CompactString::operator==(const StringRef &other) const {
|
||||
/// │ Key behaviors: │
|
||||
/// │ - After 3 checks: attempts >= 3, stop checking │
|
||||
/// │ - Non-roaming disconnect: clear_roaming_state_() resets counter │
|
||||
/// │ - Scan error (SCANNING→IDLE): counter preserved │
|
||||
/// │ - Disconnect during scan (SCANNING→RECONNECTING): counter preserved │
|
||||
/// │ - Roaming success (CONNECTING→IDLE): counter reset (can roam again) │
|
||||
/// │ - Roaming fail (RECONNECTING→IDLE): counter preserved (ping-pong) │
|
||||
/// └──────────────────────────────────────────────────────────────────────┘
|
||||
@@ -2072,9 +2072,10 @@ void WiFiComponent::retry_connect() {
|
||||
ESP_LOGD(TAG, "Roam failed, reconnecting (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS);
|
||||
this->roaming_state_ = RoamingState::RECONNECTING;
|
||||
} else if (this->roaming_state_ == RoamingState::SCANNING) {
|
||||
// Roam scan failed (e.g., scan error on ESP8266) - go back to idle, keep counter
|
||||
ESP_LOGD(TAG, "Roam scan failed (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS);
|
||||
this->roaming_state_ = RoamingState::IDLE;
|
||||
// Disconnected during roam scan - transition to RECONNECTING so the attempts
|
||||
// counter is preserved when reconnection succeeds (IDLE would reset it)
|
||||
ESP_LOGD(TAG, "Disconnected during roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS);
|
||||
this->roaming_state_ = RoamingState::RECONNECTING;
|
||||
} else if (this->roaming_state_ == RoamingState::IDLE) {
|
||||
// Not a roaming-triggered reconnect, reset state
|
||||
this->clear_roaming_state_();
|
||||
|
||||
Reference in New Issue
Block a user