fix: correct postcard encoding for u8/i8 fields (was using varint/zigzag)

ROOT CAUSE: postcard encodes u8 and i8 as raw bytes, NOT varint/zigzag.
The Python encoders used varint() for u8 and zigzag() for i8. For small
values this was silently correct (varint(7) == raw byte 7), but for
tx_power_dbm: zigzag(14) = 28, which the new validation correctly
rejected as out of range (-9..22). This was a pre-existing bug masked
by the absence of validation.

Fix all RadioConfig field encoders in both donglora.py and meshcore_rx.py.
Fix docs/PROTOCOL.md to correctly document i8 as raw byte, not zigzag.
Restore full config validation.
This commit is contained in:
swaits committed 2026-03-29 20:42:58 -06:00
1 parent a0d9b3b4f0
commit 0b4eb04591
3 files changed
+22 -15

No files matched your search

+8 -7
View File
@@ -426,12 +426,12 @@ def zigzag(n: int) -> bytes:
def encode_radio_config(cfg: dict) -> bytes:
out = varint(cfg["freq_hz"])
out += varint(cfg["bw"])
out += varint(cfg["sf"])
out += varint(cfg["cr"])
out += varint(cfg["sync_word"])
out += zigzag(cfg["tx_power_dbm"])
out = varint(cfg["freq_hz"]) # u32: varint
out += varint(cfg["bw"]) # enum: varint variant index
out += struct.pack("B", cfg["sf"]) # u8: raw byte
out += struct.pack("B", cfg["cr"]) # u8: raw byte
out += varint(cfg["sync_word"]) # u16: varint
out += struct.pack("b", cfg["tx_power_dbm"]) # i8: raw byte (signed)
return out
@@ -931,7 +931,8 @@ def _format_rssi_snr(rssi: int, snr: int) -> str:
def configure_and_listen(ser: serial.Serial):
send_cmd(ser, {"type": "SetConfig", "config": RADIO_CONFIG}, "SetConfig 910.525/62.5k/SF7/CR4_5")
send_cmd(ser, {"type": "Ping"}, "Ping")
send_cmd(ser, {"type": "SetConfig", "config": RADIO_CONFIG}, "SetConfig 910.525/62.5k/SF7/CR4/5")
send_cmd(ser, {"type": "StartRx"}, "StartRx")
print(f"\n{BWHT}Listening for packets{RST} {DIM}(Ctrl+C to stop){RST}\n")