@mentra/bluetooth-sdk 0.1.5 → 0.1.7

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 (92) hide show
  1. package/README.md +45 -27
  2. package/android/build.gradle +2 -9
  3. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +53 -36
  4. package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +22 -9
  5. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +25 -36
  6. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +9 -4
  7. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +68 -56
  8. package/android/src/main/java/com/mentra/bluetoothsdk/audio/AudioModels.kt +125 -0
  9. package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +209 -0
  10. package/android/src/main/java/com/mentra/bluetoothsdk/connection/ConnectionModels.kt +78 -0
  11. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +4 -3
  12. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +2 -1
  13. package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +72 -0
  14. package/android/src/main/java/com/mentra/bluetoothsdk/internal/MapParsing.kt +132 -0
  15. package/android/src/main/java/com/mentra/bluetoothsdk/requests/DisplayRequests.kt +39 -0
  16. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +1 -1
  17. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +2 -1
  18. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +1 -1
  19. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +168 -10
  20. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +1 -1
  21. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +7 -3
  22. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +3 -1
  23. package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +607 -0
  24. package/android/src/main/java/com/mentra/bluetoothsdk/status/RuntimeState.kt +201 -0
  25. package/android/src/main/java/com/mentra/bluetoothsdk/status/WifiHotspotStatus.kt +173 -0
  26. package/android/src/main/java/com/mentra/bluetoothsdk/streaming/StreamModels.kt +348 -0
  27. package/android/src/main/java/com/mentra/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +1 -3
  28. package/android/src/main/java/com/mentra/bluetoothsdk/types/DeviceModels.kt +75 -0
  29. package/build/BluetoothSdk.types.d.ts +46 -20
  30. package/build/BluetoothSdk.types.d.ts.map +1 -1
  31. package/build/BluetoothSdk.types.js +1 -0
  32. package/build/BluetoothSdk.types.js.map +1 -1
  33. package/build/_private/BluetoothSdkModule.d.ts +6 -5
  34. package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
  35. package/build/_private/BluetoothSdkModule.js +40 -5
  36. package/build/_private/BluetoothSdkModule.js.map +1 -1
  37. package/build/index.d.ts +1 -1
  38. package/build/index.d.ts.map +1 -1
  39. package/build/index.js +4 -2
  40. package/build/index.js.map +1 -1
  41. package/build/react/useMentraBluetooth.d.ts +5 -3
  42. package/build/react/useMentraBluetooth.d.ts.map +1 -1
  43. package/build/react/useMentraBluetooth.js +15 -4
  44. package/build/react/useMentraBluetooth.js.map +1 -1
  45. package/ios/BluetoothSdkModule.swift +45 -28
  46. package/ios/MentraBluetoothSDK.podspec +0 -3
  47. package/ios/Source/Audio/AudioModels.swift +159 -0
  48. package/ios/Source/Bridge.swift +22 -11
  49. package/ios/Source/Camera/CameraModels.swift +248 -0
  50. package/ios/Source/Connection/ScanSession.swift +27 -0
  51. package/ios/Source/DeviceManager.swift +20 -97
  52. package/ios/Source/DeviceStore.swift +13 -4
  53. package/ios/Source/Errors/BluetoothError.swift +19 -0
  54. package/ios/Source/Events/BluetoothEvents.swift +149 -0
  55. package/ios/Source/Internal/BluetoothAvailability.swift +58 -0
  56. package/ios/Source/Internal/ValueParsing.swift +90 -0
  57. package/ios/Source/MentraBluetoothSDK.swift +50 -2150
  58. package/ios/Source/Requests/DisplayRequests.swift +58 -0
  59. package/ios/Source/Status/DeviceStatus.swift +471 -0
  60. package/ios/Source/Status/RuntimeState.swift +359 -0
  61. package/ios/Source/Status/WifiHotspotStatus.swift +326 -0
  62. package/ios/Source/Streaming/StreamModels.swift +436 -0
  63. package/ios/Source/Types/DeviceModels.swift +134 -0
  64. package/ios/Source/controllers/ControllerManager.swift +3 -3
  65. package/ios/Source/controllers/R1.swift +1 -1
  66. package/ios/Source/sgcs/G1.swift +1 -1
  67. package/ios/Source/sgcs/G2.swift +99 -39
  68. package/ios/Source/sgcs/Mach1.swift +1 -1
  69. package/ios/Source/sgcs/MentraLive.swift +109 -12
  70. package/ios/Source/sgcs/MentraNex.swift +1 -1
  71. package/ios/Source/sgcs/SGCManager.swift +11 -3
  72. package/ios/Source/sgcs/Simulated.swift +2 -2
  73. package/ios/Source/stt/SherpaOnnxTranscriber.swift +1 -4
  74. package/package.json +1 -1
  75. package/src/BluetoothSdk.types.ts +48 -28
  76. package/src/_private/BluetoothSdkModule.ts +47 -21
  77. package/src/index.ts +6 -4
  78. package/src/react/useMentraBluetooth.ts +19 -7
  79. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +0 -1810
  80. package/android/src/main/java/com/mentra/bluetoothsdk/stt/VadGateSpeechPolicy.kt +0 -221
  81. package/ios/Packages/VAD/Common/VAD/VADQuality.swift +0 -41
  82. package/ios/Packages/VAD/Common/VAD/VADState.swift +0 -26
  83. package/ios/Packages/VAD/Common/VAD/VADStrategy.swift +0 -29
  84. package/ios/Packages/VAD/Common/VAD/VADType.swift +0 -14
  85. package/ios/Packages/VAD/Data/Configuration.swift +0 -68
  86. package/ios/Packages/VAD/Data/FrameSize.swift +0 -39
  87. package/ios/Packages/VAD/Data/Record.swift +0 -13
  88. package/ios/Packages/VAD/Data/Result.swift +0 -22
  89. package/ios/Packages/VAD/Data/SampleRate.swift +0 -48
  90. package/ios/Packages/VAD/Silero/Model/silero_vad.onnx +0 -0
  91. package/ios/Packages/VAD/Silero/SileroVAD.swift +0 -284
  92. package/ios/Packages/VAD/Silero/SileroVADStrategy.swift +0 -64
