Expose best_effort/fast/wait/reliable via UART, dashboard, and CLI so
loss vs latency can be compared under real multi-pod load.
Co-authored-by: Cursor <cursoragent@cursor.com>
Accel/tap use fire-and-forget ESP-NOW with a 10 ms FreeRTOS-safe cadence, OTA recovers from seq gaps and auto-reboots after success, and bootloader app rollback confirms after a stable boot.
Co-authored-by: Cursor <cursoragent@cursor.com>
Allow the same staged firmware upload path on BLE as UART, fix distribute stack/event-group crashes, and recover sticky slave OTA sessions instead of failing with err=4.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add BLE RTT/stream tests and live tick median in the UI, fix concurrent WebSocket writes and late BATTERY replies, and skip 2M PHY updates that assert under ESP-NOW coexistence.
Co-authored-by: Cursor <cursoragent@cursor.com>
Serve starts without a required port; REST/WS/UI can scan and switch transports, with BLE live ticks and UART-only OTA.
Co-authored-by: Cursor <cursoragent@cursor.com>
Master can speak the same framed protobuf protocol over NimBLE or UART; goTool gains -ble, ble-rtt, and ble-stream timing checks for ESP-NOW coexistence.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose multitap parameters over UART/ESP-NOW (like deadzone), store per node in NVS, and allow get/set from CLI, REST, and the dashboard without poll-overwrite while editing.
Co-authored-by: Cursor <cursoragent@cursor.com>
Detect under-voltage on GPIO1/11, persist UV state in NVS, enter a minimal
power mode without ESP-NOW, and recover after charge; expose LED mode 6
battery-low for host testing via goTool.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose the command via goTool CLI/REST and dashboard controls so log verbosity can be tuned without reflashing.
Co-authored-by: Cursor <cursoragent@cursor.com>
ReadFrame now returns on serial timeout instead of looping forever, and
serve closes and reopens the port after a master reboot so polling and
API commands can resume.
Co-authored-by: Cursor <cursoragent@cursor.com>
Go exits on Ctrl+C without running defers, leaving the serial port locked; register shutdown hooks for serve and CLI commands.
Co-authored-by: Cursor <cursoragent@cursor.com>
Split ESP-NOW into core/master/slave modules, block non-OTA UART traffic during updates, and hold the host serial port exclusively so dashboard polling cannot interleave with firmware uploads.
Co-authored-by: Cursor <cursoragent@cursor.com>
Document UART command flow, ESP-NOW data paths, and module map for
developers without covering goTool; link from main/README.
Co-authored-by: Cursor <cursoragent@cursor.com>
Centralize multitap tuning so sensitivity and timing can be adjusted without changing driver init logic.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace separate accel/tap commands and messages with set_input_stream and input pushes that combine accel and tap per client, including pre_fetch timing.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace separate accel/tap snapshot UART commands with one clients[] response
that omits unsubscribed fields; remove snapshot handlers and CLI commands.
Add goTool/docs for WebSocket streams and REST; tap-snapshot REST uses CACHE_STATUS.
Co-authored-by: Cursor <cursoragent@cursor.com>
Combine cached accel and tap in one low-overhead master command for ~16 ms
host polling. The dashboard uses a single live-stream toggle plus per-slave
accel-stream controls; fix live_stream state so polling is not cleared every
slow client refresh.
Co-authored-by: Cursor <cursoragent@cursor.com>
Slaves forward configured tap kinds to the master; goTool exposes CLI, dashboard, REST, and WebSocket with separate notify vs receive and 2s display cache.
Co-authored-by: Cursor <cursoragent@cursor.com>
Slaves report pack voltages every 30s; the master caches them for fast
BATTERY_STATUS reads. goTool exposes REST/WebSocket and shows values in
the dashboard, with a nanopb fix so optional lipo submessages encode.
Co-authored-by: Cursor <cursoragent@cursor.com>
Solid color mode fills all ring LEDs; master routes UART commands to slaves
via ESPNOW_LED_RING. goTool exposes POST /api/led-ring, WebSocket set_led_ring,
and a dashboard LED panel with master/slave/all targets.
Co-authored-by: Cursor <cursoragent@cursor.com>
Slaves push BMA456 samples at 16ms when enabled; the master caches per
client and exposes ACCEL_SNAPSHOT and ACCEL_STREAM over UART. goTool adds
dashboard stream controls, HTTP accel-stream routes, and an external
WebSocket API with per-connection receive/interval and slave stream commands.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose MessageType 24 with protobuf response (success, x, y, z in raw LSB),
firmware handler with mutex-safe I2C read, goTool `accel` CLI, and docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
Each node saves its local deadzone on UART or ESP-NOW set; pod_settings loads and applies it after BMA456 init.
Co-authored-by: Cursor <cursoragent@cursor.com>
Default brightness is ~5%; UART blink mode and green/red pulses mark OTA success or failure. Failed UART uploads skip ESP-NOW distribution.
Co-authored-by: Cursor <cursoragent@cursor.com>
Stop the main-loop digit demo so host-driven display persists; expose
clear/progress/digit modes with RGB and intensity via protobuf and goTool.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose OTA_SLAVE_PROGRESS on the master, track per-slave state during
distribution, run ESP-NOW OTA in a background task so the host can poll
while slaves update, and show master/slave progress in the dashboard
with table layout and faster WebSocket refresh during uploads.
Co-authored-by: Cursor <cursoragent@cursor.com>
Describe master-to-slave distribution after UART OTA, partial final block, reboot, and goTool /api/ota behaviour.
Co-authored-by: Cursor <cursoragent@cursor.com>
After UART OTA the master reads the staged partition in 4 KiB blocks (200 B ESP-NOW chunks), waits for per-slave block ACKs, and fixes the final partial block. Slaves reuse ota_uart; send pacing and logging improve reliability.
Co-authored-by: Cursor <cursoragent@cursor.com>
Share UART OTA logic between CLI and serve via POST /api/ota, WebSocket progress events, and a dashboard upload UI showing the running partition.
Co-authored-by: Cursor <cursoragent@cursor.com>
Firmware buffers 200-byte chunks into 4 KiB blocks for esp_ota_write; goTool
uploads with per-block ACK flow control and larger UART buffers to avoid stalls.
Co-authored-by: Cursor <cursoragent@cursor.com>
TODO: Hardware pinning in powerpod.h (TASTER_GPIO, V_LIPO_1/2_GPIO) does not
match final hardware yet — verify against schematic before production.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show master deadzone input with read/set controls; apply bulk slave
changes via slaves_only without changing the master's BMA456.
Co-authored-by: Cursor <cursoragent@cursor.com>
Serve polls the master over UART and pushes live state via WebSocket;
reopens the serial port when the device is unplugged and comes back.
Co-authored-by: Cursor <cursoragent@cursor.com>
Bench configs define command and console serial paths; scenarios can
reset nodes via esptool before tests. Smoke resets all nodes then waits
for ESP-NOW join.
Co-authored-by: Cursor <cursoragent@cursor.com>
JSON configs describe network and node MACs; scenarios run command
sequences with expect checks. Share UART client API across CLI and tests.
Co-authored-by: Cursor <cursoragent@cursor.com>