Files
client-rs/CHANGELOG.md
T
swaits 6937ad47ba feat!: Protocol v2 client rewrite with Dongle/Session model
The full 1.0 client surface, matching the protocol v2 wire definitions from donglora-protocol 1.0.0.

* Public API is now async. The blocking Client<T: Transport> is replaced by Dongle (from donglora_client::connect / connect_with / ConnectOptions).

* src/client.rs and src/codec.rs are removed in favor of src/dongle.rs (high-level surface), src/session.rs (per-client tag/slot state), src/retry.rs (RetryPolicy + tx_with_retry), src/errors.rs (thiserror-based ClientError / ClientResult). src/protocol.rs is replaced by direct donglora-protocol imports.

* Transport is now tokio-serial for USB and tokio::net::{UnixStream, TcpStream} for mux, replacing the blocking serial + shim model.

* Dongle::tx_with_retry(data, &RetryPolicy) implements PROTOCOL.md §6.10 randomized backoff for CHANNEL_BUSY / EBUSY, returning a TxOutcome with per-attempt trace.

* Background keepalive task pings every 500 ms on host idle, tracking the 1 s inactivity timeout from §3.4 with 2x margin. Disable via ConnectOptions::keepalive(false).

* Auto-recovery from ERR(ENOTCONFIGURED): the Dongle caches the last SET_CONFIG and silently re-applies on session drop, retrying once.

* Error taxonomy switches from anyhow to thiserror. Transport-level conditions (Timeout, TransportClosed, ReaderExited, BadFrame) are first-class.

* Examples rewritten for the async API: examples/ping.rs, examples/tx.rs, examples/rx.rs all target the MeshCore US preset (910.525 MHz / BW 62.5 / SF 7 / CR 4/5 / sync 0x1424 / 20 dBm). examples/common/mod.rs holds the shared helper.

* tests/vectors.rs gains protocol-level roundtrip coverage anchored to the published donglora-protocol 1.0.0 types.
2026-04-22 09:45:38 -06:00

5.1 KiB
Raw Blame History

Changelog

1.0.0-alpha.1 — 2026-04-21

Breaking

  • Migrated to the DongLoRa Protocol v2 wire format. All message types, tag correlation, and framing now follow PROTOCOL.md v1.0. This is a wire-incompatible break with 0.x clients and firmware. donglora-client now depends on donglora-protocol for the normative type definitions.
  • Full tokio-async rewrite. Public API is async; the blocking Client<T: Transport> is gone. Replace with Dongle from donglora_client::connect() (or the new ConnectOptions builder + connect_with). Serial I/O is now tokio-serial; mux connections are tokio::net::UnixStream / tokio::net::TcpStream.
  • thiserror-based error taxonomy. anyhow::Result on public APIs is replaced by donglora_client::ClientResult<T> = Result<T, ClientError>. Variants mirror the Python client's DongloraError hierarchy plus transport-level conditions (Timeout, TransportClosed, ReaderExited, BadFrame).

Added

  • Dongle::tx_with_retry(data, &RetryPolicy) — randomized backoff + exponential retry for TX_DONE(CHANNEL_BUSY) and ERR(EBUSY), per spec §6.10. Returns a [TxOutcome] capturing every per-attempt result so callers (the bridge TUI especially) can display retry state.
  • Auto-recovery from ERR(ENOTCONFIGURED). Dongle caches the applied config from the most recent SET_CONFIG and silently re-applies it + retries once when the firmware's inactivity timer expires mid-session.
  • Background keepalive task. Spawned at connect time, pings the device every 500 ms when the host has been idle, tracking the 1 s inactivity window from spec §3.4 with 2× safety margin. Disable via ConnectOptions::keepalive(false).
  • Rich RxPayload metadata. Bridge-relevant fields (rssi_tenths_dbm, snr_tenths_db, freq_err_hz, timestamp_us, crc_valid, packets_dropped, origin) are surfaced directly from the wire.
  • New examples: cargo run --example tx / --example rx alongside the existing ping, all using the MeshCore US preset (910.525 MHz / BW 62.5 / SF 7 / CR 4/5 / sync 0x1424 / 20 dBm).

Removed

  • The Client<T>, Response, RadioConfig, Bandwidth, and TX_POWER_MAX types. Modulation / LoRaConfig / LoRaBandwidth (re-exported from donglora-protocol) replace them.

0.2.1 — 2026-04-07

Fixed

  • connect() no longer falls through from mux to USB serial. If a mux socket file exists, connect(None, timeout) and try_connect(timeout) now commit to the mux and return an error if the mux is unreachable — instead of silently bypassing it and grabbing the USB port directly. This prevents a race condition where a client could steal the serial port from the mux during reconnect. Callers with explicit port = Some(...) are unaffected.

0.2.0 — 2026-04-07

Features

  • Ping-on-connect validation — all connect functions automatically ping the device after connecting and reject non-DongLoRa devices within 200ms. No more accidentally talking LoRa protocol to an Arduino.
  • try_connect(timeout) — non-blocking alternative to connect(). Returns an error immediately if no DongLoRa device is found instead of blocking indefinitely.
  • USB-UART bridge chip fallback — find_port() now detects boards using CP2102, CH9102, CH340, or FT232R bridge chips (validated via ping).
  • Payload size validation — transmit() rejects payloads exceeding 256 bytes with a clear error before hitting the wire.
  • ErrorCode implements std::error::Error — usable in error chains.

Breaking changes

  • Wire-level tag constants (CMD_TAG_*, RESP_TAG_*, ERROR_INVALID_CONFIG) removed from the top-level re-exports. Access them via donglora_client::protocol::* if needed.
  • connect() and friends now validate the device on connect. Code that previously connected to non-DongLoRa serial devices will now get an error.

Fixes

  • Fixed repository URL in crate metadata.
  • drain_rx no longer swallows the original error if timeout restore also fails.
  • Removed dead firmware/PROTOCOL.md reference from docs.

0.1.0 — 2026-04-06

Initial release.

Features

  • High-level Client<T> with send/recv and command helpers (ping, set_config, start_rx, stop_rx, transmit, get_config, get_mac, display_on, display_off)
  • COBS wire framing via ucobs (matches firmware implementation)
  • Auto-detection connection: TCP mux, Unix socket mux, direct USB serial
  • Bounded RX packet buffering (256 packets, FIFO eviction)
  • FrameReader accumulator for streaming byte sources
  • USB device discovery by VID:PID with blocking wait

Resilience

  • Cross-platform timeout handling: TimedOut (Windows) and WouldBlock (Linux/macOS) both treated as clean timeouts in read_frame
  • EINTR/Interrupted signals retried automatically in read_frame
  • drain_rx always restores the original timeout, even on I/O errors
  • TCP mux connections use connect_timeout (bounded by caller's timeout)
  • Mux sockets set both read and write timeouts
  • SerialTransport tracks timeout accurately for save/restore
  • Unexpected unsolicited frames logged via tracing::warn instead of silently discarded