@@ -22,9 +22,15 @@ export type HeadUpEvent = {
22
22
  up: boolean
23
23
  }
24
24
 
25
- export type VadStatusEvent = {
26
- type: "vad_status"
27
- status: boolean
25
+ export type VoiceActivityDetectionStatusEvent = {
26
+ type: "voice_activity_detection_status"
27
+ voiceActivityDetectionEnabled: boolean
28
+ }
29
+
30
+ export type SpeakingStatusEvent = {
31
+ type: "speaking_status"
32
+ speaking: boolean
33
+ timestamp: number
28
34
  }
29
35
 
30
36
  export type BatteryStatusEvent = {
@@ -61,6 +67,7 @@ export function createDisconnectedGlassesStatus(): Partial<GlassesStatus> {
61
67
  return {
62
68
  connection: {state: 'disconnected'},
63
69
  hotspot: {state: 'disabled'},
70
+ voiceActivityDetectionEnabled: true,
64
71
  wifi: {state: 'disconnected'},
65
72
  }
66
73
  }
@@ -190,8 +197,6 @@ export type RgbLedControlResponseEvent =
190
197
 
191
198
  export type RgbLedAction = "on" | "off"
192
199
  export type RgbLedColor = "red" | "green" | "blue" | "orange" | "white"
193
- /** `"auto"` enables local button photo/video capture; `"manual"` reports button events without local gallery capture. */
194
- export type GalleryMode = "auto" | "manual"
195
200
  export type PhotoSize = "small" | "medium" | "large" | "full"
196
201
  export type ButtonPhotoSize = "small" | "medium" | "large"
197
202
  export type PhotoCompression = "none" | "medium" | "heavy"
@@ -223,14 +228,30 @@ export type CameraFovSetting = {
223
228
  roiPosition: number
224
229
  }
225
230
 
231
+ type NativeCameraFovSetting = {
232
+ fov: number
233
+ roi_position: number
234
+ }
235
+
226
236
  export type MicPreference = "auto" | "phone" | "glasses" | "bluetooth"
227
237
  export type MicMode = "phone" | "glasses" | "bluetoothClassic" | "bluetooth"
228
238
 
239
+ export type PhotoRequestParams = {
240
+ requestId: string
241
+ appId: string
242
+ size: PhotoSize
243
+ webhookUrl: string | null
244
+ authToken: string | null
245
+ compress: PhotoCompression
246
+ sound: boolean
247
+ exposureTimeNs?: number | null
248
+ }
249
+
229
250
  export type StreamVideoConfig = {
230
251
  width?: number
231
252
  height?: number
232
253
  bitrate?: number
233
- frameRate?: number
254
+ fps?: number
234
255
  }
235
256
 
236
257
  export type StreamAudioConfig = {
@@ -299,7 +320,7 @@ export type MicPcmEvent = {
299
320
  bitsPerSample: 16
300
321
  channels: 1
301
322
  encoding: "pcm_s16le"
302
- vadGated: boolean
323
+ voiceActivityDetectionEnabled: boolean
303
324
  }
304
325
 
305
326
  export type MicLc3Event = {
@@ -312,7 +333,7 @@ export type MicLc3Event = {
312
333
  frameSizeBytes: number
313
334
  bitrate: number
314
335
  packetizedFromGlasses: boolean
315
- vadGated: boolean
336
+ voiceActivityDetectionEnabled: boolean
316
337
  }
317
338
 
318
339
  export type StreamStatusLifecycleState = "initializing" | "streaming" | "stopping" | "stopped"
@@ -450,7 +471,8 @@ export type BluetoothSdkModuleEvents = {
450
471
  button_press: (event: ButtonPressEvent) => void
451
472
  touch_event: (event: TouchEvent) => void
452
473
  head_up: (event: HeadUpEvent) => void
453
- vad_status: (event: VadStatusEvent) => void
474
+ voice_activity_detection_status: (event: VoiceActivityDetectionStatusEvent) => void
475
+ speaking_status: (event: SpeakingStatusEvent) => void
454
476
  battery_status: (event: BatteryStatusEvent) => void
455
477
  local_transcription: (event: LocalTranscriptionEvent) => void
456
478
  wifi_status_change: (event: WifiStatusChangeEvent) => void
@@ -500,7 +522,7 @@ export type PublicBluetoothStatus = Pick<
500
522
  | "wifiScanResults"
501
523
  | "lastLog"
502
524
  | "otherBtConnected"
503
- | "galleryModeAuto"
525
+ | "galleryModeEnabled"
504
526
  >
505
527
 
506
528
  export type BluetoothSdkEventMap = {
@@ -511,7 +533,8 @@ export type BluetoothSdkEventMap = {
511
533
  button_press: ButtonPressEvent
512
534
  touch_event: TouchEvent
513
535
  head_up: HeadUpEvent
514
- vad_status: VadStatusEvent
536
+ voice_activity_detection_status: VoiceActivityDetectionStatusEvent
537
+ speaking_status: SpeakingStatusEvent
515
538
  battery_status: BatteryStatusEvent
516
539
  local_transcription: LocalTranscriptionEvent
517
540
  wifi_status_change: WifiStatusChangeEvent
@@ -577,22 +600,15 @@ export interface BluetoothSdkPublicModule {
577
600
  forgetWifiNetwork(ssid: string): Promise<void>
578
601
  setHotspotState(enabled: boolean): Promise<void>
579
602
 
580
- setGalleryMode(mode: GalleryMode): Promise<void>
603
+ setGalleryModeEnabled(enabled: boolean): Promise<void>
604
+ setVoiceActivityDetectionEnabled(enabled: boolean): Promise<void>
581
605
  setButtonPhotoSettings(size: ButtonPhotoSize): Promise<void>
582
- setButtonVideoRecordingSettings(width: number, height: number, frameRate: number): Promise<void>
606
+ setButtonVideoRecordingSettings(width: number, height: number, fps: number): Promise<void>
583
607
  setButtonCameraLed(enabled: boolean): Promise<void>
584
608
  setButtonMaxRecordingTime(minutes: number): Promise<void>
585
609
  setCameraFov(fov: CameraFov): Promise<void>
586
610
  queryGalleryStatus(): Promise<void>
587
- requestPhoto(
588
- requestId: string,
589
- appId: string,
590
- size: PhotoSize,
591
- webhookUrl: string | null,
592
- authToken: string | null,
593
- compress: PhotoCompression,
594
- sound: boolean,
595
- ): Promise<void>
611
+ requestPhoto(params: PhotoRequestParams): Promise<void>
596
612
  startVideoRecording(requestId: string, save: boolean, sound: boolean): Promise<void>
597
613
  stopVideoRecording(requestId: string): Promise<void>
598
614
 
@@ -603,7 +619,6 @@ export interface BluetoothSdkPublicModule {
603
619
  setMicState(
604
620
  enabled: boolean,
605
621
  useGlassesMic?: boolean,
606
- bypassVad?: boolean,
607
622
  sendTranscript?: boolean,
608
623
  sendLc3Data?: boolean,
609
624
  ): Promise<void>
@@ -664,6 +679,7 @@ export interface GlassesStatus {
664
679
  // state:
665
680
  connection: GlassesConnectionStatus
666
681
  micEnabled: boolean
682
+ voiceActivityDetectionEnabled: boolean
667
683
  bluetoothClassicConnected: boolean
668
684
  signalStrength: number
669
685
  /** Milliseconds since epoch when signalStrength was last refreshed by the phone BLE stack. */
@@ -728,6 +744,10 @@ export interface Device {
728
744
  name: string
729
745
  /** Platform address/identifier when available: Android Bluetooth address, iOS CoreBluetooth identifier. */
730
746
  address?: string
747
+ /**
748
+ * Optional scan signal strength. It may be undefined at first discovery and
749
+ * appear in a later scan update when the platform reports RSSI metadata.
750
+ */
731
751
  rssi?: number
732
752
  }
733
753
 
@@ -783,7 +803,7 @@ export interface BluetoothStatus {
783
803
  lastLog: string[]
784
804
  otherBtConnected: boolean
785
805
  // desired settings the SDK sends to compatible connected glasses:
786
- galleryModeAuto: boolean
806
+ galleryModeEnabled: boolean
787
807
  }
788
808
 
789
809
  export type BluetoothSettingsUpdate = Partial<{
@@ -801,19 +821,19 @@ export type BluetoothSettingsUpdate = Partial<{
801
821
  dashboard_height: number
802
822
  dashboard_depth: number
803
823
  menu_apps: DashboardMenuItem[] | CoreDashboardMenuItem[] | Array<Record<string, unknown>> | null
804
- galleryModeAuto: boolean
824
+ gallery_mode: boolean
825
+ voice_activity_detection_enabled: boolean
805
826
  button_photo_size: ButtonPhotoSize
806
- button_video_settings: {width: number; height: number; frameRate: number}
827
+ button_video_settings: {width: number; height: number; fps: number}
807
828
  button_video_width: number
808
829
  button_video_height: number
809
830
  button_video_fps: number
810
831
  button_camera_led: boolean
811
832
  button_max_recording_time: number
812
- camera_fov: CameraFovSetting
833
+ camera_fov: NativeCameraFovSetting
813
834
  should_send_pcm: boolean
814
835
  should_send_lc3: boolean
815
836
  should_send_transcript: boolean
816
- bypass_vad: boolean
817
837
  offline_mode: boolean
818
838
  offline_captions_running: boolean
819
839
  local_stt_fallback_active: boolean
@@ -12,14 +12,12 @@ import {
12
12
  DashboardMenuItem,
13
13
  Device,
14
14
  DeviceModel,
15
- GalleryMode,
16
15
  GlassesMediaVolumeGetResult,
17
16
  GlassesMediaVolumeSetResult,
18
17
  GlassesStatus,
19
18
  MicPreference,
20
19
  ObservableStoreCategory,
21
- PhotoCompression,
22
- PhotoSize,
20
+ PhotoRequestParams,
23
21
  PublicBluetoothStatus,
24
22
  RgbLedAction,
25
23
  RgbLedColor,
@@ -96,22 +94,15 @@ declare class BluetoothSdkNativeModule extends NativeModule<BluetoothSdkModuleEv
96
94
  logCurrentWifiFrequency(): Promise<void>
97
95
 
98
96
  // Gallery Commands
99
- setGalleryMode(mode: GalleryMode): Promise<void>
97
+ setGalleryModeEnabled(enabled: boolean): Promise<void>
98
+ setVoiceActivityDetectionEnabled(enabled: boolean): Promise<void>
100
99
  setButtonPhotoSettings(size: ButtonPhotoSize): Promise<void>
101
- setButtonVideoRecordingSettings(width: number, height: number, frameRate: number): Promise<void>
100
+ setButtonVideoRecordingSettings(width: number, height: number, fps: number): Promise<void>
102
101
  setButtonCameraLed(enabled: boolean): Promise<void>
103
102
  setButtonMaxRecordingTime(minutes: number): Promise<void>
104
103
  setCameraFov(fov: CameraFov): Promise<void>
105
104
  queryGalleryStatus(): Promise<void>
106
- requestPhoto(
107
- requestId: string,
108
- appId: string,
109
- size: PhotoSize,
110
- webhookUrl: string | null,
111
- authToken: string | null,
112
- compress: PhotoCompression,
113
- sound: boolean,
114
- ): Promise<void>
105
+ requestPhoto(params: PhotoRequestParams): Promise<void>
115
106
 
116
107
  // OTA Commands
117
108
  sendOtaStart(): Promise<void>
@@ -133,7 +124,6 @@ declare class BluetoothSdkNativeModule extends NativeModule<BluetoothSdkModuleEv
133
124
  setMicState(
134
125
  enabled: boolean,
135
126
  useGlassesMic?: boolean,
136
- bypassVad?: boolean,
137
127
  sendTranscript?: boolean,
138
128
  sendLc3Data?: boolean,
139
129
  ): Promise<void>
@@ -301,7 +291,6 @@ NativeBluetoothSdkModule.getDefaultDevice = function () {
301
291
  const nativeSetMicState = NativeBluetoothSdkModule.setMicState.bind(NativeBluetoothSdkModule) as (
302
292
  enabled: boolean,
303
293
  useGlassesMic: boolean,
304
- bypassVad: boolean,
305
294
  sendTranscript: boolean,
306
295
  sendLc3Data: boolean,
307
296
  ) => MaybePromise<void>
@@ -355,15 +344,23 @@ NativeBluetoothSdkModule.setScreenDisabled = function (disabled: boolean) {
355
344
  return this.updateBluetoothSettings({screen_disabled: disabled})
356
345
  }
357
346
 
347
+ NativeBluetoothSdkModule.setGalleryModeEnabled = function (enabled: boolean) {
348
+ return this.updateBluetoothSettings({gallery_mode: enabled})
349
+ }
350
+
351
+ NativeBluetoothSdkModule.setVoiceActivityDetectionEnabled = function (enabled: boolean) {
352
+ return this.updateBluetoothSettings({voice_activity_detection_enabled: enabled})
353
+ }
354
+
358
355
  NativeBluetoothSdkModule.setButtonPhotoSettings = function (size: ButtonPhotoSize) {
359
356
  return this.updateBluetoothSettings({button_photo_size: size})
360
357
  }
361
358
 
362
- NativeBluetoothSdkModule.setButtonVideoRecordingSettings = function (width: number, height: number, frameRate: number) {
359
+ NativeBluetoothSdkModule.setButtonVideoRecordingSettings = function (width: number, height: number, fps: number) {
363
360
  return this.updateBluetoothSettings({
364
361
  button_video_width: width,
365
362
  button_video_height: height,
366
- button_video_fps: frameRate,
363
+ button_video_fps: fps,
367
364
  })
368
365
  }
369
366
 
@@ -376,13 +373,15 @@ NativeBluetoothSdkModule.setButtonMaxRecordingTime = function (minutes: number)
376
373
  }
377
374
 
378
375
  NativeBluetoothSdkModule.setCameraFov = function (fov: CameraFov) {
379
- return this.updateBluetoothSettings({camera_fov: CAMERA_FOV_SETTINGS[fov]})
376
+ const setting = CAMERA_FOV_SETTINGS[fov]
377
+ return this.updateBluetoothSettings({
378
+ camera_fov: {fov: setting.fov, roi_position: setting.roiPosition},
379
+ })
380
380
  }
381
381
 
382
382
  NativeBluetoothSdkModule.setMicState = function (
383
383
  enabled: boolean,
384
384
  useGlassesMic?: boolean,
385
- bypassVad?: boolean,
386
385
  sendTranscript?: boolean,
387
386
  sendLc3Data?: boolean,
388
387
  ) {
@@ -390,7 +389,6 @@ NativeBluetoothSdkModule.setMicState = function (
390
389
  nativeSetMicState(
391
390
  enabled,
392
391
  useGlassesMic ?? true,
393
- bypassVad ?? true,
394
392
  sendTranscript ?? false,
395
393
  sendLc3Data ?? false,
396
394
  ),
@@ -466,6 +464,9 @@ NativeBluetoothSdkModule.scan = async function (
466
464
  }
467
465
 
468
466
  const handleBluetoothStatus = (status: Partial<BluetoothStatus>) => {
467
+ if (!Array.isArray(status.searchResults)) {
468
+ return
469
+ }
469
470
  emitResults(searchResultsForModel(status, scanOptions.model))
470
471
  }
471
472
 
@@ -484,5 +485,30 @@ NativeBluetoothSdkModule.scan = async function (
484
485
  })
485
486
  }
486
487
 
488
+ /** Expo Android bridge rejects null values in Map<String, Any> — omit optional nullish fields. */
489
+ function photoRequestParamsForNative(params: PhotoRequestParams): Record<string, string | number | boolean> {
490
+ const payload: Record<string, string | number | boolean> = {
491
+ requestId: params.requestId,
492
+ appId: params.appId,
493
+ size: params.size,
494
+ webhookUrl: params.webhookUrl ?? "",
495
+ compress: params.compress,
496
+ flash: true,
497
+ sound: params.sound,
498
+ }
499
+ if (params.authToken != null && params.authToken.length > 0) {
500
+ payload.authToken = params.authToken
501
+ }
502
+ if (params.exposureTimeNs != null && Number.isFinite(params.exposureTimeNs) && params.exposureTimeNs > 0) {
503
+ payload.exposureTimeNs = params.exposureTimeNs
504
+ }
505
+ return payload
506
+ }
507
+
508
+ const nativeRequestPhoto = NativeBluetoothSdkModule.requestPhoto.bind(NativeBluetoothSdkModule)
509
+ NativeBluetoothSdkModule.requestPhoto = function (params: PhotoRequestParams) {
510
+ return nativeRequestPhoto(photoRequestParamsForNative(params) as unknown as PhotoRequestParams)
511
+ }
512
+
487
513
  export default NativeBluetoothSdkModule
488
514
  export const BluetoothSdk = NativeBluetoothSdkModule as BluetoothSdkPublicModule
package/src/index.ts CHANGED
@@ -13,7 +13,8 @@ const PUBLIC_EVENT_NAMES = new Set<BluetoothSdkEventName>([
13
13
  "button_press",
14
14
  "touch_event",
15
15
  "head_up",
16
- "vad_status",
16
+ "voice_activity_detection_status",
17
+ "speaking_status",
17
18
  "battery_status",
18
19
  "local_transcription",
19
20
  "wifi_status_change",
@@ -70,7 +71,8 @@ export const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({
70
71
  sendWifiCredentials: PrivateBluetoothSdkModule.sendWifiCredentials.bind(PrivateBluetoothSdkModule),
71
72
  forgetWifiNetwork: PrivateBluetoothSdkModule.forgetWifiNetwork.bind(PrivateBluetoothSdkModule),
72
73
  setHotspotState: PrivateBluetoothSdkModule.setHotspotState.bind(PrivateBluetoothSdkModule),
73
- setGalleryMode: PrivateBluetoothSdkModule.setGalleryMode.bind(PrivateBluetoothSdkModule),
74
+ setGalleryModeEnabled: PrivateBluetoothSdkModule.setGalleryModeEnabled.bind(PrivateBluetoothSdkModule),
75
+ setVoiceActivityDetectionEnabled: PrivateBluetoothSdkModule.setVoiceActivityDetectionEnabled.bind(PrivateBluetoothSdkModule),
74
76
  setButtonPhotoSettings: PrivateBluetoothSdkModule.setButtonPhotoSettings.bind(PrivateBluetoothSdkModule),
75
77
  setButtonVideoRecordingSettings: PrivateBluetoothSdkModule.setButtonVideoRecordingSettings.bind(PrivateBluetoothSdkModule),
76
78
  setButtonCameraLed: PrivateBluetoothSdkModule.setButtonCameraLed.bind(PrivateBluetoothSdkModule),
@@ -124,7 +126,6 @@ export type {
124
126
  Device,
125
127
  DeviceModel,
126
128
  EnabledHotspotStatus,
127
- GalleryMode,
128
129
  GalleryStatusEvent,
129
130
  GlassesConnectionStatus,
130
131
  GlassesMediaVolumeGetResult,
@@ -151,6 +152,7 @@ export type {
151
152
  ScanModelOptions,
152
153
  ScanOptions,
153
154
  ScanResultsCallback,
155
+ SpeakingStatusEvent,
154
156
  StreamAudioConfig,
155
157
  StreamKeepAliveRequest,
156
158
  StreamStartRequest,
@@ -162,7 +164,7 @@ export type {
162
164
  SwipeVolumeStatusEvent,
163
165
  SwitchStatusEvent,
164
166
  TouchEvent,
165
- VadStatusEvent,
167
+ VoiceActivityDetectionStatusEvent,
166
168
  WifiSearchResult,
167
169
  WifiStatus,
168
170
  WifiStatusChangeEvent,
@@ -11,7 +11,6 @@ import type {
11
11
  ConnectOptions,
12
12
  Device,
13
13
  DeviceModel,
14
- GalleryMode,
15
14
  GlassesConnectionStatus,
16
15
  HotspotStatus,
17
16
  PublicBluetoothStatus,
@@ -78,12 +77,13 @@ export type GlassesRuntimeState =
78
77
  hotspot: HotspotStatus
79
78
  ready: boolean
80
79
  signal: SignalState
80
+ voiceActivityDetectionEnabled: boolean
81
81
  wifi: WifiStatus
82
82
  }
83
83
 
84
84
  export type GalleryModeState = {
85
85
  applying: boolean
86
- desired: GalleryMode
86
+ enabled: boolean
87
87
  error: unknown | null
88
88
  }
89
89
 
@@ -134,7 +134,8 @@ export type MentraBluetoothSession = {
134
134
  scan: ScanController
135
135
  sdk: PhoneSdkRuntimeState
136
136
  setDefaultDevice: (device: Device | null) => Promise<void>
137
- setGalleryMode: (mode: GalleryMode) => Promise<void>
137
+ setGalleryModeEnabled: (enabled: boolean) => Promise<void>
138
+ setVoiceActivityDetectionEnabled: (enabled: boolean) => Promise<void>
138
139
  }
139
140
 
140
141
  function stringValue(value: unknown): string | undefined {
@@ -220,6 +221,7 @@ function runtimeGlassesState(status: Partial<PublicGlassesStatus>): GlassesRunti
220
221
  strengthDbm: numberValue((status as Record<string, unknown>).signalStrength),
221
222
  updatedAt: numberValue((status as Record<string, unknown>).signalStrengthUpdatedAt),
222
223
  },
224
+ voiceActivityDetectionEnabled: status.voiceActivityDetectionEnabled ?? true,
223
225
  wifi: status.wifi ?? {state: "disconnected"},
224
226
  }
225
227
  }
@@ -269,11 +271,11 @@ export function useMentraBluetooth(options: UseMentraBluetoothOptions = {}): Men
269
271
  const [galleryModeApplying, setGalleryModeApplying] = useState(false)
270
272
  const [galleryModeError, setGalleryModeError] = useState<unknown | null>(null)
271
273
 
272
- async function setGalleryMode(mode: GalleryMode) {
274
+ async function setGalleryModeEnabled(enabled: boolean) {
273
275
  setGalleryModeApplying(true)
274
276
  setGalleryModeError(null)
275
277
  try {
276
- await BluetoothSdk.setGalleryMode(mode)
278
+ await BluetoothSdk.setGalleryModeEnabled(enabled)
277
279
  } catch (error) {
278
280
  setGalleryModeError(error)
279
281
  options.onError?.(error)
@@ -283,9 +285,18 @@ export function useMentraBluetooth(options: UseMentraBluetoothOptions = {}): Men
283
285
  }
284
286
  }
285
287
 
288
+ async function setVoiceActivityDetectionEnabled(enabled: boolean) {
289
+ try {
290
+ await BluetoothSdk.setVoiceActivityDetectionEnabled(enabled)
291
+ } catch (error) {
292
+ options.onError?.(error)
293
+ throw error
294
+ }
295
+ }
296
+
286
297
  const galleryMode: GalleryModeState = {
287
298
  applying: galleryModeApplying,
288
- desired: connection.bluetoothStatus.galleryModeAuto === false ? "manual" : "auto",
299
+ enabled: connection.bluetoothStatus.galleryModeEnabled !== false,
289
300
  error: galleryModeError,
290
301
  }
291
302
 
@@ -302,6 +313,7 @@ export function useMentraBluetooth(options: UseMentraBluetoothOptions = {}): Men
302
313
  scan: scanController(connection),
303
314
  sdk: phoneSdkState(connection.bluetoothStatus, connection.defaultDevice, galleryMode),
304
315
  setDefaultDevice: connection.setDefaultDevice,
305
- setGalleryMode,
316
+ setGalleryModeEnabled,
317
+ setVoiceActivityDetectionEnabled,
306
318
  }
307
319
  }