@mentra/bluetooth-sdk 0.1.10 → 0.1.11

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 (36) hide show
  1. package/README.md +1 -1
  2. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +39 -16
  3. package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +14 -0
  4. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +22 -3
  5. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +8 -0
  6. package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +2 -1
  7. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +829 -643
  8. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +40 -64
  9. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +11 -1
  10. package/build/BluetoothSdk.types.d.ts +12 -1
  11. package/build/BluetoothSdk.types.d.ts.map +1 -1
  12. package/build/BluetoothSdk.types.js.map +1 -1
  13. package/build/_private/BluetoothSdkModule.d.ts +1 -0
  14. package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
  15. package/build/_private/BluetoothSdkModule.js +14 -1
  16. package/build/_private/BluetoothSdkModule.js.map +1 -1
  17. package/build/index.d.ts +1 -1
  18. package/build/index.d.ts.map +1 -1
  19. package/build/index.js +2 -0
  20. package/build/index.js.map +1 -1
  21. package/ios/BluetoothSdkModule.swift +3 -0
  22. package/ios/Source/Bridge.swift +10 -0
  23. package/ios/Source/DeviceManager.swift +24 -21
  24. package/ios/Source/DeviceStore.swift +8 -2
  25. package/ios/Source/camera/CameraModels.swift +1 -0
  26. package/ios/Source/sgcs/G1.swift +3 -3
  27. package/ios/Source/sgcs/G2.swift +1022 -640
  28. package/ios/Source/sgcs/Mach1.swift +2 -2
  29. package/ios/Source/sgcs/MentraLive.swift +2 -2
  30. package/ios/Source/sgcs/MentraNex.swift +215 -85
  31. package/ios/Source/sgcs/SGCManager.swift +13 -4
  32. package/ios/Source/sgcs/Simulated.swift +2 -2
  33. package/package.json +1 -1
  34. package/src/BluetoothSdk.types.ts +13 -1
  35. package/src/_private/BluetoothSdkModule.ts +22 -3
  36. package/src/index.ts +3 -0
@@ -241,6 +241,7 @@ struct ViewState {
241
241
  get { DeviceStore.shared.get("bluetooth", "shouldSendBootingMessage") as? Bool ?? true }
242
242
  set { DeviceStore.shared.apply("bluetooth", "shouldSendBootingMessage", newValue) }
243
243
  }
244
+
244
245
  private var lastSystemTimeSyncConnectionKey = ""
245
246
 
