From ff7eb2f4344102682aae4c250e9af3b0f3486b38 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 9 Nov 2025 18:06:51 -0600 Subject: [PATCH] respect users config --- esphome/components/wifi/wifi_component.cpp | 65 ++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index df79e3e09e..940db309cd 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -42,6 +42,71 @@ namespace wifi { static const char *const TAG = "wifi"; +/// WiFi Retry Logic - Priority-Based BSSID Selection +/// +/// The WiFi component uses a state machine with priority degradation to handle connection failures +/// and automatically cycle through different BSSIDs in mesh networks or multiple configured networks. +/// +/// Connection Flow (with fast_connect enabled): +/// ┌──────────────────────────────────────────────────────────────────────┐ +/// │ Fast Connect Path (Optional) │ +/// ├──────────────────────────────────────────────────────────────────────┤ +/// │ │ +/// │ 1. INITIAL_CONNECT → Try saved credentials (1 attempt) │ +/// │ ↓ │ +/// │ [FAILED] → FAST_CONNECT_CYCLING_APS │ +/// │ ↓ │ +/// │ 2. Cycle through all configured APs (1 attempt each) │ +/// │ ↓ │ +/// │ [All Failed] → Fall back to scan-based connection │ +/// └──────────────────────────────────────────────────────────────────────┘ +/// ↓ +/// ┌──────────────────────────────────────────────────────────────────────┐ +/// │ Scan-Based Connection Path │ +/// ├──────────────────────────────────────────────────────────────────────┤ +/// │ │ +/// │ 1. SCAN → Sort by priority (highest first), then RSSI │ +/// │ ┌─────────────────────────────────────────────────┐ │ +/// │ │ scan_result_[0] = Best BSSID (highest priority) │ │ +/// │ │ scan_result_[1] = Second best │ │ +/// │ │ scan_result_[2] = Third best │ │ +/// │ └─────────────────────────────────────────────────┘ │ +/// │ ↓ │ +/// │ 2. SCAN_CONNECTING → Try scan_result_[0] (2 attempts) │ +/// │ ↓ │ +/// │ 3. FAILED → Decrease priority: 0.0 → -1.0 → -2.0 │ +/// │ (stored in persistent sta_priorities_) │ +/// │ ↓ │ +/// │ 4. SCAN_WITH_HIDDEN → Try SSIDs not in scan OR marked hidden │ +/// │ (skips visible SSIDs not marked hidden) │ +/// │ ↓ │ +/// │ 5. FAILED → RESTARTING_ADAPTER │ +/// │ ↓ │ +/// │ 6. RESCAN → Apply stored priorities, sort again │ +/// │ ┌─────────────────────────────────────────────────┐ │ +/// │ │ scan_result_[0] = BSSID B (priority 0.0) ← NEW │ │ +/// │ │ scan_result_[1] = BSSID C (priority 0.0) │ │ +/// │ │ scan_result_[2] = BSSID A (priority -2.0) ← OLD │ │ +/// │ └─────────────────────────────────────────────────┘ │ +/// │ ↓ │ +/// │ 7. SCAN_CONNECTING → Try scan_result_[0] (next best) │ +/// │ │ +/// │ Key: Priority system cycles through BSSIDs ACROSS scan cycles │ +/// │ Always try best available BSSID (scan_result_[0]) │ +/// └──────────────────────────────────────────────────────────────────────┘ +/// +/// Retry Phases: +/// - INITIAL_CONNECT: First attempt (try saved credentials if fast_connect enabled) +/// - FAST_CONNECT_CYCLING_APS: Cycle through configured APs (1 attempt per AP, fast_connect only) +/// - SCAN_CONNECTING: Connect using scan results (2 attempts per BSSID) +/// - SCAN_WITH_HIDDEN: Try hidden mode for SSIDs not in scan or marked hidden (1 attempt per SSID) +/// - RESTARTING_ADAPTER: Restart WiFi adapter to clear stuck state +/// +/// Smart Hidden Mode Skip: +/// - SSIDs marked 'hidden: true' → Always tried in hidden mode (respects user config) +/// - SSIDs visible in scan + not marked hidden → Skipped (we know they're not hidden) +/// - SSIDs not in scan → Tried in hidden mode (might be hidden) + static const LogString *retry_phase_to_log_string(WiFiRetryPhase phase) { switch (phase) { case WiFiRetryPhase::INITIAL_CONNECT: