@mentra/bluetooth-sdk 3.3.0-dev.517 → 3.3.0-dev.523

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 (50) hide show
  1. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +2 -0
  2. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +55 -10
  3. package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +5 -5
  4. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Nimo.kt +63 -6
  5. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasCoordinator.kt +26 -13
  6. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasSession.kt +31 -19
  7. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SerializedGattCallback.kt +5 -0
  8. package/android/src/test/java/com/mentra/bluetoothsdk/DeviceManagerSceneHandoffTest.kt +111 -2
  9. package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveGattCallbackTest.kt +33 -0
  10. package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasCoordinatorTest.kt +44 -4
  11. package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasSessionTest.kt +82 -13
  12. package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoMicReconnectTest.kt +93 -0
  13. package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoProtocolTest.kt +11 -0
  14. package/android/src/testDebug/java/com/mentra/bluetoothsdk/sgcs/NimoLifecycleTest.kt +94 -0
  15. package/android/src/testDebug/java/com/mentra/bluetoothsdk/sgcs/NimoReadinessDriverTest.kt +15 -9
  16. package/build/BluetoothSdk.types.d.ts +2 -0
  17. package/build/BluetoothSdk.types.d.ts.map +1 -1
  18. package/build/BluetoothSdk.types.js +1 -0
  19. package/build/BluetoothSdk.types.js.map +1 -1
  20. package/build/_private/BluetoothSdkModule.d.ts +2 -0
  21. package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
  22. package/build/_private/BluetoothSdkModule.js.map +1 -1
  23. package/build/generated/releaseMetadata.js +5 -5
  24. package/build/generated/releaseMetadata.js.map +1 -1
  25. package/ios/BluetoothSdkModule.swift +4 -0
  26. package/ios/Source/BluetoothSdkDefaults.swift +1 -1
  27. package/ios/Source/DeviceManager.swift +66 -50
  28. package/ios/Source/GeneratedReleaseMetadata.swift +5 -5
  29. package/ios/Source/audio/GlassesMicWatchdog.swift +33 -0
  30. package/ios/Source/sgcs/Ar99.swift +1 -2
  31. package/ios/Source/sgcs/G2.swift +259 -245
  32. package/ios/Source/sgcs/G2ConnectionSession.swift +101 -0
  33. package/ios/Source/sgcs/Nimo.swift +104 -43
  34. package/ios/Source/sgcs/NimoCanvasCoordinator.swift +20 -6
  35. package/ios/Source/sgcs/NimoCanvasSession.swift +30 -14
  36. package/ios/Source/sgcs/NimoDiscovery.swift +49 -0
  37. package/ios/Source/status/DeviceStatus.swift +1 -0
  38. package/ios/Source/stt/SherpaOnnxTranscriber.swift +49 -189
  39. package/ios/Source/utils/DemandDrivenAudioWorker.swift +150 -0
  40. package/ios/Tests/DemandDrivenAudioWorkerTests.swift +157 -0
  41. package/ios/Tests/DeviceManagerReconnectTests.swift +362 -0
  42. package/ios/Tests/G2ConnectionSessionTests.swift +172 -0
  43. package/ios/Tests/NimoCanvasSessionTests.swift +74 -5
  44. package/ios/Tests/NimoCanvasTransportTests.swift +25 -0
  45. package/ios/Tests/NimoDeviceCommandsTests.swift +16 -0
  46. package/ios/Tests/NimoDiscoveryTests.swift +79 -0
  47. package/package.json +2 -2
  48. package/src/BluetoothSdk.types.ts +3 -0
  49. package/src/_private/BluetoothSdkModule.ts +2 -0
  50. package/src/generated/releaseMetadata.ts +5 -5
