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
+33 -7
View File
@@ -21,6 +21,7 @@ from micromesh import PortNum, SerialInterface
EVENT_PREFIX = "MMEVT "
COMMAND_PREFIX = "MMCMD "
MAX_BRIDGE_BUFFER = 8192
class PySerialUART:
@@ -85,7 +86,10 @@ class XiaoBridge:
command = {"type": kind}
command.update(values)
line = COMMAND_PREFIX + json.dumps(command, separators=(",", ":")) + "\n"
self.port.write(line.encode("utf-8"))
data = line.encode("utf-8")
written = self.port.write(data)
if written is not None and written != len(data):
raise OSError("short serial write")
def connect(self):
self._command("refresh")
@@ -101,6 +105,11 @@ class XiaoBridge:
waiting = self.port.in_waiting
if waiting:
self._buffer.extend(self.port.read(waiting))
if len(self._buffer) > MAX_BRIDGE_BUFFER and b"\n" not in self._buffer:
self._buffer = bytearray()
self.state.decode_errors += 1
self.state.status = "discarded oversized bridge line"
return
while True:
newline = self._buffer.find(b"\n")
if newline < 0:
@@ -112,8 +121,11 @@ class XiaoBridge:
if marker < 0:
continue
try:
self._event(json.loads(line[marker + len(EVENT_PREFIX):]))
except (ValueError, TypeError) as error:
event = json.loads(line[marker + len(EVENT_PREFIX):])
if not isinstance(event, dict):
raise ValueError("event is not an object")
self._event(event)
except (KeyError, ValueError, TypeError) as error:
self.state.decode_errors += 1
self.state.status = "bad bridge event: %s" % error
@@ -206,6 +218,17 @@ def node_values(info):
return node_id(info.num), name, short, snr, battery, hops, heard
def config_status(mesh, state):
"""Describe useful progress even when the completion ID never matches."""
if mesh.config_complete:
return "complete"
if mesh.my_info is not None and mesh.nodes:
return "ready"
if state.frames or mesh.my_info is not None or mesh.nodes:
return "receiving"
return "waiting"
def add_line(screen, row, text, style=0):
height, width = screen.getmaxyx()
if 0 <= row < height and width > 1:
@@ -225,13 +248,13 @@ def draw(screen, mesh, state):
add_line(screen, 0, " MicroMesh dashboard ", title_style)
local = node_id(mesh.my_info.my_node_num) if mesh.my_info else "unknown"
connected = "yes" if mesh.config_complete else "waiting"
config = config_status(mesh, state)
uptime = int(time.monotonic() - state.started)
add_line(
screen,
1,
"Local: %s Config: %s Uptime: %ds Nodes: %d" % (
local, connected, uptime, len(mesh.nodes)
local, config, uptime, len(mesh.nodes)
),
)
add_line(
@@ -348,10 +371,10 @@ def run(screen, port_name, baudrate, xiao_bridge):
state.status = "configuration requested"
elif key in (10, 13, curses.KEY_ENTER):
text = state.draft.strip()
state.draft = ""
if text:
try:
mesh.sendText(text)
state.draft = ""
state.text_sent += 1
state.add_message("local", "all", text)
state.status = "message queued"
@@ -372,7 +395,10 @@ def run(screen, port_name, baudrate, xiao_bridge):
def main():
parser = argparse.ArgumentParser(description="MicroMesh curses dashboard")
parser.add_argument("port", help="Meshtastic serial port, such as /dev/cu.usbmodem1234")
parser.add_argument("--baud", type=int, default=115200, help="UART baud rate (default: 115200)")
parser.add_argument(
"--baud", type=int, default=115200,
help="UART baud rate (default: 115200)",
)
parser.add_argument(
"--xiao-bridge",
action="store_true",