Two related changes to make sender/receiver logs analyzable:
1. MeshCoreRadio.send no longer returns until the radio firmware
reports the packet was actually transmitted. send_chan_msg only
waits for EventType.OK (firmware accepted bytes) — no
tx-complete event is pushed for channel messages, so we poll
commands.get_stats_packets() and wait for nb_sent to strictly
increment past a pre-send baseline. Times out after 30s.
2. Each test packet now embeds a random 8-hex-char token as the
4th comma-separated field of the prefix, distinct from any
radio-assigned packet id. Receivers extract it from the text
and write it on every TSV row, so a sender's queued/sent rows
tie 1:1 to each receiver's record without depending on
whatever packet id the radio surfaces on each side.
TSV gains a new column (3rd, after packet_id):
queued: ts queued <id> <token> <freq,bw,sf,cr,pow>
sent: ts sent <id> <token> <duration_ms> <text>
received: ts received <id> <token> <text>
Missing token writes "-".
UDP simulator regex updated to accept both legacy 3-field test
payloads and the new 4-field format with token.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Concept spec calls for `<testname>.tsv`. Filename is now
`<testname>-<station>-<ts>.tsv` so reruns of the same test name
don't clobber prior runs and multiple stations stay distinguishable.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the modjam package: a MeshCore-backed test station service for
Pi (IDLE + RUNNING states, cuesheet-driven), a control station REPL
for the Mac, and a UDP simulator that swaps in for the radio when
SIMULATOR=true (drops cross-config packets and a configurable
fraction of test-payload datagrams to mimic real radio loss).
docker-compose runs three sim stations + control on a bridge net.
TSV log format matches the reference traces.
Pytest suite covers protocol codec, cuesheet builder, TSV logger,
config loader, and UDP radio packet routing/loss; .forgejo/workflows
runs it on push to main and on PRs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>