add UBX-MON-VER support and surface device identification in CLI/GUI
Add the Ver message parser and a fixed UbxQuery (was unused and had a broken semaphore/state bug) to poll MON-VER once on connect. The CLI prints hw/sw version and extensions; the GUI polls it per receiver, pre-fills the read-only ID field with a connection counter and rewrites it from the MOD= extension once the device answers, and propagates the resolved display name to the Sky and Plot tabs so they no longer show the stale placeholder ID. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XM4FNUjhu9x8df5Dp1hHvd
This commit is contained in:
@@ -3,6 +3,7 @@ import time
|
||||
import json
|
||||
import signal
|
||||
import argparse
|
||||
import threading
|
||||
|
||||
from backend.network_backend import NetworkBackend
|
||||
from backend.serial_backend import SerialBackend
|
||||
@@ -16,8 +17,9 @@ from nmea.messages import Gll, Gsa, Gsv, Gga, Rmc
|
||||
from ubx.ubx import frame_create
|
||||
from ubx.msg_types import *
|
||||
from ubx.packetizer import UbxPacketizer
|
||||
from ubx.messages import Sig, Sat, RawX, UbxMsg
|
||||
from ubx.messages import Sig, Sat, RawX, Ver, UbxMsg
|
||||
from ubx.listener import UbxListener
|
||||
from ubx.query import UbxQuery
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -87,7 +89,8 @@ def _make_listeners(name: str):
|
||||
|
||||
|
||||
def wire_source(name: str, backend, log_dir: str | None,
|
||||
loggers: list, transceivers: dict, pacer_delay: float = 0.0):
|
||||
loggers: list, transceivers: dict, ver_queries: dict,
|
||||
pacer_delay: float = 0.0):
|
||||
xcvr = Transceiver(name)
|
||||
backend.register_xcvr(xcvr)
|
||||
transceivers[name] = xcvr
|
||||
@@ -104,6 +107,10 @@ def wire_source(name: str, backend, log_dir: str | None,
|
||||
|
||||
nmea_rx, ubx_rx = _make_listeners(name)
|
||||
|
||||
ver_query = UbxQuery(xcvr, Ver())
|
||||
ubx_rx.append(ver_query)
|
||||
ver_queries[name] = ver_query
|
||||
|
||||
if pacer_delay > 0:
|
||||
nmea_pacer = ReplayPacer(pacer_delay)
|
||||
ubx_pacer = ReplayPacer(pacer_delay)
|
||||
@@ -157,6 +164,7 @@ if __name__ == '__main__':
|
||||
backends = []
|
||||
loggers = []
|
||||
transceivers = {}
|
||||
ver_queries = {}
|
||||
|
||||
# Network sources → one shared NetworkBackend
|
||||
net_sources = [s for s in sources if s['type'] == 'network']
|
||||
@@ -165,13 +173,14 @@ if __name__ == '__main__':
|
||||
for s in net_sources])
|
||||
backends.append(net_be)
|
||||
for s in net_sources:
|
||||
wire_source(s['name'], net_be, log_dir, loggers, transceivers)
|
||||
wire_source(s['name'], net_be, log_dir, loggers, transceivers, ver_queries)
|
||||
|
||||
# Serial sources → one SerialBackend each
|
||||
for s in [s for s in sources if s['type'] == 'serial']:
|
||||
serial_sources = [s for s in sources if s['type'] == 'serial']
|
||||
for s in serial_sources:
|
||||
ser_be = SerialBackend(s['device'], s.get('baudrate', 115200))
|
||||
backends.append(ser_be)
|
||||
wire_source(s['name'], ser_be, log_dir, loggers, transceivers)
|
||||
wire_source(s['name'], ser_be, log_dir, loggers, transceivers, ver_queries)
|
||||
|
||||
# File sources → one shared FileBackend (no secondary logging)
|
||||
file_sources = [s for s in sources if s['type'] == 'file']
|
||||
@@ -182,7 +191,8 @@ if __name__ == '__main__':
|
||||
name = source_id_from_path(s['path'])
|
||||
if name:
|
||||
wire_source(name, file_be, log_dir=None, loggers=loggers,
|
||||
transceivers=transceivers, pacer_delay=delay)
|
||||
transceivers=transceivers, ver_queries=ver_queries,
|
||||
pacer_delay=delay)
|
||||
|
||||
signal.signal(signal.SIGINT,
|
||||
lambda sig, frm: handler(sig, frm, backends, loggers))
|
||||
@@ -191,6 +201,21 @@ if __name__ == '__main__':
|
||||
be.connect()
|
||||
be.start()
|
||||
|
||||
# Poll MON-VER once per live (network/serial) source, off the main thread
|
||||
# since UbxQuery.poll() blocks until the response frame arrives.
|
||||
def report_version(name: str, query: UbxQuery):
|
||||
ver = query.poll()
|
||||
if ver is None:
|
||||
return
|
||||
ext = '; '.join(e['extension'] for e in ver['extensions'])
|
||||
print(f"{name}: device hw={ver['hw_version']} sw={ver['sw_version']}"
|
||||
+ (f" ({ext})" if ext else ""))
|
||||
|
||||
for s in net_sources + serial_sources:
|
||||
name = s['name']
|
||||
threading.Thread(target=report_version, args=(name, ver_queries[name]),
|
||||
daemon=True).start()
|
||||
|
||||
# Poll loop – only meaningful for network/serial sources
|
||||
net_names = [s['name'] for s in net_sources]
|
||||
if net_names:
|
||||
|
||||
Reference in New Issue
Block a user