e9c4bb3e93149ba5334c4669815ed479d3f86d3d
The 1.0 Python client, mirroring the Rust client 1.0 API and the DongLoRa Protocol v2 wire format. * Module split: monolithic protocol.py / client.py replaced with dongle.py (high-level async Dongle), session.py (reader task + tag routing), frame.py (streaming FrameDecoder + encode_frame), commands.py / events.py / errors.py / modulation.py / info.py / crc.py / chip_id (re-export) matching the donglora-protocol Rust crate. * Async API throughout. Serial I/O via asyncio-serial; mux connections via asyncio streams. The blocking client surface is gone. * thiserror-equivalent error hierarchy (DongloraError base with Timeout, TransportClosed, ReaderExited, BadFrame, ErrClientError variants mirroring the Rust ClientError). * Tag-aware dispatch with concurrent in-flight commands: TagAllocator hands out 16-bit device tags, Session routes each response back to the originating coroutine. * Auto-recovery from ERR(ENOTCONFIGURED): the Dongle caches the last SET_CONFIG and silently re-applies on timeout. * 500 ms background keepalive task per PROTOCOL.md §3.4. * Tests rewritten: test_dongle, test_session, test_frame, test_events, test_modulation, test_crc, test_ergonomics; old test_client / test_protocol removed. * Sticky mux reconnect (from the prior fix commit) is preserved: once a mux socket is in use, reconnects commit to it instead of falling back to USB.
DongLoRa Python Client
Python client library for talking to a DongLoRa device — either directly over USB or through the mux daemon.
Install
pip install donglora
Or with uv:
uv add donglora
Quick Start
import donglora as dl
ser = dl.connect()
dl.send(ser, "SetConfig", config=dl.DEFAULT_CONFIG)
dl.send(ser, "StartRx")
while True:
pkt = dl.recv(ser)
if pkt:
print(pkt["rssi"], pkt["payload"].hex())
Connection Functions
| Function | Description |
|---|---|
connect() |
Auto-detect: TCP mux, Unix socket mux, then USB serial |
connect_default() |
Convenience wrapper with default timeout |
try_connect() |
Like connect() but non-blocking — raises if no device found |
connect_mux_auto() |
Mux only — never falls back to USB serial |
mux_connect() |
Connect via Unix domain socket |
mux_tcp_connect() |
Connect via TCP |
Module Structure
| Module | Contents |
|---|---|
donglora.protocol |
Wire types, RadioConfig, encode/decode, constants |
donglora.codec |
COBS framing |
donglora.discovery |
USB device discovery by VID:PID |
donglora.transport |
MuxConnection (socket wrapper) |
donglora.connect |
Connection auto-detection and mux helpers |
donglora.client |
High-level send/recv/validate |
Everything is re-exported from the top-level donglora package.
Dependencies
cobs— COBS framingpyserial— USB serial communication
Optional extras: meshcore (crypto), orac (AI bot).
Development
just check # fmt + lint + test
just fmt # format code
just test # run tests
Languages
Python
99.7%
Just
0.3%