@mentra/bluetooth-sdk 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +35 -32
  2. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +5 -5
  3. package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +38 -12
  4. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +1 -1
  5. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +88 -3
  6. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +11 -5
  7. package/build/BluetoothSdk.types.d.ts +20 -7
  8. package/build/BluetoothSdk.types.d.ts.map +1 -1
  9. package/build/BluetoothSdk.types.js.map +1 -1
  10. package/build/_internal.d.ts +1 -1
  11. package/build/_internal.js +1 -1
  12. package/build/_internal.js.map +1 -1
  13. package/build/_private/BluetoothSdkModule.d.ts +5 -4
  14. package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
  15. package/build/_private/BluetoothSdkModule.js +1 -1
  16. package/build/_private/BluetoothSdkModule.js.map +1 -1
  17. package/build/index.d.ts +4 -3
  18. package/build/index.d.ts.map +1 -1
  19. package/build/index.js +81 -2
  20. package/build/index.js.map +1 -1
  21. package/build/react/index.d.ts +2 -2
  22. package/build/react/index.d.ts.map +1 -1
  23. package/build/react/index.js +1 -2
  24. package/build/react/index.js.map +1 -1
  25. package/build/react/useBluetoothStatus.js +1 -1
  26. package/build/react/useBluetoothStatus.js.map +1 -1
  27. package/build/react/useGlassesConnection.d.ts.map +1 -1
  28. package/build/react/useGlassesConnection.js +13 -0
  29. package/build/react/useGlassesConnection.js.map +1 -1
  30. package/build/react/useMentraBluetooth.d.ts +98 -0
  31. package/build/react/useMentraBluetooth.d.ts.map +1 -0
  32. package/build/react/useMentraBluetooth.js +156 -0
  33. package/build/react/useMentraBluetooth.js.map +1 -0
  34. package/ios/BluetoothSdkModule.swift +5 -5
  35. package/ios/Source/Bridge.swift +42 -8
  36. package/ios/Source/DeviceManager.swift +0 -1
  37. package/ios/Source/DeviceStore.swift +1 -1
  38. package/ios/Source/MentraBluetoothSDK.swift +117 -10
  39. package/package.json +1 -1
  40. package/src/BluetoothSdk.types.ts +20 -7
  41. package/src/_internal.ts +1 -1
  42. package/src/_private/BluetoothSdkModule.ts +7 -5
  43. package/src/index.ts +93 -4
  44. package/src/react/index.ts +13 -11
  45. package/src/react/useBluetoothStatus.ts +1 -1
  46. package/src/react/useGlassesConnection.ts +15 -0
  47. package/src/react/useMentraBluetooth.ts +307 -0
