M1 step 2: Wi-Fi Service, Saved Networks, NTP, Settings page

- lib/wifi (host-tested): SavedNetworks (up to 8, validated, hidden
  flag, persisted) and WifiController (joins the strongest Saved
  Network, tries hidden ones in turn, backoff 10/30/60 s, connect
  timeout, Monitoring override, radio off without Saved Networks)
- WifiService carries out the controller's actions, sets the EU
  country code, and syncs the Clock over SNTP without touching the TZ
- Wi-Fi On/Off setting; Settings > Wi-Fi page: status, add from a scan
  or a hidden network, forget
- Status Bar: W + signal bars, W? while searching, MON while monitoring
- Serial: wifi add / wifi status (replaces the step 1 heap probe)

Verified on the device: joins the test network ~5 s after boot, clock
set over NTP, ~129 KB free heap while connected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-02 14:46:07 +02:00
co-authored by Claude Opus 5.5
parent d8fe676c65
commit 1a0baf4ac7
22 changed files with 1108 additions and 48 deletions
+16 -2
View File
@@ -30,6 +30,9 @@ bool SettingsApp::onKey(const KeyEvent& e) {
case Page::Choice: return onChoiceKey(e);
case Page::Storage: return onStorageKey(e);
case Page::About: return onAboutKey(e);
case Page::Wifi:
if (!wifiPage_.onKey(e)) page_ = Page::Menu;
return true;
}
return false;
}
@@ -61,7 +64,16 @@ bool SettingsApp::onMenuKey(const KeyEvent& e) {
break;
case Kind::Toggle: menu_.toggle(i); break;
case Kind::Slider: break;
case Kind::Page: page_ = menu_.row(i) == Row::Storage ? Page::Storage : Page::About; break;
case Kind::Page:
switch (menu_.row(i)) {
case Row::Storage: page_ = Page::Storage; break;
case Row::Wifi:
page_ = Page::Wifi;
wifiPage_.enter();
break;
default: page_ = Page::About; break;
}
break;
}
return true;
}
@@ -123,7 +135,8 @@ bool SettingsApp::onAboutKey(const KeyEvent& e) {
void SettingsApp::update(uint32_t nowMs) {
// Live values on Storage and About.
if ((page_ == Page::Storage || page_ == Page::About) && nowMs - lastRefreshMs_ >= 1000) {
bool live = page_ == Page::Storage || page_ == Page::About || (page_ == Page::Wifi && wifiPage_.live());
if (live && nowMs - lastRefreshMs_ >= 500) {
lastRefreshMs_ = nowMs;
requestRedraw();
}
@@ -204,6 +217,7 @@ void SettingsApp::draw(Canvas& c) {
*eraseDialog_);
break;
case Page::About: widgets::textLines(c, aboutLines(), 0, area); break;
case Page::Wifi: wifiPage_.draw(c); break;
}
}