@mentra/bluetooth-sdk 0.1.21-beta.3 → 3.1.0-dev.4
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 +38 -2
- package/android/build.gradle +7 -4
- package/android/lc3Lib/build.gradle +18 -4
- package/android/silero/build.gradle +9 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +16 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +39 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +209 -21
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +2 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +11 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +112 -8
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraLocalNetworkModule.kt +93 -12
- package/android/src/main/java/com/mentra/bluetoothsdk/OtaManifest.kt +5 -7
- package/android/src/main/java/com/mentra/bluetoothsdk/ScopedNetworkReadiness.kt +17 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/audio/AudioModels.kt +15 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +24 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/net/LocalIpv4.kt +57 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/otaserver/LocalOtaServer.kt +304 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/otaserver/MentraOtaServerModule.kt +120 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/MentraPhotoReceiverModule.kt +2 -49
- package/android/src/main/java/com/mentra/bluetoothsdk/services/Foreground.kt +61 -30
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +1381 -284
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +8 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +17 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/types/DeviceModels.kt +12 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BleJsonCompact.java +74 -79
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtils.java +3 -3
- package/android/src/test/java/com/mentra/bluetoothsdk/OtaStartResponsePolicyTest.kt +30 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/ScopedNetworkReadinessTest.kt +39 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/otaserver/LocalOtaServerTest.kt +82 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/services/ForegroundServiceTypeTest.kt +69 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveGattCharacteristicsTest.kt +39 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/BleJsonCompactTest.java +148 -7
- package/build/BluetoothSdk.types.d.ts +63 -2
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_internal.d.ts +2 -0
- package/build/_internal.d.ts.map +1 -1
- package/build/_internal.js +2 -0
- package/build/_internal.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +4 -1
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +1 -1
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/_private/MentraLocalNetworkModule.d.ts +1 -0
- package/build/_private/MentraLocalNetworkModule.d.ts.map +1 -1
- package/build/_private/MentraLocalNetworkModule.js.map +1 -1
- package/build/_private/sdkOtaManifest.d.ts +3 -12
- package/build/_private/sdkOtaManifest.d.ts.map +1 -1
- package/build/_private/sdkOtaManifest.js +5 -17
- package/build/_private/sdkOtaManifest.js.map +1 -1
- package/build/generated/releaseMetadata.d.ts +12 -0
- package/build/generated/releaseMetadata.d.ts.map +1 -0
- package/build/generated/releaseMetadata.js +10 -0
- package/build/generated/releaseMetadata.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +10 -2
- package/build/index.js.map +1 -1
- package/build/ota-server/MentraOtaServer.types.d.ts +14 -0
- package/build/ota-server/MentraOtaServer.types.d.ts.map +1 -0
- package/build/ota-server/MentraOtaServer.types.js +2 -0
- package/build/ota-server/MentraOtaServer.types.js.map +1 -0
- package/build/ota-server/MentraOtaServerModule.d.ts +21 -0
- package/build/ota-server/MentraOtaServerModule.d.ts.map +1 -0
- package/build/ota-server/MentraOtaServerModule.js +3 -0
- package/build/ota-server/MentraOtaServerModule.js.map +1 -0
- package/build/ota-server/MentraOtaServerModule.web.d.ts +10 -0
- package/build/ota-server/MentraOtaServerModule.web.d.ts.map +1 -0
- package/build/ota-server/MentraOtaServerModule.web.js +12 -0
- package/build/ota-server/MentraOtaServerModule.web.js.map +1 -0
- package/build/ota-server/index.d.ts +3 -0
- package/build/ota-server/index.d.ts.map +1 -0
- package/build/ota-server/index.js +3 -0
- package/build/ota-server/index.js.map +1 -0
- package/expo-module.config.json +3 -2
- package/ios/BackgroundOtaArtifactDownloader.swift +125 -0
- package/ios/BluetoothSdkModule.swift +16 -2
- package/ios/LocalIPv4.swift +150 -0
- package/ios/LocalOtaServer.swift +309 -0
- package/ios/MentraBluetoothSDK.podspec +5 -1
- package/ios/MentraOtaServerModule.swift +147 -0
- package/ios/MentraPhotoReceiverModule.swift +1 -81
- package/ios/Source/BluetoothSdkDefaults.swift +4 -1
- package/ios/Source/Bridge.swift +47 -3
- package/ios/Source/DeviceManager.swift +146 -16
- package/ios/Source/DeviceStore.swift +2 -0
- package/ios/Source/GeneratedReleaseMetadata.swift +11 -0
- package/ios/Source/MentraBluetoothSDK.swift +74 -6
- package/ios/Source/OtaManifest.swift +5 -7
- package/ios/Source/audio/AudioModels.swift +17 -0
- package/ios/Source/camera/CameraModels.swift +1 -0
- package/ios/Source/events/BluetoothEvents.swift +27 -0
- package/ios/Source/sgcs/MentraLive.swift +498 -77
- package/ios/Source/sgcs/SGCManager.swift +11 -0
- package/ios/Source/status/DeviceStatus.swift +23 -0
- package/ios/Source/types/DeviceModels.swift +23 -2
- package/ios/Source/utils/BleJsonCompact.swift +73 -71
- package/package.json +5 -1
- package/plugin/build/withIos.d.ts +3 -1
- package/plugin/build/withIos.js +22 -10
- package/scripts/verify-release-package.mjs +34 -0
- package/scripts/write-release-metadata.mjs +154 -0
- package/scripts/write-release-metadata.test.mjs +29 -0
- package/src/BluetoothSdk.types.ts +74 -3
- package/src/_internal.ts +2 -0
- package/src/_private/BluetoothSdkModule.ts +5 -5
- package/src/_private/MentraLocalNetworkModule.ts +1 -1
- package/src/_private/sdkOtaManifest.ts +5 -17
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +19 -2
- package/src/ota-server/MentraOtaServer.types.ts +10 -0
- package/src/ota-server/MentraOtaServerModule.ts +23 -0
- package/src/ota-server/MentraOtaServerModule.web.ts +17 -0
- package/src/ota-server/index.ts +2 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Generated by release CI. Do not edit in a release checkout.
|
|
4
|
+
enum GeneratedReleaseMetadata {
|
|
5
|
+
static let familyBaseVersion = "3.1.0"
|
|
6
|
+
static let releaseIdentity = "3.1.0-dev.4"
|
|
7
|
+
static let releaseSetId = "mentra-3.1.0-dev.4"
|
|
8
|
+
static let sourceCommit = "43b81aea1c84675fade024077063e45fddde4861"
|
|
9
|
+
static let otaManifestUrl = "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-v3.1.0-dev.4/mentra-live-ota-3.1.0-dev.4.json"
|
|
10
|
+
static let otaManifestSha256 = "8fbea7589345658dc5dffcb394229ffc5c52fbe75352acb8f6827d83290ce750"
|
|
11
|
+
}
|
|
@@ -309,6 +309,8 @@ public final class MentraBluetoothSDK {
|
|
|
309
309
|
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "device_name", device.name)
|
|
310
310
|
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "device_address", device.identifier ?? "")
|
|
311
311
|
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "project_name", device.projectName ?? "")
|
|
312
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_name", "")
|
|
313
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_address", "")
|
|
312
314
|
finishDefaultDeviceApply(generation: generation)
|
|
313
315
|
}
|
|
314
316
|
|
|
@@ -320,6 +322,8 @@ public final class MentraBluetoothSDK {
|
|
|
320
322
|
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "device_name", "")
|
|
321
323
|
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "device_address", "")
|
|
322
324
|
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "project_name", "")
|
|
325
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_name", "")
|
|
326
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_address", "")
|
|
323
327
|
finishDefaultDeviceApply(generation: generation)
|
|
324
328
|
}
|
|
325
329
|
|
|
@@ -394,6 +398,9 @@ public final class MentraBluetoothSDK {
|
|
|
394
398
|
}
|
|
395
399
|
if options.saveAsDefault && !isController {
|
|
396
400
|
setDefaultDevice(device)
|
|
401
|
+
} else if !isController {
|
|
402
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_name", device.name)
|
|
403
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_address", device.identifier ?? "")
|
|
397
404
|
}
|
|
398
405
|
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_wearable", device.model.deviceType)
|
|
399
406
|
DeviceManager.shared.connectByName(device.name)
|
|
@@ -418,6 +425,8 @@ public final class MentraBluetoothSDK {
|
|
|
418
425
|
|
|
419
426
|
public func cancelConnectionAttempt() {
|
|
420
427
|
clearBluetoothRestoreIntent()
|
|
428
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_name", "")
|
|
429
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_address", "")
|
|
421
430
|
DeviceManager.shared.disconnect()
|
|
422
431
|
}
|
|
423
432
|
|
|
@@ -428,6 +437,8 @@ public final class MentraBluetoothSDK {
|
|
|
428
437
|
|
|
429
438
|
public func disconnect() {
|
|
430
439
|
clearBluetoothRestoreIntent()
|
|
440
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_name", "")
|
|
441
|
+
DeviceStore.shared.apply(ObservableStore.bluetoothCategory, "pending_device_address", "")
|
|
431
442
|
DeviceManager.shared.disconnect()
|
|
432
443
|
}
|
|
433
444
|
|
|
@@ -890,6 +901,13 @@ public final class MentraBluetoothSDK {
|
|
|
890
901
|
}
|
|
891
902
|
}
|
|
892
903
|
|
|
904
|
+
/// Fire-and-forget Mentra Live Wi-Fi ADB toggle. Glasses do not ack this
|
|
905
|
+
/// command, so there is no pending-response wait (unlike hotspot / Wi-Fi forget).
|
|
906
|
+
public func setWifiAdbState(enabled: Bool) async throws {
|
|
907
|
+
try requireGlassesConnected(operation: "toggle Wi-Fi ADB")
|
|
908
|
+
DeviceManager.shared.setWifiAdbState(enabled)
|
|
909
|
+
}
|
|
910
|
+
|
|
893
911
|
func setSystemTime(timestampMs: Int64) {
|
|
894
912
|
DeviceManager.shared.setSystemTime(timestampMs)
|
|
895
913
|
}
|
|
@@ -1141,6 +1159,36 @@ public final class MentraBluetoothSDK {
|
|
|
1141
1159
|
}
|
|
1142
1160
|
}
|
|
1143
1161
|
|
|
1162
|
+
public func queryVideoRecordingStatus(requestId: String) async throws -> VideoRecordingStatusEvent {
|
|
1163
|
+
guard !requestId.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
|
|
1164
|
+
throw BluetoothSdkError(
|
|
1165
|
+
code: "missing_request_id",
|
|
1166
|
+
message: "requestId is required to query video recording status."
|
|
1167
|
+
)
|
|
1168
|
+
}
|
|
1169
|
+
try requireGlassesConnected(operation: "query video recording status")
|
|
1170
|
+
let pending = PendingResponse<VideoRecordingStatusEvent>(operation: "query video recording status \(requestId)")
|
|
1171
|
+
guard pendingVideoRecordingRequests[requestId] == nil else {
|
|
1172
|
+
throw BluetoothSdkError(
|
|
1173
|
+
code: "request_in_flight",
|
|
1174
|
+
message: "A video recording command is already waiting for requestId \(requestId)."
|
|
1175
|
+
)
|
|
1176
|
+
}
|
|
1177
|
+
pendingVideoRecordingRequests[requestId] = PendingVideoRecordingRequest(
|
|
1178
|
+
expectedStatus: "recording_status",
|
|
1179
|
+
pending: pending
|
|
1180
|
+
)
|
|
1181
|
+
DeviceManager.shared.queryVideoRecordingStatus(requestId)
|
|
1182
|
+
do {
|
|
1183
|
+
let event = try await pending.wait()
|
|
1184
|
+
pendingVideoRecordingRequests.removeValue(forKey: requestId)
|
|
1185
|
+
return event
|
|
1186
|
+
} catch {
|
|
1187
|
+
pendingVideoRecordingRequests.removeValue(forKey: requestId)
|
|
1188
|
+
throw error
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1144
1192
|
public func requestVersionInfo() async throws -> VersionInfoResult {
|
|
1145
1193
|
guard pendingVersionInfo == nil else {
|
|
1146
1194
|
throw BluetoothSdkError(
|
|
@@ -1165,11 +1213,13 @@ public final class MentraBluetoothSDK {
|
|
|
1165
1213
|
}
|
|
1166
1214
|
}
|
|
1167
1215
|
|
|
1168
|
-
|
|
1216
|
+
/// Select the HTTP(S) manifest used by subsequent OTA checks and installs.
|
|
1217
|
+
public func setOtaVersionUrl(_ otaVersionUrl: String) throws {
|
|
1169
1218
|
configuredOtaVersionUrl = try OtaManifestChecker.normalizeHttpUrl(otaVersionUrl)
|
|
1170
1219
|
}
|
|
1171
1220
|
|
|
1172
|
-
|
|
1221
|
+
/// Return the configured OTA manifest, or this SDK release's default manifest.
|
|
1222
|
+
public func getOtaVersionUrl() throws -> String {
|
|
1173
1223
|
try configuredOtaVersionUrl ?? OtaManifestDefaults.defaultOtaVersionUrl()
|
|
1174
1224
|
}
|
|
1175
1225
|
|
|
@@ -2057,6 +2107,8 @@ private func dispatchDiscoveredDevices(_ rawSearchResults: Any?) {
|
|
|
2057
2107
|
if !event.lc3.isEmpty {
|
|
2058
2108
|
delegate?.mentraBluetoothSDK(self, didReceiveMicLc3: event)
|
|
2059
2109
|
}
|
|
2110
|
+
case "mic_health":
|
|
2111
|
+
delegate?.mentraBluetoothSDK(self, didReceive: .micHealth(MicHealthEvent(values: data)))
|
|
2060
2112
|
case "local_transcription":
|
|
2061
2113
|
let event = LocalTranscriptionEvent(
|
|
2062
2114
|
text: data["text"] as? String ?? "",
|
|
@@ -2105,6 +2157,10 @@ private func dispatchDiscoveredDevices(_ rawSearchResults: Any?) {
|
|
|
2105
2157
|
let event = GalleryStatusEvent(values: data)
|
|
2106
2158
|
pendingGalleryStatus?.resolve(event)
|
|
2107
2159
|
delegate?.mentraBluetoothSDK(self, didReceive: .raw(name: "gallery_status", values: event.values))
|
|
2160
|
+
case "pairing_info":
|
|
2161
|
+
delegate?.mentraBluetoothSDK(self, didReceive: .raw(name: "pairing_info", values: data))
|
|
2162
|
+
case "entering_pairing_mode", "owner_replaced":
|
|
2163
|
+
delegate?.mentraBluetoothSDK(self, didReceive: .raw(name: eventName, values: data))
|
|
2108
2164
|
case "photo_response":
|
|
2109
2165
|
let event = PhotoResponseEvent(values: data)
|
|
2110
2166
|
handlePhotoResponseForRequests(event)
|
|
@@ -2147,7 +2203,13 @@ private func dispatchDiscoveredDevices(_ rawSearchResults: Any?) {
|
|
|
2147
2203
|
var resultValues = data
|
|
2148
2204
|
resultValues["type"] = "ota_status"
|
|
2149
2205
|
pendingOtaQuery?.resolve(OtaQueryResult(values: resultValues))
|
|
2150
|
-
|
|
2206
|
+
let event = OtaStatusEvent(values: resultValues)
|
|
2207
|
+
if let errorCode = otaStartRejectionErrorCode(event) {
|
|
2208
|
+
pendingOtaStart?.reject(
|
|
2209
|
+
BluetoothSdkError(code: errorCode, message: "Glasses rejected OTA start: \(errorCode)")
|
|
2210
|
+
)
|
|
2211
|
+
}
|
|
2212
|
+
delegate?.mentraBluetoothSDK(self, didReceive: .otaStatus(event))
|
|
2151
2213
|
case "settings_ack":
|
|
2152
2214
|
let event = SettingsAckEvent(values: data)
|
|
2153
2215
|
handleSettingsAckForRequests(event)
|
|
@@ -2172,6 +2234,12 @@ private func dispatchDiscoveredDevices(_ rawSearchResults: Any?) {
|
|
|
2172
2234
|
}
|
|
2173
2235
|
}
|
|
2174
2236
|
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2237
|
+
/// OTA status messages are not request-correlated, so only known pre-ack failures settle a start.
|
|
2238
|
+
private func otaStartRejectionErrorCode(_ event: OtaStatusEvent) -> String? {
|
|
2239
|
+
guard event.status.lowercased() == "failed",
|
|
2240
|
+
event.errorMessage?.lowercased() == "battery_low"
|
|
2241
|
+
else {
|
|
2242
|
+
return nil
|
|
2243
|
+
}
|
|
2244
|
+
return "battery_low"
|
|
2245
|
+
}
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
3
|
enum OtaManifestDefaults {
|
|
4
|
-
private static let sdkOtaReleaseBaseUrl = "https://github.com/Mentra-Community/MentraOS/releases/download/bluetooth-sdk-ota"
|
|
5
4
|
// ASG builds before 39 ignore ota_start.ota_version_url, so SDK checks must
|
|
6
5
|
// use the same legacy production manifest those glasses will install from.
|
|
7
6
|
static let legacyProdOtaVersionUrl = "https://ota.mentraglass.com/prod_live_version.json"
|
|
8
7
|
|
|
9
8
|
static func defaultOtaVersionUrl() throws -> String {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
else {
|
|
9
|
+
let manifestUrl = GeneratedReleaseMetadata.otaManifestUrl.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
10
|
+
guard !manifestUrl.isEmpty else {
|
|
13
11
|
throw BluetoothSdkError(
|
|
14
|
-
code: "
|
|
15
|
-
message: "
|
|
12
|
+
code: "ota_manifest_unconfigured",
|
|
13
|
+
message: "This source-built Bluetooth SDK has no embedded OTA manifest. Configure one with the debug API."
|
|
16
14
|
)
|
|
17
15
|
}
|
|
18
|
-
return
|
|
16
|
+
return manifestUrl
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
19
|
|
|
@@ -7,6 +7,23 @@ public enum MicPreference: String {
|
|
|
7
7
|
case bluetooth
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
struct MicHealth {
|
|
11
|
+
let sequenceGapEvents: Int64
|
|
12
|
+
let decodeFailures: Int64
|
|
13
|
+
let lastLc3ReceivedAt: Int64?
|
|
14
|
+
let lastPcmProducedAt: Int64?
|
|
15
|
+
|
|
16
|
+
var dictionary: [String: Any] {
|
|
17
|
+
var values: [String: Any] = [
|
|
18
|
+
"sequenceGapEvents": sequenceGapEvents,
|
|
19
|
+
"decodeFailures": decodeFailures,
|
|
20
|
+
]
|
|
21
|
+
if let lastLc3ReceivedAt { values["lastLc3ReceivedAt"] = lastLc3ReceivedAt }
|
|
22
|
+
if let lastPcmProducedAt { values["lastPcmProducedAt"] = lastPcmProducedAt }
|
|
23
|
+
return values
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
10
27
|
public struct LocalTranscriptionEvent: CustomStringConvertible {
|
|
11
28
|
public let text: String
|
|
12
29
|
public let isFinal: Bool
|
|
@@ -73,6 +73,30 @@ public struct SpeakingStatusEvent: CustomStringConvertible {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
public struct MicHealthEvent: CustomStringConvertible {
|
|
77
|
+
public let reason: String
|
|
78
|
+
public let sequenceGapEvents: Int
|
|
79
|
+
public let decodeFailures: Int
|
|
80
|
+
public let lastLc3ReceivedAt: Int?
|
|
81
|
+
public let lastPcmProducedAt: Int?
|
|
82
|
+
public let timestamp: Int
|
|
83
|
+
public let values: [String: Any]
|
|
84
|
+
|
|
85
|
+
public init(values: [String: Any]) {
|
|
86
|
+
reason = stringValue(values, "reason") ?? ""
|
|
87
|
+
sequenceGapEvents = intValue(values["sequenceGapEvents"]) ?? 0
|
|
88
|
+
decodeFailures = intValue(values["decodeFailures"]) ?? 0
|
|
89
|
+
lastLc3ReceivedAt = intValue(values["lastLc3ReceivedAt"])
|
|
90
|
+
lastPcmProducedAt = intValue(values["lastPcmProducedAt"])
|
|
91
|
+
timestamp = intValue(values["timestamp"]) ?? Int(Date().timeIntervalSince1970 * 1000)
|
|
92
|
+
self.values = values
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public var description: String {
|
|
96
|
+
"MicHealthEvent(reason: \(reason), sequenceGapEvents: \(sequenceGapEvents), decodeFailures: \(decodeFailures))"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
76
100
|
public struct OtaStartAckEvent: CustomStringConvertible {
|
|
77
101
|
public let timestamp: Int?
|
|
78
102
|
public let values: [String: Any]
|
|
@@ -216,6 +240,7 @@ public enum BluetoothEvent: CustomStringConvertible {
|
|
|
216
240
|
case touch(TouchEvent)
|
|
217
241
|
case voiceActivityDetectionStatus(VoiceActivityDetectionStatusEvent)
|
|
218
242
|
case speakingStatus(SpeakingStatusEvent)
|
|
243
|
+
case micHealth(MicHealthEvent)
|
|
219
244
|
case wifiStatus(WifiStatusEvent)
|
|
220
245
|
case hotspotStatus(HotspotStatusEvent)
|
|
221
246
|
case hotspotError(HotspotErrorEvent)
|
|
@@ -244,6 +269,8 @@ public enum BluetoothEvent: CustomStringConvertible {
|
|
|
244
269
|
event.description
|
|
245
270
|
case let .speakingStatus(event):
|
|
246
271
|
event.description
|
|
272
|
+
case let .micHealth(event):
|
|
273
|
+
event.description
|
|
247
274
|
case let .wifiStatus(event):
|
|
248
275
|
event.description
|
|
249
276
|
case let .hotspotStatus(event):
|