diff --git a/examples/companion_radio/CompanionWiFi.h b/examples/companion_radio/CompanionWiFi.h index 18d8acca..697aea5b 100644 --- a/examples/companion_radio/CompanionWiFi.h +++ b/examples/companion_radio/CompanionWiFi.h @@ -44,6 +44,10 @@ enum class CompanionWiFiPowerSaveResult : uint8_t { // from the main loop so a button callback never tears down an active server. bool toggleCompanionWiFi(); bool isCompanionWiFiEnabled(); +// Display-facing station state. Arduino's cached WL status can briefly lag the +// ESP-IDF association record, so accept either source while the AP link is +// live. Unlike localIP(), the driver record is cleared on a real disconnect. +bool isCompanionWiFiConnected(); // Reload saved credentials after a text-terminal update. The reconnect is // deferred so the command reply can leave USB/TCP before WiFi is restarted. diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index ead2f041..b94d835a 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -1144,6 +1144,13 @@ void halt() { return companion_wifi_requested; } + bool isCompanionWiFiConnected() { + if (!companion_wifi_requested || !companion_wifi_active) return false; + if (WiFi.status() == WL_CONNECTED) return true; + wifi_ap_record_t access_point = {}; + return esp_wifi_sta_get_ap_info(&access_point) == ESP_OK; + } + bool toggleCompanionWiFi() { #if defined(COMPANION_EXCLUSIVE_WIFI_BLE) const CompanionTransportMode current = getCompanionTransportMode(); diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index e22f8ee1..719f4bc5 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -162,7 +162,7 @@ static void drawCompanionWiFiSetupPage(DisplayDriver& display) { display.setColor(UIColor::secondary_txt); display.drawTextCentered(display.width() / 2, 90, "SELECT WIFI"); display.drawTextCentered(display.width() / 2, 112, "THEN REBOOT"); - } else if (WiFi.status() == WL_CONNECTED) { + } else if (isCompanionWiFiConnected()) { display.setTextSize(2); display.drawTextCentered(display.width() / 2, 25, "WIFI READY"); const String ssid = WiFi.SSID(); @@ -273,6 +273,7 @@ class HomeScreen : public UIScreen { bool _shutdown_init; #if UI_WIFI_SETUP_HOME_PAGE == 1 bool _wifi_setup_was_active; + bool _wifi_was_connected; #endif uint32_t _uptime_last_millis; uint64_t _uptime_millis; @@ -405,12 +406,13 @@ public: : _task(task), _rtc(rtc), _sensors(sensors), _node_prefs(node_prefs), _page(0), _shutdown_init(false), #if UI_WIFI_SETUP_HOME_PAGE == 1 - _wifi_setup_was_active(false), + _wifi_setup_was_active(false), _wifi_was_connected(false), #endif _uptime_last_millis(millis()), _uptime_millis(0), sensors_lpp(200) { #if UI_WIFI_SETUP_HOME_PAGE == 1 _wifi_setup_was_active = WebConfigServer::getSetupInfo( nullptr, 0, nullptr, 0); + _wifi_was_connected = isCompanionWiFiConnected(); if (_wifi_setup_was_active) _page = HomePage::WIFI_SETUP; #endif } @@ -436,6 +438,14 @@ public: _task->gotoHomeScreen(); } _wifi_setup_was_active = wifi_setup_active; + const bool wifi_connected = isCompanionWiFiConnected(); + if (wifi_connected != _wifi_was_connected) { + // A network transition must invalidate the page immediately. This also + // recovers from a previously retained CONNECTING frame even if the + // ordinary one-second render deadline was delayed by another service. + _wifi_was_connected = wifi_connected; + _task->gotoHomeScreen(); + } #endif if (_shutdown_init && !_task->isButtonPressed()) { // must wait for USR button to be released _task->shutdown(); diff --git a/test/test_indicator_render_profile.py b/test/test_indicator_render_profile.py index 37ccf3e3..8dc71f2b 100644 --- a/test/test_indicator_render_profile.py +++ b/test/test_indicator_render_profile.py @@ -176,6 +176,9 @@ int main() { self.assertIn("_page == HomePage::WIFI_SETUP", ui) self.assertIn("if (_page == HomePage::WIFI_SETUP) return 1000;", ui) self.assertIn("wifi_setup_active && !_wifi_setup_was_active", ui) + self.assertIn("isCompanionWiFiConnected()", page) + self.assertIn("wifi_connected != _wifi_was_connected", ui) + self.assertIn("_task->gotoHomeScreen();", ui) main = MAIN.read_text(encoding="utf-8") loop = main[main.index("\nvoid loop()") :]