246
247
  private var systemMicUnavailable: Bool {
@@ -564,7 +565,7 @@ struct ViewState {
564
565
  // Check if we've completed all cycles
565
566
  if cycles >= totalCycles {
566
567
  // End animation with final message
567
- sgc?.sendTextWall(" /// MentraOS Connected \\\\\\")
568
+ Task { await sgc?.sendTextWall(" /// MentraOS Connected \\\\\\") }
568
569
  animationQueue.asyncAfter(deadline: .now() + 1.0) {
569
570
  self.sgc?.clearDisplay()
570
571
  }
@@ -574,7 +575,7 @@ struct ViewState {
574
575
  // Display current animation frame
575
576
  let frameText =
576
577
  " \(arrowFrames[frameIndex]) MentraOS Booting \(arrowFrames[frameIndex])"
577
- sgc?.sendTextWall(frameText)
578
+ Task { await sgc?.sendTextWall(frameText) }
578
579
 
579
580
  // Move to next frame
580
581
  frameIndex = (frameIndex + 1) % arrowFrames.count
@@ -692,20 +693,20 @@ struct ViewState {
692
693
  switch layoutType {
693
694
  case "text_wall":
694
695
  let text = currentViewState.text
695
- sgc?.sendTextWall(text)
696
+ await sgc?.sendTextWall(text)
696
697
  case "double_text_wall":
697
698
  let topText = currentViewState.topText
698
699
  let bottomText = currentViewState.bottomText
699
- sgc?.sendDoubleTextWall(topText, bottomText)
700
+ await sgc?.sendDoubleTextWall(topText, bottomText)
700
701
  case "reference_card":
701
- sgc?.sendTextWall(currentViewState.title + "\n\n" + currentViewState.text)
702
+ await sgc?.sendTextWall(currentViewState.title + "\n\n" + currentViewState.text)
702
703
  case "bitmap_view":
703
- Bridge.log("MAN: Processing bitmap_view layout")
704
+ // Bridge.log("MAN: Processing bitmap_view layout")
704
705
  guard let data = currentViewState.data else {
705
706
  Bridge.log("MAN: ERROR: bitmap_view missing data field")
706
707
  return
707
708
  }
708
- Bridge.log("MAN: Processing bitmap_view with base64 data, length: \(data.count)")
709
+ // Bridge.log("MAN: Processing bitmap_view with base64 data, length: \(data.count)")
709
710
  await sgc?.displayBitmap(
710
711
  base64ImageData: data,
711
712
  x: currentViewState.bmpX,
@@ -890,11 +891,24 @@ struct ViewState {
890
891
 
891
892
  let connectionKey = "\(sgc.type):\(deviceName)"
892
893
  syncSystemTimeOnceForConnection(sgc, connectionKey: connectionKey)
894
+
895
+ // re-apply display height/depth after reconnection
896
+ DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
897
+ // Re-read the current sgc rather than capturing the connect-time instance: the user may
898
+ // have disconnected or switched glasses during the 2s window, and we must not push to a
899
+ // stale/torn-down connection.
900
+ guard let sgc = self?.sgc else { return }
901
+ let h = DeviceStore.shared.get("bluetooth", "dashboard_height") as? Int ?? 4
902
+ // Fall back to the canonical default (2), matching DeviceStore — not 1.
903
+ let rawDepth = DeviceStore.shared.get("bluetooth", "dashboard_depth") as? Int ?? 2
904
+ let d = min(max(rawDepth, 1), 4)
905
+ sgc.setDashboardPosition(h, d)
906
+ }
893
907
 
894
908
  // Show welcome message on first connect for all display glasses
895
909
  if shouldSendBootingMessage {
896
910
  Task {
897
- sgc.sendTextWall("// MentraOS Connected")
911
+ await sgc.sendTextWall("// MentraOS Connected")
898
912
  try? await Task.sleep(nanoseconds: 3_000_000_000) // 1 second
899
913
  sgc.clearDisplay()
900
914
  }
@@ -920,17 +934,6 @@ struct ViewState {
920
934
  Bridge.saveSetting("device_name", deviceName)
921
935
  Bridge.saveSetting("device_address", deviceAddress)
922
936
 
923
- // Re-apply display height after reconnection
924
- let h = DeviceStore.shared.get("bluetooth", "dashboard_height") as? Int ?? 4
925
- #if !SWIFT_PACKAGE || MENTRA_FEATURE_NEX
926
- let d = NexDashboardDisplayWire.clampDepthFromStore(
927
- DeviceStore.shared.get("bluetooth", "dashboard_depth")
928
- )
929
- #else
930
- let rawDepth = DeviceStore.shared.get("bluetooth", "dashboard_depth") as? Int ?? 1
931
- let d = min(max(rawDepth, 1), 4)
932
- #endif
933
- sgc.setDashboardPosition(h, d)
934
937
  }
935
938
 
936
939
  private func syncSystemTimeOnceForConnection(_ sgc: SGCManager, connectionKey: String) {
@@ -1006,7 +1009,7 @@ struct ViewState {
1006
1009
  }
1007
1010
 
1008
1011
  Bridge.log("MAN: Displaying text: \(text)")
1009
- sgc?.sendTextWall(text)
1012
+ Task { await sgc?.sendTextWall(text) }
1010
1013
  }
1011
1014
 
1012
1015
  func displayEvent(_ event: [String: Any]) {
@@ -1096,7 +1099,7 @@ struct ViewState {
1096
1099
  }
1097
1100
 
1098
1101
  func showNotificationsPanel() {
1099
- sgc?.showNotificationsPanel()
1102
+ Task { await sgc?.showNotificationsPanel() }
1100
1103
  }
1101
1104
 
1102
1105
  func ping() {
@@ -84,6 +84,7 @@ class DeviceStore {
84
84
  store.set("bluetooth", "dashboard_height", 4)
85
85
  store.set("bluetooth", "dashboard_depth", 2)
86
86
  store.set("bluetooth", "head_up_angle", 30)
87
+ store.set("bluetooth", "imu_enabled", false)
87
88
  store.set("bluetooth", "contextual_dashboard", true)
88
89
  store.set("bluetooth", "gallery_mode", true)
89
90
  store.set("bluetooth", "voice_activity_detection_enabled", BluetoothSdkDefaults.voiceActivityDetectionEnabled)
@@ -186,7 +187,7 @@ class DeviceStore {
186
187
  let auto = store.get("bluetooth", "auto_brightness") as? Bool ?? true
187
188
  Task {
188
189
  DeviceManager.shared.sgc?.setBrightness(b, autoMode: auto)
189
- DeviceManager.shared.sgc?.sendTextWall("Set brightness to \(b)%")
190
+ await DeviceManager.shared.sgc?.sendTextWall("Set brightness to \(b)%")
190
191
  try? await Task.sleep(nanoseconds: 800_000_000) // 0.8 seconds
191
192
  DeviceManager.shared.sgc?.clearDisplay()
192
193
  }
@@ -198,7 +199,7 @@ class DeviceStore {
198
199
  Task {
199
200
  DeviceManager.shared.sgc?.setBrightness(b, autoMode: auto)
200
201
  if autoBrightnessChanged {
201
- DeviceManager.shared.sgc?.sendTextWall(
202
+ await DeviceManager.shared.sgc?.sendTextWall(
202
203
  auto ? "Enabled auto brightness" : "Disabled auto brightness"
203
204
  )
204
205
  try? await Task.sleep(nanoseconds: 800_000_000) // 0.8 seconds
@@ -217,6 +218,11 @@ class DeviceStore {
217
218
  DeviceManager.shared.sgc?.setHeadUpAngle(angle)
218
219
  }
219
220
 
221
+ case ("bluetooth", "imu_enabled"):
222
+ if let enabled = value as? Bool {
223
+ Task { await DeviceManager.shared.sgc?.setImuEnabled(enabled) }
224
+ }
225
+
220
226
  case ("bluetooth", "menu_apps"):
221
227
  if let items = value as? [[String: Any]] {
222
228
  DeviceManager.shared.sgc?.setDashboardMenu(items)
@@ -11,6 +11,7 @@ public enum ButtonPhotoSize: String {
11
11
  case small
12
12
  case medium
13
13
  case large
14
+ case max
14
15
  }
15
16
 
16
17
  public enum PhotoCompression: String {
@@ -786,7 +786,7 @@ class G1: NSObject, SGCManager {
786
786
  // }
787
787
  }
788
788
 
789
- func sendTextWall(_ text: String) {
789
+ func sendTextWall(_ text: String) async {
790
790
  let chunks = textHelper.createTextWallChunks(text)
791
791
  queueChunks(chunks, sleepAfterMs: 10)
792
792
  }
@@ -799,7 +799,7 @@ class G1: NSObject, SGCManager {
799
799
  }
800
800
  }
801
801
 
802
- func sendDoubleTextWall(_ top: String, _ bottom: String) {
802
+ func sendDoubleTextWall(_ top: String, _ bottom: String) async {
803
803
  let chunks = textHelper.createDoubleTextWallChunks(textTop: top, textBottom: bottom)
804
804
  queueChunks(chunks, sleepAfterMs: 10)
805
805
 
@@ -1886,7 +1886,7 @@ extension G1 {
1886
1886
 
1887
1887
  func clearDisplay() {
1888
1888
  Bridge.log("G1: clearDisplay() - Using space")
1889
- sendTextWall(" ")
1889
+ Task { await sendTextWall(" ") }
1890
1890
  }
1891
1891
 
1892
1892
  /// Create a simple test BMP pattern in hex format