From 4316e2d56d76847521b0f91f7ea1a6522a45f126 Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Sat, 10 Oct 2026 10:42:06 +1100 Subject: [PATCH] WiFi setup: Connecting, IP and Could not connect popups, 15 s limit; README WiFi steps --- README.md | 12 ++-- examples/companion_radio/main.cpp | 5 ++ .../companion_radio/ui-new/SettingsScreen.h | 59 +++++++++++++------ 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 9ff8b733..34f0cce5 100644 --- a/README.md +++ b/README.md @@ -274,10 +274,14 @@ The WiFi companion variants (`meck_audio_wifi`, `meck_4g_wifi`) connect to the M **Connecting:** -1. Navigate to the **WiFi** home page (use D to page through) -2. Press **Enter** to toggle WiFi on -3. The device scans for networks — select yours and enter the password -4. Once connected, the IP address is displayed on the WiFi home page +WiFi is off at boot, so it has to be turned on in Settings first. + +1. Open **Settings** and select the **WiFi Radio** row to turn it **ON**. It takes several seconds before the row shows ON, so please be patient. +2. Select the **WiFi** row (it shows **WiFi: (not connected)** until you have joined a network). The device scans for networks. +3. Select your network, enter the password and press **Enter**. +4. A **Connecting...** popup shows while the device joins the network. This can take up to 15 seconds. +5. Once connected, a popup shows the device's IP address for 2 seconds and you are returned to Settings. The IP address is also displayed on the WiFi home page. +6. If the device can't connect within 15 seconds, a **Could not connect** popup shows and you are returned to the network list to try again. Connect the MeshCore web app or meshcore.js to `:5000`. diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 6fa58bcf..53262582 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -884,6 +884,11 @@ static uint32_t _atoi(const char* sp) { // the lock state without pulling in the full UITask header. bool meck_alarm_is_locked() { return ui_task.isLocked(); } #endif + #ifdef MECK_WIFI_COMPANION + // Lets the Settings WiFi setup (which only forward-declares UITask) show + // its Connecting / IP / Could not connect popups. + void meckShowAlert(const char* text, int duration_millis) { ui_task.showAlert(text, duration_millis); } + #endif #endif StdRNG fast_rng; diff --git a/examples/companion_radio/ui-new/SettingsScreen.h b/examples/companion_radio/ui-new/SettingsScreen.h index ddd2e581..a65d291a 100644 --- a/examples/companion_radio/ui-new/SettingsScreen.h +++ b/examples/companion_radio/ui-new/SettingsScreen.h @@ -290,6 +290,8 @@ enum FmPhase : uint8_t { #endif #define SETTINGS_TEXT_BUF 33 // 32 chars + null #define SETTINGS_FLIP_MS 2000 // channel row too long for the line: time on its start, then its end +#define SETTINGS_WIFI_CONNECT_MS 15000 // WiFi setup: give up joining a network after this long +#define SETTINGS_WIFI_ALERT_MS 2000 // WiFi setup: how long the IP / "Could not connect" popups stay up class SettingsScreen : public UIScreen { private: @@ -390,6 +392,7 @@ private: char _wifiPassBuf[64]; int _wifiPassLen; unsigned long _wifiFormLastChar; // For brief password reveal + unsigned long _wifiConnectStart; // When the current join attempt started (CONNECTING phase) #endif #ifdef MECK_OTA_UPDATE @@ -798,6 +801,7 @@ public: _wifiPassLen = 0; memset(_wifiPassBuf, 0, sizeof(_wifiPassBuf)); _wifiFormLastChar = 0; + _wifiConnectStart = 0; #endif rebuildRows(); } @@ -918,6 +922,31 @@ public: return _editMode == EDIT_WIFI && _wifiPhase == WIFI_PHASE_SELECT; } + // CONNECTING phase, called from poll(): on success show the IP address and + // return to the Settings list; after SETTINGS_WIFI_CONNECT_MS without a + // connection, say so and return to the network list to try again. + void pollWifiConnect() { + extern void meckShowAlert(const char* text, int duration_millis); + if (WiFi.status() == WL_CONNECTED) { + Serial.printf("Settings: WiFi connected to %s, IP: %s\n", + _wifiSSIDs[_wifiSSIDSelected].c_str(), + WiFi.localIP().toString().c_str()); + IPAddress ip = WiFi.localIP(); + char ipMsg[24]; + snprintf(ipMsg, sizeof(ipMsg), MECK_TR("IP: %d.%d.%d.%d", "IP : %d.%d.%d.%d"), + ip[0], ip[1], ip[2], ip[3]); + _editMode = EDIT_NONE; + _wifiPhase = WIFI_PHASE_IDLE; + if (_onboarding) _onboarding = false; // Finish onboarding + meckShowAlert(ipMsg, SETTINGS_WIFI_ALERT_MS); + } else if ((long)(millis() - _wifiConnectStart) >= SETTINGS_WIFI_CONNECT_MS) { + Serial.println("Settings: WiFi connection failed"); + // Go back to SSID selection so user can retry + _wifiPhase = WIFI_PHASE_SELECT; + meckShowAlert(MECK_TR("Could not connect", "Connexion impossible"), SETTINGS_WIFI_ALERT_MS); + } + } + #endif bool wantsWatchChannels() const { return _wantsWatchChannels; } @@ -3241,24 +3270,12 @@ public: WiFi.disconnect(false); WiFi.begin(_wifiSSIDs[_wifiSSIDSelected].c_str(), _wifiPassBuf); - // Brief blocking wait — fine for e-ink (screen won't update during this anyway) - unsigned long timeout = millis() + 8000; - while (WiFi.status() != WL_CONNECTED && millis() < timeout) { - delay(100); - } - - if (WiFi.status() == WL_CONNECTED) { - Serial.printf("Settings: WiFi connected to %s, IP: %s\n", - _wifiSSIDs[_wifiSSIDSelected].c_str(), - WiFi.localIP().toString().c_str()); - _editMode = EDIT_NONE; - _wifiPhase = WIFI_PHASE_IDLE; - if (_onboarding) _onboarding = false; // Finish onboarding - } else { - Serial.println("Settings: WiFi connection failed"); - // Go back to SSID selection so user can retry - _wifiPhase = WIFI_PHASE_SELECT; - } + // Don't wait here: poll() checks for the result each loop, so the + // "Connecting..." popup can be drawn while the device joins the + // network. Its time runs past the limit; the result popup replaces it. + _wifiConnectStart = millis(); + extern void meckShowAlert(const char* text, int duration_millis); + meckShowAlert(MECK_TR("Connecting...", "Connexion..."), SETTINGS_WIFI_CONNECT_MS + 2000); return true; } if (c == '\b') { @@ -4204,6 +4221,12 @@ public: // then restart a few seconds after the result is on screen. The restart // rebuilds everything keyed by contact index from the empty store. void poll() override { + #ifdef MECK_WIFI_COMPANION + if (_editMode == EDIT_WIFI && _wifiPhase == WIFI_PHASE_CONNECTING) { + pollWifiConnect(); + return; + } + #endif if (_editMode != EDIT_PURGE) return; if (_purgePhase == PURGE_RUNNING && (long)(millis() - _purgeAt) >= 0) { extern void meckPurgeAllContacts(int* contactsRemoved, bool* contactsOk, int* dmsRemoved);