The BLE subsystem in the AppPlatform app is a native-integrated, resilient device communication layer. It features a deeply embedded iOS-native CoreBluetooth runtime, a robust React Native bridge for cross-platform eventing, and a sophisticated TypeScript orchestration layer that intelligently selects between native transport and a react-native-ble-plx fallback. This architecture is designed for high reliability, especially under demanding mobile OS lifecycle constraints.
Scope: This document covers the iOS native BLE runtime, the React Native bridge module, the TypeScript integration and orchestration layer, the dual-transport selection strategy, the custom binary application protocol, and mechanisms for background operation and reconnection. For related subsystems, see Related Documents at the end.
The decision for a deeply integrated native BLE runtime on iOS is driven by two critical mobile operating system realities:
React Native's native modules are typically initialized lazily. However, iOS's CoreBluetooth provides state restoration, requiring CBCentralManager to be created early in the app lifecycle (with CBCentralManagerOptionRestoreIdentifierKey) for centralManager:willRestoreState: to be delivered. A purely JS-driven, lazy initialization would miss this critical window, leading to lost connection state and an unreliable user experience.
Goal: Meet strict OS timing constraints without coupling platform correctness to bridge availability.
AppDeviceBLEInitializer.swift — Initialization Comment
// iOS State Restoration for CoreBluetooth requires CBCentralManager to be
// created with the same restoration identifier BEFORE iOS tries to restore state.
// React Native creates native module instances LAZILY...
// ...CBCentralManager doesn't exist → willRestoreState callback is missed
// SOLUTION: This initializer is called from AppDelegate's didFinishLaunchingWithOptionsMobile OSes impose strict limitations on background app execution. A native, early-initialized BLE runtime ensures persistent connection management and reliable event delivery, allowing the OS to manage BLE connections and handle reconnections without constant, unreliable JavaScript intervention.
Goal: A native, early-initialized runtime ensures BLE connections survive app termination and background transitions without JavaScript availability.
The BLE subsystem is structured in distinct, interacting layers, designed for modularity and platform resilience:
Layered Design:
| Layer | Component | Responsibility |
|---|---|---|
| Native Transport | AppDeviceBLECore.swift |
Singleton CBCentralManager owner. State restoration, GATT discovery, MTU negotiation, explicit disconnect classification (bondingLost, encryptionFailed, deviceSleep). |
| Bridge | AppDeviceBLEModule.swift |
RCTEventEmitter with EventBuffer for buffered delivery when JS listeners are absent. Overflow reporting via onBufferOverflow. |
| JS Integration | AppDeviceBLE.ts / useAppDeviceBLEIntegration.ts |
Type-safe wrapper and React hook forwarding native events to BluetoothHandler. |
| Protocol | AppDeviceProtocolService.ts |
Custom binary frames with CRC16 checksums, sequence numbers, ACK/NACK, and event deduplication by eventId. |
| Orchestration | BluetoothService.ts / BLERestorationService.ts |
High-level scanning, connection, reconnection with backoff, dormant mode, and device lifecycle management via OutboxRepository. |
Event Flow: AppDeviceBLECore → AppDeviceBLEModule (RCTEventEmitter) → useAppDeviceBLEIntegration hook → BluetoothHandler → BluetoothService and AppDeviceProtocolService.
Guarantee: BLE connections survive app termination. Native events are buffered until the JS bridge is ready. No events are silently dropped.
The foundation of robust iOS BLE is the precise timing of its initialization:
AppDelegate.mmIntegration — Calls[AppDeviceBLEInitializer initializeBLECore]before the React Native bridge or any other major framework.AppDeviceBLEInitializer.swift— Ensures theAppDeviceBLECoresingleton is instantiated, configuringCBCentralManagerwithCBCentralManagerOptionRestoreIdentifierKey.- Restoration Readiness — Guarantees the
centralManager:willRestoreState:callback is enabled from the earliest app launch, vital for background operations and connection persistence.
The core of the native BLE implementation on iOS resides within AppDeviceBLECore.swift, acting as the authoritative layer:
- Singleton Ownership —
AppDeviceBLECoreis a shared singleton, owning and managing the singleCBCentralManagerinstance. - CoreBluetooth Delegation — Implements
CBCentralManagerDelegateandCBPeripheralDelegatefor all BLE events. - Restoration Identifier — Configured with
CBCentralManagerOptionRestoreIdentifierKeyand implementscentralManager:willRestoreState:to re-adopt system-connected peripherals. - Explicit State Machine — Maintains a clear
ConnectionStatemachine (DISCONNECTEDtoREADY) with defined transitions, timeouts, and disconnect reason classification. - Resilience Mechanisms — Includes logic to
classifyDisconnectReason(e.g., inspectingCBError.codefor GATT faults),cancelAllTimers, andreconcileSystemConnections()for robust connection management.
Guarantee: Native singleton initialization before the React Native bridge ensures
willRestoreStateis never missed.
The AppDeviceBLEModule.swift bridge is designed for reliability and robust event delivery:
RCTEventEmitter— Exposes native Swift events to JavaScript.- Exposed Operations — Provides synchronous (e.g.,
startScan,disconnect) and asynchronous (e.g.,write,getConnectionState) methods. - Buffered Event Delivery (
EventBuffer) — Stores native events (onConnectionStateChange,onDataReceived) when JavaScript listeners are absent (e.g., during startup or background). - Overflow Reporting (
onBufferOverflow) — If theEventBufferoverflows, it drops the oldest event and explicitly emits anonBufferOverflowevent, signaling potential data loss to JavaScript for higher-level recovery. - Listener Lifecycle —
startObserving()flushes buffered events,stopObserving()pauses buffering. - Fail-Fast Operations — Emits
onOperationRejectedevents for synchronous rejections (e.g.,connectwhile Bluetooth is not ready), allowing immediate JS reaction.
Guarantee: No native BLE events are silently dropped. Events are either delivered or reported as overflow.
The JavaScript layer integrates with the native module via code-snippets/native/AppDeviceBLE.ts and code-snippets/native/useAppDeviceBLEIntegration.ts:
AppDeviceBLENative.tsWrapper — A thin, type-safe TypeScript wrapper around theNativeModules.AppDeviceBLEobject.useAppDeviceBLEIntegration.tsHook — The primary integration point:- Synchronous Subscriptions — Registers native event listeners synchronously early in the JS lifecycle to prevent missing events.
- Asynchronous Reconciliation — Performs tasks like
syncKnownDevices(to share stored device IDs with native) andAppDeviceBLENative.checkSystemConnections()(to reconcile OS-level active connections). - State Mirroring — Translates native
ConnectionStateEvents intoBluetoothHandler's state updates, ensuring JS mirrors the native runtime. - Protocol Data Routing — Routes
onDataReceivedevents directly toAppDeviceProtocolService.onDataReceived()for binary protocol processing.
Above the raw BLE transport, TypeScript services (code-snippets/services/ble/) orchestrate higher-level device communication:
BluetoothHandler(BluetoothContext.tsx) — The central JS singleton. Manages dual-transport selection,ConnectionState, reconnection logic, and dispatches data to other protocol services.BluetoothService— Provides application-level device management APIs (discovery, persistence).BLERestorationService— Handles application-level device/session state restoration.EventSyncService(code-snippets/services/ble/EventSyncService.ts) — Manages event-level synchronization (e.g.,lastEventId,timeSyncAnchor, handshake flow), processing hit events asynchronously.DeviceSettingsService(code-snippets/services/ble/DeviceSettingsService.ts) — Manages device settings (e.g.,sensitivity) with optimistic updates, debounce, and factory reset detection.- OTA Integration — Services like
OtaPostUpdateVerifierintegrate withBluetoothHandlerfor post-firmware-update connection and verification.
The architecture uses a dynamic transport selection strategy:
shouldUseNativeTransport()(code-snippets/services/ble/transport/index.ts) — Determines whether theAppDeviceBLEnative module (iOS) is available.- iOS Native Path — When available,
BluetoothHandlerdelegates core BLE operations to the Swift-based native module for deep CoreBluetooth integration. react-native-ble-plxFallback Path — For Android and as a general fallback,BluetoothHandlerdirectly managesBleManagerfromreact-native-ble-plx.
Transport Comparison: iOS Native vs. Android / Fallback
| Feature | iOS Native Path (AppDeviceBLECore.swift) |
Android / Fallback (react-native-ble-plx) |
|---|---|---|
| Core Bluetooth Ownership | AppDeviceBLECore singleton owns CBCentralManager |
BluetoothHandler owns BleManager |
| State Restoration | Explicit CBCentralManagerOptionRestoreIdentifierKey & willRestoreState |
BleManager's restoreStateIdentifier & restoreStateFunction |
| Native Bridge Depth | Deep, custom Swift module (AppDeviceBLEModule) |
Thin JS wrapper around BleManager's JS API |
| Primary Transport | Yes (leveraged for iOS-specific resilience) | Yes (primary transport for Android) |
| Event Buffering | AppDeviceBLEModule has EventBuffer with overflow handling |
Not directly in BleManager (handled by higher JS layers) |
| Reconnection Logic | Native timers, isManualDisconnect, reconcileSystemConnections |
JS timers, isDormantReconnectionMode, circuitBreaker |
| Sleep Disconnect | Explicit Swift override of false bonding errors | JS heuristic + flags (isSleepDisconnect) |
| Proof Strength | Very Strong (explicit Swift code, AppDelegate integration) | Moderate (relies on ble-plx abstraction, JS orchestration) |
The BLE communication adheres to a custom binary application protocol, defining the communication contract with the APP DEVICE device firmware:
- Transport vs. Protocol Separation — The protocol layer (
AppDeviceProtocolService.ts,protocol/) is distinct from the raw BLE transport. - Framed Binary Messages — Messages conform to a structured frame (SOF, type, version, sequence, length, CRC16) for robust parsing.
- CRC16 for Integrity —
crc16.tsimplements CRC16-CCITT-FALSE for end-to-end data integrity. - ACK/NACK for Reliable Delivery —
AppDeviceProtocolServicemanages ACK/NACK and retransmission logic. Criticalv2.4.0fixes ensure ACKs are asynchronously awaited before heavy JS processing to prevent firmware timeouts. - Message Types (
MessageTypeenum) —protocol/types.tsdefines distinct values for application-level commands (MSG_HELLO,MSG_TIME_SYNC,MSG_SET_CONFIG,MSG_ENTER_OTA_MODE,MSG_CLEAR_BONDS) and data (MSG_HIT_EVENT,MSG_BATTERY_STATUS). - Device Contract Boundary — This binary protocol defines the strict, versioned contract between the mobile app and the APP DEVICE device firmware.
Guarantee: Every frame is integrity-checked (CRC16) and delivery-confirmed (ACK/NACK). No corrupted or lost frames propagate to the application layer.
The BLE subsystem is engineered for resilience under mobile OS constraints:
- State Restoration and Process Relaunch — Early initialization of
AppDeviceBLECoreon iOS ensures correct handling ofCBCentralManagerstate restoration, vital for background operation. - Background Event Windows — The
AppDeviceBLEModule'sEventBufferensures native events are safely delivered to JavaScript even when the JS runtime is suspended. - Background-Safe Storage —
SecureStorageService.tsexplicitly usesSecureStore.AFTER_FIRST_UNLOCKaccessibility for private Keychain items on iOS. This bypasses "User interaction is not allowed" errors during background BLE operations, enabling services likeDeviceServiceto retrieve user context reliably. - Listener Timing Sensitivity —
useAppDeviceBLEIntegration.tsestablishes synchronous, early subscriptions to native events, minimizing missed events. - OS Background Keep-Alive —
BluetoothHandler'sAppStatelistener and activeMSG_HEARTBEATsignals maintain BLE activity in the background, signaling to the OS that the connection is active and reducing termination risk.
- Restoration Correctness — Early native initialization and
CBCentralManager's restoration capabilities on iOS prevent silent connection loss. - Buffered Event Durability — The
EventBufferensures native events are eventually delivered or explicitly reported asonBufferOverflow. - Overflow Visibility —
onBufferOverflowevents alert JavaScript to potential data loss, enabling higher-level recovery strategies. - Reconnection and Bonding-Loss Handling —
DisconnectReasonclassification, exponential backoff, dormant reconnection, andEC-SLEEP-BOND-FIX-001(AppDeviceBLECore.swift) provide robust handling of disconnections and avoid false bonding errors. - ACK Timing and Security — Critical
v2.4.0fixes inAppDeviceProtocolServiceensure ACKs are sent before heavy JS processing, preventing firmware timeouts.EC-HEARTBEAT-SUICIDE-001inBluetoothContext.tsxprotects against security-related health check failures. - Fault Containment — Fail-fast on critical errors (e.g., invalid protocol frames) prevents state corruption, while non-critical failures are managed with retry logic.
The architecture is strongly grounded in the codebase, with explicit proof points:
- Proven iOS-Native Depth —
AppDeviceBLEInitializer.swift,AppDeviceBLECore.swift, and their integration inAppDelegate.mmconfirm deep iOS-native CoreBluetooth integration. - Proven RN Bridge Reliability — The
EventBufferandonBufferOverflowmechanisms inAppDeviceBLEModule.swiftare clear code-level proofs of intentional bridge durability. - JS Orchestration and Protocol —
BluetoothHandler,EventSyncService, andAppDeviceProtocolServicedemonstrate a sophisticated JavaScript layer for orchestration and custom binary protocol handling. - Android Scope Caveats — The codebase primarily showcases iOS-native implementations. While Android is supported via
react-native-ble-plx(as indicated byshouldUseNativeTransport()), the provided snippets do not demonstrate an equivalent depth of custom-native Android runtime. The Android experience relies more heavily onreact-native-ble-plx's abstraction and the shared TypeScript orchestration layer. This document reflects this divergence honestly; the Android story may evolve with future native work.
| Document | Focus Area |
|---|---|
| System Architecture | High-level system overview and service boundaries. |
| Data Flow Map | Detailed data paths within the application. |
| Health Ingestion Pipeline | HealthKit / Health Connect integration and data ingestion. |
| Failure Modes | System failure modes and recovery strategies. |