@@ -159,8 +159,10 @@ public enum DeviceModel: String {
159
159
  public struct Device: Identifiable, Equatable, CustomStringConvertible {
160
160
  public let model: DeviceModel
161
161
  public let name: String
162
+ /// CoreBluetooth identifier when available.
162
163
  public let identifier: String?
163
164
  public let rssi: Int?
165
+ /// Stable app-facing scan-result key. Do not parse; use typed fields instead.
164
166
  public let id: String
165
167
 
166
168
  public init(
@@ -527,7 +529,7 @@ public struct BluetoothStatus: CustomStringConvertible {
527
529
  public var shouldSendPcm: Bool { boolValue(values, "should_send_pcm") ?? false }
528
530
  public var shouldSendLc3: Bool { boolValue(values, "should_send_lc3") ?? false }
529
531
  public var shouldSendTranscript: Bool { boolValue(values, "should_send_transcript") ?? false }
530
- public var bypassVad: Bool { boolValue(values, "bypass_vad") ?? false }
532
+ public var bypassVad: Bool { boolValue(values, "bypass_vad") ?? true }
531
533
  public var offlineCaptionsRunning: Bool { boolValue(values, "offline_captions_running") ?? false }
532
534
  public var localSttFallbackActive: Bool { boolValue(values, "local_stt_fallback_active") ?? false }
533
535
  public var shouldSendBootingMessage: Bool { boolValue(values, "shouldSendBootingMessage") ?? true }
@@ -1912,6 +1914,109 @@ public struct LocalTranscriptionEvent: CustomStringConvertible {
1912
1914
  }
1913
1915
  }
1914
1916
 
1917
+ public struct MicPcmEvent: CustomStringConvertible {
1918
+ public static let sampleRate = 16_000
1919
+ public static let bitsPerSample = 16
1920
+ public static let channels = 1
1921
+ public static let encoding = "pcm_s16le"
1922
+
1923
+ public let pcm: Data
1924
+ public let sampleRate: Int
1925
+ public let bitsPerSample: Int
1926
+ public let channels: Int
1927
+ public let encoding: String
1928
+ public let vadGated: Bool
1929
+ public let values: [String: Any]
1930
+
1931
+ public init(values: [String: Any]) {
1932
+ let pcm = values["pcm"] as? Data ?? Data()
1933
+ let sampleRate = intValue(values["sampleRate"]) ?? Self.sampleRate
1934
+ let bitsPerSample = intValue(values["bitsPerSample"]) ?? Self.bitsPerSample
1935
+ let channels = intValue(values["channels"]) ?? Self.channels
1936
+ let encoding = values["encoding"] as? String ?? Self.encoding
1937
+ let vadGated = boolValue(values, "vadGated") ?? false
1938
+
1939
+ var normalized = values
1940
+ normalized["type"] = "mic_pcm"
1941
+ normalized["pcm"] = pcm
1942
+ normalized["sampleRate"] = sampleRate
1943
+ normalized["bitsPerSample"] = bitsPerSample
1944
+ normalized["channels"] = channels
1945
+ normalized["encoding"] = encoding
1946
+ normalized["vadGated"] = vadGated
1947
+
1948
+ self.pcm = pcm
1949
+ self.sampleRate = sampleRate
1950
+ self.bitsPerSample = bitsPerSample
1951
+ self.channels = channels
1952
+ self.encoding = encoding
1953
+ self.vadGated = vadGated
1954
+ self.values = normalized
1955
+ }
1956
+
1957
+ public var description: String {
1958
+ "MicPcmEvent(bytes: \(pcm.count), sampleRate: \(sampleRate), bitsPerSample: \(bitsPerSample), channels: \(channels), encoding: \(encoding), vadGated: \(vadGated))"
1959
+ }
1960
+ }
1961
+
1962
+ public struct MicLc3Event: CustomStringConvertible {
1963
+ public static let sampleRate = 16_000
1964
+ public static let channels = 1
1965
+ public static let encoding = "lc3"
1966
+ public static let frameDurationMs = 10
1967
+ public static let defaultFrameSizeBytes = 60
1968
+
1969
+ public let lc3: Data
1970
+ public let sampleRate: Int
1971
+ public let channels: Int
1972
+ public let encoding: String
1973
+ public let frameDurationMs: Int
1974
+ public let frameSizeBytes: Int
1975
+ public let bitrate: Int
1976
+ public let packetizedFromGlasses: Bool
1977
+ public let vadGated: Bool
1978
+ public let values: [String: Any]
1979
+
1980
+ public init(values: [String: Any]) {
1981
+ let lc3 = values["lc3"] as? Data ?? Data()
1982
+ let sampleRate = intValue(values["sampleRate"]) ?? Self.sampleRate
1983
+ let channels = intValue(values["channels"]) ?? Self.channels
1984
+ let encoding = values["encoding"] as? String ?? Self.encoding
1985
+ let frameDurationMs = intValue(values["frameDurationMs"]) ?? Self.frameDurationMs
1986
+ let frameSizeBytes = intValue(values["frameSizeBytes"]) ?? Self.defaultFrameSizeBytes
1987
+ let bitrate = intValue(values["bitrate"]) ?? frameSizeBytes * 8 * (1000 / frameDurationMs)
1988
+ let packetizedFromGlasses = boolValue(values, "packetizedFromGlasses") ?? false
1989
+ let vadGated = boolValue(values, "vadGated") ?? false
1990
+
1991
+ var normalized = values
1992
+ normalized["type"] = "mic_lc3"
1993
+ normalized["lc3"] = lc3
1994
+ normalized["sampleRate"] = sampleRate
1995
+ normalized["channels"] = channels
1996
+ normalized["encoding"] = encoding
1997
+ normalized["frameDurationMs"] = frameDurationMs
1998
+ normalized["frameSizeBytes"] = frameSizeBytes
1999
+ normalized["bitrate"] = bitrate
2000
+ normalized["packetizedFromGlasses"] = packetizedFromGlasses
2001
+ normalized["vadGated"] = vadGated
2002
+
2003
+ self.lc3 = lc3
2004
+ self.sampleRate = sampleRate
2005
+ self.channels = channels
2006
+ self.encoding = encoding
2007
+ self.frameDurationMs = frameDurationMs
2008
+ self.frameSizeBytes = frameSizeBytes
2009
+ self.bitrate = bitrate
2010
+ self.packetizedFromGlasses = packetizedFromGlasses
2011
+ self.vadGated = vadGated
2012
+ self.values = normalized
2013
+ }
2014
+
2015
+ public var description: String {
2016
+ "MicLc3Event(bytes: \(lc3.count), sampleRate: \(sampleRate), channels: \(channels), frameDurationMs: \(frameDurationMs), frameSizeBytes: \(frameSizeBytes), bitrate: \(bitrate), packetizedFromGlasses: \(packetizedFromGlasses), vadGated: \(vadGated))"
2017
+ }
2018
+ }
2019
+
1915
2020
  public struct GlassesMediaVolumeGetResult: CustomStringConvertible {
1916
2021
  public let level: Int?
1917
2022
  public let statusCode: Int?
@@ -1989,8 +2094,8 @@ public protocol MentraBluetoothSDKDelegate: AnyObject {
1989
2094
  func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didDiscover device: Device)
1990
2095
  func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didStopScan reason: ScanStopReason)
1991
2096
  func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didReceive event: BluetoothEvent)
1992
- func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didReceiveMicPcm frame: Data)
1993
- func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didReceiveMicLc3 frame: Data)
2097
+ func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didReceiveMicPcm event: MicPcmEvent)
2098
+ func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didReceiveMicLc3 event: MicLc3Event)
1994
2099
  func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didChangeDefaultDevice device: Device?)
