feat: hard cutover to meshtastic-sdk — eliminate AIDL pipeline#5379
Draft
jamesarich wants to merge 53 commits intomeshtastic:mainfrom
Draft
feat: hard cutover to meshtastic-sdk — eliminate AIDL pipeline#5379jamesarich wants to merge 53 commits intomeshtastic:mainfrom
jamesarich wants to merge 53 commits intomeshtastic:mainfrom
Conversation
Wires core flows to the meshtastic-sdk (0.1.0-SNAPSHOT) while keeping the legacy path alive. Goal: prove the SDK works with a real Android app and surface API deficiencies. Build: - settings.gradle.kts: composite build inclusion for meshtastic-sdk (../meshtastic-sdk) with dependency substitution for all SDK artifacts - libs.versions.toml: sdk = "0.1.0-SNAPSHOT", mavenCentral snapshots repo - app/build.gradle.kts: sdk-core, sdk-proto, sdk-transport-ble, sdk-storage-sqldelight dependencies Bootstrap: - MeshUtilApplication: AndroidContextHolder.context set in onCreate() before startKoin so SqlDelightStorageProvider can locate app files - RadioClientProvider (@single, binds SdkClientLifecycle): mutex-serialized rebuildAndConnect(), strips 'x' prefix from BLE devAddr, holds RadioClient StateFlow - RadioClientViewModel: exposes RadioClientProvider to UI layer SDK ViewModels (POC quality, compile-verified): - SdkNodeListViewModel: NodeChange.Snapshot/Added/Updated/Removed → UiNode - SdkMessagingViewModel: sendText() via client.sendText(), incomingText via client.textMessages (Gap B — now fixed in SDK) - SdkConfigViewModel: configBundle reads, setConfig/setOwner writes, loadChannels() via admin, Gap G workaround (local override map) - SdkTelemetryViewModel: TelemetryApi.observe(NodeId), requestDeviceMetrics Service lifecycle: - SdkClientLifecycle interface in core:service (avoids reverse dep from service → app); RadioClientProvider implements it - MeshService.onDestroy: calls sdkClientLifecycle.disconnect() before serviceJob.cancel() - BlePeripheralFactory.kt in core:ble: public buildPeripheralForAddress() wrapper (Gap F workaround; proper fix needed in SDK transport-ble) SDK gaps discovered and logged: Gap B - textMessages flow (FIXED in SDK feat/meshtastic-android-integration-gaps) Gap C - channels StateFlow (no reactive cache, only admin.listChannels()) Gap F - BleTransport MAC string factory (requires live Peripheral today) Gap G - configBundle not refreshed after editSettings writes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the two-step buildPeripheralForSavedAddress() + BleTransport(peripheral, address)
with the new SDK factory BleTransport(address) { autoConnectIf { true } }.
The SDK's transport-ble androidMain now exposes BleTransport(address: String,
builderAction: PeripheralBuilder.() -> Unit) directly, removing the need for
the core:ble workaround. The autoConnectIf { true } flag preserves bonded-device
behavior (avoids GATT 133 on reconnect without a fresh advertisement).
Gap F note removed from RadioClientProvider KDoc — gap is resolved in SDK.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- RadioClientProvider: support BLE, TCP, and Serial transports via InterfaceId routing; handle MOCK/NOP gracefully - SdkNodeListViewModel: use SDK's MeshNode model for 20+ enriched fields (isOnline, battery, position, signal quality, etc.) - SdkConfigViewModel: remove Gap G workaround (_localConfigOverrides), add reactive channels StateFlow from SDK Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the legacy AIDL-based AndroidRadioControllerImpl with an SDK-backed implementation that delegates all operations through RadioClient: SdkRadioControllerImpl: - Full RadioController interface impl (~35 methods) - Local admin ops → SDK AdminApi/TelemetryApi/RoutingApi - Remote admin ops → raw MeshPacket via RadioClient.send() - Registered as @single(binds = [RadioController::class]) in Koin SdkStateBridge: - Bridges SDK reactive flows (connection, nodes, packets, events) into ServiceRepository and NodeManager for legacy UI compatibility - Connection state mapping (SDK states → app ConnectionState enum) - Node snapshot/added/updated/removed → NodeManager - Inbound telemetry/position/user packets → NodeManager handlers - Events (reboot, security warnings, drops) → notification layer AndroidRadioControllerImpl: - @single annotation disabled (commented out) to prevent Koin conflict - Class retained for reference/fallback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SdkStateBridge: - Remove redundant manual proto decode (telemetry/position/user) — SDK's NodeChange flow already provides updated NodeInfo with all fields - Forward raw packets to meshPacketFlow for RadioConfigViewModel + TAK - Handle ServiceActions directly via SDK AdminApi (Favorite, Ignore, Mute, Reaction, ImportContact, SendContact, GetDeviceMetadata) - Bypasses entire CommandSender → MeshActionHandler → MeshRouter chain MeshServiceOrchestrator: - Remove radioInterfaceService.connect() — SDK owns transport now - Remove receivedData → messageProcessor wiring — SDK handles packets - Remove serviceAction → actionHandler subscription — SdkStateBridge handles - Remove resetReceivedBuffer — no raw byte pipeline to drain - Retain: TAK integration, database init, service notifications - Remove unused constructor params (serviceRepository, messageProcessor, router) Architecture after this commit: - All in-app flows: Feature VM → RadioController → SdkRadioControllerImpl → SDK - ServiceActions: UI → ServiceRepository.onServiceAction → SdkStateBridge → SDK - AIDL binder: only remaining path to old CommandSender/MeshActionHandler (for external 3rd-party app compat only) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d nodes Phase 1: Drop AIDL - Delete all 6 .aidl files (core/api/src/main/aidl/) - Strip binder object from MeshService (onBind returns null) - Simplify MeshServiceClient to lifecycle observer (no AIDL binding) - Remove meshService field from AndroidServiceRepository - Delete ServiceClient, AndroidRadioControllerImpl, FakeIMeshService, IMeshServiceContractTest Phase 2: Migrate TAK to RadioController - GenericCoTHandler: RadioController replaces CommandSender - TAKMeshIntegration: RadioController replaces CommandSender - CoreTakServerModule: DI updated Phase 3: Port remaining consumers - MeshConnectionManagerImpl: RadioController, remove time sync/passkey (SDK handles internally), wrap telemetry in coroutine - MeshConfigFlowManagerImpl: remove CommandSender dependency, use 0L for currentPacketId - RefreshLocalStatsAction: RadioController for widget telemetry - EnsureRemoteAdminSessionUseCase: serviceRepository.onServiceAction() replaces meshActionHandler Phase 4: Delete dead pipeline - Delete FromRadioPacketHandler interface + FromRadioPacketHandlerImpl - Delete MeshMessageProcessor interface + MeshMessageProcessorImpl - Delete related tests - Remove MeshMessageProcessor dep from MeshActionHandlerImpl - Keep CommandSender/MeshRouter/MeshActionHandler for DirectRadioControllerImpl (desktop target) Phase 5: SDK-backed NodeRepository - New SdkNodeRepositoryImpl: in-memory StateFlow backed by NodeManager - SDK handles persistence via its own SqlDelight storage - Deactivate Room-backed NodeRepositoryImpl (@single removed) - NodeManagerImpl propagates myNodeNum to SdkNodeRepositoryImpl - Cold start: brief empty state until SDK emits snapshot (<1s) - Node notes: in-memory for POC (does not survive process death) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Documents completed phases (A-G partial), remaining blockers, and recommended execution order for full SDK migration. Key remaining items: - Desktop SDK migration (unblocks ~2,000 LOC deletion) - Module restructuring (unblocks VM direct-binding) - 22 VM migrations to RadioClient - 4 deferred UseCase deletions - Phase C completion (packet flow cleanup) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…a deletion
Major architectural changes:
1. SHARED KMP BRIDGE (core/data/radio/):
- RadioClientAccessor: Platform-agnostic interface for SDK RadioClient
- SdkRadioController: Shared RadioController impl (replaces per-platform copies)
- SdkStateBridge: Shared SDK→repository bridge (event dispatch, node sync)
- SdkPacketHandler: Thin SDK-backed PacketHandler for MQTT/XModem/History
2. DESKTOP SDK CUTOVER:
- DesktopRadioClientProvider: TCP + Serial transport support
- Removed DirectRadioControllerImpl (old desktop radio path)
- Desktop now shares the same SDK bridge code as Android
3. DEAD INFRASTRUCTURE DELETION (~5,100 LOC removed):
- PacketHandlerImpl, MeshDataHandlerImpl, MeshRouterImpl
- CommandSenderImpl, MeshActionHandlerImpl, MeshConfigFlowManagerImpl
- MeshConnectionManagerImpl, AdminPacketHandlerImpl
- ServiceBroadcasts (Android intent-based pub/sub)
- NodeRepositoryImpl (Room-backed, replaced by SdkNodeRepositoryImpl)
- 8 trivial UseCases (SetLocale, SetTheme, ToggleAnalytics, etc.)
- All associated test files for deleted impls
- Deleted interfaces: AdminPacketHandler, CommandSender, MeshActionHandler,
MeshConfigFlowManager, MeshConnectionManager, MeshRouter, ServiceBroadcasts
4. NEW FEATURES:
- NodeMetadataEntity + Room migration 38→39 (persistent favorites/notes)
- AppMetadataRepository (clean access to node metadata)
- MessagePersistenceHandler (focused rememberDataPacket for StoreForward)
All three targets compile clean: :app:compileGoogleDebugKotlin,
:desktop:compileKotlin, :core:data:jvmTest passes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nterfaceService - Delete entire transport layer: BleRadioTransport, TcpRadioTransport, SerialRadioTransport, StreamTransport, HeartbeatSender, StreamFrameCodec, AndroidRadioTransportFactory, BaseRadioTransportFactory, MockRadioTransport, NopRadioTransport, BleReconnectPolicy, TcpTransport, SerialTransport - Delete MeshConfigHandler interface + impl (replaced by RadioConfigRepository) - Delete RadioTransportCallback, RadioTransport, RadioTransportFactory interfaces - Delete FakeRadioTransport, RadioTransportTest, MeshConfigHandlerImplTest - Delete UseCase tests (impls restored, tests for deleted patterns removed) - Slim RadioInterfaceService interface: remove transport internals, keep only device-address/connection surface needed by Scanner and connections UIs - Create SdkRadioInterfaceService: thin SDK-backed impl delegating to RadioPrefs + RadioClientAccessor - Update NoopRadioInterfaceService to match slimmed interface - Update JvmUsbScanner to use SDK's JvmSerialPorts.list() instead of deleted SerialTransport.getAvailablePorts() - Remove DesktopRadioTransportFactory from desktop DI module - Fix NodeListViewModel: replace RadioInterfaceService with RadioPrefs - Fix MeshServiceOrchestratorTest: align with updated constructor params - Fix UIViewModel: use emptyFlow() for meshActivity (SDK doesn't emit raw transport-level activity events) All targets compile clean, all JVM + Android unit tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Delete SdkConfigViewModel, SdkMessagingViewModel, SdkTelemetryViewModel (unused POC) - Delete RadioClientViewModel, SdkNodeListViewModel (POC logging only) - Remove POC VM instantiation from Main.kt - Delete NoopRadioInterfaceService (superseded by SdkRadioInterfaceService) - Delete dead app/test/Fakes.kt (both classes unused) - Fix stale KDoc references to MeshConnectionManager, RadioInterfaceService.connectionState Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Constants.kt re-exported MeshtasticIntent constants for the deleted ServiceBroadcasts system. No consumers remain after broadcast removal. Also remove MeshService.actionReceived() companion method (no callers). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MeshLogRepositoryImpl was the sole external consumer of NodeInfoReadDataSource — it only needed myNodeNum to identify the local node in logs. Replace with NodeRepository.myNodeInfo (already SDK-backed via SdkNodeRepositoryImpl). PacketRepositoryImpl referenced NodeInfoDao.MAX_BIND_PARAMS — inlined as a private constant since it's just the SQLite bind-param limit. With zero external consumers remaining, delete: - NodeInfoReadDataSource interface - SwitchingNodeInfoReadDataSource implementation The Room NodeInfoDao/NodeEntity/MyNodeEntity remain in the database module for now (internal tests + migration history) but have no external dependents — ready for a future Room migration 40 to DROP. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove my_node, nodes, metadata tables via AutoMigration with @deletetable - Parameterize all 34 PacketDao queries to accept myNodeNum directly - Delete NodeInfoDao, NodeEntity, MyNodeEntity, MetadataEntity - Delete CommonNodeInfoDaoTest (dead) - Rewrite PacketRepositoryImpl to inject NodeRepository for myNodeNum - Rewrite CommonPacketDaoTest and CommonPacketRepositoryTest - Update MigrationTest to remove nodeInfoDao usage - Update core/database README to reflect current schema SDK is now sole source of truth for all node data. Room only stores messages, logs, and user annotations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Activity - Merge NodeManagerImpl logic into SdkNodeRepositoryImpl (single source of truth for all node state — eliminates duplicate in-memory maps) - SdkNodeRepositoryImpl now binds NodeRepository, NodeManager, NodeIdLookup - Delete NodeManagerImpl.kt (377 LOC) - Add meshActivityFlow to ServiceRepository for nav-bar icon animation - Emit MeshActivity.Send from SdkPacketHandler and SdkRadioController - Emit MeshActivity.Receive from ServiceRepositoryImpl.emitMeshPacket() - Wire UIViewModel.meshActivity to serviceRepository.meshActivityFlow - Align insertMetadata signature (remove unnecessary suspend) - Adapt NodeManagerImplTest to test SdkNodeRepositoryImpl directly - Update FakeServiceRepository with meshActivityFlow stub All targets compile clean (Android + Desktop), all tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NodeManager merge and MeshActivity restoration are done. Only optional VM param slimming and test coverage remain. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Delete dead methods from NodeManager/NodeRepository interfaces: - allowNodeDbWrites, setAllowNodeDbWrites (never read) - loadCachedNodeDB (no-op, zero-value call in orchestrator) - getNodes(): List<NodeInfo> (deprecated, unused) - handleReceivedPaxcounter (zero callers) - handleReceivedNodeStatus, updateNodeStatus (zero callers) - insertMetadata (zero production callers) Delete NodeInfo data class (85 LOC): - All consumers now use Node domain model directly - Retained MeshUser, Position, DeviceMetrics, EnvironmentMetrics which have active consumers across feature modules Remove corresponding implementations from SdkNodeRepositoryImpl, FakeNodeRepository, and test verifications. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eliminate the vestigial NodeManager/NodeRepository interface split. All runtime node state management methods (handleReceivedUser, handleReceivedPosition, handleReceivedTelemetry, updateNode, etc.) now live directly on NodeRepository alongside the query surface. - Delete NodeManager.kt (82 LOC) - Extend NodeRepository with NodeIdLookup and add all manager methods - Update 8 consumers to inject NodeRepository instead of NodeManager - Remove dead nodeManager param from MeshServiceOrchestrator - Add NodeManager methods to FakeNodeRepository test double - Update all tests (mocks, constructor params, verifications) - SdkNodeRepositoryImpl now binds [NodeRepository, NodeIdLookup] Build: assembleDebug ✅, desktop:compileKotlin ✅, all jvmTests ✅ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SdkStateBridge: - Wrap handleServiceAction in try/catch to prevent bridge death - Favorite/Ignore/Mute: only apply local state update on admin success (eliminates optimistic state inconsistency) - ImportContact: guard with runCatching, log failures - Extract dispatchAction for clean separation of concerns SdkRadioController: - Wrap sendMessage with try/catch + logging before re-throw - Wrap sendRemoteAdmin with try/catch + logging before re-throw - Ensures BLE disconnect errors are visible in logs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- NodeInfo.kt → MeshModels.kt (no longer contains NodeInfo class) - NodeManagerImplTest.kt → SdkNodeRepositoryImplTest.kt (tests SdkNodeRepositoryImpl) - Update MIGRATION-REMAINING.md with dead code removal, error handling, and NodeManager merge status Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…taPacket, integrate SDK utilities Android rearchitecture consuming meshtastic-sdk improvements: A1 — ConnectionState Enrichment: - Rich sealed interface with Connecting(attempt), Configuring(phase, progress), Reconnecting(attempt) - SdkStateBridge maps SDK states preserving metadata A2 — MessageHandle Integration: - MessageDeliveryTracker: tracks delivery via SDK MessageHandle - SdkRadioController captures handles on send A3 — RadioController Decomposition: - Split into 5 focused interfaces: MessageSender, DeviceAdmin, RemoteAdmin, DeviceControl, DataRequester - RadioController extends all; SdkRadioController binds all via Koin A4 — DataPacket Simplification: - to/from fields changed from String? to Int (node numbers directly) - Removed string ID parsing layer; added BROADCAST/LOCAL constants - Updated ~40 consumer files across feature modules A5 — SDK Utility Consumption: - DeviceVersion, Capabilities, SfppHasher, LocationUtils delegate to SDK - Removed duplicated protocol logic A6 — Presence Events: - SdkStateBridge handles NodeChange.WentOffline/CameOnline - Updates node online status via repository Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ad code, integration tests ViewModel Narrowing: - V1: Created ConnectionAware interface; MessageSender, DeviceAdmin, DeviceControl extend it - V2: Narrowed 6 ViewModels/actions to focused sub-interfaces (DeviceAdmin, MessageSender, DataRequester, DeviceControl) Cleanup: - C1: Deleted dead MeshDataMapper and its DI registration Integration Tests: - T2: SdkStateBridgeTest verifying WentOffline/CameOnline presence handling - Verified Koin resolution, full test suite passes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ongestion surfacing I1 — RetryPolicy in MessageDeliveryTracker: - track() now accepts optional RetryPolicy (default: ExponentialBackoff 3 attempts) - Failed sends automatically retry before marking ERROR - UI sees ENROUTE during retry attempts I2 — Store-and-Forward SDK consumption: - SdkStateBridge observes storeForward.events and servers - ServiceRepository exposes storeForwardServers StateFlow - SdkRadioController.requestStoreForwardHistory() delegates to SDK - HistoryManagerImpl uses SDK path instead of manual packet construction I3 — Congestion level surfacing: - SdkStateBridge handles MeshEvent.CongestionWarning - ServiceRepository.congestionLevel StateFlow exposed to UI - Cleared on disconnect Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…F badges - SdkStateBridge: handle SfppLinkProvided/SfppCanonAnnounced events from SDK - StoreForwardPacketHandlerImpl: SFPP parsing removed (SDK-owned) - NeighborInfoHandlerImpl: delegate formatting to SDK NeighborInfo.fromProto() - NodeStatusIcons: CongestionBadge (yellow/orange/red for MEDIUM/HIGH/CRITICAL) - NodeStatusIcons: StoreForwardBadge (blue cloud icon for S&F servers) - NodeListViewModel: expose congestionLevel + storeForwardServers flows - Tests updated for SFPP bridge coverage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Delete SfppHasher wrapper (SDK SfppHash handles SFPP hashing) - Remove unused NodeRepository from StoreForwardPacketHandlerImpl - Update tests to match constructor change Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove handleStoreForwardPlusPlus() from interface + impl (dead code post-SDK cutover) - Move StoreForwardBadge/CongestionBadge hardcoded strings to string resources (i18n) - Add SdkStateBridge tests: congestion warning → ServiceRepository, S&F server propagation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove handler interfaces, implementations, and tests that have zero production callers after the SDK became authoritative for protocol handling: - TelemetryPacketHandler/Impl — SDK owns telemetry via NodeChange.Updated - StoreForwardPacketHandler/Impl — SDK owns S&F lifecycle + SFPP - NeighborInfoHandler/Impl — SDK owns NeighborInfo model - TracerouteHandler/Impl — SDK owns traceroute via AdminResult flow - MeshDataHandler/MessagePersistenceHandler — handleReceivedData was no-op - HistoryManager/Impl — only caller was deleted StoreForwardPacketHandlerImpl Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace all isLocalNode/sendRemoteAdmin patterns with client.admin.forNode(NodeId(destNum)).method() - Use client.sendReaction() instead of manual MeshPacket construction - Use client.admin.forNode(dest).getDeviceMetadata() for remote metadata - Delete sendRemoteAdmin() and isLocalNode() helpers - Remove unused imports (AdminMessage, Data, MeshPacket from SdkStateBridge) Net: -131 lines, all admin ops now go through SDK's typed API with proper ACK tracking and session-key retry. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- sendMessage() now uses client.send(portnum, payload, to, channel, ...) - requestUserInfo() now uses client.requestNodeInfo(NodeId) - SdkStateBridge position publishing calls SDK directly (removes intermediate DataPacket + RadioController dependency) - Remove unused imports: MeshPacket, Data, okio.toByteString - Remove unused radioController dependency from SdkStateBridge Net: SdkRadioController no longer imports MeshPacket or Data proto. Only AdminMessage remains (for beginEditSettings/commitEditSettings). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tion
Replace the manual packet-ID tracking and meshPacketFlow subscription in
RadioConfigViewModel with direct typed returns from the SDK via
RadioConfigUseCase. The ViewModel now awaits typed results (User, Config,
ModuleConfig, channels, etc.) from suspend calls and maps AdminException
to UI error states.
Key changes:
- Delete ProcessRadioResponseUseCase (130 lines of manual proto decode)
- Remove requestIds state, registerRequestId, processPacketResponse,
sendAdminRequest, and meshPacketFlow subscription from ViewModel
- Rewrite setResponseStateLoading to use direct coroutine calls
- Admin actions (reboot/shutdown/etc.) fire directly without session key
preflight (SDK handles retryOnSessionExpiry transparently)
- All setters (setConfig, setModuleConfig, setOwner, updateChannels)
no longer return/track packetIds
- Remove messageSender dependency from NodeManagementActions
- Update InstallProfileUseCase to use editSettings {} receiver pattern
- Update all callers: CleanNodeDatabaseUseCase, Esp32OtaUpdateHandler,
NodeManagementActions
- Rewrite RadioConfigViewModelTest for new direct-await semantics
- Update RadioConfigUseCaseTest and InstallProfileUseCaseTest
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- P0: setDeviceAddress now persists address to RadioPrefs before reconnect - P0: Document nodedbReset firmware limitation (preserveFavorites is local-only) - P1: Add writeAction helper for AdminException → sendError in RadioConfigViewModel - P1: Wrap CommonNodeRequestActions scope.launch with runCatching for crash safety - P1: Create CongestionLevel typealias in core/model to decouple feature modules from SDK - P1: Cancel prior loadJob in setResponseStateLoading to prevent stale results Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace magic int dispatch in requestTelemetry with TelemetryType enum - Update DataRequester interface: remove requestId param, use TelemetryType directly - Add HEALTH and TRAFFIC_MANAGEMENT to TelemetryType, remove stale PAX variant - Create MeshTopologyService wrapping SDK's MeshTopology with thread-safe Mutex - Wire NeighborInfo packet ingestion in SdkStateBridge → topology graph - Clear topology on node snapshot (reconnect) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove getPacketId() from MessageSender interface (SDK owns packet IDs) - Remove requestId parameter from requestTraceroute/requestNeighborInfo - Make getPacketId() private in SdkRadioController (still used internally for delivery tracking correlation) - Replace radioController.getPacketId() in map with local Random.nextInt() for waypoint ID generation (only needs uniqueness, not SDK correlation) - Remove messageSender dependency from CommonNodeRequestActions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Only feature/messaging actually imports from core.service (SendMessageWorker). The other 5 feature modules (connections, firmware, map, node, settings) had vestigial dependency declarations from pre-migration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove unused feature/node → feature/map dependency (nothing imported) - Add @immutable to RadioConfigState, DiscoveredDevices, DeviceListEntry to prevent unnecessary Compose recompositions from unstable inference Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- feature/map: remove unused core.data, core.database, core.datastore; add missing core.common, core.repository (actual dependencies) - feature/node: remove unused core.datastore - feature/connections: remove unused core.database - Add @immutable to NodesUiState, NodeFilterState Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The combine(serviceRepository.connectionState, radioConfigState) pattern subscribed to the ViewModel's own output StateFlow, causing redundant re-evaluations on every state change. Replace with direct observation of the source connectionState flow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move ResponseState<T> to core/model - Move PacketResponseStateDialog to core/ui/component - Create RadioConfigStateProvider interface in core/model - RadioConfigViewModel implements RadioConfigStateProvider - ConnectionsScreen accepts interface instead of concrete VM - ConnectionsNavigation receives provider via lambda from app/desktop - Remove projects.feature.settings dependency from connections build This eliminates a feature→feature dependency, improving build parallelism and enforcing proper module boundaries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…dioConfigViewModel Extract self-contained logic into plain coordinator classes: - MqttProbeCoordinator: MQTT broker probe state + cancellation - ProfileCoordinator: import/export/install profile file I/O RadioConfigViewModel delegates to coordinators while retaining state ownership and config-loading orchestration (its core job). Reduces VM body by ~60 lines of implementation detail. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Change RadioConfigState.route from String to Enum<*>? - ChannelScreen resolves navigation target via typed cast instead of string lookup through getNavRouteFrom() - Delete dead SettingsNavUtils.kt (getNavRouteFrom now unused) - Eliminates fragile string→enum round-trip that could silently fail Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add AdminException.RateLimited to domain exception hierarchy - Handle AdminResult.RateLimited in SdkRadioController.unwrap() - Update MeshTopologyService for SDK's new suspend API: topology.nodes → topology.nodes(), topology.edgeCount → edgeCount() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- frequentEmojis: computed List → cached StateFlow (avoids parse+sort on every recomposition) - SdkNodeRepositoryImpl: SharingStarted.Eagerly → WhileSubscribed(5_000) for ourNodeInfo, myId, localStats - PacketRepositoryImpl: deduplicate flatMapLatest chains via shared combine(myNodeNumFlow, currentDb) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When ignoring a node, wipe position, deviceMetrics, and publicKey locally to match what firmware does on the device side. Un-ignoring just clears the isIgnored flag (device will re-populate on next heard packet). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Parse UTF-8 payload from NODE_STATUS_APP (PortNum=36) and update the node's nodeStatus field. Already displayed in NodeItem and NodeDetailsSection. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
12 integration tests covering: - T4a: SDK packets/events propagate through bridges to repositories - T4b: Connection lifecycle state transitions (connect/disconnect/reconnect) - T4c: Error resilience (malformed protos, unknown ports, rapid fire, empty payloads) Tests verify the full chain from FakeRadioTransport through RadioClient, SdkStateBridge orchestration, and into service/node/topology repositories. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add KDoc to 3 JSON datasource interfaces and 7 repository implementations - Remove IndoorAirQuality stub comments - Remove commented-out WRITE_EXTERNAL_STORAGE permission from manifest - Update foreground service comment to architecture note (Android 14+) - Remove redundant inline comments in PacketDao.kt Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cb669c1 to
8133161
Compare
After rebase, MqttManagerImpl gained a nodeRepository parameter. Updated test to mock and pass the new dependency. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete hard cutover from the legacy AIDL/MeshService pipeline to
meshtastic-sdk. The app now connects to radios via the SDK'sRadioClientdirectly, eliminating ~20k lines of intermediary code.Architecture (52 commits, 305 files, +11.4k / −20.5k lines)
What changed:
SdkRadioControllerImpl+SdkStateBridgereplace the old AIDLIMeshServicebindingRadioClient→SdkStateBridge→Repository— three-layer data flowConnectionAware,NodeProvider, etc.)What was removed (~20.5k lines):
IMeshService+MeshServicepipelineProcessRadioResponseUseCaseand packet-ID correlationSfppHasher, deadNodeManager, unusedNodeRepositoryinjectionMeshDataMapper,CommandSenderindirectionWhat was added (~11.4k lines):
SdkStateBridge,SdkRadioControllerImpl,MeshTopologyServiceMessageDeliveryTrackerwith SDK retry policyTests (400+ tests, 0 failures)
SdkRadioController,PacketRepository,MeshTopologyService,MessageDeliveryTrackerMqttManagerImpl,UIViewModel,ScannedQrCodeViewModelAppMetadata,DeviceHardware,FirmwareRelease(Robolectric)KDoc & Cleanup