- 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
- IrcService: networking on its own task, TLS with the built-in CA
bundle (or trust-on-first-use pinning when self-signed is allowed),
plain TCP when TLS is off; connects only while Wi-Fi is Connected,
marks pauses for Monitoring, reconnects with backoff, pings a quiet
server, writes Logs, raises Notifications for Mentions
- Session: forget /quit once disconnected (it was handled every loop);
the server Buffer never counts as unread (MOTD showed as [4])
- Status Bar: unread count
- Frame buffer 16 -> 8-bit colour (M1 Q46): min free heap with IRC on
TLS went from 51 KB to 79 KB
- Serial: irc start / say / dump
Verified on the device against irc.libera.chat:6697: certificate
checked, joined #roro9stack-test, sent a message, quit cleanly.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
- lib/storage_model (host-tested): FAT-safe names, daily Log paths,
dates from Log/Capture file names, CleanupPlan by category and age,
byte formatting
- StorageService does all card I/O on its task: queued Log lines are
written in batches each second (dropped while Logs are paused),
plus file listing and deletion jobs
- Settings > Storage moves into StoragePage: usage, Clean up
(category, age with size preview, confirmation), Erase SD card
- Clock: local date for Log names
- Serial: log <text>, sd list
Verified on the device: lines land in /irc/dev/#test/2026-10-02.log
with folders created as needed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
- 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
The firmware accepts burst, key <name>, sound on|off and short|normal
over serial, so UI behaviour can be reproduced on the device without
the keyboard. scripts/serial_log.sh records (and drives) it in a named
container that flash.sh removes before uploading.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
- pioarduino platform 55.03.312 (Arduino-ESP32 3.3.x / ESP-IDF 5.5),
board m5stack-stamps3, M5Cardputer 1.1.1
- native env with Unity for host-side tests
- scripts/ci.sh and scripts/flash.sh run PlatformIO in a container
- version injected from git describe
- boot stub shows name, version and pressed keys
- GPL-3.0 license
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT