M1 step 6: Wi-Fi Tools from ordinary scans

- lib/wifi (host-tested): channel occupancy (neighbour spill, signal
  weighting, quietest of 1/6/11) and a signal tracker (history, lost
  detection, click interval)
- WifiService: scan results carry BSSID, channel and security; a scan
  can target one channel for quick tracker refreshes; endListScans()
  turns the radio back off when Wi-Fi is disabled
- Wi-Fi Tools App: networks nearby, channel occupancy bars, signal
  tracker with clicks (m to mute)
- M1 plan: Monitoring-mode views and captures deferred

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 16:33:11 +02:00
co-authored by Claude Opus 5.5
parent 076baa77d1
commit 4cd6a63498
11 changed files with 512 additions and 16 deletions
+12 -4
View File
@@ -12,9 +12,12 @@
namespace roro {
struct ScanEntry {
std::string ssid;
std::string ssid; // empty for a hidden network
std::string bssid;
int channel;
int rssi;
bool open;
std::string security; // "open", "WPA2", "WPA3"...
};
// Owns the Wi-Fi radio: carries out the WifiController's decisions with the ESP32 Wi-Fi stack,
@@ -31,10 +34,14 @@ class WifiService : public Service {
const std::string& ssid() const { return controller_.ssid(); }
int rssi() const;
// Scan for the "add a network" list; results arrive in listScan() when listScanDone().
void startListScan();
// Scans for a list of nearby networks (all channels, or just one for a quick refresh); results
// arrive in listScan() when listScanDone(), and listScanSeq() counts completed scans.
void startListScan(int channel = 0);
bool listScanDone() const { return !listScanPending_; }
const std::vector<ScanEntry>& listScan() const { return listScan_; }
uint32_t listScanSeq() const { return listScanSeq_; }
// Done with list scans: switch the radio back off if Wi-Fi itself is off.
void endListScans();
// A Saved Network was added: try it now rather than after the retry delay.
void savedNetworksChanged() { controller_.retryNow(millis()); }
@@ -44,7 +51,7 @@ class WifiService : public Service {
private:
void apply(const WifiController::Step& step);
void startScan();
void startScan(int channel = 0);
void finishScan(uint32_t nowMs);
void startNtp();
@@ -55,6 +62,7 @@ class WifiService : public Service {
bool scanRunning_ = false;
bool listScanPending_ = false;
std::vector<ScanEntry> listScan_;
uint32_t listScanSeq_ = 0;
bool ntpWaiting_ = false;
bool radioInitialised_ = false;
};