@mentra/bluetooth-sdk 0.1.9 → 0.1.10
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 +116 -18
- package/android/build.gradle +289 -16
- package/android/gradle.properties.example +9 -0
- package/android/lc3Lib/build.gradle +95 -6
- package/android/settings.gradle +3 -0
- package/android/silero/LICENSE.md +17 -0
- package/android/silero/build.gradle +42 -0
- package/android/silero/proguard-rules.pro +24 -0
- package/android/silero/src/androidTest/assets/hello.wav +0 -0
- package/android/silero/src/androidTest/java/com/konovalov/vad/silero/VadSileroTest.kt +79 -0
- package/android/silero/src/main/assets/LICENSE +21 -0
- package/android/silero/src/main/assets/silero_vad.onnx +0 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/Vad.kt +160 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/VadSilero.kt +449 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/FrameSize.kt +15 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/Mode.kt +14 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/SampleRate.kt +12 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/AudioUtils.kt +47 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/TensorMap.kt +41 -0
- package/android/silero/src/test/java/com/konovalov/vad/silero/utils/AudioUtilsTest.kt +44 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkDefaults.kt +6 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +165 -27
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +89 -21
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +189 -16
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +22 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +787 -85
- package/android/src/main/java/com/mentra/bluetoothsdk/audio/AudioModels.kt +6 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +123 -10
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +12 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +8 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/debug/BleTraceLogger.kt +33 -17
- package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +101 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/internal/MapParsing.kt +8 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistry.java +108 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +399 -74
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/MentraPhotoReceiverModule.kt +100 -17
- package/android/src/main/java/com/mentra/bluetoothsdk/requests/DisplayRequests.kt +17 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +569 -220
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +271 -66
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +176 -104
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraosBle.java +12753 -27036
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +54 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +16 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +60 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/streaming/StreamModels.kt +12 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/STTTools.kt +87 -36
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +13 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/VadGateSpeechPolicy.kt +229 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/tts/TTSTools.kt +180 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/AvifExifStripper.java +573 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadService.java +488 -50
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/HeifExifTagReader.java +199 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunkReassembler.java +18 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunker.java +64 -18
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/NexSGCUtils.kt +48 -39
- package/android/src/test/java/com/mentra/bluetoothsdk/camera/PhotoRequestTest.kt +23 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistryTest.java +75 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/AvifExifStripperTest.java +30 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadServiceTest.java +98 -0
- package/android/src/test/resources/avif_with_exif.avif +0 -0
- package/build/BluetoothSdk.types.d.ts +241 -43
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js +11 -10
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +36 -23
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +30 -52
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/_private/photoRequestPayload.d.ts +4 -0
- package/build/_private/photoRequestPayload.d.ts.map +1 -0
- package/build/_private/photoRequestPayload.js +25 -0
- package/build/_private/photoRequestPayload.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +23 -0
- package/build/index.js.map +1 -1
- package/build/react/useMentraBluetooth.d.ts +2 -2
- package/build/react/useMentraBluetooth.d.ts.map +1 -1
- package/build/react/useMentraBluetooth.js +3 -3
- package/build/react/useMentraBluetooth.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +174 -70
- package/ios/LocalPhotoUploadServer.swift +370 -105
- package/ios/MentraBluetoothSDK.podspec +3 -1
- package/ios/MentraPhotoReceiverModule.swift +62 -10
- package/ios/Packages/CoreObjC/include/PcmConverter.h +22 -0
- package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +668 -26
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +13 -9
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/c-api.h +4551 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/cxx-api.h +1745 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/c-api.h +4551 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h +1745 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
- package/ios/Source/BluetoothSdkDefaults.swift +6 -0
- package/ios/Source/Bridge.swift +58 -19
- package/ios/Source/DeviceManager.swift +149 -17
- package/ios/Source/DeviceStore.swift +16 -6
- package/ios/Source/MentraBluetoothSDK.swift +803 -47
- package/ios/Source/ObservableStore.swift +6 -0
- package/ios/Source/{Audio → audio}/AudioModels.swift +9 -7
- package/ios/Source/{Camera → camera}/CameraModels.swift +225 -16
- package/ios/Source/controllers/ControllerManager.swift +4 -3
- package/ios/Source/controllers/R1.swift +3 -3
- package/ios/Source/{Events → events}/BluetoothEvents.swift +183 -1
- package/ios/Source/{Internal → internal}/ValueParsing.swift +10 -1
- package/ios/Source/{Requests → requests}/DisplayRequests.swift +28 -4
- package/ios/Source/services/PhoneMic.swift +1 -0
- package/ios/Source/sgcs/G1.swift +2 -2
- package/ios/Source/sgcs/G2.swift +645 -403
- package/ios/Source/sgcs/Mach1.swift +2 -2
- package/ios/Source/sgcs/MentraLive.swift +812 -319
- package/ios/Source/sgcs/MentraNex.swift +412 -182
- package/ios/Source/sgcs/SGCManager.swift +57 -3
- package/ios/Source/sgcs/Simulated.swift +7 -3
- package/ios/Source/sgcs/mentraos_ble.pb.swift +3073 -3134
- package/ios/Source/status/DeviceStatus.swift +974 -0
- package/ios/Source/{Status → status}/WifiHotspotStatus.swift +4 -4
- package/ios/Source/{Streaming → streaming}/StreamModels.swift +24 -9
- package/ios/Source/stt/STTTools.swift +27 -12
- package/ios/Source/stt/SherpaOnnxTranscriber.swift +31 -8
- package/ios/Source/tts/TTSTools.swift +164 -0
- package/ios/Source/utils/JSCExperiment.swift +7 -7
- package/ios/Source/utils/MessageChunkReassembler.swift +20 -1
- package/ios/Source/utils/MessageChunker.swift +78 -21
- package/ios/Source/utils/TarBz2Extractor.swift +53 -2
- package/package.json +1 -1
- package/plugin/build/withAndroid.js +68 -4
- package/src/BluetoothSdk.types.ts +331 -59
- package/src/_private/BluetoothSdkModule.ts +113 -102
- package/src/_private/photoRequestPayload.ts +28 -0
- package/src/index.ts +58 -15
- package/src/react/useMentraBluetooth.ts +6 -4
- package/android/.project +0 -28
- package/android/lc3Lib/.project +0 -28
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/cargs.h +0 -162
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/c-api.h +0 -1852
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/cxx-api.h +0 -674
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/sherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/sherpa-onnx.a +0 -0
- package/ios/Source/Status/DeviceStatus.swift +0 -471
- /package/ios/Source/{Connection → connection}/ScanSession.swift +0 -0
- /package/ios/Source/{Errors → errors}/BluetoothError.swift +0 -0
- /package/ios/Source/{Internal → internal}/BluetoothAvailability.swift +0 -0
- /package/ios/Source/{Status → status}/RuntimeState.swift +0 -0
- /package/ios/Source/{Types → types}/DeviceModels.swift +0 -0
|
@@ -1,471 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
|
|
3
|
-
public struct WifiScanResult: CustomStringConvertible {
|
|
4
|
-
public let ssid: String
|
|
5
|
-
public let requiresPassword: Bool
|
|
6
|
-
public let signalStrength: Int
|
|
7
|
-
public let frequency: Int?
|
|
8
|
-
|
|
9
|
-
public init(ssid: String, requiresPassword: Bool, signalStrength: Int, frequency: Int? = nil) {
|
|
10
|
-
self.ssid = ssid
|
|
11
|
-
self.requiresPassword = requiresPassword
|
|
12
|
-
self.signalStrength = signalStrength
|
|
13
|
-
self.frequency = frequency
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
init(values: [String: Any]) {
|
|
17
|
-
ssid = stringValue(values, "ssid") ?? ""
|
|
18
|
-
requiresPassword = boolValue(values, "requiresPassword") ?? false
|
|
19
|
-
signalStrength = intValue(values["signalStrength"]) ?? -1
|
|
20
|
-
frequency = intValue(values["frequency"])
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
var dictionary: [String: Any] {
|
|
24
|
-
var values: [String: Any] = [
|
|
25
|
-
"ssid": ssid,
|
|
26
|
-
"requiresPassword": requiresPassword,
|
|
27
|
-
"signalStrength": signalStrength,
|
|
28
|
-
]
|
|
29
|
-
if let frequency {
|
|
30
|
-
values["frequency"] = frequency
|
|
31
|
-
}
|
|
32
|
-
return values
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public var description: String {
|
|
36
|
-
"WifiScanResult(ssid: \(ssid), signalStrength: \(signalStrength))"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
public enum GlassesConnectionState: String, CustomStringConvertible, Equatable {
|
|
41
|
-
case disconnected = "DISCONNECTED"
|
|
42
|
-
case scanning = "SCANNING"
|
|
43
|
-
case connecting = "CONNECTING"
|
|
44
|
-
case bonding = "BONDING"
|
|
45
|
-
case connected = "CONNECTED"
|
|
46
|
-
|
|
47
|
-
public init(_ value: String?) {
|
|
48
|
-
self = Self.fromValue(value) ?? .disconnected
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public static func fromValue(_ value: String?) -> GlassesConnectionState? {
|
|
52
|
-
guard let normalized = value?.trimmingCharacters(in: .whitespacesAndNewlines).uppercased(),
|
|
53
|
-
!normalized.isEmpty
|
|
54
|
-
else {
|
|
55
|
-
return nil
|
|
56
|
-
}
|
|
57
|
-
return Self(rawValue: normalized)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public var isConnected: Bool {
|
|
61
|
-
self == .connected
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
public var isBusy: Bool {
|
|
65
|
-
self == .scanning || self == .connecting || self == .bonding
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
func statusValues(connected: Bool, fullyBooted: Bool) -> [String: Any] {
|
|
69
|
-
if self == .connected || connected || fullyBooted {
|
|
70
|
-
return ["state": "connected", "fullyBooted": fullyBooted]
|
|
71
|
-
}
|
|
72
|
-
switch self {
|
|
73
|
-
case .scanning:
|
|
74
|
-
return ["state": "scanning"]
|
|
75
|
-
case .connecting:
|
|
76
|
-
return ["state": "connecting"]
|
|
77
|
-
case .bonding:
|
|
78
|
-
return ["state": "bonding"]
|
|
79
|
-
case .connected:
|
|
80
|
-
return ["state": "connected", "fullyBooted": fullyBooted]
|
|
81
|
-
case .disconnected:
|
|
82
|
-
return ["state": "disconnected"]
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
public var description: String {
|
|
87
|
-
rawValue
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
struct GlassesStatus: CustomStringConvertible {
|
|
92
|
-
let values: [String: Any]
|
|
93
|
-
|
|
94
|
-
init(values: [String: Any]) {
|
|
95
|
-
self.values = values
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
func applying(_ update: GlassesStatusUpdate) -> GlassesStatus {
|
|
99
|
-
GlassesStatus(values: values.merging(update.values) { _, new in new })
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
func withBattery(level: Int, charging: Bool) -> GlassesStatus {
|
|
103
|
-
applying(GlassesStatusUpdate(values: ["batteryLevel": level, "charging": charging]))
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
func withWifi(_ wifi: WifiStatus) -> GlassesStatus {
|
|
107
|
-
applying(GlassesStatusUpdate(values: wifi.storeValues))
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
func withHotspot(_ hotspot: HotspotStatus) -> GlassesStatus {
|
|
111
|
-
applying(GlassesStatusUpdate(values: hotspot.storeValues))
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
func disconnected() -> GlassesStatus {
|
|
115
|
-
applying(GlassesStatusUpdate(values: [
|
|
116
|
-
"connected": false,
|
|
117
|
-
"connectionState": "DISCONNECTED",
|
|
118
|
-
"fullyBooted": false,
|
|
119
|
-
"batteryLevel": -1,
|
|
120
|
-
"charging": false,
|
|
121
|
-
"hotspotEnabled": false,
|
|
122
|
-
"hotspotGatewayIp": "",
|
|
123
|
-
"hotspotPassword": "",
|
|
124
|
-
"hotspotSsid": "",
|
|
125
|
-
"wifiConnected": false,
|
|
126
|
-
"wifiSsid": "",
|
|
127
|
-
"wifiLocalIp": "",
|
|
128
|
-
"signalStrength": -1,
|
|
129
|
-
"signalStrengthUpdatedAt": 0,
|
|
130
|
-
]))
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
var fullyBooted: Bool { boolValue(values, "fullyBooted") ?? false }
|
|
134
|
-
var connected: Bool { boolValue(values, "connected") ?? false }
|
|
135
|
-
var micEnabled: Bool { boolValue(values, "micEnabled") ?? false }
|
|
136
|
-
var voiceActivityDetectionEnabled: Bool { boolValue(values, "voiceActivityDetectionEnabled") ?? true }
|
|
137
|
-
var connectionState: GlassesConnectionState { GlassesConnectionState(stringValue(values, "connectionState")) }
|
|
138
|
-
var bluetoothClassicConnected: Bool { boolValue(values, "bluetoothClassicConnected") ?? false }
|
|
139
|
-
var signalStrength: Int { intValue(values["signalStrength"]) ?? -1 }
|
|
140
|
-
var signalStrengthUpdatedAt: Int { intValue(values["signalStrengthUpdatedAt"]) ?? 0 }
|
|
141
|
-
var deviceModel: String { stringValue(values, "deviceModel") ?? "" }
|
|
142
|
-
var androidVersion: String { stringValue(values, "androidVersion") ?? "" }
|
|
143
|
-
var firmwareVersion: String { stringValue(values, "firmwareVersion") ?? "" }
|
|
144
|
-
var besFirmwareVersion: String { stringValue(values, "besFirmwareVersion") ?? "" }
|
|
145
|
-
var mtkFirmwareVersion: String { stringValue(values, "mtkFirmwareVersion") ?? "" }
|
|
146
|
-
var bluetoothMacAddress: String { stringValue(values, "bluetoothMacAddress") ?? "" }
|
|
147
|
-
var leftMacAddress: String { stringValue(values, "leftMacAddress") ?? "" }
|
|
148
|
-
var rightMacAddress: String { stringValue(values, "rightMacAddress") ?? "" }
|
|
149
|
-
var macAddress: String { stringValue(values, "macAddress") ?? "" }
|
|
150
|
-
var buildNumber: String { stringValue(values, "buildNumber") ?? "" }
|
|
151
|
-
var otaVersionUrl: String { stringValue(values, "otaVersionUrl") ?? "" }
|
|
152
|
-
var appVersion: String { stringValue(values, "appVersion") ?? "" }
|
|
153
|
-
var bluetoothName: String { stringValue(values, "bluetoothName") ?? "" }
|
|
154
|
-
var serialNumber: String { stringValue(values, "serialNumber") ?? "" }
|
|
155
|
-
var style: String { stringValue(values, "style") ?? "" }
|
|
156
|
-
var color: String { stringValue(values, "color") ?? "" }
|
|
157
|
-
var wifi: WifiStatus { WifiStatus.fromStoreValues(values) ?? .disconnected }
|
|
158
|
-
var hotspot: HotspotStatus { HotspotStatus.fromStoreValues(values) ?? .disabled }
|
|
159
|
-
var dictionary: [String: Any] { Self.dictionary(from: values) }
|
|
160
|
-
var batteryLevel: Int { intValue(values["batteryLevel"]) ?? -1 }
|
|
161
|
-
var charging: Bool { boolValue(values, "charging") ?? false }
|
|
162
|
-
var caseBatteryLevel: Int { intValue(values["caseBatteryLevel"]) ?? -1 }
|
|
163
|
-
var caseCharging: Bool { boolValue(values, "caseCharging") ?? false }
|
|
164
|
-
var caseOpen: Bool { boolValue(values, "caseOpen") ?? true }
|
|
165
|
-
var caseRemoved: Bool { boolValue(values, "caseRemoved") ?? true }
|
|
166
|
-
var headUp: Bool { boolValue(values, "headUp") ?? false }
|
|
167
|
-
var controllerConnected: Bool { boolValue(values, "controllerConnected") ?? false }
|
|
168
|
-
var controllerFullyBooted: Bool { boolValue(values, "controllerFullyBooted") ?? false }
|
|
169
|
-
var controllerMacAddress: String { stringValue(values, "controllerMacAddress") ?? "" }
|
|
170
|
-
var controllerBatteryLevel: Int { intValue(values["controllerBatteryLevel"]) ?? -1 }
|
|
171
|
-
var controllerSignalStrength: Int { intValue(values["controllerSignalStrength"]) ?? -1 }
|
|
172
|
-
var ringSignalStrength: Int { intValue(values["ringSignalStrength"]) ?? -1 }
|
|
173
|
-
|
|
174
|
-
var description: String {
|
|
175
|
-
values.description
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
static func dictionary(from values: [String: Any]) -> [String: Any] {
|
|
179
|
-
var dictionary = values
|
|
180
|
-
dictionary["connection"] = GlassesConnectionState(stringValue(values, "connectionState")).statusValues(
|
|
181
|
-
connected: boolValue(values, "connected") ?? false,
|
|
182
|
-
fullyBooted: boolValue(values, "fullyBooted") ?? false
|
|
183
|
-
)
|
|
184
|
-
dictionary.removeValue(forKey: "connected")
|
|
185
|
-
dictionary.removeValue(forKey: "fullyBooted")
|
|
186
|
-
dictionary.removeValue(forKey: "connectionState")
|
|
187
|
-
dictionary["wifi"] = (WifiStatus.fromStoreValues(values) ?? .disconnected).values
|
|
188
|
-
dictionary["hotspot"] = (HotspotStatus.fromStoreValues(values) ?? .disabled).values
|
|
189
|
-
dictionary.removeValue(forKey: "wifiConnected")
|
|
190
|
-
dictionary.removeValue(forKey: "wifiSsid")
|
|
191
|
-
dictionary.removeValue(forKey: "wifiLocalIp")
|
|
192
|
-
dictionary.removeValue(forKey: "hotspotEnabled")
|
|
193
|
-
dictionary.removeValue(forKey: "hotspotSsid")
|
|
194
|
-
dictionary.removeValue(forKey: "hotspotPassword")
|
|
195
|
-
dictionary.removeValue(forKey: "hotspotGatewayIp")
|
|
196
|
-
return dictionary
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
static func updateDictionary(from values: [String: Any]) -> [String: Any] {
|
|
200
|
-
var dictionary = values
|
|
201
|
-
if hasAnyKey(values, "connection", "connected", "fullyBooted", "connectionState") {
|
|
202
|
-
dictionary["connection"] = (values["connection"] as? [String: Any])
|
|
203
|
-
?? GlassesConnectionState(stringValue(values, "connectionState")).statusValues(
|
|
204
|
-
connected: boolValue(values, "connected") ?? false,
|
|
205
|
-
fullyBooted: boolValue(values, "fullyBooted") ?? false
|
|
206
|
-
)
|
|
207
|
-
dictionary.removeValue(forKey: "connected")
|
|
208
|
-
dictionary.removeValue(forKey: "fullyBooted")
|
|
209
|
-
dictionary.removeValue(forKey: "connectionState")
|
|
210
|
-
}
|
|
211
|
-
if hasAnyKey(values, "wifi", "wifiConnected", "wifiSsid", "wifiLocalIp") {
|
|
212
|
-
let wifi = (values["wifi"] as? [String: Any]).flatMap(WifiStatus.init(values:))
|
|
213
|
-
?? WifiStatus.fromStoreValues(values)
|
|
214
|
-
if let wifi {
|
|
215
|
-
dictionary["wifi"] = wifi.values
|
|
216
|
-
}
|
|
217
|
-
dictionary.removeValue(forKey: "wifiConnected")
|
|
218
|
-
dictionary.removeValue(forKey: "wifiSsid")
|
|
219
|
-
dictionary.removeValue(forKey: "wifiLocalIp")
|
|
220
|
-
}
|
|
221
|
-
if hasAnyKey(values, "hotspot") {
|
|
222
|
-
if let hotspot = (values["hotspot"] as? [String: Any]).flatMap(HotspotStatus.init(values:)) {
|
|
223
|
-
dictionary["hotspot"] = hotspot.values
|
|
224
|
-
}
|
|
225
|
-
} else if hasAnyKey(values, "hotspotEnabled", "hotspotSsid", "hotspotPassword", "hotspotGatewayIp") {
|
|
226
|
-
if let hotspot = HotspotStatus.fromStoreValues(values) {
|
|
227
|
-
dictionary["hotspot"] = hotspot.values
|
|
228
|
-
}
|
|
229
|
-
dictionary.removeValue(forKey: "hotspotEnabled")
|
|
230
|
-
dictionary.removeValue(forKey: "hotspotSsid")
|
|
231
|
-
dictionary.removeValue(forKey: "hotspotPassword")
|
|
232
|
-
dictionary.removeValue(forKey: "hotspotGatewayIp")
|
|
233
|
-
}
|
|
234
|
-
return dictionary
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
struct BluetoothStatus: CustomStringConvertible {
|
|
239
|
-
let values: [String: Any]
|
|
240
|
-
|
|
241
|
-
init(values: [String: Any]) {
|
|
242
|
-
self.values = Self.normalized(values)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
private static func normalized(_ values: [String: Any]) -> [String: Any] {
|
|
246
|
-
var normalizedValues = values
|
|
247
|
-
if let searchResults = values["searchResults"] as? [[String: Any]] {
|
|
248
|
-
normalizedValues["searchResults"] = searchResults.compactMap { Device(values: $0)?.dictionary }
|
|
249
|
-
}
|
|
250
|
-
if let galleryMode = boolValue(values, "gallery_mode") {
|
|
251
|
-
normalizedValues["galleryModeEnabled"] = galleryMode
|
|
252
|
-
normalizedValues.removeValue(forKey: "gallery_mode")
|
|
253
|
-
}
|
|
254
|
-
return normalizedValues
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
func applying(_ update: BluetoothStatusUpdate) -> BluetoothStatus {
|
|
258
|
-
BluetoothStatus(values: values.merging(update.values) { _, new in new })
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
func withDefaultDevice(_ device: Device?) -> BluetoothStatus {
|
|
262
|
-
applying(BluetoothStatusUpdate(values: [
|
|
263
|
-
"default_wearable": device?.model.deviceType ?? "",
|
|
264
|
-
"device_name": device?.name ?? "",
|
|
265
|
-
"device_address": device?.identifier ?? "",
|
|
266
|
-
]))
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
var searching: Bool { boolValue(values, "searching") ?? false }
|
|
270
|
-
var searchingController: Bool { boolValue(values, "searchingController") ?? false }
|
|
271
|
-
var systemMicUnavailable: Bool { boolValue(values, "systemMicUnavailable") ?? false }
|
|
272
|
-
var micEnabled: Bool { boolValue(values, "micEnabled") ?? false }
|
|
273
|
-
var currentMic: String { stringValue(values, "currentMic") ?? "" }
|
|
274
|
-
var micRanking: [String] { stringListValue(values, "micRanking") }
|
|
275
|
-
/// Nearby glasses in stable discovery order. Existing entries keep their array position as
|
|
276
|
-
/// details refresh; new glasses append at the end, and removals should not reorder remaining entries.
|
|
277
|
-
var searchResults: [Device] {
|
|
278
|
-
dictionaryListValue(values, "searchResults").compactMap(Device.init(values:))
|
|
279
|
-
}
|
|
280
|
-
var wifiScanResults: [WifiScanResult] {
|
|
281
|
-
dictionaryListValue(values, "wifiScanResults").map(WifiScanResult.init(values:))
|
|
282
|
-
}
|
|
283
|
-
var lastLog: [String] { stringListValue(values, "lastLog") }
|
|
284
|
-
var otherBtConnected: Bool { boolValue(values, "otherBtConnected") ?? false }
|
|
285
|
-
var defaultWearable: String { stringValue(values, "default_wearable") ?? "" }
|
|
286
|
-
var pendingWearable: String { stringValue(values, "pending_wearable") ?? "" }
|
|
287
|
-
var deviceName: String { stringValue(values, "device_name") ?? "" }
|
|
288
|
-
var deviceAddress: String { stringValue(values, "device_address") ?? "" }
|
|
289
|
-
var defaultController: String { stringValue(values, "default_controller") ?? "" }
|
|
290
|
-
var pendingController: String { stringValue(values, "pending_controller") ?? "" }
|
|
291
|
-
var controllerDeviceName: String { stringValue(values, "controller_device_name") ?? "" }
|
|
292
|
-
var screenDisabled: Bool { boolValue(values, "screen_disabled") ?? false }
|
|
293
|
-
var preferredMic: String { stringValue(values, "preferred_mic") ?? "auto" }
|
|
294
|
-
var sensingEnabled: Bool { boolValue(values, "sensing_enabled") ?? true }
|
|
295
|
-
var powerSavingMode: Bool { boolValue(values, "power_saving_mode") ?? false }
|
|
296
|
-
var brightness: Int { intValue(values["brightness"]) ?? 50 }
|
|
297
|
-
var autoBrightness: Bool { boolValue(values, "auto_brightness") ?? true }
|
|
298
|
-
var dashboardHeight: Int { intValue(values["dashboard_height"]) ?? 4 }
|
|
299
|
-
var dashboardDepth: Int { intValue(values["dashboard_depth"]) ?? 2 }
|
|
300
|
-
var headUpAngle: Int { intValue(values["head_up_angle"]) ?? 30 }
|
|
301
|
-
var contextualDashboard: Bool { boolValue(values, "contextual_dashboard") ?? true }
|
|
302
|
-
var galleryModeEnabled: Bool { boolValue(values, "gallery_mode") ?? boolValue(values, "galleryModeEnabled") ?? true }
|
|
303
|
-
var buttonPhotoSize: ButtonPhotoSize {
|
|
304
|
-
ButtonPhotoSize(rawValue: stringValue(values, "button_photo_size") ?? "") ?? .medium
|
|
305
|
-
}
|
|
306
|
-
var buttonCameraLed: Bool { boolValue(values, "button_camera_led") ?? true }
|
|
307
|
-
var buttonMaxRecordingTime: Int { intValue(values["button_max_recording_time"]) ?? 10 }
|
|
308
|
-
var buttonVideoWidth: Int { intValue(values["button_video_width"]) ?? 1280 }
|
|
309
|
-
var buttonVideoHeight: Int { intValue(values["button_video_height"]) ?? 720 }
|
|
310
|
-
var buttonVideoFrameRate: Int { intValue(values["button_video_fps"]) ?? 30 }
|
|
311
|
-
var shouldSendPcm: Bool { boolValue(values, "should_send_pcm") ?? false }
|
|
312
|
-
var shouldSendLc3: Bool { boolValue(values, "should_send_lc3") ?? false }
|
|
313
|
-
var shouldSendTranscript: Bool { boolValue(values, "should_send_transcript") ?? false }
|
|
314
|
-
var offlineCaptionsRunning: Bool { boolValue(values, "offline_captions_running") ?? false }
|
|
315
|
-
var localSttFallbackActive: Bool { boolValue(values, "local_stt_fallback_active") ?? false }
|
|
316
|
-
var shouldSendBootingMessage: Bool { boolValue(values, "shouldSendBootingMessage") ?? true }
|
|
317
|
-
|
|
318
|
-
var defaultDevice: Device? {
|
|
319
|
-
guard !defaultWearable.isEmpty else { return nil }
|
|
320
|
-
return Device(
|
|
321
|
-
model: DeviceModel.fromDeviceType(defaultWearable),
|
|
322
|
-
name: deviceName,
|
|
323
|
-
identifier: deviceAddress.isEmpty ? nil : deviceAddress
|
|
324
|
-
)
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
var description: String {
|
|
328
|
-
values.description
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
struct GlassesStatusUpdate: CustomStringConvertible {
|
|
333
|
-
let values: [String: Any]
|
|
334
|
-
|
|
335
|
-
init(values: [String: Any]) {
|
|
336
|
-
self.values = values
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
var fullyBooted: Bool? { optionalBoolValue(values, "fullyBooted") }
|
|
340
|
-
var connected: Bool? { optionalBoolValue(values, "connected") }
|
|
341
|
-
var micEnabled: Bool? { optionalBoolValue(values, "micEnabled") }
|
|
342
|
-
var voiceActivityDetectionEnabled: Bool? { optionalBoolValue(values, "voiceActivityDetectionEnabled") }
|
|
343
|
-
var connectionState: GlassesConnectionState? {
|
|
344
|
-
GlassesConnectionState.fromValue(optionalStringValue(values, "connectionState"))
|
|
345
|
-
}
|
|
346
|
-
var bluetoothClassicConnected: Bool? { optionalBoolValue(values, "bluetoothClassicConnected") }
|
|
347
|
-
var signalStrength: Int? { optionalIntValue(values, "signalStrength") }
|
|
348
|
-
var signalStrengthUpdatedAt: Int? { optionalIntValue(values, "signalStrengthUpdatedAt") }
|
|
349
|
-
var deviceModel: String? { optionalStringValue(values, "deviceModel") }
|
|
350
|
-
var androidVersion: String? { optionalStringValue(values, "androidVersion") }
|
|
351
|
-
var firmwareVersion: String? { optionalStringValue(values, "firmwareVersion") }
|
|
352
|
-
var besFirmwareVersion: String? { optionalStringValue(values, "besFirmwareVersion") }
|
|
353
|
-
var mtkFirmwareVersion: String? { optionalStringValue(values, "mtkFirmwareVersion") }
|
|
354
|
-
var bluetoothMacAddress: String? { optionalStringValue(values, "bluetoothMacAddress") }
|
|
355
|
-
var leftMacAddress: String? { optionalStringValue(values, "leftMacAddress") }
|
|
356
|
-
var rightMacAddress: String? { optionalStringValue(values, "rightMacAddress") }
|
|
357
|
-
var macAddress: String? { optionalStringValue(values, "macAddress") }
|
|
358
|
-
var buildNumber: String? { optionalStringValue(values, "buildNumber") }
|
|
359
|
-
var otaVersionUrl: String? { optionalStringValue(values, "otaVersionUrl") }
|
|
360
|
-
var appVersion: String? { optionalStringValue(values, "appVersion") }
|
|
361
|
-
var bluetoothName: String? { optionalStringValue(values, "bluetoothName") }
|
|
362
|
-
var serialNumber: String? { optionalStringValue(values, "serialNumber") }
|
|
363
|
-
var style: String? { optionalStringValue(values, "style") }
|
|
364
|
-
var color: String? { optionalStringValue(values, "color") }
|
|
365
|
-
var wifi: WifiStatus? {
|
|
366
|
-
if let wifi = values["wifi"] as? [String: Any] {
|
|
367
|
-
return WifiStatus(values: wifi)
|
|
368
|
-
}
|
|
369
|
-
if hasAnyKey(values, "wifiConnected", "wifiSsid", "wifiLocalIp") {
|
|
370
|
-
return WifiStatus.fromStoreValues(values)
|
|
371
|
-
}
|
|
372
|
-
return nil
|
|
373
|
-
}
|
|
374
|
-
var hotspot: HotspotStatus? {
|
|
375
|
-
if let hotspot = values["hotspot"] as? [String: Any] {
|
|
376
|
-
return HotspotStatus(values: hotspot)
|
|
377
|
-
}
|
|
378
|
-
if hasAnyKey(values, "hotspotEnabled", "hotspotSsid", "hotspotPassword", "hotspotGatewayIp") {
|
|
379
|
-
return HotspotStatus.fromStoreValues(values)
|
|
380
|
-
}
|
|
381
|
-
return nil
|
|
382
|
-
}
|
|
383
|
-
var dictionary: [String: Any] { GlassesStatus.updateDictionary(from: values) }
|
|
384
|
-
var batteryLevel: Int? { optionalIntValue(values, "batteryLevel") }
|
|
385
|
-
var charging: Bool? { optionalBoolValue(values, "charging") }
|
|
386
|
-
var caseBatteryLevel: Int? { optionalIntValue(values, "caseBatteryLevel") }
|
|
387
|
-
var caseCharging: Bool? { optionalBoolValue(values, "caseCharging") }
|
|
388
|
-
var caseOpen: Bool? { optionalBoolValue(values, "caseOpen") }
|
|
389
|
-
var caseRemoved: Bool? { optionalBoolValue(values, "caseRemoved") }
|
|
390
|
-
var headUp: Bool? { optionalBoolValue(values, "headUp") }
|
|
391
|
-
var controllerConnected: Bool? { optionalBoolValue(values, "controllerConnected") }
|
|
392
|
-
var controllerFullyBooted: Bool? { optionalBoolValue(values, "controllerFullyBooted") }
|
|
393
|
-
var controllerMacAddress: String? { optionalStringValue(values, "controllerMacAddress") }
|
|
394
|
-
var controllerBatteryLevel: Int? { optionalIntValue(values, "controllerBatteryLevel") }
|
|
395
|
-
var controllerSignalStrength: Int? { optionalIntValue(values, "controllerSignalStrength") }
|
|
396
|
-
var ringSignalStrength: Int? { optionalIntValue(values, "ringSignalStrength") }
|
|
397
|
-
|
|
398
|
-
var description: String {
|
|
399
|
-
values.description
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
struct BluetoothStatusUpdate: CustomStringConvertible {
|
|
404
|
-
let values: [String: Any]
|
|
405
|
-
|
|
406
|
-
init(values: [String: Any]) {
|
|
407
|
-
var normalizedValues = values
|
|
408
|
-
if let searchResults = values["searchResults"] as? [[String: Any]] {
|
|
409
|
-
normalizedValues["searchResults"] = searchResults.compactMap { Device(values: $0)?.dictionary }
|
|
410
|
-
}
|
|
411
|
-
if let galleryMode = optionalBoolValue(values, "gallery_mode") {
|
|
412
|
-
normalizedValues["galleryModeEnabled"] = galleryMode
|
|
413
|
-
normalizedValues.removeValue(forKey: "gallery_mode")
|
|
414
|
-
}
|
|
415
|
-
self.values = normalizedValues
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
var searching: Bool? { optionalBoolValue(values, "searching") }
|
|
419
|
-
var searchingController: Bool? { optionalBoolValue(values, "searchingController") }
|
|
420
|
-
var systemMicUnavailable: Bool? { optionalBoolValue(values, "systemMicUnavailable") }
|
|
421
|
-
var micEnabled: Bool? { optionalBoolValue(values, "micEnabled") }
|
|
422
|
-
var currentMic: String? { optionalStringValue(values, "currentMic") }
|
|
423
|
-
var micRanking: [String]? { optionalStringListValue(values, "micRanking") }
|
|
424
|
-
/// Nearby glasses in stable discovery order when included in an update. Existing entries keep their
|
|
425
|
-
/// array position as details refresh; new glasses append at the end, and removals should not reorder
|
|
426
|
-
/// remaining entries.
|
|
427
|
-
var searchResults: [Device]? {
|
|
428
|
-
optionalDictionaryListValue(values, "searchResults")?.compactMap(Device.init(values:))
|
|
429
|
-
}
|
|
430
|
-
var wifiScanResults: [WifiScanResult]? {
|
|
431
|
-
optionalDictionaryListValue(values, "wifiScanResults")?.map(WifiScanResult.init(values:))
|
|
432
|
-
}
|
|
433
|
-
var lastLog: [String]? { optionalStringListValue(values, "lastLog") }
|
|
434
|
-
var otherBtConnected: Bool? { optionalBoolValue(values, "otherBtConnected") }
|
|
435
|
-
var defaultWearable: String? { optionalStringValue(values, "default_wearable") }
|
|
436
|
-
var pendingWearable: String? { optionalStringValue(values, "pending_wearable") }
|
|
437
|
-
var deviceName: String? { optionalStringValue(values, "device_name") }
|
|
438
|
-
var deviceAddress: String? { optionalStringValue(values, "device_address") }
|
|
439
|
-
var defaultController: String? { optionalStringValue(values, "default_controller") }
|
|
440
|
-
var pendingController: String? { optionalStringValue(values, "pending_controller") }
|
|
441
|
-
var controllerDeviceName: String? { optionalStringValue(values, "controller_device_name") }
|
|
442
|
-
var screenDisabled: Bool? { optionalBoolValue(values, "screen_disabled") }
|
|
443
|
-
var preferredMic: String? { optionalStringValue(values, "preferred_mic") }
|
|
444
|
-
var sensingEnabled: Bool? { optionalBoolValue(values, "sensing_enabled") }
|
|
445
|
-
var powerSavingMode: Bool? { optionalBoolValue(values, "power_saving_mode") }
|
|
446
|
-
var brightness: Int? { optionalIntValue(values, "brightness") }
|
|
447
|
-
var autoBrightness: Bool? { optionalBoolValue(values, "auto_brightness") }
|
|
448
|
-
var dashboardHeight: Int? { optionalIntValue(values, "dashboard_height") }
|
|
449
|
-
var dashboardDepth: Int? { optionalIntValue(values, "dashboard_depth") }
|
|
450
|
-
var headUpAngle: Int? { optionalIntValue(values, "head_up_angle") }
|
|
451
|
-
var contextualDashboard: Bool? { optionalBoolValue(values, "contextual_dashboard") }
|
|
452
|
-
var galleryModeEnabled: Bool? { optionalBoolValue(values, "gallery_mode") ?? optionalBoolValue(values, "galleryModeEnabled") }
|
|
453
|
-
var buttonPhotoSize: ButtonPhotoSize? {
|
|
454
|
-
optionalStringValue(values, "button_photo_size").flatMap(ButtonPhotoSize.init(rawValue:))
|
|
455
|
-
}
|
|
456
|
-
var buttonCameraLed: Bool? { optionalBoolValue(values, "button_camera_led") }
|
|
457
|
-
var buttonMaxRecordingTime: Int? { optionalIntValue(values, "button_max_recording_time") }
|
|
458
|
-
var buttonVideoWidth: Int? { optionalIntValue(values, "button_video_width") }
|
|
459
|
-
var buttonVideoHeight: Int? { optionalIntValue(values, "button_video_height") }
|
|
460
|
-
var buttonVideoFrameRate: Int? { optionalIntValue(values, "button_video_fps") }
|
|
461
|
-
var shouldSendPcm: Bool? { optionalBoolValue(values, "should_send_pcm") }
|
|
462
|
-
var shouldSendLc3: Bool? { optionalBoolValue(values, "should_send_lc3") }
|
|
463
|
-
var shouldSendTranscript: Bool? { optionalBoolValue(values, "should_send_transcript") }
|
|
464
|
-
var offlineCaptionsRunning: Bool? { optionalBoolValue(values, "offline_captions_running") }
|
|
465
|
-
var localSttFallbackActive: Bool? { optionalBoolValue(values, "local_stt_fallback_active") }
|
|
466
|
-
var shouldSendBootingMessage: Bool? { optionalBoolValue(values, "shouldSendBootingMessage") }
|
|
467
|
-
|
|
468
|
-
var description: String {
|
|
469
|
-
values.description
|
|
470
|
-
}
|
|
471
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|