Add ESP-NOW heartbeat, client timeout, and slave reconnect.
Slaves send HEARTBEAT every 1s; the master marks clients inactive after 3s without traffic and reactivates on reconnect. CLIENT_INFO reports last_ping as milliseconds since the last packet, not uptime. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+7
-4
@@ -77,6 +77,7 @@ WiFi is brought up in STA mode (no AP association). Channel = `app_config.networ
|
||||
|------|-------|-----------|---------|
|
||||
| `DISCOVER` | 1 | Master → broadcast `FF:FF:FF:FF:FF:FF` | Master is searching for slaves |
|
||||
| `SLAVE_INFO` | 2 | Slave → master | Slave registration |
|
||||
| `HEARTBEAT` | 3 | Slave → master | Keep-alive (header only, no extra payload) |
|
||||
|
||||
`SLAVE_INFO` payload (after header bytes 0–2):
|
||||
|
||||
@@ -88,9 +89,9 @@ WiFi is brought up in STA mode (no AP association). Channel = `app_config.networ
|
||||
| `available` | uint8 | 1 = available |
|
||||
| `used` | uint8 | 0 = unused |
|
||||
|
||||
**Master:** task `espnow_disc` sends `DISCOVER` every **500 ms** on the configured network. Logs `slave joined id=… mac=… ver=…` when a new slave is seen (up to 16 entries).
|
||||
**Master:** task `espnow_disc` sends `DISCOVER` every **500 ms** on the configured network. Logs `slave joined id=… mac=… ver=…` when a new slave is seen (up to 16 entries). Task `espnow_mon` runs every **1 s** and marks a client **inactive** (`available = false`) if no `SLAVE_INFO` or `HEARTBEAT` was received for **3 s** (three missed 1 s heartbeats). A later heartbeat sets `available` true again and logs reactivation.
|
||||
|
||||
**Slave:** on first matching `DISCOVER`, logs `joined network N, master …`, sends `SLAVE_INFO` once, then ignores further discovers from that master (no repeat log or reply).
|
||||
**Slave:** on first matching `DISCOVER`, logs `joined network N, master …`, sends `SLAVE_INFO` once, then sends `HEARTBEAT` to the master every **1 s**. While joined, periodic discovers from the same master refresh a “master alive” timer; if no discover arrives for **5 s**, the slave treats the master as lost, clears join state, and will register again on the next discover (reconnect). Discover from a different master is ignored while already joined.
|
||||
|
||||
Monitor via USB-JTAG (`/dev/ttyACM0`) while using a USB-serial adapter on **GPIO2/3** (`/dev/ttyUSB0`) for UART — they are different interfaces.
|
||||
|
||||
@@ -188,7 +189,7 @@ Encoding: `uart_send_uart_message()` in `uart_proto.c`.
|
||||
|
||||
**Response:** payload `04` + nanopb `UartMessage` with `client_info_response.clients` — one `ClientInfo` per registered slave (from ESP-NOW `SLAVE_INFO`).
|
||||
|
||||
Fields per client: `id`, `mac`, `version`, `available`, `used`, `last_ping`, `last_success_ping` (milliseconds since boot, updated on each `SLAVE_INFO`).
|
||||
Fields per client: `id`, `mac`, `version`, `available`, `used`, `last_ping`, `last_success_ping` — **milliseconds since** the last packet / last successful heartbeat (computed when `CLIENT_INFO` is answered; typically 0–1000 while the slave is heartbeating every 1 s).
|
||||
|
||||
## Client registry
|
||||
|
||||
@@ -196,9 +197,11 @@ Fields per client: `id`, `mac`, `version`, `available`, `used`, `last_ping`, `la
|
||||
|-----|-------------|
|
||||
| `client_registry_init()` | Clear all slots (called from `esp_now_comm_init`) |
|
||||
| `client_registry_upsert(mac, id, version, …)` | Add or refresh client; updates ping timestamps |
|
||||
| `client_registry_heartbeat(mac, id, version, …)` | Same as upsert for heartbeats; reactivates inactive clients |
|
||||
| `client_registry_check_timeouts(timeout_ms)` | Mark stale clients inactive (master monitor task) |
|
||||
| `client_registry_count()` / `client_registry_at(i)` | Iterate for UART encoding |
|
||||
|
||||
Slaves register when the master receives `SLAVE_INFO` on the matching network.
|
||||
Slaves register when the master receives `SLAVE_INFO` on the matching network; `HEARTBEAT` keeps them marked available.
|
||||
|
||||
## Host tool (`goTool/`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user