Skip to content

Wearables Module Integration And SDK Implementation

Plan Metadata

  • Plan type: plan
  • Parent plan: N/A
  • Depends on: N/A
  • Status: documentation

System Intent

  • What is being built: A source-of-truth contract for using WearablesModule from the app layer, plus an implementation map of how the module bridges to Android, iOS, web, and Meta Ray-Ban SDK dependencies.
  • Primary consumer(s): Mobile app surfaces that call wearables functions (AppInit, SettingsScreen, Debugger) and maintainers of main/app/wearables-module.
  • Boundary (black-box scope only): The public API exported by main/app/wearables-module/src/WearablesModule.ts and the runtime outcomes it guarantees for initialize, registration, stream lifecycle, recording lifecycle, and debug-state retrieval.

Stage Gate Tracker

  • [x] Stage 1 Mermaid approved
  • [x] Stage 2 I/O contracts approved
  • [x] Stage 3 pseudocode approved or skipped

1. Mermaid Diagram

Reference: .agent/skills/create-mermaid-diagram/SKILL.md

flowchart TD
  A[WearablesModule black box - main/app/wearables-module/src/WearablesModule.ts] -->|android runtime resolves module API calls| D[Android implementation - main/app/wearables-module/android/src/main/java/expo/modules/wearablesmodule/WearablesModule.kt]
  A -->|ios runtime resolves module API calls| E[iOS implementation - main/app/wearables-module/ios/WearablesModule.swift]
  A -->|web runtime resolves module API calls to stub behavior| F[Web implementation - main/app/wearables-module/src/WearablesModule.web.ts]

  D -->|implements Android native contract and delegates helper utilities| G[Android helpers - main/app/wearables-module/android/src/main/java/expo/modules/wearablesmodule/WearablesHelpers.kt]
  E -->|implements iOS native contract and delegates helper utilities| I[iOS helpers - main/app/wearables-module/ios/WearablesHelpers.swift]

  D -->|uses Android SDK runtime for device lifecycle permissions and streaming| K[Meta SDK Android libs - main/app/wearables-module/android/libs/mwdat-core-0.3.0.aar main/app/wearables-module/android/libs/mwdat-camera-0.3.0.aar]
  G -->|creates stream sessions and device availability checks via SDK| K
  E -->|uses iOS SDK runtime for device lifecycle permissions and streaming| L[Meta SDK iOS frameworks - main/app/wearables-module/ios/Frameworks/MWDATCore.xcframework main/app/wearables-module/ios/Frameworks/MWDATCamera.xcframework]

  classDef unchanged fill:#d3d3d3,stroke:#666,stroke-width:1px;
  classDef updated fill:#ffe58a,stroke:#666,stroke-width:1px;
  classDef deleted fill:#f4a6a6,stroke:#666,stroke-width:1px;
  classDef created fill:#a8e6a3,stroke:#666,stroke-width:1px;

  class A,D,E,F,G,I,K,L unchanged;

2. Black-Box Inputs and Outputs

Keep this short. Define types in JSON-style blocks and capture each flow with path-level rows.

Global Types

Define shared types used across multiple flows.

Platform {
  value: "android" | "ios"
}

DeviceDebugInfo {
  sdkAvailable: boolean
  registrationState: string
  deviceCount: number
  devices: Array<{
    id: string
    name: string
    linkState: string
    deviceType: string
    compatibility: string
  }>
}

Flow: main/app/wearables-module/src/WearablesModule.ts.initialize, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt, main/app/wearables-module/ios/WearablesModuleTests/WearablesModuleTests.swift

Type Definitions

InitializeInput = none (no parameters)
InitializeOutput = void (no return payload)

Paths

path-name input output/expected state change path-type notes
initialize.success none void; module runtime state becomes initialized happy path native module is ready for subsequent calls
initialize.sdk-unavailable-stub none throws Error error SDK unavailable path should fail fast instead of silently stubbing
initialize.failure none throws Error error propagate native initialization error

Flow: main/app/wearables-module/src/WearablesModule.ts.isAnyDeviceAvailable, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt, main/app/wearables-module/ios/WearablesModuleTests/WearablesModuleTests.swift

Type Definitions

IsAnyDeviceAvailableInput = none (no parameters)

IsAnyDeviceAvailableOutput {
  value: boolean
}

Paths

path-name input output/expected state change path-type notes
isAnyDeviceAvailable.snapshot none IsAnyDeviceAvailableOutput value=true | false happy path reads current device availability snapshot

Flow: main/app/wearables-module/src/WearablesModule.ts.isAnyDeviceRegisted, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt, main/app/wearables-module/ios/WearablesModuleTests/WearablesModuleTests.swift

Type Definitions

IsAnyDeviceRegistedInput = none (no parameters)

IsAnyDeviceRegistedOutput {
  value: boolean
}

Paths

path-name input output/expected state change path-type notes
isAnyDeviceRegisted.snapshot none IsAnyDeviceRegistedOutput value=true | false happy path reads current registration snapshot
isAnyDeviceRegisted.sdk-unavailable none IsAnyDeviceRegistedOutput value=true | false subpath value comes from native helper fallback state when SDK is unavailable