1995
2100
  func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didLog message: String)
1996
2101
  func mentraBluetoothSDK(_ sdk: MentraBluetoothSDK, didFail error: BluetoothError)
@@ -2003,8 +2108,8 @@ public extension MentraBluetoothSDKDelegate {
2003
2108
  func mentraBluetoothSDK(_: MentraBluetoothSDK, didDiscover _: Device) {}
2004
2109
  func mentraBluetoothSDK(_: MentraBluetoothSDK, didStopScan _: ScanStopReason) {}
2005
2110
  func mentraBluetoothSDK(_: MentraBluetoothSDK, didReceive _: BluetoothEvent) {}
2006
- func mentraBluetoothSDK(_: MentraBluetoothSDK, didReceiveMicPcm _: Data) {}
2007
- func mentraBluetoothSDK(_: MentraBluetoothSDK, didReceiveMicLc3 _: Data) {}
2111
+ func mentraBluetoothSDK(_: MentraBluetoothSDK, didReceiveMicPcm _: MicPcmEvent) {}
2112
+ func mentraBluetoothSDK(_: MentraBluetoothSDK, didReceiveMicLc3 _: MicLc3Event) {}
2008
2113
  func mentraBluetoothSDK(_: MentraBluetoothSDK, didChangeDefaultDevice _: Device?) {}
2009
2114
  func mentraBluetoothSDK(_: MentraBluetoothSDK, didLog _: String) {}
2010
2115
  func mentraBluetoothSDK(_: MentraBluetoothSDK, didFail _: BluetoothError) {}
@@ -2298,7 +2403,7 @@ public final class MentraBluetoothSDK {
2298
2403
  public func setMicState(
2299
2404
  enabled: Bool,
2300
2405
  useGlassesMic: Bool = true,
2301
- bypassVad: Bool = false,
2406
+ bypassVad: Bool = true,
2302
2407
  sendTranscript: Bool = false,
2303
2408
  sendLc3Data: Bool = false
2304
2409
  ) {
@@ -2567,12 +2672,14 @@ public final class MentraBluetoothSDK {
2567
2672
  case "touch_event":
2568
2673
  delegate?.mentraBluetoothSDK(self, didReceive: .touch(TouchEvent(values: data)))
2569
2674
  case "mic_pcm":
2570
- if let frame = data["pcm"] as? Data {
2571
- delegate?.mentraBluetoothSDK(self, didReceiveMicPcm: frame)
2675
+ let event = MicPcmEvent(values: data)
2676
+ if !event.pcm.isEmpty {
2677
+ delegate?.mentraBluetoothSDK(self, didReceiveMicPcm: event)
2572
2678
  }
2573
2679
  case "mic_lc3":
2574
- if let frame = data["lc3"] as? Data {
2575
- delegate?.mentraBluetoothSDK(self, didReceiveMicLc3: frame)
2680
+ let event = MicLc3Event(values: data)
2681
+ if !event.lc3.isEmpty {
2682
+ delegate?.mentraBluetoothSDK(self, didReceiveMicLc3: event)
2576
2683
  }
2577
2684
  case "local_transcription":
2578
2685
  let event = LocalTranscriptionEvent(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentra/bluetooth-sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "SDK for communicating with smart glasses",
5
5
  "main": "build/index.js",
6
6
  "react-native": "src/index.ts",
@@ -295,11 +295,24 @@ export type WsBinEvent = {
295
295
  export type MicPcmEvent = {
296
296
  type: "mic_pcm"
297
297
  pcm: ArrayBuffer
298
+ sampleRate: 16000
299
+ bitsPerSample: 16
300
+ channels: 1
301
+ encoding: "pcm_s16le"
302
+ vadGated: boolean
298
303
  }
299
304
 
300
305
  export type MicLc3Event = {
301
306
  type: "mic_lc3"
302
307
  lc3: ArrayBuffer
308
+ sampleRate: 16000
309
+ channels: 1
310
+ encoding: "lc3"
311
+ frameDurationMs: 10
312
+ frameSizeBytes: number
313
+ bitrate: number
314
+ packetizedFromGlasses: boolean
315
+ vadGated: boolean
303
316
  }
304
317
 
305
318
  export type StreamStatusLifecycleState = "initializing" | "streaming" | "stopping" | "stopped"
@@ -381,7 +394,7 @@ export type OtaUpdateAvailableEvent = {
381
394
  cache_ready?: boolean
382
395
  }
383
396
 
384
- /** @deprecated Glasses no longer emit ota_progress; use {@link OtaStatusEvent} and legacy store mapping. */
397
+ /** @deprecated Glasses no longer emit ota_progress; use {@link OtaStatusEvent} and status-store mapping. */
385
398
  export type OtaProgressEvent = {
386
399
  type: "ota_progress"
387
400
  stage?: OtaStage
@@ -491,8 +504,6 @@ export type PublicBluetoothStatus = Pick<
491
504
  >
492
505
 
493
506
  export type BluetoothSdkEventMap = {
494
- glasses_status: Partial<PublicGlassesStatus>
495
- bluetooth_status: Partial<PublicBluetoothStatus>
496
507
  log: LogEvent
497
508
  device_discovered: Device
498
509
  default_device_changed: {device?: Device}
@@ -540,8 +551,6 @@ export interface BluetoothSdkPublicModule {
540
551
  listener: BluetoothSdkEventListener<EventName>,
541
552
  ): BluetoothSdkSubscription
542
553
 
543
- getGlassesStatus(): Promise<PublicGlassesStatus>
544
- getBluetoothStatus(): Promise<PublicBluetoothStatus>
545
554
  getDefaultDevice(): Promise<Device | null>
546
555
  setDefaultDevice(device: Device | null): Promise<void>
547
556
  clearDefaultDevice(): Promise<void>
@@ -614,8 +623,6 @@ export interface BluetoothSdkPublicModule {
614
623
  ): Promise<void>
615
624
 
616
625
  requestVersionInfo(): Promise<void>
617
- onGlassesStatus(callback: (changed: Partial<PublicGlassesStatus>) => void): () => void
618
- onBluetoothStatus(callback: (changed: Partial<PublicBluetoothStatus>) => void): () => void
619
626
  }
620
627
 
621
628
  // OTA update status types
@@ -711,9 +718,15 @@ export interface CoreSettings {
711
718
  }
712
719
 
713
720
  export interface Device {
721
+ /**
722
+ * Stable app-facing key for this scan result, within the limits of the
723
+ * platform identifier available to the SDK. Do not parse this value; use the
724
+ * typed model, name, address, and rssi fields instead.
725
+ */
714
726
  id: string
715
727
  model: DeviceModel
716
728
  name: string
729
+ /** Platform address/identifier when available: Android Bluetooth address, iOS CoreBluetooth identifier. */
717
730
  address?: string
718
731
  rssi?: number
719
732
  }
package/src/_internal.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * MentraOS-only compatibility entrypoint.
3
3
  *
4
- * Partner apps should import from `@mentra/bluetooth-sdk`. This file is not a
4
+ * Apps should import from `@mentra/bluetooth-sdk`. This file is not a
5
5
  * package export; MentraOS resolves it through its local
6
6
  * `@mentra/bluetooth-sdk-internal` alias while the app is migrated onto the
7
7
  * public SDK surface.
@@ -20,6 +20,7 @@ import {
20
20
  ObservableStoreCategory,
21
21
  PhotoCompression,
22
22
  PhotoSize,
23
+ PublicBluetoothStatus,
23
24
  RgbLedAction,
24
25
  RgbLedColor,
25
26
  ScanModelOptions,
@@ -33,17 +34,18 @@ import {
33
34
  *
34
35
  * This file intentionally lives under `_private` so the package root can expose
35
36
  * a small SDK surface while MentraOS uses its monorepo-only internal alias
36
- * during migration.
37
+ * during migration. Raw status getters/listeners stay here so React hooks can
38
+ * shape native store snapshots before app code sees them.
37
39
  */
38
40
 
39
41
  type GlassesListener = (changed: Partial<GlassesStatus>) => void
40
- type BluetoothStatusListener = (changed: Partial<BluetoothStatus>) => void
42
+ type BluetoothStatusListener = (changed: Partial<PublicBluetoothStatus>) => void
41
43
  type MaybePromise<T> = T | Promise<T>
42
44
 
43
45
  declare class BluetoothSdkNativeModule extends NativeModule<BluetoothSdkModuleEvents> {
44
46
  // Observable Store Functions (native)
45
47
  getGlassesStatus(): Promise<GlassesStatus>
46
- getBluetoothStatus(): Promise<BluetoothStatus>
48
+ getBluetoothStatus(): Promise<PublicBluetoothStatus>
47
49
  getDefaultDevice(): Promise<Device | null>
48
50
  update(category: ObservableStoreCategory, values: object): Promise<void>
49
51
 
@@ -194,7 +196,7 @@ const CAMERA_FOV_SETTINGS: Record<CameraFov, CameraFovSetting> = {
194
196
  wide: {fov: 118, roiPosition: 0},
195
197
  }
196
198
 
197
- function searchResultsForModel(status: Partial<BluetoothStatus>, model: DeviceModel): Device[] {
199
+ function searchResultsForModel(status: Partial<PublicBluetoothStatus>, model: DeviceModel): Device[] {
198
200
  return status.searchResults?.filter((device) => device.model === model) ?? []
199
201
  }
200
202
 
@@ -388,7 +390,7 @@ NativeBluetoothSdkModule.setMicState = function (
388
390
  nativeSetMicState(
389
391
  enabled,
390
392
  useGlassesMic ?? true,
391
- bypassVad ?? false,
393
+ bypassVad ?? true,
392
394
  sendTranscript ?? false,
393
395
  sendLc3Data ?? false,
394
396
  ),
package/src/index.ts CHANGED
@@ -1,10 +1,101 @@
1
- import {BluetoothSdk} from "./_private/BluetoothSdkModule"
1
+ import PrivateBluetoothSdkModule from "./_private/BluetoothSdkModule"
2
+ import type {
3
+ BluetoothSdkEventListener,
4
+ BluetoothSdkEventName,
5
+ BluetoothSdkPublicModule,
6
+ } from "./BluetoothSdk.types"
7
+
8
+ const PUBLIC_EVENT_NAMES = new Set<BluetoothSdkEventName>([
9
+ "log",
10
+ "device_discovered",
11
+ "default_device_changed",
12
+ "glasses_not_ready",
13
+ "button_press",
14
+ "touch_event",
15
+ "head_up",
16
+ "vad_status",
17
+ "battery_status",
18
+ "local_transcription",
19
+ "wifi_status_change",
20
+ "hotspot_status_change",
21
+ "hotspot_error",
22
+ "photo_response",
23
+ "gallery_status",
24
+ "compatible_glasses_search_stop",
25
+ "swipe_volume_status",
26
+ "switch_status",
27
+ "rgb_led_control_response",
28
+ "pair_failure",
29
+ "audio_pairing_needed",
30
+ "audio_connected",
31
+ "audio_disconnected",
32
+ "mic_pcm",
33
+ "mic_lc3",
34
+ "stream_status",
35
+ "keep_alive_ack",
36
+ ])
37
+
38
+ const addListener: BluetoothSdkPublicModule["addListener"] = (eventName, listener) => {
39
+ if (!PUBLIC_EVENT_NAMES.has(eventName)) {
40
+ throw new Error(
41
+ `Unsupported BluetoothSdk event "${eventName}". Use @mentra/bluetooth-sdk/react for status state.`,
42
+ )
43
+ }
44
+ return PrivateBluetoothSdkModule.addListener(
45
+ eventName,
46
+ listener as BluetoothSdkEventListener<BluetoothSdkEventName>,
47
+ )
48
+ }
49
+
50
+ export const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({
51
+ addListener,
52
+ getDefaultDevice: PrivateBluetoothSdkModule.getDefaultDevice.bind(PrivateBluetoothSdkModule),
53
+ setDefaultDevice: PrivateBluetoothSdkModule.setDefaultDevice.bind(PrivateBluetoothSdkModule),
54
+ clearDefaultDevice: PrivateBluetoothSdkModule.clearDefaultDevice.bind(PrivateBluetoothSdkModule),
55
+ startScan: PrivateBluetoothSdkModule.startScan.bind(PrivateBluetoothSdkModule),
56
+ stopScan: PrivateBluetoothSdkModule.stopScan.bind(PrivateBluetoothSdkModule),
57
+ scan: PrivateBluetoothSdkModule.scan.bind(PrivateBluetoothSdkModule) as BluetoothSdkPublicModule["scan"],
58
+ connect: PrivateBluetoothSdkModule.connect.bind(PrivateBluetoothSdkModule),
59
+ connectDefault: PrivateBluetoothSdkModule.connectDefault.bind(PrivateBluetoothSdkModule),
60
+ cancelConnectionAttempt: PrivateBluetoothSdkModule.cancelConnectionAttempt.bind(PrivateBluetoothSdkModule),
61
+ disconnect: PrivateBluetoothSdkModule.disconnect.bind(PrivateBluetoothSdkModule),
62
+ forget: PrivateBluetoothSdkModule.forget.bind(PrivateBluetoothSdkModule),
63
+ displayText: PrivateBluetoothSdkModule.displayText.bind(PrivateBluetoothSdkModule),
64
+ clearDisplay: PrivateBluetoothSdkModule.clearDisplay.bind(PrivateBluetoothSdkModule),
65
+ showDashboard: PrivateBluetoothSdkModule.showDashboard.bind(PrivateBluetoothSdkModule),
66
+ setDashboardPosition: PrivateBluetoothSdkModule.setDashboardPosition.bind(PrivateBluetoothSdkModule),
67
+ setHeadUpAngle: PrivateBluetoothSdkModule.setHeadUpAngle.bind(PrivateBluetoothSdkModule),
68
+ setScreenDisabled: PrivateBluetoothSdkModule.setScreenDisabled.bind(PrivateBluetoothSdkModule),
69
+ requestWifiScan: PrivateBluetoothSdkModule.requestWifiScan.bind(PrivateBluetoothSdkModule),
70
+ sendWifiCredentials: PrivateBluetoothSdkModule.sendWifiCredentials.bind(PrivateBluetoothSdkModule),
71
+ forgetWifiNetwork: PrivateBluetoothSdkModule.forgetWifiNetwork.bind(PrivateBluetoothSdkModule),
72
+ setHotspotState: PrivateBluetoothSdkModule.setHotspotState.bind(PrivateBluetoothSdkModule),
73
+ setGalleryMode: PrivateBluetoothSdkModule.setGalleryMode.bind(PrivateBluetoothSdkModule),
74
+ setButtonPhotoSettings: PrivateBluetoothSdkModule.setButtonPhotoSettings.bind(PrivateBluetoothSdkModule),
75
+ setButtonVideoRecordingSettings: PrivateBluetoothSdkModule.setButtonVideoRecordingSettings.bind(PrivateBluetoothSdkModule),
76
+ setButtonCameraLed: PrivateBluetoothSdkModule.setButtonCameraLed.bind(PrivateBluetoothSdkModule),
77
+ setButtonMaxRecordingTime: PrivateBluetoothSdkModule.setButtonMaxRecordingTime.bind(PrivateBluetoothSdkModule),
78
+ setCameraFov: PrivateBluetoothSdkModule.setCameraFov.bind(PrivateBluetoothSdkModule),
79
+ queryGalleryStatus: PrivateBluetoothSdkModule.queryGalleryStatus.bind(PrivateBluetoothSdkModule),
80
+ requestPhoto: PrivateBluetoothSdkModule.requestPhoto.bind(PrivateBluetoothSdkModule),
81
+ startVideoRecording: PrivateBluetoothSdkModule.startVideoRecording.bind(PrivateBluetoothSdkModule),
82
+ stopVideoRecording: PrivateBluetoothSdkModule.stopVideoRecording.bind(PrivateBluetoothSdkModule),
83
+ startStream: PrivateBluetoothSdkModule.startStream.bind(PrivateBluetoothSdkModule),
84
+ stopStream: PrivateBluetoothSdkModule.stopStream.bind(PrivateBluetoothSdkModule),
85
+ keepStreamAlive: PrivateBluetoothSdkModule.keepStreamAlive.bind(PrivateBluetoothSdkModule),
86
+ setMicState: PrivateBluetoothSdkModule.setMicState.bind(PrivateBluetoothSdkModule),
87
+ setPreferredMic: PrivateBluetoothSdkModule.setPreferredMic.bind(PrivateBluetoothSdkModule),
88
+ setOwnAppAudioPlaying: PrivateBluetoothSdkModule.setOwnAppAudioPlaying.bind(PrivateBluetoothSdkModule),
89
+ getGlassesMediaVolume: PrivateBluetoothSdkModule.getGlassesMediaVolume.bind(PrivateBluetoothSdkModule),
90
+ setGlassesMediaVolume: PrivateBluetoothSdkModule.setGlassesMediaVolume.bind(PrivateBluetoothSdkModule),
91
+ rgbLedControl: PrivateBluetoothSdkModule.rgbLedControl.bind(PrivateBluetoothSdkModule),
92
+ requestVersionInfo: PrivateBluetoothSdkModule.requestVersionInfo.bind(PrivateBluetoothSdkModule),
93
+ })
2
94
 
3
95
  export default BluetoothSdk
4
96
 
5
97
  export {
6
98
  DeviceModels,
7
- createDisconnectedGlassesStatus,
8
99
  isBusyGlassesConnectionStatus,
9
100
  isConnectedGlassesConnectionStatus,
10
101
  isConnectedWifiStatus,
@@ -54,8 +145,6 @@ export type {
54
145
  PhotoCompression,
55
146
  PhotoResponseEvent,
56
147
  PhotoSize,
57
- PublicBluetoothStatus as BluetoothStatus,
58
- PublicGlassesStatus as GlassesStatus,
59
148
  RgbLedAction,
60
149
  RgbLedColor,
61
150
  RgbLedControlResponseEvent,
@@ -8,15 +8,17 @@ export {
8
8
  type BluetoothScanHookResult,
9
9
  type UseBluetoothScanOptions,
10
10
  } from "./useBluetoothScan"
11
+ export type {DefaultDeviceStorage} from "./useGlassesConnection"
11
12
  export {
12
- useBluetoothStatus,
13
- type BluetoothStatusHookResult,
14
- type UseBluetoothStatusOptions,
15
- } from "./useBluetoothStatus"
16
- export {
17
- useGlassesConnection,
18
- type DefaultDeviceStorage,
19
- type GlassesConnectionAction,
20
- type GlassesConnectionHookResult,
21
- type UseGlassesConnectionOptions,
22
- } from "./useGlassesConnection"
13
+ useMentraBluetooth,
14
+ type BatteryState,
15
+ type ConnectedGlassesInfo,
16
+ type FirmwareInfo,
17
+ type GalleryModeState,
18
+ type GlassesRuntimeState,
19
+ type MentraBluetoothSession,
20
+ type PhoneSdkRuntimeState,
21
+ type ScanController,
22
+ type SignalState,
23
+ type UseMentraBluetoothOptions,
24
+ } from "./useMentraBluetooth"
@@ -1,6 +1,6 @@
1
1
  import {useEffect, useRef, useState} from "react"
2
2
 
3
- import BluetoothSdk from "../index"
3
+ import BluetoothSdk from "../_private/BluetoothSdkModule"
4
4
  import {
5
5
  createDisconnectedGlassesStatus,
6
6
  isConnectedGlassesConnectionStatus,
@@ -96,6 +96,21 @@ export function useGlassesConnection(
96
96
  }
97
97
  }, [])
98
98
 
99
+ useEffect(() => {
100
+ const subscription = BluetoothSdk.addListener("default_device_changed", (event) => {
101
+ const nextDefaultDevice = event.device ?? null
102
+ setDefaultDeviceState(nextDefaultDevice)
103
+ void defaultDeviceStorageRef.current?.save(nextDefaultDevice).catch((nextError) => {
104
+ setOperationError(nextError)
105
+ onErrorRef.current?.(nextError)
106
+ })
107
+ })
108
+
109
+ return () => {
110
+ subscription.remove()
111
+ }
112
+ }, [])
113
+
99
114
  useEffect(() => {
100
115
  if (!options.autoConnectDefault || autoConnectAttemptedRef.current || status.connected || !defaultDevice) {
101
116
  return