Unify cache polling on CACHE_STATUS and split API docs.

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>
This commit is contained in:
2026-05-29 21:23:09 +02:00
co-authored by Cursor
parent a85d48320e
commit 31e539052a
25 changed files with 1243 additions and 1269 deletions
+16 -53
View File
@@ -222,10 +222,9 @@ Host and master speak nanopb-encoded `UartMessage` inside UART frames (byte 0 =
| 21 | `OTA_SLAVE_PROGRESS` | Implemented (`cmd/cmd_ota_slave_progress.c`) — query per-slave ESP-NOW OTA progress |
| 22 | `FIND_ME` | Implemented (`cmd/cmd_espnow_find_me.c`) — `client_id=0` local ring, `>0` ESP-NOW to slave |
| 23 | `RESTART` | Implemented (`cmd/cmd_restart.c`) — `client_id=0` reboot master, `>0` ESP-NOW reboot slave |
| 24 | `ACCEL_SNAPSHOT` | Implemented (`cmd/cmd_accel_snapshot.c`) — cached slave accel from ESP-NOW stream |
| 25 | `ACCEL_STREAM` | Implemented — enable/disable slave ESP-NOW accel stream to master |
| 27 | `TAP_NOTIFY` | Implemented (`cmd/cmd_tap_notify.c`) — get/set which tap kinds notify via ESP-NOW |
| 28 | `TAP_SNAPSHOT` | Implemented (`cmd/cmd_tap_snapshot.c`) — consume cached tap events from master registry |
| 29 | `CACHE_STATUS` | Implemented (`cmd/cmd_cache_status.c`) — combined accel + tap cache in one UART round-trip |
| 29 | `CACHE_STATUS` | Implemented (`cmd/cmd_cache_status.c`) — subscribed accel + tap cache (one UART round-trip) |
Regenerate C code:
@@ -319,29 +318,6 @@ Sets the **software** deadzone used by `bosch456.c` when logging accel (see [BMA
**Response:** `accel_deadzone_response` with applied `deadzone`, `success`, and `slaves_updated` (ESP-NOW count).
### ACCEL_SNAPSHOT command
Read **cached** accelerometer samples on the **master** (one entry per registered slave). Slaves send `ESPNOW_ACCEL_SAMPLE` to the master every **16 ms** (`esp_now_comm.c`); the master stores the latest value per client in `client_registry.c`.
**Request:** framed `18` (`0x18`) + optional `accel_snapshot_request` (`client_id`: `0` = all slaves, `>0` = one id).
**Response:** `accel_snapshot_response.samples[]`:
| Field | Meaning |
|-------|---------|
| `client_id` | Slave id (registry) |
| `valid` | At least one ESP-NOW sample received since boot |
| `x`, `y`, `z` | Raw BMA456 LSB (±2g) |
| `age_ms` | Ms since last sample from that slave |
Host:
```bash
go run . -port /dev/ttyUSB0 accel
```
External API (`serve -api-addr :8081`) polls this command every 16 ms and streams JSON over WebSocket.
### TAP_NOTIFY command
Configure which BMA456 tap kinds a **slave** forwards to the master over ESP-NOW. The slave only sends `ESPNOW_TAP_EVENT` when the matching notify flag is enabled (set locally on the slave via ESP-NOW).
@@ -364,41 +340,30 @@ go run . -port /dev/ttyUSB0 tap-notify -client 16 -set -single
go run . -port /dev/ttyUSB0 tap-notify -client 16
```
### TAP_SNAPSHOT command
Read **cached** tap events on the **master** (one pending event per slave). Slaves send `ESPNOW_TAP_EVENT` on tap; the master stores the latest value per client in `client_registry.c` for up to **16 ms** (`CLIENT_REGISTRY_TAP_MAX_AGE_MS`). Each snapshot **consumes** fresh events (cleared after read).
### CACHE_STATUS command
Fast combined poll for host tools at **16 ms** or faster: one UART frame, no request body (command id `0x1d` only).
Read **cached** accel and/or tap data on the **master** in one UART round-trip. Slaves send `ESPNOW_ACCEL_SAMPLE` every **16 ms** when streaming; tap events arrive via `ESPNOW_TAP_EVENT` and are held up to **16 ms** (`CLIENT_REGISTRY_TAP_MAX_AGE_MS`). Pending taps are **consumed** on read (like the former `TAP_SNAPSHOT`).
**Response:** `cache_status_response` with:
**Request:** framed `1d` (`0x1d`) only — no body (`CacheStatusRequest` empty).
- `accel[]` — same as `ACCEL_SNAPSHOT`, only clients with `accel_stream_enabled`
- `taps[]` — same as `TAP_SNAPSHOT`, only clients with any tap notify flag; pending taps are consumed
**Response:** `cache_status_response.clients[]` — one entry per slave with `accel_stream_enabled` and/or any tap-notify flag:
The master walks `client_registry` once per request (`cmd/cmd_cache_status.c`). Prefer this over separate `ACCEL_SNAPSHOT` + `TAP_SNAPSHOT` when polling both streams.
| Field | When present |
|-------|----------------|
| `client_id` | Always (for listed slaves) |
| `accel` | Slave has accel stream on (`valid`, `x`/`y`/`z`, `age_ms` when sample fresh) |
| `tap` | Tap notify on **and** a pending tap was consumed (`kind`, `age_ms`) |
Only slaves with at least one tap-notify flag enabled are included.
Unsubscribed submessages are omitted on the wire (proto3 defaults). The master walks `client_registry` once per request (`cmd/cmd_cache_status.c`).
**Request:** framed `1c` (`0x1c`) + optional `tap_snapshot_request` (`client_id`: `0` = all, `>0` = one id).
**Response:** `tap_snapshot_response.events[]`:
| Field | Meaning |
|-------|---------|
| `client_id` | Slave id (registry) |
| `valid` | Fresh tap available (≤16 ms) |
| `kind` | `TAP_SINGLE`, `TAP_DOUBLE`, or `TAP_TRIPLE` |
| `age_ms` | Ms since tap was received on master |
Host tools poll this only when **receive** is enabled (dashboard tap column, WebSocket `set_tap_stream`). They keep events visible for **2 s** in the UI/API after first sight.
Host tools poll this at **16 ms** when live-stream / WebSocket receive is enabled. Tap events stay visible for **2 s** in the UI/API after first sight.
```bash
go run . -port /dev/ttyUSB0 tap
go run . -port /dev/ttyUSB0 tap -client 16
go run . -port /dev/ttyUSB0 cache-status
```
External API (`serve -api-addr :8081`) uses the same command for WebSocket `accel` / `tap` push.
### ESPNOW_UNICAST_TEST command
Minimal master→slave ESP-NOW unicast check (no BMA456). Use this before debugging `ACCEL_DEADZONE` unicast.
@@ -564,10 +529,8 @@ Target: ESP32-S3. Close serial monitor on the UART adapter port before running `
| `cmd/cmd_client_info.c/h` | CLIENT_INFO handler |
| `client_registry.c/h` | Registered slave table |
| `bosch456.c/h` | BMA456H I2C driver, accel poll, on-demand read, tap INT, deadzone filter |
| `cmd/cmd_accel_snapshot.c` | UART `ACCEL_SNAPSHOT` — cached slave accel |
| `cmd/cmd_tap_notify.c` | UART `TAP_NOTIFY` — ESP-NOW tap notify config |
| `cmd/cmd_tap_snapshot.c` | UART `TAP_SNAPSHOT` — consume cached tap events |
| `cmd/cmd_cache_status.c` | UART `CACHE_STATUS` — combined accel + tap cache poll |
| `cmd/cmd_cache_status.c` | UART `CACHE_STATUS` — subscribed accel + tap cache poll |
| `board_input.c/h` | Taster GPIO12, LiPo ADC on GPIO1 / GPIO12 |
| `pod_settings.c/h` | NVS persistence (accel deadzone, …) |
| `led_ring.c/h` | LED ring (digit display, progress bar) |