mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-03-28 18:52:42 -04:00
feat: Desktop USB serial transport (#4836)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
@@ -27,7 +27,7 @@ Modules that share JVM-specific code between Android and desktop now standardize
|
||||
| `core:database` | ✅ | ✅ | Room KMP |
|
||||
| `core:domain` | ✅ | ✅ | UseCases |
|
||||
| `core:prefs` | ✅ | ✅ | Preferences layer |
|
||||
| `core:network` | ✅ | ✅ | Ktor, `StreamFrameCodec`, `TcpTransport` |
|
||||
| `core:network` | ✅ | ✅ | Ktor, `StreamFrameCodec`, `TcpTransport`, `SerialTransport` |
|
||||
| `core:data` | ✅ | ✅ | Data orchestration |
|
||||
| `core:ble` | ✅ | ✅ | Kable multiplatform BLE abstractions in commonMain |
|
||||
| `core:nfc` | ✅ | ✅ | NFC contract in commonMain; hardware in androidMain |
|
||||
@@ -56,13 +56,14 @@ Modules that share JVM-specific code between Android and desktop now standardize
|
||||
Working Compose Desktop application with:
|
||||
- Navigation 3 shell (`NavigationRail` + `NavDisplay`) using shared routes
|
||||
- Full Koin DI graph (stubs + real implementations)
|
||||
- TCP transport with auto-reconnect and full `want_config` handshake
|
||||
- TCP, Serial/USB, and BLE transports with auto-reconnect and full `want_config` handshake
|
||||
- Adaptive list-detail screens for nodes and contacts
|
||||
- **Dynamic Connections screen** with automatic discovery of platform-supported transports (TCP)
|
||||
- **Dynamic Connections screen** with automatic discovery of platform-supported transports (TCP, Serial/USB, BLE)
|
||||
- **Desktop language picker** backed by `UiPreferencesDataSource.locale`, with immediate Compose Multiplatform resource updates
|
||||
- **Navigation-preserving locale switching** via `Main.kt` `staticCompositionLocalOf` recomposition instead of recreating the Nav3 backstack
|
||||
- Node detail metrics screens (Device, Environment, Signal, Power, Pax) wired with shared KMP + Vico charts
|
||||
- 7 desktop-specific screens (Settings, Device, Position, Network, Security, ExternalNotification, Debug)
|
||||
- **Native notifications and system tray icon** wired via `DesktopNotificationManager`
|
||||
- **Native release pipeline** generating `.dmg` (macOS), `.msi` (Windows), and `.deb` (Linux) installers in CI
|
||||
|
||||
## Scorecard
|
||||
@@ -107,7 +108,7 @@ Based on the latest codebase investigation, the following steps are proposed to
|
||||
| Material 3 Adaptive (JetBrains) | ✅ Done | Version `1.3.0-alpha06` aligned with CMP `1.11.0-alpha04` |
|
||||
| JetBrains lifecycle/nav3 alias alignment | ✅ Done | All forked deps use `jetbrains-*` prefix in version catalog; `core:data` commonMain uses JetBrains lifecycle runtime |
|
||||
| Expect/actual consolidation | ✅ Done | 7 pairs eliminated; 15+ genuinely platform-specific retained |
|
||||
| Transport deduplication | ✅ Done | `StreamFrameCodec` + `TcpTransport` shared in `core:network` |
|
||||
| Transport deduplication | ✅ Done | `StreamFrameCodec`, `TcpTransport`, and `SerialTransport` shared in `core:network` |
|
||||
| **Transport UI Unification** | ✅ Done | `RadioInterfaceService` provides dynamic transport capability to shared UI |
|
||||
| Emoji picker unification | ✅ Done | Single commonMain implementation replacing 3 platform variants |
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ here| **Migrate to JetBrains Compose Multiplatform dependencies** | High | Low |
|
||||
- ✅ **Settings:** ~35 screens with real configuration, including theme/about parity and desktop language picker support
|
||||
- ✅ **Nodes:** Adaptive list-detail with node management
|
||||
- ✅ **Messaging:** Adaptive contacts with message view + send
|
||||
- ✅ **Connections:** Dynamic discovery of platform-supported transports (TCP)
|
||||
- ✅ **Connections:** Dynamic discovery of platform-supported transports (TCP, Serial/USB, BLE)
|
||||
- ❌ **Map:** Placeholder only, needs MapLibre or alternative
|
||||
- ⚠️ **Firmware:** Placeholder wired into nav graph; native DFU not applicable to desktop
|
||||
- ⚠️ **Intro:** Onboarding flow (may not apply to desktop)
|
||||
@@ -41,7 +41,7 @@ here| **Migrate to JetBrains Compose Multiplatform dependencies** | High | Low |
|
||||
- Test navigation flows end-to-end
|
||||
2. **Tier 2: Polish (High Priority)**
|
||||
- Additional desktop-specific settings polish
|
||||
- Keyboard shortcuts
|
||||
- ✅ **MenuBar integration** and Keyboard shortcuts
|
||||
- Window management
|
||||
- State persistence
|
||||
3. **Tier 3: Advanced (Nice-to-have)**
|
||||
@@ -53,9 +53,10 @@ here| **Migrate to JetBrains Compose Multiplatform dependencies** | High | Low |
|
||||
| Transport | Platform | Status |
|
||||
|---|---|---|
|
||||
| TCP | Desktop (JVM) | ✅ Done — shared `StreamFrameCodec` + `TcpTransport` in `core:network` |
|
||||
| Serial/USB | Desktop (JVM) | ❌ Next — jSerialComm |
|
||||
| Serial/USB | Desktop (JVM) | ✅ Done — jSerialComm |
|
||||
| MQTT | All (KMP) | ❌ Planned — Ktor/MQTT (currently Android-only via Eclipse Paho) |
|
||||
| BLE | Desktop | ❌ Future — Kable (JVM) |
|
||||
| BLE | Android | ✅ Done — Kable |
|
||||
| BLE | Desktop | ✅ Done — Kable (JVM) |
|
||||
| BLE | iOS | ❌ Future — Kable/CoreBluetooth |
|
||||
|
||||
### Desktop Feature Gaps
|
||||
@@ -70,6 +71,8 @@ here| **Migrate to JetBrains Compose Multiplatform dependencies** | High | Low |
|
||||
| Map | ❌ Needs MapLibre or equivalent |
|
||||
| Charts | ✅ Vico KMP charts wired in commonMain (Device, Environment, Signal, Power, Pax) |
|
||||
| Debug Panel | ✅ Real screen (mesh log viewer via shared `DebugViewModel`) |
|
||||
| Notifications | ✅ Desktop native notifications with system tray icon support |
|
||||
| MenuBar | ✅ Done — Native application menu bar with File/View menus |
|
||||
| About | ✅ Shared `commonMain` screen (AboutLibraries KMP `produceLibraries` + per-platform JSON) |
|
||||
| Packaging | ✅ Done — Native distribution pipeline in CI (DMG, MSI, DEB) |
|
||||
|
||||
@@ -89,9 +92,9 @@ here| **Migrate to JetBrains Compose Multiplatform dependencies** | High | Low |
|
||||
- ✅ **Done:** Extracted remaining 5 ViewModels: `SettingsViewModel`, `RadioConfigViewModel`, `DebugViewModel`, `MetricsViewModel`, `UIViewModel` to shared KMP modules.
|
||||
- ✅ **Done:** Extracted service, worker, and radio files from `app` to `core:service/androidMain` and `core:network/androidMain`.
|
||||
- **Next:** Extract remaining Android-specific files (e.g., Navigation files, App Widgets, message queues, and root Activity logic) out of `:app` to establish a truly thin app module.
|
||||
2. **Serial/USB transport** — direct radio connection on Desktop via jSerialComm
|
||||
2. ✅ **Done:** **Serial/USB transport** — direct radio connection on Desktop via jSerialComm
|
||||
3. **MQTT transport** — cloud relay operation (KMP, benefits all targets)
|
||||
4. **Evaluate KMP-native mocking** — Evaluate `mockative` or similar to replace `mockk` in `commonMain` of `core:testing` for iOS readiness.
|
||||
4. **Evaluate KMP-native testing tools** — Evaluate `Mokkery` or `Mockative` to replace `mockk` in `commonMain` of `core:testing` for iOS readiness. Integrate `Turbine` for shared `Flow` testing.
|
||||
5. **Desktop ViewModel auto-wiring** — ✅ Done: ensured Koin K2 Compiler Plugin generates ViewModel modules for JVM target; eliminated manual wiring in `DesktopKoinModule`
|
||||
5. **KMP charting** — ✅ Done: Vico charts migrated to `feature:node/commonMain` using KMP artifacts; desktop wires them directly
|
||||
6. **Navigation contract extraction** — ✅ Done: shared `TopLevelDestination` enum in `core:navigation`; icon mapping in `core:ui`; parity tests in place. Both shells derive from the same source of truth.
|
||||
@@ -100,17 +103,23 @@ here| **Migrate to JetBrains Compose Multiplatform dependencies** | High | Low |
|
||||
## Longer-Term (90+ days)
|
||||
|
||||
1. **iOS proof target** — declare `iosArm64()`/`iosSimulatorArm64()` in KMP modules; BLE via Kable/CoreBluetooth
|
||||
2. **Map on Desktop** — evaluate MapLibre for cross-platform maps
|
||||
2. **Platform-Native UI Interop** —
|
||||
- **iOS Maps & Camera:** Implement `MapLibre` or `MKMapView` via Compose Multiplatform's `UIKitView`. Leverage `AVCaptureSession` wrapped in `UIKitView` to fulfill the `LocalBarcodeScannerProvider` contract.
|
||||
- **Desktop Maps:** Implement maps via `SwingPanel` wrapper, utilizing experimental interop blending (`compose.interop.blending=true`) to ensure tooltips and Compose overlays render correctly on top of the native JComponent.
|
||||
- **Web (wasmJs) Integrations:** Leverage `HtmlView` to embed raw DOM elements (e.g., `<video>`, `<iframe>`, or canvas-based maps) directly into the Compose UI tree while binding the root app via `CanvasBasedWindow`.
|
||||
3. **`core:api` contract split** — separate transport-neutral service contracts from Android AIDL packaging
|
||||
4. **Native packaging** — ✅ Done: DMG, MSI, DEB distributions for Desktop via release pipeline
|
||||
5. **Module maturity dashboard** — living inventory of per-module KMP readiness
|
||||
6. **Shared UI vs Shared Logic split** — If the iOS target utilizes native SwiftUI instead of Compose Multiplatform, evaluate splitting feature modules into pure `sharedLogic` (business rules, ViewModels) and `sharedUI` (Compose Multiplatform) to prevent dragging Compose dependencies into pure native iOS apps.
|
||||
|
||||
## Design Principles
|
||||
|
||||
1. **Solve in `commonMain` first.** If it doesn't need platform APIs, it belongs in `commonMain`.
|
||||
2. **Interfaces in `commonMain`, implementations per-target.** The repository pattern is established — extend it.
|
||||
3. **Stubs are a valid first implementation.** Every target starts with no-op stubs, then graduates to real implementations.
|
||||
4. **Feature modules stay target-agnostic in `commonMain`.** Platform UI goes in platform source sets.
|
||||
5. **Transport is a pluggable adapter.** BLE, serial, TCP, MQTT all implement `RadioInterfaceService`.
|
||||
6. **CI validates every target.** If a module declares `jvm()`, CI compiles it. No exceptions.
|
||||
7. **Test in `commonTest` first.** ViewModel and business logic tests belong in `commonTest` so every target runs them.
|
||||
2. **Interfaces in `commonMain`, implementations per-target.** The repository pattern is established — extend it. Prefer dependency injection (Koin) with interfaces over `expect`/`actual` declarations whenever possible to keep architecture decoupled and highly testable.
|
||||
3. **UI Interop Strategies.** When a Compose Multiplatform equivalent doesn't exist (e.g., Maps, Camera), use standard interop APIs rather than extracting the entire screen to native code. Use `AndroidView` for Android, `UIKitView` for iOS, `SwingPanel` for JVM/Desktop, and `HtmlView` for Web (`wasmJs`). Always wrap these in a shared `commonMain` interface contract (like `LocalBarcodeScannerProvider`).
|
||||
4. **Stubs are a valid first implementation.** Every target starts with no-op stubs, then graduates to real implementations.
|
||||
5. **Feature modules stay target-agnostic in `commonMain`.** Platform UI goes in platform source sets. Keep the UI layer dumb and rely on shared ViewModels (Unidirectional Data Flow) to drive state.
|
||||
6. **Transport is a pluggable adapter.** BLE, serial, TCP, MQTT all implement `RadioInterfaceService`.
|
||||
7. **CI validates every target.** If a module declares `jvm()`, CI compiles it. No exceptions. Run tests on appropriate host runners (macOS for iOS, Linux for JVM/Android) to catch platform regressions.
|
||||
8. **Test in `commonTest` first.** ViewModel and business logic tests belong in `commonTest` so every target runs them. Use shared `core:testing` utilities to minimize duplication.
|
||||
9. **Zero Platform Leaks.** Never import `java.*` or `android.*` inside `commonMain`. Use KMP-native alternatives like `kotlinx-datetime` and `Okio`.
|
||||
|
||||
Reference in New Issue
Block a user