@mentra/bluetooth-sdk 3.2.1-dev.314 → 3.3.0-beta.942
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.
- package/README.md +72 -10
- package/android/build.gradle +15 -0
- package/android/lc3Lib/build.gradle +6 -1
- package/android/src/debug/java/com/mentra/bluetoothsdk/sgcs/NimoDiagnostics.kt +368 -0
- package/android/src/debug/java/com/mentra/bluetoothsdk/sgcs/NimoFramebufferProtocol.kt +156 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkAnalytics.kt +63 -14
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkAnalyticsTracker.kt +55 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkDefaults.kt +4 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkInstallId.kt +23 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +8 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkUpdateCheck.kt +184 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkUsageTracker.kt +388 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +2 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +133 -26
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +37 -13
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedChangelogCatalog.kt +3 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +6 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +227 -36
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraLocalNetworkModule.kt +24 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/NetworkDiagnostics.kt +25 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/VersionInfoResponseAccumulator.kt +13 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/debug/BleTraceLogger.kt +3 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/requests/DisplayRequests.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/services/Foreground.kt +33 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/services/G2ConnectionRecovery.kt +47 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ClassicAudioConnectionTracker.kt +4 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ClassicAudioServiceDiscovery.kt +70 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.kt +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1TextSanitizer.kt +11 -32
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +72 -21
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/LatinTextSanitizer.kt +39 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +194 -40
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +12 -8
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Nimo.kt +314 -395
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasCodec.kt +247 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasCoordinator.kt +238 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasEncoder.kt +58 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasSession.kt +180 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +11 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SelectedDeviceAddress.kt +17 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SerializedGattCallback.kt +5 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/G2Text.kt +7 -0
- package/android/src/release/java/com/mentra/bluetoothsdk/sgcs/NimoDiagnostics.kt +20 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/BluetoothSdkAnalyticsTrackerTest.kt +58 -3
- package/android/src/test/java/com/mentra/bluetoothsdk/BluetoothSdkUpdateCheckTest.kt +124 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/BluetoothSdkUsageTrackerTest.kt +263 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/DashboardContentFormatterTest.kt +2 -2
- package/android/src/test/java/com/mentra/bluetoothsdk/DeviceIdentityPairingTest.kt +59 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/DeviceManagerSceneHandoffTest.kt +666 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/G2TextTest.kt +13 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/NetworkDiagnosticsTest.kt +55 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/ScanCompletionTest.kt +5 -1
- package/android/src/test/java/com/mentra/bluetoothsdk/VersionInfoResponseAccumulatorTest.kt +71 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/debug/BleTraceLoggerTest.kt +69 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/services/G2ConnectionRecoveryTest.kt +51 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/ClassicAudioServiceDiscoveryTest.kt +124 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/G1PairingTest.kt +105 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/G1TextSanitizerTest.kt +29 -4
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/G2DisplayThreadTest.kt +120 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/G2PairingTargetTest.kt +90 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveClassicDisconnectTest.kt +133 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveFileTransferSessionTest.kt +55 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveGattCallbackTest.kt +33 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveIncidentDispatchTest.kt +126 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLivePairingTargetTest.kt +65 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveWifiCredentialLogTest.kt +55 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraNexPairingTest.kt +151 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoBitmapAcceptanceTest.kt +105 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasCodecTest.kt +233 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasCoordinatorTest.kt +348 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoCanvasSessionTest.kt +339 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoMicReconnectTest.kt +93 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/NimoProtocolTest.kt +11 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/SelectedDeviceAddressTest.kt +27 -0
- package/android/src/testDebug/java/com/mentra/bluetoothsdk/sgcs/NimoDiagnosticsTest.kt +287 -0
- package/android/src/testDebug/java/com/mentra/bluetoothsdk/sgcs/NimoFramebufferProtocolTest.kt +127 -0
- package/android/src/testDebug/java/com/mentra/bluetoothsdk/sgcs/NimoLifecycleTest.kt +288 -0
- package/android/src/testDebug/java/com/mentra/bluetoothsdk/sgcs/NimoReadinessDriverTest.kt +205 -0
- package/build/BluetoothSdk.types.d.ts +16 -0
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js +1 -0
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +4 -0
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +5 -1
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/_private/MentraLocalNetworkModule.d.ts +23 -0
- package/build/_private/MentraLocalNetworkModule.d.ts.map +1 -1
- package/build/_private/MentraLocalNetworkModule.js.map +1 -1
- package/build/_private/nativeLogConsole.d.ts +19 -0
- package/build/_private/nativeLogConsole.d.ts.map +1 -1
- package/build/_private/nativeLogConsole.js +12 -0
- package/build/_private/nativeLogConsole.js.map +1 -1
- package/build/generated/changelogCatalog.d.ts +5 -2
- package/build/generated/changelogCatalog.d.ts.map +1 -1
- package/build/generated/changelogCatalog.js +6 -2
- package/build/generated/changelogCatalog.js.map +1 -1
- package/build/generated/releaseMetadata.js +6 -6
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/ota-transport/index.d.ts +4 -0
- package/build/ota-transport/index.d.ts.map +1 -1
- package/build/ota-transport/index.js +2 -0
- package/build/ota-transport/index.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +17 -4
- package/ios/MentraBluetoothSDK.podspec +3 -2
- package/ios/Source/BluetoothBackgroundMode.swift +32 -0
- package/ios/Source/BluetoothSdkDefaults.swift +7 -2
- package/ios/Source/Bridge.swift +15 -2
- package/ios/Source/DeviceManager.swift +102 -66
- package/ios/Source/DeviceStore.swift +26 -7
- package/ios/Source/GeneratedChangelogCatalog.swift +3 -2
- package/ios/Source/GeneratedReleaseMetadata.swift +6 -6
- package/ios/Source/MentraBluetoothSDK.swift +313 -54
- package/ios/Source/audio/GlassesMicWatchdog.swift +33 -0
- package/ios/Source/internal/BluetoothAvailability.swift +6 -0
- package/ios/Source/internal/BluetoothSdkAnalytics.swift +87 -13
- package/ios/Source/internal/BluetoothSdkAnalyticsTracker.swift +54 -1
- package/ios/Source/internal/BluetoothSdkInstallId.swift +21 -0
- package/ios/Source/internal/BluetoothSdkUpdateCheck.swift +223 -0
- package/ios/Source/internal/BluetoothSdkUsageTracker.swift +428 -0
- package/ios/Source/requests/DisplayRequests.swift +1 -1
- package/ios/Source/requests/VersionInfoResponseAccumulator.swift +11 -1
- package/ios/Source/sgcs/Ar99.swift +1 -2
- package/ios/Source/sgcs/G1.swift +68 -38
- package/ios/Source/sgcs/G1ConnectionTarget.swift +13 -0
- package/ios/Source/sgcs/G2.swift +261 -247
- package/ios/Source/sgcs/G2ConnectionSession.swift +101 -0
- package/ios/Source/sgcs/Mach1.swift +19 -7
- package/ios/Source/sgcs/MentraLive.swift +272 -197
- package/ios/Source/sgcs/MentraLiveFileTransferSession.swift +137 -0
- package/ios/Source/sgcs/MentraLivePairingAdvertisement.swift +47 -0
- package/ios/Source/sgcs/MentraNex.swift +8 -31
- package/ios/Source/sgcs/NexConnectionTarget.swift +15 -0
- package/ios/Source/sgcs/Nimo.swift +280 -408
- package/ios/Source/sgcs/NimoCanvasCodec.swift +272 -0
- package/ios/Source/sgcs/NimoCanvasCoordinator.swift +233 -0
- package/ios/Source/sgcs/NimoCanvasImage.swift +53 -0
- package/ios/Source/sgcs/NimoCanvasSession.swift +166 -0
- package/ios/Source/sgcs/NimoDiscovery.swift +49 -0
- package/ios/Source/sgcs/SGCManager.swift +25 -1
- package/ios/Source/sgcs/VuzixConnectionTarget.swift +15 -0
- package/ios/Source/status/DeviceStatus.swift +1 -0
- package/ios/Source/stt/SherpaOnnxTranscriber.swift +49 -189
- package/ios/Source/utils/AudioSessionMonitor.swift +44 -8
- package/ios/Source/utils/DemandDrivenAudioWorker.swift +150 -0
- package/ios/Source/utils/G1Text.swift +2 -24
- package/ios/Source/utils/G1TextSanitizer.swift +27 -0
- package/ios/Source/utils/G2Text.swift +11 -0
- package/ios/Source/utils/LatinTextSanitizer.swift +48 -0
- package/ios/Tests/BluetoothAudioRouteTests.swift +26 -0
- package/ios/Tests/BluetoothBackgroundModeTests.swift +32 -0
- package/ios/Tests/BluetoothSdkAnalyticsTrackerTests.swift +54 -3
- package/ios/Tests/BluetoothSdkUpdateCheckTests.swift +153 -0
- package/ios/Tests/BluetoothSdkUsageTrackerTests.swift +296 -0
- package/ios/Tests/DashboardContentFormatterTests.swift +2 -2
- package/ios/Tests/DashboardRenderingTests.swift +31 -0
- package/ios/Tests/DemandDrivenAudioWorkerTests.swift +157 -0
- package/ios/Tests/DeviceIdentityPairingTests.swift +49 -0
- package/ios/Tests/DeviceManagerReconnectTests.swift +362 -0
- package/ios/Tests/G1PairingTests.swift +162 -0
- package/ios/Tests/G1TextSanitizerTests.swift +32 -0
- package/ios/Tests/G2ConnectionSessionTests.swift +172 -0
- package/ios/Tests/G2TextTests.swift +10 -0
- package/ios/Tests/IncidentLogDispatchTests.swift +111 -0
- package/ios/Tests/MentraLiveFileTransferSessionTests.swift +47 -0
- package/ios/Tests/MentraLiveReconnectPolicyTests.swift +58 -0
- package/ios/Tests/MentraLiveSessionReadinessTests.swift +163 -0
- package/ios/Tests/NimoCanvasCodecTests.swift +217 -0
- package/ios/Tests/NimoCanvasSessionTests.swift +181 -0
- package/ios/Tests/NimoCanvasTransportTests.swift +186 -0
- package/ios/Tests/NimoDeviceCommandsTests.swift +16 -0
- package/ios/Tests/NimoDiscoveryTests.swift +79 -0
- package/ios/Tests/SGCConnectionTargetTests.swift +48 -0
- package/ios/Tests/VersionInfoCommandTests.swift +194 -0
- package/ios/Tests/VersionInfoResponseAccumulatorTests.swift +65 -0
- package/ios/Tests/VideoRecordingCommandTests.swift +81 -0
- package/ios/Tests/WifiCredentialLoggingTests.swift +42 -0
- package/package.json +2 -2
- package/plugin/build/withIos.d.ts +2 -0
- package/plugin/build/withIos.js +12 -1
- package/src/BluetoothSdk.types.ts +15 -0
- package/src/_private/BluetoothSdkModule.ts +10 -1
- package/src/_private/MentraLocalNetworkModule.ts +28 -0
- package/src/_private/nativeLogConsole.ts +19 -0
- package/src/generated/changelogCatalog.ts +6 -2
- package/src/generated/releaseMetadata.ts +6 -6
- package/src/index.ts +1 -0
- package/src/ota-transport/index.ts +10 -1
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Readiness belongs to an authenticated pair and a completed initialization attempt, never to
|
|
4
|
+
/// a gesture from one arm. A generation retires asynchronous setup when either arm is lost.
|
|
5
|
+
struct G2ConnectionSession {
|
|
6
|
+
enum Side: String, CaseIterable {
|
|
7
|
+
case left = "L"
|
|
8
|
+
case right = "R"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
private(set) var generation: UInt64 = 0
|
|
12
|
+
private var initialized: Set<Side> = []
|
|
13
|
+
private var authenticatedSides: Set<Side> = []
|
|
14
|
+
private var authStarted = false
|
|
15
|
+
private var setupComplete = false
|
|
16
|
+
|
|
17
|
+
var isReady: Bool {
|
|
18
|
+
initialized.count == 2 && authenticatedSides.count == 2 && setupComplete
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func needsRecovery(attempt: UInt64) -> Bool {
|
|
22
|
+
generation == attempt && !isReady
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
mutating func initialize(_ side: Side) {
|
|
26
|
+
initialized.insert(side)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
mutating func beginAuthentication() -> UInt64? {
|
|
30
|
+
guard initialized.count == 2, !authStarted else { return nil }
|
|
31
|
+
authStarted = true
|
|
32
|
+
return generation
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
mutating func authenticated(_ side: Side, success: Bool) {
|
|
36
|
+
guard authStarted else { return }
|
|
37
|
+
if success { authenticatedSides.insert(side) }
|
|
38
|
+
else { authenticatedSides.remove(side) }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
mutating func completeSetup(generation: UInt64) {
|
|
42
|
+
guard self.generation == generation, authStarted else { return }
|
|
43
|
+
setupComplete = true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
mutating func reset() {
|
|
47
|
+
generation &+= 1
|
|
48
|
+
initialized.removeAll()
|
|
49
|
+
authenticatedSides.removeAll()
|
|
50
|
+
authStarted = false
|
|
51
|
+
setupComplete = false
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
enum G2ConnectionTarget {
|
|
56
|
+
/// A serial-scoped cached UUID identifies an arm even without a new advertisement. Nearby
|
|
57
|
+
/// arms can share the G2_32 name fragment; only an advertisement's serial can select an
|
|
58
|
+
/// uncached arm. Never fall back to names alone or another pair's cached identifiers.
|
|
59
|
+
static func side(
|
|
60
|
+
identifier: UUID, name: String?, advertisedSerial: String?, searchID: String,
|
|
61
|
+
leftUUID: UUID?, rightUUID: UUID?
|
|
62
|
+
) -> G2ConnectionSession.Side? {
|
|
63
|
+
guard !searchID.isEmpty, searchID != "NOT_SET" else { return nil }
|
|
64
|
+
if identifier == leftUUID, identifier == rightUUID { return nil }
|
|
65
|
+
if identifier == leftUUID { return .left }
|
|
66
|
+
if identifier == rightUUID { return .right }
|
|
67
|
+
guard let advertisedSerial, advertisedSerial.contains(searchID), let name else { return nil }
|
|
68
|
+
if name.contains("_L_") { return .left }
|
|
69
|
+
if name.contains("_R_") { return .right }
|
|
70
|
+
return nil
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// Normal pairing connects the arms sequentially. Surface a missing arm only after the
|
|
75
|
+
/// same partial link has persisted for three seconds, using monotonic time.
|
|
76
|
+
struct G2PartialConnection {
|
|
77
|
+
static let noticeDelay: TimeInterval = 3
|
|
78
|
+
private(set) var missingSide: G2ConnectionSession.Side?
|
|
79
|
+
private var partialSince: TimeInterval = 0
|
|
80
|
+
|
|
81
|
+
mutating func update(leftConnected: Bool, rightConnected: Bool, now: TimeInterval) {
|
|
82
|
+
let missing: G2ConnectionSession.Side? = leftConnected == rightConnected
|
|
83
|
+
? nil : (leftConnected ? .right : .left)
|
|
84
|
+
if missing != missingSide {
|
|
85
|
+
missingSide = missing
|
|
86
|
+
partialSince = now
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
func visibleMissingSide(now: TimeInterval) -> G2ConnectionSession.Side? {
|
|
91
|
+
now - partialSince >= Self.noticeDelay ? missingSide : nil
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
var timeoutError: String {
|
|
95
|
+
switch missingSide {
|
|
96
|
+
case .left: "errors:g2LeftArmUnavailable"
|
|
97
|
+
case .right: "errors:g2RightArmUnavailable"
|
|
98
|
+
case nil: "errors:g2ConnectionTimedOut"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -133,6 +133,15 @@ class Mach1: UltraliteBaseViewController, SGCManager {
|
|
|
133
133
|
|
|
134
134
|
/// Store discovered peripherals by their identifier
|
|
135
135
|
private var discoveredPeripherals: [String: CBPeripheral] = [:]
|
|
136
|
+
private var selectedPeripheralID: String?
|
|
137
|
+
|
|
138
|
+
private var currentDeviceMatchesSelection: Bool {
|
|
139
|
+
guard let selectedPeripheralID else { return true }
|
|
140
|
+
let currentDevice = UltraliteManager.shared.currentDevice
|
|
141
|
+
return VuzixConnectionTarget.matches(
|
|
142
|
+
name: currentDevice?.peripheral?.name ?? currentDevice?.getName(), target: selectedPeripheralID
|
|
143
|
+
)
|
|
144
|
+
}
|
|
136
145
|
|
|
137
146
|
private var textHandle: Int?
|
|
138
147
|
private var tapTextHandle: Int?
|
|
@@ -146,6 +155,7 @@ class Mach1: UltraliteBaseViewController, SGCManager {
|
|
|
146
155
|
if setupDone { return }
|
|
147
156
|
isConnectedListener = BondListener(listener: { [weak self] value in
|
|
148
157
|
guard let self else { return }
|
|
158
|
+
guard !value || self.currentDeviceMatchesSelection else { return }
|
|
149
159
|
Bridge.log("MACH1: isConnectedListener: \(value)")
|
|
150
160
|
|
|
151
161
|
if value {
|
|
@@ -171,6 +181,7 @@ class Mach1: UltraliteBaseViewController, SGCManager {
|
|
|
171
181
|
|
|
172
182
|
batteryLevelListener = BondListener(listener: { [weak self] value in
|
|
173
183
|
guard let self else { return }
|
|
184
|
+
guard self.currentDeviceMatchesSelection else { return }
|
|
174
185
|
Bridge.log("MACH1: batteryLevelListener: \(value)")
|
|
175
186
|
batteryLevel = value
|
|
176
187
|
DeviceStore.shared.apply("glasses", "batteryLevel", value)
|
|
@@ -238,23 +249,22 @@ class Mach1: UltraliteBaseViewController, SGCManager {
|
|
|
238
249
|
|
|
239
250
|
// Extract the ID from the device name if it contains brackets
|
|
240
251
|
// e.g., "Vuzix Z100 [f1b87c]" -> "f1b87c"
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
peripheralId = String(deviceId)
|
|
244
|
-
}
|
|
252
|
+
let peripheralId = VuzixConnectionTarget.identifier(id)
|
|
253
|
+
selectedPeripheralID = peripheralId
|
|
245
254
|
|
|
246
255
|
let isLinked = UltraliteManager.shared.isLinked.value
|
|
247
256
|
let currentDevice = UltraliteManager.shared.currentDevice
|
|
248
257
|
let isConnected =
|
|
249
258
|
isLinked && currentDevice != nil && currentDevice!.isPaired
|
|
250
259
|
&& currentDevice!.isConnected.value
|
|
251
|
-
let
|
|
260
|
+
let matchesSelection = currentDeviceMatchesSelection
|
|
261
|
+
let peripheral = discoveredPeripherals[peripheralId] ?? (matchesSelection ? currentDevice?.peripheral : nil)
|
|
252
262
|
|
|
253
263
|
// Bind listeners to get notified when device connects
|
|
254
264
|
UltraliteManager.shared.currentDevice?.isConnected.bind(listener: isConnectedListener!)
|
|
255
265
|
UltraliteManager.shared.currentDevice?.batteryLevel.bind(listener: batteryLevelListener!)
|
|
256
266
|
|
|
257
|
-
if isConnected {
|
|
267
|
+
if isConnected && matchesSelection {
|
|
258
268
|
// Already connected, request control now
|
|
259
269
|
let gotControl = currentDevice?.requestControl(
|
|
260
270
|
layout: UltraliteSDK.Ultralite.Layout.textBottomLeftAlign, timeout: 0,
|
|
@@ -266,7 +276,7 @@ class Mach1: UltraliteBaseViewController, SGCManager {
|
|
|
266
276
|
return
|
|
267
277
|
}
|
|
268
278
|
|
|
269
|
-
if !isLinked {
|
|
279
|
+
if !isLinked || !matchesSelection {
|
|
270
280
|
if peripheral == nil {
|
|
271
281
|
Bridge.log("Mach1Manager: No peripheral found or stored with ID: \(peripheralId)")
|
|
272
282
|
CONNECTING_DEVICE = peripheralId
|
|
@@ -279,6 +289,8 @@ class Mach1: UltraliteBaseViewController, SGCManager {
|
|
|
279
289
|
UltraliteManager.shared.stopScan()
|
|
280
290
|
CONNECTING_DEVICE = ""
|
|
281
291
|
|
|
292
|
+
// Replace the SDK link only after finding the explicitly selected device.
|
|
293
|
+
if isLinked { UltraliteManager.shared.unlink() }
|
|
282
294
|
UltraliteManager.shared.link(device: peripheral!, callback: linked)
|
|
283
295
|
UltraliteManager.shared.currentDevice?.isConnected.bind(listener: isConnectedListener!)
|
|
284
296
|
UltraliteManager.shared.currentDevice?.batteryLevel.bind(
|