Commit Graph
11 Commits
Author SHA1 Message Date
Kaj Schittecat e077d8b097 Merge wip/verify-2026-10-26: today's merges proven off-device, six fixes
wada.sys.random full range no longer divides by zero, wada.ui.input Enter
submits on touch boards with an external keyboard, the OTA download ends
its HTTP connection when no buffer could be allocated, an accepted clock set
lifts the floor (a chip stuck at it no longer keeps the stale time), the host
build refuses removes with '..', and 10 new host tests plus headless scripts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	scripts/run-host-tests.sh
#	src/helpers/esp32/TouchPrefsStore.cpp
#	test/clock_floor_fakes/helpers/AutoDiscoverRTCClock.h
2026-10-26 15:12:00 +01:00
Kaj SchittecatandClaude Opus 5.5 698546011c touch: T-Display P4 under Launcher: SD after a cold boot, missing store, honest restore (#708)
Based on @oumike's draft PR #709, made to compile and checked off-device.

- P4 SD: Launcher reads the card over SPI, and a card in SPI mode ignores the
  native-mode CMD0 every SD_MMC mount starts with until it loses power. After
  a failed first mount, power the slot off with all six SD lines driven low
  for 300 ms, then retry the first rung before the slower ones.
- P4 store: the boot log names the 'storage' partition and its size, or says
  it is missing (Launcher's own partition table from the app-only .bin), and
  a boot alert says identity, channels and contacts cannot be saved. No
  fallback onto another data partition: under Launcher that belongs to
  another app.
- Restore: uiImportBackup reports when the identity or node prefs could not
  be written (out_saved). The picker and File Transfer's Restore then say so
  instead of "Imported N contacts" and a reboot into an empty store. The
  BackupImport enum now sits outside the WADA_WEB_FILE_TRANSFER block (the
  draft did not build without it), and the web stand-in mirrors out_saved.
- Two new strings in all 15 .lang files (de, es, fr, nl translated).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 13:34:36 +01:00
Kaj SchittecatandClaude Opus 5.5 8faab0467a test: prove the UI request slot expiry (cec1431c) off-device
The 45 s expiry moves into src/helpers/UiRequestSlot.h, shared by
MyMesh::uiRequestTick and the web stand-in, so one constant and one rule
cover both (firmware behaviour unchanged).

test/test_ui_request_slot.cpp: the boundary (free at 45000 ms, not 44999),
millis() wrap, an unanswered ask holding the admin app's STATUS until the
expiry, an answered one clearing at once, a late reply matching nothing,
the deferred login's own 45 s, and a source check that every slot taker in
MyMesh.h and WebMesh.cpp stamps its time.

web/scripts/ui-slot-expiry.wada: the Discord report end to end in the host
build. WADA_DEMO_SILENT_TELEMETRY=1 makes the demo repeater lose its
telemetry reply; the contact sheet's Telemetry (no deadline without SD)
takes the slot, the admin app logs in and Status stays blank until 45 s
after the ask, then the queued STATUS goes out and Status fills. With the
expiry disabled the same run stays blank.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 13:31:40 +01:00
Kaj SchittecatandClaude Opus 5.5 cec1431c7a touch: free the UI request slot after 45 s without a reply
The status, telemetry, neighbour and region requests share one single-flight
slot in MyMesh. The telemetry auto-poll and the Home sensor widget take it
without a deadline of their own, so one unanswered request held it until
reboot. The repeater admin app then queued every status, neighbours and
access-list request behind it and sent nothing: logged in, blank status,
Refresh does nothing (reported on Discord against beta_99).

uiRequestTick() now expires the slot and the deferred guest login 45 s after
they were taken; every sender with its own deadline gives up well before.
The web build's stand-in gets the same expiry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 11:37:38 +01:00
Kaj SchittecatandClaude Opus 5.5 028d3777ea web: no-threads freeze, copies fighting over the node, position kept, refit
- File writes go straight to the descriptor: musl's fwrite retried a 0-byte
  write for ever, which froze the http copy mid Store install / backup import.
- A copy out of sight lets the node go; a link the node drops soon after
  opening backs off, and the page says another app took it.
- The UI's own position is saved in the browser and outranks the node's.
- The home-screen app re-measures the screen once iOS has settled.
- ?nt forces the no-threads engine; scripts/node-store-probe.mjs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 19:48:58 +02:00
Kaj SchittecatandClaude Opus 5.5 817004c861 web: merge main (repeater admin); the stand-in serves the admin app
Merges main 8954fe06. The drift alarm caught the repeater admin app's new
members: sendStatusPingForUI, sendTelemetryRequestForUI,
uiSendBinaryRequest (-> onBinaryReply), UiReqKind::Binary and
uiLastLoginInfo/UiLoginInfo. Over a node: CMD_SEND_BINARY_REQ and its tagged
PUSH_BINARY_RESPONSE, the ACL and firmware level of a modern LOGIN_OK. The
demo's repeater and room log in (any password = admin, empty = guest) and
answer status, neighbours, the access list, owner info and CLI lines; the
mock node answers neighbours and owner info.

Also from main: nvs_open/nvs_close in the compat (SdNvsPrefs asks first),
and the tiles partition now has to exist before the UI mounts it: the compat
partition table reports "tiles" (the web board's LittleFS volume). Font
guards keep WADA_WEB next to main's new SenseCAP Indicator.

No-threads bundle: a UI-thread wait called from the page (not the main
loop) no longer sleeps (it hung the flush after a Store install).

A wheel turn counts as user activity (no screensaver mid-scroll).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:42:56 +02:00
Kaj SchittecatandClaude Opus 5.5 48a8303db3 web: the Store, Lua apps and backups in the browser
Store: the firmware's own catalog, install and language code over
wadaHttpRequest; http://firmware.wadamesh.com/apps/... becomes the
same-origin fw/apps/... (serve.py and the nginx snippet proxy exactly those
paths). The update check, OTA images and reports stay unreachable
(CAP_FW_UPDATE_CHECK 0); the Store badge fetches the catalog on its own.
CAP_STORE_DOWNLOADS keeps the baked apps and languages as the offline first
load and turns the Apps tab and language downloads on. Other servers
(wada.net) are fetched directly: CORS decides, no open proxy. Installs and
app data live in the backend's IndexedDB data dir.

Backups: the stand-in exports and imports the device's backup file (no
private key); CAP_FILE_HANDOFF downloads an export and imports a file picked
on the computer through the UI's own confirm + import. A restart waits for
the node commands an import queued. The bar's More menu backs up and
restores the whole data dir of this browser as one .tar.

webtest: a Store app installed via the proxy survives a reload and runs; a
backup goes out (download) and into a fresh profile (file picker); a
browser backup restores the app and the settings into another one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:03:11 +02:00
Kaj SchittecatandClaude Opus 5.5 71f1829a2e web: the browser's location is the GPS, map tiles, polish
Location: the web board has CAP_GPS 1. web/platform/WebLocation.* is its
SensorManager + LocationProvider, fed by navigator.geolocation (page shell,
only while the UI's GPS is on, the prompt deferred to a tap) or WADA_GPS on
the host, so the GPS switch, status, map centring, distances and
wada.sys.gps (with speed/course) work unchanged. The position reaches a
connected node (CMD_SET_ADVERT_LATLON, displaced by the Location privacy
radius) only while the node's advert-location setting is "share"; the demo
moves its cast to the visitor's location.

Map tiles: wadaHttpRequest serves the firmware's default tile server only:
a synchronous emscripten_fetch from the tile_fetch pthread to the
same-origin tiles/ path (serve.py proxies it; nginx location for the site),
plain HTTP natively. WiFi reports connected while the browser is online.
Fixes the static-init order of the host VFS (the UI's own tiles LittleFS
copied an empty impl).

Polish: Lua apps that need the board's own radio carry "radio": "own" in the
catalog (baked under CAP_RADIO_TOOLS, greyed in the Store); mouse wheel and
trackpad scrolling; Settings > Wi-Fi / Bluetooth explain the page bar
(CAP_WIFI_SETUP / CAP_BT_SETUP); no Download mode (CAP_USB_FLASH); no
receiver settings on Settings > GPS (CAP_GPS_RECEIVER).

Tests: webtest checks the map centres on Playwright's Ghent location and
shows tiles; nodetest checks the location privacy rule against the mock node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 14:25:13 +02:00
Kaj SchittecatandClaude Opus 5.5 8cf67ec709 web: companion: the node's CLI in the Terminal, BLE PIN, WEB_BUILD.md
The Terminal runs every command on the node (CMD_RUN_CLI_COMMAND, MeshCore
1.18), with the old local subset as the fallback; setBLEPin sets the node's
PIN. WEB_BUILD.md documents the companion backend: protocol mapping,
transports and framing, read-only mode, members moved from unavailable to
working, and the known gaps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:48:17 +02:00
Kaj SchittecatandClaude Opus 5.5 b3caafe511 web: companion backend: the real UI drives a MeshCore companion node
CompanionBackend speaks the companion frame protocol (stock MeshCore 1.17/1.18,
wadamesh extras handled) over a CompanionTransport: USB serial and TCP natively
(--serial / --tcp), Web Serial, Web Bluetooth and WebSocket in the browser (JS
glue in web/mesh/js, framing in C++). The stand-in gains the node-only events
(self info, raw RX, login, CLI, regions, contact removal) and computes the RX
log, advert routes, repeats heard and message route info from the node's raw
RX pushes, as the device does. Demo stays the default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:44:58 +02:00
Kaj SchittecatandClaude Opus 5.5 963c75df5d web: host build of the real touch UI (SDL2, demo backend)
The touch UI (src/ui-touch, unmodified apart from WADA_WEB board guards)
builds for macOS with CMake and runs in an SDL2 window: a compat layer
for the Arduino/ESP-IDF/FreeRTOS surface, a MyMesh stand-in with a
MeshBackend interface (DemoBackend now), and the web board's SDL
display/touch/keyboard drivers. WEB_BUILD.md follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:06:04 +02:00