Enhance testing and error handling; update documentation and examples

This commit is contained in:
pdxlocations
2026-08-01 01:14:46 -07:00
parent d242a82d1d
commit dbaa3b38b8
21 changed files with 228 additions and 61 deletions
+46 -19
View File
@@ -22,7 +22,7 @@ three wires, and regular Python.
- Send binary data and positions
- Read user, position, signal, battery, and hop information
- Preserve unknown protobuf fields for forward compatibility
- Recover from serial noise and skip newer messages it cannot decode
- Recover from serial noise and optionally report and skip undecodable frames
- Run a curses dashboard with live stats, nodes, and messages
- Work on MicroPython without third-party runtime dependencies
@@ -59,16 +59,21 @@ You need:
- A separate Meshtastic-compatible radio running Meshtastic firmware
- Three jumper wires for TX, RX, and GND
- A data-capable USB cable for the XIAO
- Python 3 on your Mac, Linux computer, or Windows PC
- Python 3.8 or newer on your Mac, Linux computer, or Windows PC
Configure the Meshtastic radio's serial interface for:
For the UART-through-microcontroller setups, configure the Meshtastic radio's serial
module for:
```text
Enabled: yes
Mode: PROTO
Baud: 115200
Baud: 115200 (must match the MicroPython UART)
```
Meshtastic's serial-module default is 38400 baud; these examples deliberately use
115200. Set both ends to the same value. A direct USB connection to the radio does not
use this external-UART setup.
The radio's UART pin names depend on its model. Consult that board's pinout before
connecting wires.
@@ -168,8 +173,14 @@ mpremote connect /dev/cu.usbmodem2101 fs cp examples/xiao_rp2040.py :main.py
mpremote connect /dev/cu.usbmodem2101 reset
```
To stop or replace an automatically running script, connect the XIAO, press `Ctrl-C`
in `mpremote repl`, and upload a different `main.py`.
To replace an automatically running script, upload a different `main.py`; `mpremote`
stops the running program before filesystem commands. To disable automatic startup
without replacing it:
```sh
mpremote connect /dev/cu.usbmodem2101 rm :main.py
mpremote connect /dev/cu.usbmodem2101 reset
```
## Curses dashboard through the XIAO
@@ -178,10 +189,17 @@ It displays live connection stats, known nodes, battery levels, SNR, hops, last-
times, and incoming messages. The XIAO runs a small bridge between the radio UART and
the dashboard over USB.
The header shows `Config: complete` after a matching configuration handshake. Some
radios do not return the matching completion ID; once local and node data are usable,
the dashboard shows `Config: ready` instead.
The dashboard needs a small bridge program on the XIAO. The regular
`xiao_rp2040.py` example prints human-readable logs; it does not expose structured data
to desktop applications.
Complete the XIAO quick-start installation through step 4 first, so the `micromesh`
package is present on the board.
### 1. Install the desktop dependencies
```sh
@@ -214,7 +232,8 @@ Only one application can own a serial port. Close `mpremote`, Arduino Serial Mon
screen, minicom, and other serial tools before launching the dashboard.
The message field is always active. Type a message and press Enter—there is no separate
compose mode.
compose mode. `message queued` means the radio accepted the packet for transmission;
it is not a delivery receipt.
| Key | Action |
| --- | --- |
@@ -296,9 +315,11 @@ Send a **new** text from another Meshtastic node while MicroMesh is running.
### A frame is skipped or reports a decode error
Meshtastic's protobuf schema evolves. MicroMesh reports and skips newer messages that
its compact schema does not yet understand. Text and other supported packets continue
processing. Update the installed files after pulling a newer MicroMesh version:
Meshtastic's protobuf schema evolves. Unknown fields are retained automatically. When
an `on_error` callback is configured—as it is in the board examples—MicroMesh reports
and skips a frame if it is malformed or conflicts with the compact schema; later
frames continue processing. Without that callback, `poll()` raises the decoding error.
Update the installed files after pulling a newer MicroMesh version:
```sh
mpremote connect /dev/cu.usbmodem2101 mip install package.json
@@ -324,14 +345,19 @@ def received(packet):
if packet.WhichOneof("payload_variant") != "decoded":
return
if packet.decoded.portnum == PortNum.TEXT_MESSAGE_APP:
print("from !%08x: %s" % (
packet.from_,
packet.decoded.payload.decode("utf-8"),
))
try:
text = packet.decoded.payload.decode("utf-8")
except UnicodeError:
text = repr(packet.decoded.payload)
print("from !%08x: %s" % (packet.from_, text))
def decode_error(error, payload):
print("skipping undecodable frame:", error, "(%d bytes)" % len(payload))
uart = UART(0, 115200, tx=Pin(0), rx=Pin(1), timeout=0, rxbuf=1024)
mesh = SerialInterface(uart, on_packet=received)
mesh = SerialInterface(uart, on_packet=received, on_error=decode_error)
mesh.connect()
while True:
@@ -355,8 +381,9 @@ mesh.sendPosition(45.5152, -122.6784, altitude=15)
mesh.sendData(b"custom", portNum=PortNum.PRIVATE_APP)
```
Payloads may be at most 233 bytes. `poll()` is non-blocking when the UART uses
`timeout=0`, so call it frequently from your main loop.
Data payloads may be at most 233 bytes, including UTF-8 encoded text bytes rather than
characters. `poll()` is non-blocking when the UART uses `timeout=0`, so call it
frequently from your main loop.
### Inspect connection state
@@ -437,8 +464,8 @@ python -m pip install -e .
python -m unittest discover -s tests
```
The test suite covers encoding, decoding, framing, serial recovery, sending, and
configuration state.
The test suite covers encoding, decoding, field presence, framing, serial recovery,
sending, input validation, and configuration state.
## Releasing to PyPI