feat(mesh): implement multi-hop BLE mesh routing with GATT relay and end-to-end message delivery#8
Conversation
- Create `RelayDiscoveryScreen` and `RelayDiscoveryViewModel` to manage discovery, manual connection, and auto-connect settings for relay nodes
- Enhance `RelayNodeScanner` with improved scan filtering, batch result handling, and RSSI-based sorting of discovered relays
- Update `RelayNodeConnection` to handle GATT connection lifecycle, including UTF-8 message encoding and improved error logging
- Integrate relay status into `DiscoveryScreen` via a new `RelayStatusBanner` component
- Implement auto-connect logic using `SharedPreferences` to automatically link to the strongest discovered relay node
- Register `relay_discovery` route in `MainActivity` navigation graph
- Refactor `DiscoveryViewModel` to handle both peer discovery and relay scanning simultaneously
- Standardize Bluetooth permission handling across discovery components using `@SuppressLint("MissingPermission")`
- Rename `FriendDatabase` to `AppDatabase` and update related DI providers and tests - Implement relay message queue functionality in `MessageRepository` and `RelayMessageDao` - Update UI icons in `RelayDiscoveryScreen` and `DiscoveryScreen` for better visual status representation - Upgrade Kotlin to `2.1.0` and Gradle to `9.2.1` - Add Timber logging library dependency - Configure `gradle.properties` and `settings.gradle.kts` with updated build features and repository management - Add resource packaging exclusion for OSGI manifest to improve build compatibility
- Introduce `MeshRoutingEngine` to handle message delivery, TTL-based filtering, and probabilistic relaying (75% forward rate) - Implement `MeshMessageSerialiser` for converting mesh messages to/from a compact 512-byte BLE-compatible binary format - Add `SeenMessageCache` using an LRU-based `LinkedHashSet` to prevent redundant message processing and circular relaying - Define `MeshMessage` domain model and `RelayMessageEntity` for persistent storage of messages in transit - Rename `FriendDatabase` to `AppDatabase` and update to version 8, adding `RelayMessageDao` and support for mesh message persistence - Implement `MeshRoutingEngineTest` to verify local delivery, duplicate suppression, and TTL decrementing logic - Add `RelayMessageDao` to manage the active relay queue, including expiration purging and message lifecycle methods
- Update `BleAdvertiser` to initialize and manage a `BluetoothGattServer` alongside BLE advertising - Configure advertising settings to `setConnectable(true)` to support mesh relay write requests - Implement `Mesh_CHARACTERISTIC_UUID` with write permissions to receive incoming mesh messages - Integrate `MeshRoutingEngine` and `MeshMessageSerialiser` into `BleAdvertiser` to process received data - Refactor logging in `BleAdvertiser` to use `Timber` and standardize Bluetooth permission handling - Add `MeshMessageSerialiser` for converting `MeshMessage` objects to/from byte arrays with 16-byte fixed-length ID fields - Add `MeshMessageSerialiserTest` to verify serialization round-trips, payload limits, and ID truncation logic
- Update current version to `v0.6.0-alpha` and project completion to ~55% - Move Friend Pairing and WiFi Direct Messaging from "Planned" to "Current" features - Update project architecture and directory structure to include WiFi Direct (`p2p`), QR pairing, and chat components - Refresh test metrics: unit test pass rate increased to 95% and core domain coverage to 82% - Update hardware and permission requirements to include WiFi Direct and QR scanning - Increase "Lines of Code" metric to ~1200 and resolve distance estimation known issue status
…utingEngine, serialiser, persistence layer and simulation tests
… support - Relocate `MeshMessageSerialiser`, `SeenMessageCache`, and `MeshRoutingEngine` from `com.fyp.crowdlink.data.mesh` to `com.fyp.crowdlink.data.mesh_backup` - Update `AndroidManifest.xml` to include `android.support.LARGE_PAGE_SIZE` meta-data for Android 15+ compatibility
- Implement `MeshRoutingEngine` integration in `BleAdvertiser` and `BleScanner` to support gossip-based message delivery - Enhance `BleAdvertiser` to manage a GATT server with a writable mesh characteristic for receiving relay packets - Update `BleScanner` to handle GATT client connections, allowing it to write mesh messages to discovered peers and manage a retry queue - Refactor `MessageViewModel` to use `MeshRoutingEngine` for outbound messages, enabling multi-hop delivery instead of direct P2P only - Migrate persistent device ID management to `UserProfileRepository` and update `PairingViewModel` to use the new repository method - Implement `relayToAllPeers` logic in `BleScanner` to broadcast mesh messages to all active GATT connections - Update `AppModule` to provide Hilt dependencies for `MeshRoutingEngine`, `MeshMessageSerialiser`, and `SeenMessageCache` - Standardize logging across BLE components using `android.util.Log` and improve error handling for advertising failures - Fix GATT service UUIDs and characteristic properties to ensure reliable discovery and write operations
… transports - Update `MessageViewModel` to use `MeshRoutingEngine` as the primary messaging path, adding support for BLE discovery and a combined discovery status UI - Enhance `WifiDirectManager` to observe the global relay queue and attempt message delivery via WiFi P2P when peers are connected - Update `RelayNodeConnection` to monitor the relay queue and automatically forward pending messages via connected ESP32 relay nodes - Refactor `ChatScreen` UI with a new discovery status banner, message status icons (Pending, Sent, Delivered), and a "High-Speed" peer connection overlay for WiFi Direct - Extend `Message` model with `transportType` and `hopCount` fields for better mesh network visibility - Update `AppDatabase` to version 9 to support updated message schema - Implement `MESH_RELAY_V1` protocol header in `WifiDirectManager` for structured mesh message exchange over socket connections
- Migrate `MeshMessageSerialiser`, `MeshRoutingEngine`, and `SeenMessageCache` to the core mesh package - Update `MeshMessageSerialiser` with increased header size (100 bytes) and device ID size (36 bytes) to accommodate standard UUID strings - This is what caused me so much pain - Enhance `MeshRoutingEngine` with `suspend` processing and local device ID verification to correctly identify messages intended for the current node - Refactor `BleScanner` to handle MTU updates (512 bytes), manage active GATT connections, and implement a relay queue observer - Update `BleAdvertiser` to process incoming GATT write requests asynchronously via the mesh routing engine - Implement mesh callback wiring in `DeviceRepositoryImpl` to handle incoming messages and automated relaying - Update `MainActivity` to automatically start mesh services (discovery and advertising) upon permission grant - Refactor `DiscoveryViewModel` to track and expose discovery/advertising states as `StateFlow` - Update `ChatScreen` to display message hop counts for multi-hop mesh transmissions - Add `generativeai` dependency and update Android Gradle Plugin to v8.13.2 - Initialize `Timber` logging in `CrowdLinkApplication` and provide missing mesh components in `AppModule`
7 tasks
- Refactor `MainActivity` by extracting the navigation logic into a new `MainScreen` and `AppNavHost` in `NavGraph.kt` - Implement a `BottomNavigationBar` in `MainScreen` for top-level destinations (Discovery, Friends, Settings) - Introduce `TransportType` enum to the `Message` model and replace the string-based transport field - Update `WifiDirectManager`, `DeviceRepositoryImpl`, and `MessageViewModel` to use the new `TransportType` (WIFI, MESH, etc.) - Add `relayNodes` field to the `Message` model and increment `AppDatabase` version to 10 - Force QR scanner activity to portrait orientation in `AndroidManifest.xml` and update `QRScannerScreen` configuration - Add `androidx.compose.material.icons.extended` dependency for additional UI icons - Scaffold new `CompassScreen` and `CompassViewModel` components - Fix `RelayNodeScanner` by adding missing Bluetooth permission annotations - Update unit and instrumented tests to reflect `Message` model changes and transport types
- Implement real-time synchronization of BLE discovery events to update `lastSeen` timestamps in the `friendRepository` - Update `MeshRoutingEngine` message processing to refresh friend `lastSeen` metadata upon receiving incoming messages - Refactor `DeviceRepositoryImpl` to streamline the discovery pipeline and reduce boilerplate logging - Simplify member function declarations in `DeviceRepositoryImpl` using expression body syntax - Maintain `lastSeen` persistence for paired friends during active scanning and message reception
- Remove deprecated backup mesh networking test suites including `MeshMessageSerialiserTest`, `MeshNetworkSimulationTest`, and `MeshRoutingEngineTest`
- Add `@SuppressLint("MissingPermission")` to `RelayNodeScanner` to suppress a lint false positive in the BLE batch scan callback
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
This PR introduces core mesh networking capabilities to CrowdLink, enabling
decentralised message routing across multiple devices using BLE and WiFi Direct.
The
meshbranch implements a custom multi-hop routing protocol allowing devicesto relay messages for one another, extending communication range beyond
point-to-point limitations. It integrates a probabilistic flood-routing engine
with GATT-based BLE relaying and WiFi Direct transport.
Key Changes
1. Mesh Routing Engine
MeshRoutingEngineto handle message processing, TTL management, and hop-count trackingSeenMessageCachefor duplicate message suppression2. BLE Transport & GATT Relay
BleAdvertiserto receive and relay mesh packetsMeshMessageSerialiserfor binary serialisation of mesh packets within BLE MTU limitsRelayMessageDaoand Room persistence for outbound relay queue management3. Transport Integration
DeviceRepositoryImplas the central orchestration pointRelayNodeScannerfor discovering dedicated ESP32 relay infrastructure4. Lifecycle & Reliability
DiscoveryViewModelandMainActivityto auto-start mesh services on launchAppModuleto manage singleton lifecycles for routing and discovery components5. UI & UX
DiscoveryScreento show real-time mesh status (scanning, advertising, relay connectivity)Testing Performed
SeenMessageCacheandMeshMessageSerialiserKnown Limitations
full write queue deferred to follow-up PR
cleanup but no automatic retry yet
identification; demoted to fallback transport