Wi-Fi Tools: scan logging to CSV, plus sort and filter

- lib/wifi (host-tested): scan_log (CSV field quoting, header/row, a
  once-per-interval throttle) and network_list_view (sort by signal /
  channel / name, filter open-only / hide-hidden / strong-only)
- ScanEntry moved to lib/wifi so both are testable on the PC
- Wi-Fi Tools networks view: s sort, o/h/w filters, l toggles logging
  to /wifi/scans/<date>.csv (header + one row per AP per logged scan,
  throttled 30 s, needs the clock for timestamps); foreground-only
- Wi-Fi scan logs replace probe-request logs as a clean-up category
- Serial: cat <path>, and key <char> injects a character

Verified on the device: CSV written with header, timestamps, BSSID,
channel, RSSI, security and SSID; hidden networks marked.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-03 20:52:43 +02:00
co-authored by Claude Opus 4.8
parent 5ac6afa557
commit 28d025fb13
15 changed files with 456 additions and 56 deletions
+23 -5
View File
@@ -5,17 +5,23 @@
#include "app.h"
#include "list_model.h"
#include "network_list_view.h"
#include "scan_log.h"
#include "services/clock_service.h"
#include "services/storage_service.h"
#include "services/wifi_service.h"
#include "signal_tracker.h"
#include "ui/theme.h"
namespace roro {
// Wi-Fi diagnostics from ordinary scans: nearby access points, how crowded each channel is, and
// a signal tracker for finding one access point. None of it interrupts the connection or IRC.
// Wi-Fi diagnostics from ordinary scans: nearby access points (sortable, filterable, optionally
// logged to CSV), how crowded each channel is, and a signal tracker. None of it interrupts the
// connection or IRC, and none of it captures anyone's traffic.
class WifiToolsApp : public App {
public:
explicit WifiToolsApp(WifiService& wifi) : wifi_(wifi) {}
WifiToolsApp(WifiService& wifi, StorageService& storage, ClockService& clock)
: wifi_(wifi), storage_(storage), clock_(clock) {}
void onEnter() override;
void onExit() override;
bool onKey(const KeyEvent& e) override;
@@ -26,18 +32,30 @@ class WifiToolsApp : public App {
enum class View { Menu, Networks, Channels, Tracker };
void open(View v);
void refreshOrder();
void logScan(uint32_t nowMs);
void drawNetworks(Canvas& c);
void drawChannels(Canvas& c);
void drawTracker(Canvas& c);
std::vector<ScanEntry> sortedScan() const;
WifiService& wifi_;
StorageService& storage_;
ClockService& clock_;
View view_ = View::Menu;
ListModel menu_{theme::kContent.h / theme::kLineHeight};
ListModel networks_{theme::kContent.h / theme::kLineHeight};
ListModel networks_{(theme::kContent.h - 14) / theme::kLineHeight};
std::vector<int> order_; // indices into the scan, after sort and filter
WifiSort sort_ = WifiSort::Signal;
NetworkFilter filter_;
uint32_t seenSeq_ = 0;
uint32_t nextScanMs_ = 0;
// Scan logging
bool logging_ = false;
ScanLogThrottle logThrottle_{30000};
std::string headerDate_;
uint32_t loggedRows_ = 0;
// Tracker
std::string targetBssid_, targetName_;
int targetChannel_ = 0;