Commit graph

2 commits

Author SHA1 Message Date
d01bef5172
fix(serial): detect passed-through /dev USB-serial nodes (container GUI detect) (#53)
pyserial comports() reads /sys USB metadata, absent inside a container for a
bind-mounted device node — so /api/serial-ports returned [] and the GUI "Detect"
showed nothing despite /dev/meshcore-rak (major 166) being present + openable.

Supplement comports() with a direct /dev scan: include char devices whose major
is a USB-serial major (166 ttyACM, 188 ttyUSB), catching /dev/ttyACM*/ttyUSB*
AND custom udev names like /dev/meshcore-rak that a tty* glob misses; exclude
legacy ttyS* (major 4). Merge deduped by realpath (pyserial metadata wins on
overlap). stable_path: by-id > stable custom name > by-path > raw. likely_radio
heuristic on the name (mesh|rak|lora|tbeam|heltec|nrf|companion) for bare nodes.
Resilient (unreadable /dev / stat error skipped, never raises).

8 new tests; suite at 10-failure baseline.

Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 23:01:08 -06:00
b1ebdd1434
feat(transport): MeshCore serial/USB + BLE support + USB auto-detect with stable paths (#52)
MeshCore can now connect over USB serial (and BLE) directly, not just TCP to
the pyMC companion. The meshcore lib already supported create_serial/create_ble;
we just wire it up. Plus a USB auto-detect scanner that resolves stable device
paths to fix ttyACM enumeration hopping across replug/reboot.

Backend:
- ConnectionConfig: meshcore_conn_type (tcp|serial|ble, default tcp),
  meshcore_serial_port, meshcore_baud=115200, meshcore_ble_address (validated)
- meshcore_transport._do_connect dispatches per mode: serial ->
  MeshCore.create_serial(port, baudrate, auto_reconnect, max_reconnect_attempts),
  ble -> create_ble(address or None), tcp -> create_tcp (unchanged). Mode-aware
  logging/reconnect. Transport otherwise unchanged (mode-agnostic once _mc exists).
- factory.meshcore_enabled(config): active when the selected mode is configured
  (serial port / ble address / tcp host); back-compat — meshcore_host + default
  tcp still activates exactly as before.
- serial_ports.list_serial_ports(): pyserial comports + stable_path resolution
  by-id -> by-path -> raw (by-id keyed on USB serial = stable across replug),
  likely_radio flag by VID (RAK/nRF/CP210x/CH340), excludes legacy ttyS*, never
  raises. GET /api/serial-ports (+ container by-id passthrough hint).

Frontend:
- SerialPortPicker component: "Detect USB devices" -> lists ports (likely-radio
  badge, shows stable_path) -> onChange sets the stable by-id path; manual text
  fallback; empty/error/note states.
- MeshCore Connection: type selector TCP/Serial/BLE + per-mode fields (serial
  picker + baud; ble address). Meshtastic serial branch now uses the picker too.

Code-ready; not activated (defaults keep TCP). 35 new tests; suite at 10-failure
baseline. Container needs /dev/serial passed through for by-id paths.

Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 22:12:03 -06:00