1
0

FIRMWARE_MIGRATION.md 3.6 KB

Touch app → FluidNC firmware migration

Status of wiring dune-weaver-touch directly to the new headless FluidNC firmware (dune-weaver-firmware), replacing the old dune-weaver host FastAPI server. The entire QML interface (properties / slots / signals) is preserved, so no .qml files were changed.

Architecture change

Concern Before (host FastAPI) After (firmware direct)
Status WebSocket /ws/status poll GET /sand_status (~1 Hz)
Actions REST /run_theta_rho, /stop_execution, … $... cmds via /command + /sand_* routes
Patterns local FS ../patterns GET /sand_patterns, files from /sd/patterns/...
Previews prebuilt PNG cache rendered locally from .thr, cached in preview_cache/
Playlists ../playlists.json /sand_playlists + .txt on SD (upload/delete file-ops)
LEDs /api/dw_leds/* numeric ids $LED/* / /sand_led named effects/palettes
Table address DUNE_WEAVER_URL (localhost) mDNS auto-discovery + DUNE_WEAVER_URL pin
Screen / LCD local sysfs (unchanged) local sysfs (unchanged)

Files

New

  • firmware_client.py — shared async HTTP client singleton (FirmwareClient.instance()); status/patterns/playlists/settings reads, $... commands, /sand_* actions, /upload file-ops, LED + clear-mode maps, firmware error surfacing.
  • discovery.py — mDNS discovery of _http._tcp tables (model=dune-weaver); optional zeroconf, degrades to empty list if missing.
  • thr_preview.py — parse .thr, render polar path → cached PNG, sync cache lookup.

Rewritten

  • backend.py — QML-facing controller. Status polling, all actions remapped to firmware, LED catalogue, playlist file editing, table connect/disconnect via the old "serial" UI, local screen/LCD kept verbatim.
  • models/pattern_model.py, models/playlist_model.py — firmware-backed, refresh on baseUrlChanged.

Updated

  • requirements.txt (+zeroconf), .env.example, run.sh (dropped localhost:8080 gate), README.md, added .gitignore.

Mapping decisions (verify on hardware)

  • Clear modes: clear_center → in, clear_perimeter → out, adaptive → adaptive, none → none (CLEAR_MODE_MAP in firmware_client.py). $Sand/Run … clear= needs a playlist: config section on the board.
  • Speed/sand_feed?mm= (motor mm/min); the 50–500 options pass through as feed.
  • "Restart backend" → reboots the table ($Bye). "Shutdown Pi" → local sudo shutdown.
  • Auto-play-on-boot: disabling clears $Playlist/Autostart reliably; enabling needs a chosen playlist name (best-effort / logged only).
  • Table picker reuses the serial UI: discovered URLs populate the port list; connectSerial(url) selects one; saved to touch_settings.json.

Verification done

  • All modules byte-compile.
  • .thr renderer produces valid PNGs; discovery.py imports with/without zeroconf.
  • Full contract check: every QML-consumed slot/property/signal exists in the rewrite.
  • Not yet run against real hardware or a live GUI (no PySide6/display in the dev env).

Known gaps / follow-ups

  • No in-UI manual IP entry — if mDNS fails, fall back to DUNE_WEAVER_URL. A kiosk text field in TableControlPage.qml would be a good addition.
  • Auto-play-on-boot could be wired to a playlist picker for full parity.
  • Live smoke test against a table still needed.

Before running

pip install -r requirements.txt   # adds zeroconf
# optionally pin the table:
echo 'DUNE_WEAVER_URL=dunetable.local' >> .env
./run.sh