feat: Desktop USB serial transport (#4836)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-03-18 07:42:24 -05:00 committed by GitHub
parent 06c990026f
commit 59408ef46e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 457 additions and 37 deletions

View file

@ -0,0 +1,5 @@
# Track desktop_serial_transport_20260317 Context
- [Specification](./spec.md)
- [Implementation Plan](./plan.md)
- [Metadata](./metadata.json)

View file

@ -0,0 +1,8 @@
{
"track_id": "desktop_serial_transport_20260317",
"type": "feature",
"status": "new",
"created_at": "2026-03-17T12:00:00Z",
"updated_at": "2026-03-17T12:00:00Z",
"description": "Implement Serial/USB transport for the Desktop target using jSerialComm. This fulfills the medium-term priority for direct radio connections on JVM and uses the shared RadioTransport interface."
}

View file

@ -0,0 +1,21 @@
# Implementation Plan: Desktop Serial/USB Transport
## Phase 1: JVM Setup & Dependency Integration [checkpoint: a05916d]
- [x] Task: Add the `jSerialComm` library to the `jvmMain` dependencies of the networking module. [checkpoint: 8994c66]
- [x] Task: Create a `jvmMain` stub implementation for a `SerialTransport` class that implements the shared `RadioTransport` interface. [checkpoint: 83668e4]
## Phase 2: Serial Port Scanning & Connection Management [checkpoint: 9cda87d]
- [x] Task: Implement port discovery using `jSerialComm` to list available serial ports. [checkpoint: c72501d]
- [x] Task: Implement connect/disconnect logic for a selected serial port, handling port locking and baud rate configuration. [checkpoint: 23ee815]
- [x] Task: Map the input/output streams of the open serial port to the existing KMP stream framing logic (`StreamFrameCodec`). [checkpoint: 04ba9c2]
## Phase 3: UI Integration
- [x] Task: Update the `feature:connections` UI or `DesktopScannerViewModel` to poll the new `SerialTransport` for available ports. [checkpoint: 2e85b5a]
- [x] Task: Wire the user's serial port selection to initiate the connection via the DI graph and active service logic. [checkpoint: 94cb97c]
## Phase 4: Validation [checkpoint: 1055752]
- [x] Task: Verify end-to-end communication with a physical Meshtastic device over USB on the desktop target. [checkpoint: 1055752]
- [x] Task: Ensure CI builds cleanly and that no `java.*` dependencies leaked into `commonMain`. [checkpoint: 1055752]
## Phase: Review Fixes
- [x] Task: Apply review suggestions [checkpoint: d2f7c82]

View file

@ -0,0 +1,20 @@
# Specification: Desktop Serial/USB Transport via jSerialComm
## Objective
Implement direct radio connection via Serial/USB on the Desktop (JVM) target using the `jSerialComm` library. This fulfills the medium-term priority of bringing physical transport parity to the desktop app and validates the newly extracted `RadioTransport` abstraction in `core:repository`.
## Background
Currently, the desktop app supports TCP connections via a shared `StreamFrameCodec`. To provide parity with Android's USB serial connection capabilities, we need to implement a JVM-specific serial transport. The `jSerialComm` library is a widely-used, cross-platform Java library that handles native serial port communication without requiring complex JNI setups.
## Requirements
- Introduce `jSerialComm` dependency to the `jvmMain` source set of the appropriate core module (likely `core:network` or a new `core:serial` module).
- Implement the `RadioTransport` interface (defined in `core:repository/commonMain`) for the desktop target, wrapping `jSerialComm`'s port scanning and connection logic.
- Ensure the serial data is encoded/decoded using the same protobuf frame structure utilized by the TCP transport (e.g., leveraging the existing `StreamFrameCodec`).
- Integrate the new transport into the `feature:connections` UI on the desktop so users can scan for and select connected USB serial devices.
- Retain platform purity: keep all `jSerialComm` and `java.io.*` imports strictly within the `jvmMain` source set.
## Success Criteria
- [ ] Desktop application successfully scans for connected Meshtastic devices over USB/Serial.
- [ ] Users can select a serial port from the `feature:connections` UI and establish a connection.
- [ ] Two-way protobuf communication is verified (e.g., the app receives node info and can send a message).
- [ ] The implementation uses the shared `RadioTransport` interface without leaking JVM dependencies into `commonMain`.

View file

@ -24,4 +24,12 @@
## Networking & Transport
- **Ktor:** Multiplatform HTTP client for web services and TCP streaming.
- **Kable:** Multiplatform BLE library used as the primary BLE transport for all targets (Android, Desktop, and future iOS).
- **Coroutines & Flows:** For asynchronous programming and state management.
- **jSerialComm:** Cross-platform Java library used for direct Serial/USB communication with Meshtastic devices on the Desktop (JVM) target.
- **Coroutines & Flows:** For asynchronous programming and state management.
## Testing (KMP)
- **Shared Tests First:** The majority of business logic, ViewModels, and state interactions are tested in the `commonTest` source set using standard `kotlin.test`.
- **Coroutines Testing:** Use `kotlinx-coroutines-test` for virtual time management in asynchronous flows.
- **Mocking Strategy:** Avoid JVM-specific mocking libraries. Prefer `Mokkery` or `Mockative` for multiplatform-compatible mocking interfaces, alongside handwritten fakes in `core:testing`.
- **Flow Assertions:** Use `Turbine` for testing multiplatform `Flow` emissions and state updates.
- **Property-Based Testing:** Consider evaluating `Kotest` for multiplatform data-driven and property-based testing scenarios if standard `kotlin.test` becomes insufficient.