Flow: main/app/wearables-module/src/WearablesModule.ts.startRegistration, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt, main/app/wearables-module/ios/WearablesModuleTests/WearablesModuleTests.swift

Type Definitions

StartRegistrationInput = none (no parameters)
StartRegistrationOutput = void (no return payload)

Paths

path-name input output/expected state change path-type notes
startRegistration.success none void happy path registration flow is requested on platform SDK
startRegistration.failure none throws Error error platform failure is surfaced to caller

Flow: main/app/wearables-module/src/WearablesModule.ts.startUnregistration, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt, main/app/wearables-module/ios/WearablesModuleTests/WearablesModuleTests.swift

Type Definitions

StartUnregistrationInput = none (no parameters)
StartUnregistrationOutput = void (no return payload)

Paths

path-name input output/expected state change path-type notes
startUnregistration.success none void happy path unregistration flow is requested on platform SDK
startUnregistration.failure none throws Error error platform failure is surfaced to caller

Flow: main/app/wearables-module/src/WearablesModule.ts.startStreamSession, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt, main/app/wearables-module/ios/WearablesModuleTests/WearablesModuleTests.swift

Type Definitions

StartStreamSessionInput = none (no parameters)
StartStreamSessionOutput = void (no return payload)

Paths

path-name input output/expected state change path-type notes
startStreamSession.success none void happy path stream session is active and can be recorded
startStreamSession.failure none throws Error error e.g. no available device or permission denied

Flow: main/app/wearables-module/src/WearablesModule.ts.stopStreamSession, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt, main/app/wearables-module/ios/WearablesModuleTests/WearablesModuleTests.swift

Type Definitions

StopStreamSessionInput = none (no parameters)
StopStreamSessionOutput = void (no return payload)

Paths

path-name input output/expected state change path-type notes
stopStreamSession.success none void happy path stream session is stopped and recording cleanup is performed if active
stopStreamSession.failure none throws Error error platform stop failure is surfaced to caller

Flow: main/app/wearables-module/src/WearablesModule.ts.startRecordingStream, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt

Type Definitions

StartRecordingStreamInput = none (no parameters)

StartRecordingStreamOutput {
  recording_path: string
}

Paths

path-name input output/expected state change path-type notes
startRecordingStream.success none StartRecordingStreamOutput recording_path=string happy path returns recording file path/URI token
startRecordingStream.failure none throws Error error fails when no active stream or platform write failure

Flow: main/app/wearables-module/src/WearablesModule.ts.stopRecordingStream, main/app/wearables-module/android/src/androidTest/java/expo/modules/wearablesmodule/WearablesModuleTest.kt

Type Definitions

StopRecordingStreamInput = none (no parameters)

StopRecordingStreamOutput {
  recording_path: string | null
}

Paths

path-name input output/expected state change path-type notes
stopRecordingStream.success none StopRecordingStreamOutput recording_path=string|null happy path returns finalized path when available
stopRecordingStream.failure none throws Error error platform stop-recording failure is surfaced to caller

Flow: main/app/wearables-module/src/WearablesModule.ts.getDeviceDebugInfo, N/A

Type Definitions

DeviceDebugInfoInput = none (no parameters)

DeviceDebugInfoOutput {
  info: DeviceDebugInfo
}

Paths

path-name input output/expected state change path-type notes
getDeviceDebugInfo.success none DeviceDebugInfoOutput info.sdkAvailable=true|false happy path returns current device and SDK status snapshot
getDeviceDebugInfo.stub none DeviceDebugInfoOutput info.sdkAvailable=false deviceCount=0 subpath SDK-unavailable path returns empty device set

3. Pseudocode for Critical Flows (Optional)

  • Flow name:: main/app/scripts/download-meta-sdk.sh.downloadMetaSdkIos (current)

    set SDK_REPO and SDK_VERSION
    if SDK_VERSION is latest:
      resolve latest tag from remote git tags
      fallback to default pinned version if resolution fails
    
    resolve repository root from script directory
    set TARGET_DIR to main/app/wearables-module/ios/Frameworks
    validate TARGET_DIR suffix and reject malformed paths
    
    create temp directory and cleanup trap
    git clone --depth 1 --branch SDK_VERSION SDK_REPO into temp dir
    
    verify required frameworks exist in clone:
      MWDATCore.xcframework
      MWDATCamera.xcframework
    copy frameworks into TARGET_DIR
    exit with error if either framework is missing
    

  • Implementation notes:

  • Critical and complex flow currently in place: WearablesModule.initialize spans platform-specific SDK bootstrapping and should throw on SDK-unavailable paths.
  • Critical and complex flow currently in place: startStreamSession and permission gating (camera, bluetooth) must be ordered correctly before recording begins.
  • Critical and complex flow currently in place: startRecordingStream and stopRecordingStream must preserve file-path semantics (string start result, string | null stop result) and handle active-session constraints.
  • Critical and complex flow currently in place: SDK artifact wiring is split across script + build config (download-meta-sdk.sh, android/build.gradle, ios/WearablesModule.podspec), so drift across these files is a high-risk integration point.

After all stages are approved, apply .agent/skills/reconcile-plans/SKILL.md to propagate contract updates across linked plans.