@mentra/bluetooth-sdk 0.1.5 → 0.1.6

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 (42) hide show
  1. package/README.md +29 -13
  2. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +15 -7
  3. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +1 -0
  4. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +34 -46
  5. package/android/src/main/java/com/mentra/bluetoothsdk/audio/AudioModels.kt +125 -0
  6. package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +187 -0
  7. package/android/src/main/java/com/mentra/bluetoothsdk/connection/ConnectionModels.kt +78 -0
  8. package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +60 -0
  9. package/android/src/main/java/com/mentra/bluetoothsdk/internal/MapParsing.kt +132 -0
  10. package/android/src/main/java/com/mentra/bluetoothsdk/requests/DisplayRequests.kt +39 -0
  11. package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +605 -0
  12. package/android/src/main/java/com/mentra/bluetoothsdk/status/RuntimeState.kt +199 -0
  13. package/android/src/main/java/com/mentra/bluetoothsdk/status/WifiHotspotStatus.kt +173 -0
  14. package/android/src/main/java/com/mentra/bluetoothsdk/streaming/StreamModels.kt +348 -0
  15. package/android/src/main/java/com/mentra/bluetoothsdk/types/DeviceModels.kt +75 -0
  16. package/build/BluetoothSdk.types.d.ts +4 -0
  17. package/build/BluetoothSdk.types.d.ts.map +1 -1
  18. package/build/BluetoothSdk.types.js.map +1 -1
  19. package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
  20. package/build/_private/BluetoothSdkModule.js +3 -0
  21. package/build/_private/BluetoothSdkModule.js.map +1 -1
  22. package/ios/BluetoothSdkModule.swift +4 -4
  23. package/ios/Source/Audio/AudioModels.swift +159 -0
  24. package/ios/Source/Camera/CameraModels.swift +246 -0
  25. package/ios/Source/Connection/ScanSession.swift +27 -0
  26. package/ios/Source/DeviceStore.swift +1 -0
  27. package/ios/Source/Errors/BluetoothError.swift +19 -0
  28. package/ios/Source/Events/BluetoothEvents.swift +115 -0
  29. package/ios/Source/Internal/BluetoothAvailability.swift +58 -0
  30. package/ios/Source/Internal/ValueParsing.swift +90 -0
  31. package/ios/Source/MentraBluetoothSDK.swift +25 -2140
  32. package/ios/Source/Requests/DisplayRequests.swift +58 -0
  33. package/ios/Source/Status/DeviceStatus.swift +463 -0
  34. package/ios/Source/Status/RuntimeState.swift +350 -0
  35. package/ios/Source/Status/WifiHotspotStatus.swift +326 -0
  36. package/ios/Source/Streaming/StreamModels.swift +436 -0
  37. package/ios/Source/Types/DeviceModels.swift +134 -0
  38. package/ios/Source/sgcs/G2.swift +97 -36
  39. package/package.json +1 -1
  40. package/src/BluetoothSdk.types.ts +4 -0
  41. package/src/_private/BluetoothSdkModule.ts +3 -0
  42. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +0 -1810
