feat!: mux on DongLoRa Protocol v2 with tag-aware dispatch
The 1.0 mux, running on the Protocol v2 wire format and full §13 multi-client semantics. * Tag-aware dispatch. Each inbound client frame is re-tagged with a mux-allocated device tag; responses are routed back to the original client using the tag mapping. The single-oneshot response slot is gone; multiple clients can have commands in flight concurrently. * Full §13.2 multi-client SET_CONFIG semantics. Tracks the (client, modulation) lock owner and synthesizes OK(APPLIED/MINE), OK(ALREADY_MATCHED/OTHER), or OK(LOCKED_MISMATCH/OTHER) based on lock ownership and parameter match. Lock releases automatically on client disconnect. * TX loopback fan-out (§13.4). On TX_DONE(TRANSMITTED) the mux synthesizes an RX frame with origin = LocalLoopback and sends it to every connected client except the transmitter. * Async ERR(EFRAME) fan-out. If the dongle emits async framing errors (tag = 0), they are broadcast to all clients rather than swallowed. * TagMapper with skip-zero allocation and per-client bulk drop on disconnect. * Per-client TX cache on ClientSession so the loopback fan-out does not need the sender to re-buffer. * 500 ms keepalive cadence matching PROTOCOL.md §3.4 inactivity window (replacing the old 5 s loop).
This commit is contained in:
7 files changed
+1081
-522
No files matched your search
+37
-6
@@ -1,14 +1,45 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
## 1.0.0-alpha.1 — 2026-04-21
|
||||
|
||||
### Breaking
|
||||
|
||||
- **Upgraded to DongLoRa Protocol v2 wire format.** Wire-incompatible with 0.x
|
||||
clients and firmware. Now depends directly on `donglora-protocol` for
|
||||
frame encode/decode.
|
||||
- **Tag-aware dispatch.** Each inbound client frame is re-tagged with a
|
||||
mux-allocated device tag; responses are routed back to the original
|
||||
client using the tag mapping. No more single-oneshot response slot —
|
||||
multiple clients can have commands in flight concurrently.
|
||||
|
||||
### Added
|
||||
|
||||
- Keepalive ping: detects unresponsive dongles (e.g. UART boards behind a
|
||||
CP2102 bridge where the serial port stays open across ESP32 resets). Pings
|
||||
every 5 seconds of idle, declares dongle lost after 2-second timeout.
|
||||
- Radio state restoration after reconnect: saved SetConfig and StartRx are
|
||||
re-sent to the dongle so clients don't need to know a reset happened.
|
||||
- **Full `§13.2` multi-client `SET_CONFIG` semantics.** Tracks the
|
||||
`(client, modulation)` lock owner. Cross-client calls synthesize:
|
||||
- `OK(APPLIED / MINE, params)` when the calling client owns the lock
|
||||
(forwarded to dongle).
|
||||
- `OK(ALREADY_MATCHED / OTHER, current)` when another client holds
|
||||
the lock and the requested params byte-match.
|
||||
- `OK(LOCKED_MISMATCH / OTHER, current)` when another client holds
|
||||
the lock and the requested params differ.
|
||||
- Lock is released automatically when the owning client disconnects.
|
||||
- **TX loopback fan-out (spec §13.4).** On `TX_DONE(TRANSMITTED)`, the
|
||||
mux synthesizes an `RX` frame with `origin = LocalLoopback` and sends
|
||||
it to every connected client except the transmitter.
|
||||
- **Async `ERR(EFRAME)` fan-out.** If the dongle emits async framing
|
||||
errors (tag = 0), they're broadcast to all clients rather than
|
||||
swallowed.
|
||||
- **Per-client TX cache** on `ClientSession` so the loopback fan-out
|
||||
doesn't need the sender to re-buffer.
|
||||
- **`TagMapper`** with skip-zero allocation and per-client bulk drop on
|
||||
disconnect.
|
||||
|
||||
### Removed
|
||||
|
||||
- The single `pending_response: oneshot::Sender` slot in the daemon
|
||||
(fundamentally incompatible with v1.0's per-tag concurrency).
|
||||
- The separate 5-second keepalive timer — replaced with a 500 ms
|
||||
internal cadence matching the spec §3.4 inactivity window.
|
||||
|
||||
## 0.2.2 — 2026-04-08
|
||||
|
||||
|
||||
Reference in new issue
Block a user