Files
mux-py/README.md
T
swaits 840d673fb9
CI / lint (push) Canceled after 0s
CI / test (3.10) (push) Canceled after 0s
CI / test (3.11) (push) Canceled after 0s
CI / test (3.12) (push) Canceled after 0s
CI / test (3.13) (push) Canceled after 0s
CI / publish (push) Canceled after 0s
chore: repoint remaining links at git.swaits.com
Rewrites lingering github.com / *.sr.ht references to this Gitea instance,
translating GitHub and Sourcehut URL shapes to Gitea's (/blob/<ref>/ and
sr.ht /tree/<ref>/item/ -> /src/branch/<ref>/, /tree/<tag> -> /src/tag/<tag>,
/actions/workflows/X -> /actions?workflow=X, /edit/ -> /_edit/).

Left pointing at the old hosts on purpose: pull-request links (PRs were not
migrated), forks that were never migrated, and GitHub-only surfaces Gitea
lacks. OpenPGP identity proofs are untouched by design.
2026-08-31 18:32:08 -06:00

2.4 KiB

DongLoRa Mux (Python)

USB multiplexer daemon — lets multiple applications share one DongLoRa dongle simultaneously. Speaks the DongLoRa Protocol v2 wire protocol (see PROTOCOL.md).

What It Does

  • Owns the USB serial connection exclusively (flock-protected).
  • Exposes a Unix domain socket and optional TCP listener speaking the DongLoRa Protocol v2 frame format.
  • Tag-correlated solicited responses — concurrent commands from multiple clients are routed back to the originator via a mux-allocated device-tag map (PROTOCOL.md §13.6).
  • RX fan-out — every over-the-air RX is broadcast to all clients.
  • TX loopback (§13.4) — a successful TX from one client is delivered to every other client as an RX event with origin = LOCAL_LOOPBACK.
  • Smart SET_CONFIG arbitration (§13.2) — the first successful call locks the config; cross-client calls get ALREADY_MATCHED / LOCKED_MISMATCH with the lock owner's params echoed. A single connected client can still retune freely (scanner mode).
  • RX_START / RX_STOP ref-counting — the radio stays in RX as long as any client wants it.

Running

just run                            # start the mux daemon
just verbose                        # start with verbose logging
just run --tcp 5741 --port /dev/ttyACM0   # with options

Depends On

  • donglora (>= 1.0) — the Python client library. Provides the wire-level frame codec, event parsers, and USB discovery helpers this mux is built on.

Relationship to donglora-mux (Rust)

This package is a Python port of the Rust donglora-mux daemon. The two implementations are functionally equivalent — they speak the same DongLoRa Protocol v2 wire protocol, implement the same §13.2 / §13.4 multi-client semantics, and are drop-in interchangeable in front of the same dongle. Pick whichever fits your ops environment:

  • Rust (cargo install donglora-mux) — single binary, no runtime deps, ~5 MB release build. Better for production / embedded Linux.
  • Python (pip install donglora-mux) — easy to hack on, integrates with a Python toolchain, useful when Rust isn't an option.

If you find a behavioural divergence between the two, that's a bug — please file it.