@@ -1062,6 +1062,8 @@ class G2: NSObject, SGCManager {
1062
1062
  private var rightAuthenticated: Bool = false
1063
1063
  private var isDisconnecting = false
1064
1064
  private var pairingTimeoutTimer: DispatchWorkItem?
1065
+ private var useEvenDashboard = true
1066
+ private var dashboardShowing = 0
1065
1067
 
1066
1068
  /// Device search
1067
1069
  var DEVICE_SEARCH_ID = "NOT_SET"
@@ -1598,11 +1600,11 @@ class G2: NSObject, SGCManager {
1598
1600
  func sendTextWall(_ text: String) {
1599
1601
  // Bridge.log("G2: sendTextWall(\(text.prefix(50))...)")
1600
1602
 
1601
- // ignore events while the dashboard is open:
1602
- // let isHeadUp = DeviceStore.shared.get("glasses", "headUp") as? Bool ?? false
1603
- // if isHeadUp {
1604
- // return
1605
- // }
1603
+ // ignore events while the ER dashboard is open:
1604
+ let useNativeDashboard = DeviceStore.shared.get("bluetooth", "use_native_dashboard") as? Bool ?? false
1605
+ if useNativeDashboard && dashboardShowing > 0 {
1606
+ return
1607
+ }
1606
1608
 
1607
1609
  if text.isEmpty {
1608
1610
  clearDisplay()
@@ -2191,8 +2193,24 @@ class G2: NSObject, SGCManager {
2191
2193
  return bmp
2192
2194
  }
2193
2195
 
2196
+ /// Bring the Even Realities dashboard (the OS-level home/idle screen) to
2197
+ /// the foreground by tearing down whatever EvenHub page we currently own.
2198
+ /// The glasses fall back to the dashboard automatically when no page is up.
2194
2199
  func showDashboard() {
2195
- // G2 doesn't have a native dashboard concept via EvenHub
2200
+ Bridge.log("G2: showDashboard")
2201
+ dashboardShowing += 2
2202
+ let msg = EvenHubProto.shutdownMessage()
2203
+ sendEvenHubCommand(msg)
2204
+ pageCreated = false
2205
+ pageHasTextContainer = false
2206
+ currentTextContent = ""
2207
+ currentBitmapBase64 = ""
2208
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
2209
+ guard let self = self else { return }
2210
+ // activate the dashboard by setting dept to the current setting:
2211
+ let currentDepth = DeviceStore.shared.get("bluetooth", "dashboard_depth") as? Int ?? 0
2212
+ self.setDashboardDepthOnly(currentDepth)
2213
+ }
2196
2214
  }
2197
2215
 
2198
2216
  func setDashboardPosition(_ height: Int, _ depth: Int) {
@@ -2302,21 +2320,33 @@ class G2: NSObject, SGCManager {
2302
2320
  sendEvenHubCommand(toSend)
2303
2321
  }
2304
2322
 
2323
+ func restartMic() {
2324
+ // if already enabled, set to disabled, then send enabled after 500ms:
2325
+ DeviceStore.shared.apply("glasses", "micEnabled", true)
2326
+ let msg = EvenHubProto.audioControlMessage(enable: false)
2327
+ sendEvenHubCommand(msg)
2328
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
2329
+ guard let self = self else { return }
2330
+ let useNativeDashboard = DeviceStore.shared.get("bluetooth", "use_native_dashboard") as? Bool ?? false
2331
+ Bridge.log("G2: setMicEnabled - useNativeDashboard=\(useNativeDashboard), dashboardShowing=\(dashboardShowing)")
2332
+ if useNativeDashboard && dashboardShowing > 0 {
2333
+ return
2334
+ }
2335
+ if (!pageCreated || !pageHasTextContainer) {
2336
+ DeviceManager.shared.sendCurrentState()// should re-create the page if needed
2337
+ }
2338
+ let msg = EvenHubProto.audioControlMessage(enable: true)
2339
+ self.sendEvenHubCommand(msg)
2340
+ }
2341
+ }
2342
+
2305
2343
  // MARK: - SGCManager: Audio Control
2306
2344
 
2307
2345
  func setMicEnabled(_ enabled: Bool) {
2308
2346
  Bridge.log("G2: setMicEnabled(\(enabled))")
2309
2347
  let currentEnabled = DeviceStore.shared.get("glasses", "micEnabled") as? Bool ?? false
2310
2348
  if currentEnabled && enabled {
2311
- // if already enabled, set to disabled, then send enabled after 500ms:
2312
- DeviceStore.shared.apply("glasses", "micEnabled", true)
2313
- let msg = EvenHubProto.audioControlMessage(enable: false)
2314
- sendEvenHubCommand(msg)
2315
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
2316
- guard let self = self else { return }
2317
- let msg = EvenHubProto.audioControlMessage(enable: true)
2318
- self.sendEvenHubCommand(msg)
2319
- }
2349
+ restartMic()
2320
2350
  return
2321
2351
  }
2322
2352
 
@@ -2505,7 +2535,8 @@ class G2: NSObject, SGCManager {
2505
2535
  // }
2506
2536
 
2507
2537
  // connectController("1B:08:26:8E:0E:E6")
2508
- connectController()
2538
+ // connectController()
2539
+ showDashboard()
2509
2540
  }
2510
2541
 
2511
2542
  func dbg2() {
@@ -2532,6 +2563,8 @@ class G2: NSObject, SGCManager {
2532
2563
  // // update the text
2533
2564
  // Bridge.log("G2: sendTextWall() - updating text container")
2534
2565
  // updateText("test2")
2566
+ let currentDepth = DeviceStore.shared.get("bluetooth", "dashboard_depth") as? Int ?? 0
2567
+ setDashboardDepthOnly(currentDepth)
2535
2568
  }
2536
2569
 
2537
2570
  // MARK: - SGCManager: Device Control
@@ -3021,15 +3054,22 @@ class G2: NSObject, SGCManager {
3021
3054
  if eventType == .doubleClick {
3022
3055
  // trigger dashboard:
3023
3056
  let isHeadUp = DeviceStore.shared.get("glasses", "headUp") as? Bool ?? false
3024
- // toggle head up:
3025
- DeviceStore.shared.apply("glasses", "headUp", !isHeadUp)
3026
- if isHeadUp {
3027
- // Bridge.log("G2: going back to home, clearing display")
3028
- // clear the display after a delay:
3029
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
3030
- self.clearDisplay()
3031
- }
3057
+
3058
+ let useNativeDashboard = DeviceStore.shared.get("bluetooth", "use_native_dashboard") as? Bool ?? false
3059
+ if useNativeDashboard {
3060
+ showDashboard()
3061
+ } else {
3062
+ // toggle head up:
3063
+ DeviceStore.shared.apply("glasses", "headUp", !isHeadUp)
3032
3064
  }
3065
+
3066
+ // if isHeadUp {
3067
+ // // Bridge.log("G2: going back to home, clearing display")
3068
+ // // clear the display after a delay:
3069
+ // DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
3070
+ // self.clearDisplay()
3071
+ // }
3072
+ // }
3033
3073
  // sendDashboardCommand(DashboardCommand.trigger)
3034
3074
 
3035
3075
  // toggle head up:
@@ -3373,18 +3413,39 @@ class G2: NSObject, SGCManager {
3373
3413
  // if we got 08011A00 that means we closed the dashboard, which means the mic is probably dead,
3374
3414
  // so we need to revive it:
3375
3415
  if data == Data([0x08, 0x01, 0x1A, 0x00]) {
3376
- Bridge.log("G2: gesture_ctrl response: dashboard closed")
3377
- // re-send mic on / update mic state:
3378
- DeviceStore.shared.apply("glasses", "micEnabled", false)
3379
- DeviceManager.shared.updateMicState() // should set the mic back on if it should be on
3380
- // // let isHeadUp = DeviceStore.shared.get("glasses", "headUp") as? Bool ?? false
3381
-
3382
- // // toggle head up:
3383
- // DeviceStore.shared.apply("glasses", "headUp", false)
3384
- // // send the current state to the glasses
3385
- // DeviceManager.shared.sendCurrentState()
3386
- // reset the text container (different from clearDisplay())
3387
- sendTextWall(" ")
3416
+ Bridge.log("G2: dashboard closed / shutdown - dashboardShowing=\(dashboardShowing)")
3417
+ let useNativeDashboard = DeviceStore.shared.get("bluetooth", "use_native_dashboard") as? Bool ?? false
3418
+ if !useNativeDashboard {
3419
+ // make sure the container exists:
3420
+ DeviceManager.shared.sendCurrentState()
3421
+ // re-send mic on / if it's enabled:
3422
+ let micEnabled = DeviceStore.shared.get("glasses", "micEnabled") as? Bool ?? false
3423
+ if micEnabled {
3424
+ restartMic()
3425
+ }
3426
+ // reset the text container (different from clearDisplay())
3427
+ // sendTextWall(" ")
3428
+ // createPageWithText(" ")
3429
+ } else {
3430
+ // if we aren't trying to show the dashboard
3431
+ // then we need to turn the mic back on and display the mentra main page:
3432
+ if dashboardShowing <= 1 {
3433
+ dashboardShowing = 0
3434
+ // make sure the container exists:
3435
+ DeviceManager.shared.sendCurrentState()
3436
+ // set the mic back on if it should be on
3437
+ let micEnabled = DeviceStore.shared.get("glasses", "micEnabled") as? Bool ?? false
3438
+ if micEnabled {
3439
+ restartMic()
3440
+ }
3441
+ return
3442
+ }
3443
+ // do nothing this time since we just closed the dashboard
3444
+ dashboardShowing -= 1
3445
+ if (dashboardShowing < 0) {
3446
+ dashboardShowing = 0
3447
+ }
3448
+ }
3388
3449
  }
3389
3450
 
3390
3451
  // if we got 08011097012200 that means we selected a menu item:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentra/bluetooth-sdk",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "SDK for communicating with smart glasses",
5
5
  "main": "build/index.js",
6
6
  "react-native": "src/index.ts",
@@ -728,6 +728,10 @@ export interface Device {
728
728
  name: string
729
729
  /** Platform address/identifier when available: Android Bluetooth address, iOS CoreBluetooth identifier. */
730
730
  address?: string
731
+ /**
732
+ * Optional scan signal strength. It may be undefined at first discovery and
733
+ * appear in a later scan update when the platform reports RSSI metadata.
734
+ */
731
735
  rssi?: number
732
736
  }
733
737
 
@@ -466,6 +466,9 @@ NativeBluetoothSdkModule.scan = async function (
466
466
  }
467
467
 
468
468
  const handleBluetoothStatus = (status: Partial<BluetoothStatus>) => {
469
+ if (!Array.isArray(status.searchResults)) {
470
+ return
471
+ }
469
472
  emitResults(searchResultsForModel(status, scanOptions.model))
470
473
  }
471
474