feat!: examples on donglora 1.0 async API with shared _common helpers
Rewrite all scripts against the DongLoRa Protocol v2 async Dongle surface, and extract the shared MeshCore US preset into a single module. * _common.py: MESHCORE_US preset (910.525 MHz / BW 62.5 / SF 7 / CR 4/5 / sync 0x1424 / 20 dBm) plus small helpers, imported by every example. * New: explore.py, which prints the device capabilities and runs a single TX + RX roundtrip for quick hardware validation. * simple_rx.py, simple_tx.py, ping_pong.py, lora_bridge.py all switch to donglora.Dongle and the new Modulation / LoRaConfig types. * all_commands.py removed; it was an index of the old v0.1 command enum that no longer exists after the Protocol v2 split. * justfile: drop stale recipes that referenced removed scripts.
This commit is contained in:
8 files changed
+204
-209
No files matched your search
+72
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Probe a DongLoRa device: print capabilities, then TX + RX once.
|
||||
|
||||
Configures the radio for the MeshCore US/Canada channel so the TX
|
||||
probe is audible to other MeshCore nodes on the same band.
|
||||
|
||||
Usage:
|
||||
python examples/explore.py [PORT]
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
import donglora as dl
|
||||
from _common import MESHCORE_US
|
||||
|
||||
|
||||
def describe_info(info: dl.Info) -> None:
|
||||
chip = info.chip.name if isinstance(info.chip, dl.RadioChipId) else f"0x{info.chip:04X}"
|
||||
print(f" Protocol: DongLoRa Protocol v{info.proto_major}.{info.proto_minor}")
|
||||
print(f" Firmware: v{info.fw_major}.{info.fw_minor}.{info.fw_patch}")
|
||||
print(f" Chip: {chip}")
|
||||
print(f" Freq: {info.freq_min_hz / 1e6:.1f} - {info.freq_max_hz / 1e6:.1f} MHz")
|
||||
print(f" TX power: {info.tx_power_min_dbm}..{info.tx_power_max_dbm} dBm")
|
||||
print(f" Max pkt: {info.max_payload_bytes} bytes")
|
||||
print(f" SF range: {info.supported_sf()}")
|
||||
print(f" MCU UID: {info.mcu_uid.hex()}")
|
||||
caps = []
|
||||
if info.supports(dl.Capability.LORA):
|
||||
caps.append("LoRa")
|
||||
if info.supports(dl.Capability.FSK):
|
||||
caps.append("FSK")
|
||||
if info.supports(dl.Capability.CAD_BEFORE_TX):
|
||||
caps.append("CAD")
|
||||
print(f" Features: {', '.join(caps) or 'none advertised'}")
|
||||
|
||||
|
||||
port = sys.argv[1] if len(sys.argv) > 1 else None
|
||||
|
||||
with dl.connect(port, config=MESHCORE_US) as d:
|
||||
print("── GET_INFO ──")
|
||||
describe_info(d.info)
|
||||
|
||||
cfg = d.config
|
||||
print(
|
||||
f"\n── Radio configured: {cfg.freq_hz / 1e6:.3f} MHz "
|
||||
f"SF{cfg.sf} BW{cfg.bw.khz:g}kHz "
|
||||
f"sync=0x{cfg.sync_word:04X} {cfg.tx_power_dbm} dBm ──"
|
||||
)
|
||||
|
||||
print("\n── TX ──")
|
||||
td = d.tx(b"hello from explore.py")
|
||||
print(
|
||||
f" result={td.result.name} airtime_us={td.airtime_us} "
|
||||
f"(~{td.airtime_us / 1000:.1f} ms on air)"
|
||||
)
|
||||
|
||||
print("\n── RX (5 s window) ──")
|
||||
start = time.monotonic()
|
||||
any_rx = False
|
||||
for pkt in d.rx(timeout=0.25):
|
||||
any_rx = True
|
||||
print(
|
||||
f" pkt: rssi={pkt.rssi_dbm:.1f}dBm snr={pkt.snr_db:.1f}dB "
|
||||
f"len={len(pkt.data)} origin={pkt.origin.name}"
|
||||
)
|
||||
if time.monotonic() - start > 5:
|
||||
break
|
||||
if not any_rx:
|
||||
print(" (no packets received — try pairing with ping_pong.py --role tx)")
|
||||
|
||||
print("\nDone.")
|
||||
Reference in new issue
Block a user