@@ -0,0 +1,79 @@
1
+ @testable import MentraBluetoothSDK
2
+ import XCTest
3
+
4
+ @MainActor
5
+ final class NimoDiscoveryTests: XCTestCase {
6
+ @MainActor
7
+ private final class Radio {
8
+ var connected: [String] = []
9
+ var events: [String] = []
10
+ var found: [String] = []
11
+ var selected: String?
12
+ lazy var discovery: NimoDiscovery<String> = NimoDiscovery(
13
+ register: { [unowned self] in self.events.append("register") },
14
+ connected: { [unowned self] in self.events.append("retrieve"); return self.connected },
15
+ scan: { [unowned self] in self.events.append("scan") },
16
+ stop: { [unowned self] in self.events.append("stop") },
17
+ name: { $0 },
18
+ found: { [unowned self] _, name, _ in
19
+ found.append(name)
20
+ if selected == name { discovery.cancel() }
21
+ }
22
+ )
23
+ }
24
+
25
+ func testAlreadyConnectedClassicDeviceIsFoundWithoutAdvertisement() {
26
+ let radio = Radio()
27
+ radio.connected = ["NIMO_1234", "NIMO_1234_BLE", "Unrelated"]
28
+ radio.discovery.start()
29
+ XCTAssertEqual(radio.events, ["register", "retrieve", "scan"])
30
+ XCTAssertEqual(radio.found, ["NIMO_1234"])
31
+ }
32
+
33
+ func testPairingInSettingsAfterScanStartedDeliversDevice() {
34
+ let radio = Radio()
35
+ radio.discovery.start()
36
+ XCTAssertTrue(radio.found.isEmpty)
37
+ // Same entry point as connectionEventDidOccur(.peerConnected).
38
+ radio.discovery.receive("NIMO_5678")
39
+ XCTAssertEqual(radio.found, ["NIMO_5678"])
40
+ }
41
+
42
+ func testSelectionFromConnectedSnapshotStopsBeforeStartingBleScan() {
43
+ let radio = Radio()
44
+ radio.selected = "NIMO_5678"
45
+ radio.connected = ["NIMO_1234", "NIMO_5678", "NIMO_9999"]
46
+ radio.discovery.start()
47
+ XCTAssertEqual(radio.found, ["NIMO_1234", "NIMO_5678"])
48
+ XCTAssertEqual(radio.events, ["register", "retrieve", "stop"])
49
+ XCTAssertFalse(radio.discovery.active)
50
+ }
51
+
52
+ func testCancelledDiscoveryIgnoresQueuedEventsAndCanRestart() {
53
+ let radio = Radio()
54
+ radio.discovery.start()
55
+ radio.discovery.cancel()
56
+ radio.discovery.receive("NIMO_1234")
57
+ XCTAssertTrue(radio.found.isEmpty)
58
+ radio.connected = ["NIMO_1234"]
59
+ radio.discovery.start()
60
+ XCTAssertEqual(radio.found, ["NIMO_1234"])
61
+ }
62
+
63
+ func testBleFallbackUsesAdvertisementNameAndPreservesSignalStrength() {
64
+ var found: [String] = []
65
+ var signal: Int?
66
+ let discovery = NimoDiscovery<String>(
67
+ register: {}, connected: { [] }, scan: {}, stop: {}, name: { _ in nil },
68
+ found: { _, name, rssi in found.append(name); signal = rssi }
69
+ )
70
+ discovery.start()
71
+ discovery.receive("uuid", advertisedName: "NiMo_1234_bLe", rssi: -60)
72
+ discovery.receive("uuid", advertisedName: "Unrelated", rssi: -60)
73
+ discovery.receive("uuid")
74
+ XCTAssertTrue(found.isEmpty)
75
+ discovery.receive("uuid", advertisedName: "NiMo_1234", rssi: -55)
76
+ XCTAssertEqual(found, ["NiMo_1234"])
77
+ XCTAssertEqual(signal, -55)
78
+ }
79
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentra/bluetooth-sdk",
3
- "version": "3.3.0-dev.517",
3
+ "version": "3.3.0-dev.523",
4
4
  "description": "SDK for communicating with smart glasses",
5
5
  "main": "build/index.js",
6
6
  "react-native": "src/index.ts",
@@ -114,7 +114,7 @@
114
114
  "registry": "https://registry.npmjs.org/"
115
115
  },
116
116
  "dependencies": {
117
- "@mentra/cloud-protocol": "3.3.0-dev.517"
117
+ "@mentra/cloud-protocol": "3.3.0-dev.523"
118
118
  },
119
119
  "devDependencies": {
120
120
  "@types/node": "^25.9.3",
@@ -82,6 +82,7 @@ export function isBusyGlassesConnectionStatus(status: GlassesConnectionStatus):
82
82
  export function createDisconnectedGlassesStatus(): Partial<GlassesStatus> {
83
83
  return {
84
84
  connection: {state: "disconnected"},
85
+ g2MissingArm: null,
85
86
  hotspot: {state: "disabled"},
86
87
  voiceActivityDetectionEnabled: DEFAULT_VOICE_ACTIVITY_DETECTION_ENABLED,
87
88
  wifi: {state: "disconnected"},
@@ -1613,6 +1614,8 @@ export interface OtaProgress {
1613
1614
  }
1614
1615
 
1615
1616
  export interface GlassesStatus {
1617
+ /** iOS G2 arm still disconnected after a three-second partial link; cleared on reset or both links. */
1618
+ g2MissingArm?: "left" | "right" | null
1616
1619
  // state:
1617
1620
  connection: GlassesConnectionStatus
1618
1621
  micEnabled: boolean
@@ -109,6 +109,8 @@ declare class BluetoothSdkNativeModule extends NativeModule<BluetoothSdkModuleEv
109
109
  connectSimulated(): Promise<void>
110
110
  disconnect(): Promise<void>
111
111
  forget(): Promise<void>
112
+ /** Explicit Unpair also resets connected NIMO glasses before forgetting. */
113
+ unpair(): Promise<void>
112
114
  forgetController(): Promise<void>
113
115
  showDashboard(): Promise<void>
114
116
  setBrightness(level: number, autoMode?: boolean | null): Promise<void>
@@ -12,9 +12,9 @@ export interface BluetoothSdkReleaseMetadata {
12
12
  export const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({
13
13
  "schemaVersion": 1,
14
14
  "familyBaseVersion": "3.3.0",
15
- "releaseIdentity": "3.3.0-dev.517",
16
- "releaseSetId": "mentra-3.3.0-dev.517",
17
- "sourceCommit": "502491326581d83be54b844485a4d2ecc4ce3cad",
18
- "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.517.json",
19
- "otaManifestSha256": "6b80b713d23476fbe5bdd3ab3ba381ea3356d06ab7392228d689a1db142d8e85"
15
+ "releaseIdentity": "3.3.0-dev.523",
16
+ "releaseSetId": "mentra-3.3.0-dev.523",
17
+ "sourceCommit": "0dd41dbb1e055eb1d80fb39d26a7ba20448de657",
18
+ "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.523.json",
19
+ "otaManifestSha256": "ad3129a46a5ff8f018c80defcecc6acf88e7ab2d248d0914ed4c2eb097c3f3ec"
20
20
  })