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>
Connect opens a chooser with the transports the browser has (Web Serial and
Web Bluetooth on Chrome / Edge, WebSocket to the node's port 8765 everywhere,
with a note where some are missing). The choice is kept and the UI reboots
into it; each backend has its own data dir (/data/demo, /data/node-<key>) so
demo and node data never mix; a reload reconnects; Disconnect returns to the
demo. The bar shows Demo / Connecting / Connected: <node> over <link> /
Reconnecting, and Reconnect / Pair again when the browser needs a click.
Transports retry a lost link and reopen a granted USB port on plug-in. A node
skips the demo's setup wizard. A link lost mid-handshake no longer reports
ready. web/build.sh nodetest: the flow end to end against the mock WS node.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Backend selection moves into the shared boot: a WadaBackendChoice
(web/mesh/BackendSelect.h) that host_main.cpp fills from --serial / --tcp /
--read-only and web_main.cpp from the page (Module.wadaBackend, with its own
data dir), and board.cpp creates the backend from it. The demo position is
only set for the demo. The companion link reports its state through
g_wada_link_hook (web_main.cpp passes it to Module.wadaLink). The browser
transports' JS joins the Emscripten link as --pre-js. WEB_BUILD.md keeps both
phases' sections. build.sh: "$0" relative to the caller's directory no longer
breaks smoke / serve / webtest.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
board.cpp owns the board globals and src/main.cpp's setup()/loop() order;
host_main.cpp keeps only the SDL window, event pump and scripted tour, so the
browser front end reuses the boot unchanged. WebDisplay tracks the changed
rectangle for the canvas upload.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>