@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
|
@@ -58,6 +58,12 @@ class ObservableStore {
|
|
|
58
58
|
values["\(Self.normalizeCategory(category)).\(key)"]
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
func wouldSkipSet(_ category: String, _ key: String, _ value: Any) -> Bool {
|
|
62
|
+
let fullKey = "\(Self.normalizeCategory(category)).\(key)"
|
|
63
|
+
guard let oldValue = values[fullKey] else { return false }
|
|
64
|
+
return areEqual(oldValue, value)
|
|
65
|
+
}
|
|
66
|
+
|
|
61
67
|
func getCategory(_ category: String) -> [String: Any] {
|
|
62
68
|
var result: [String: Any] = [:]
|
|
63
69
|
let prefix = "\(Self.normalizeCategory(category))."
|
|
@@ -24,7 +24,7 @@ public struct LocalTranscriptionEvent: CustomStringConvertible {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
public struct MicPcmEvent: CustomStringConvertible {
|
|
27
|
-
public static let sampleRate =
|
|
27
|
+
public static let sampleRate = 16000
|
|
28
28
|
public static let bitsPerSample = 16
|
|
29
29
|
public static let channels = 1
|
|
30
30
|
public static let encoding = "pcm_s16le"
|
|
@@ -43,7 +43,8 @@ public struct MicPcmEvent: CustomStringConvertible {
|
|
|
43
43
|
let bitsPerSample = intValue(values["bitsPerSample"]) ?? Self.bitsPerSample
|
|
44
44
|
let channels = intValue(values["channels"]) ?? Self.channels
|
|
45
45
|
let encoding = values["encoding"] as? String ?? Self.encoding
|
|
46
|
-
let voiceActivityDetectionEnabled =
|
|
46
|
+
let voiceActivityDetectionEnabled =
|
|
47
|
+
boolValue(values, "voiceActivityDetectionEnabled") ?? BluetoothSdkDefaults.voiceActivityDetectionEnabled
|
|
47
48
|
|
|
48
49
|
var normalized = values
|
|
49
50
|
normalized["type"] = "mic_pcm"
|
|
@@ -69,7 +70,7 @@ public struct MicPcmEvent: CustomStringConvertible {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
public struct MicLc3Event: CustomStringConvertible {
|
|
72
|
-
public static let sampleRate =
|
|
73
|
+
public static let sampleRate = 16000
|
|
73
74
|
public static let channels = 1
|
|
74
75
|
public static let encoding = "lc3"
|
|
75
76
|
public static let frameDurationMs = 10
|
|
@@ -95,7 +96,8 @@ public struct MicLc3Event: CustomStringConvertible {
|
|
|
95
96
|
let frameSizeBytes = intValue(values["frameSizeBytes"]) ?? Self.defaultFrameSizeBytes
|
|
96
97
|
let bitrate = intValue(values["bitrate"]) ?? frameSizeBytes * 8 * (1000 / frameDurationMs)
|
|
97
98
|
let packetizedFromGlasses = boolValue(values, "packetizedFromGlasses") ?? false
|
|
98
|
-
let voiceActivityDetectionEnabled =
|
|
99
|
+
let voiceActivityDetectionEnabled =
|
|
100
|
+
boolValue(values, "voiceActivityDetectionEnabled") ?? BluetoothSdkDefaults.voiceActivityDetectionEnabled
|
|
99
101
|
|
|
100
102
|
var normalized = values
|
|
101
103
|
normalized["type"] = "mic_lc3"
|
|
@@ -132,8 +134,8 @@ public struct GlassesMediaVolumeGetResult: CustomStringConvertible {
|
|
|
132
134
|
public let values: [String: Any]
|
|
133
135
|
|
|
134
136
|
public init(values: [String: Any]) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
level = intValue(values["level"])
|
|
138
|
+
statusCode = intValue(values["statusCode"])
|
|
137
139
|
self.values = values
|
|
138
140
|
}
|
|
139
141
|
|
|
@@ -149,7 +151,7 @@ public struct GlassesMediaVolumeSetResult: CustomStringConvertible {
|
|
|
149
151
|
public let values: [String: Any]
|
|
150
152
|
|
|
151
153
|
public init(values: [String: Any]) {
|
|
152
|
-
|
|
154
|
+
statusCode = intValue(values["statusCode"])
|
|
153
155
|
self.values = values
|
|
154
156
|
}
|
|
155
157
|
|
|
@@ -39,24 +39,101 @@ public struct ButtonVideoRecordingSettings {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
public enum CameraRoiPosition: Int {
|
|
43
|
+
case center = 0
|
|
44
|
+
case bottom = 1
|
|
45
|
+
case top = 2
|
|
46
|
+
|
|
47
|
+
public var label: String {
|
|
48
|
+
switch self {
|
|
49
|
+
case .center:
|
|
50
|
+
return "center"
|
|
51
|
+
case .bottom:
|
|
52
|
+
return "bottom"
|
|
53
|
+
case .top:
|
|
54
|
+
return "top"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public static func from(rawValue: Int?) -> CameraRoiPosition {
|
|
59
|
+
guard let rawValue else {
|
|
60
|
+
return .center
|
|
61
|
+
}
|
|
62
|
+
return CameraRoiPosition(rawValue: rawValue) ?? .center
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
42
66
|
public struct CameraFov {
|
|
43
|
-
public static let minFov =
|
|
67
|
+
public static let minFov = 62
|
|
44
68
|
public static let maxFov = 118
|
|
45
69
|
public static let defaultFov = 102
|
|
46
|
-
public static let
|
|
47
|
-
public static let
|
|
48
|
-
public static let
|
|
70
|
+
public static let narrowFov = 82
|
|
71
|
+
public static let defaultRoiPosition = CameraRoiPosition.center
|
|
72
|
+
public static let narrow = CameraFov(
|
|
73
|
+
fov: CameraFov.narrowFov,
|
|
74
|
+
roiPosition: CameraFov.defaultRoiPosition
|
|
75
|
+
)
|
|
76
|
+
public static let standard = CameraFov(
|
|
77
|
+
fov: CameraFov.defaultFov,
|
|
78
|
+
roiPosition: CameraFov.defaultRoiPosition
|
|
79
|
+
)
|
|
80
|
+
public static let wide = CameraFov(
|
|
81
|
+
fov: CameraFov.maxFov,
|
|
82
|
+
roiPosition: CameraFov.defaultRoiPosition
|
|
83
|
+
)
|
|
49
84
|
|
|
50
85
|
public let fov: Int
|
|
51
|
-
public let roiPosition:
|
|
86
|
+
public let roiPosition: CameraRoiPosition
|
|
52
87
|
|
|
53
|
-
public init(fov: Int = CameraFov.defaultFov, roiPosition:
|
|
88
|
+
public init(fov: Int = CameraFov.defaultFov, roiPosition: CameraRoiPosition = CameraFov.defaultRoiPosition) {
|
|
54
89
|
self.fov = min(max(fov, CameraFov.minFov), CameraFov.maxFov)
|
|
55
|
-
self.roiPosition =
|
|
90
|
+
self.roiPosition = roiPosition
|
|
56
91
|
}
|
|
57
92
|
|
|
58
93
|
var value: [String: Int] {
|
|
59
|
-
["fov": fov, "roi_position": roiPosition]
|
|
94
|
+
["fov": fov, "roi_position": roiPosition.rawValue]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public struct CameraFovResult: CustomStringConvertible {
|
|
99
|
+
public let requestId: String
|
|
100
|
+
public let fov: Int
|
|
101
|
+
public let roiPosition: CameraRoiPosition
|
|
102
|
+
public let timestamp: Int
|
|
103
|
+
|
|
104
|
+
public var values: [String: Any] {
|
|
105
|
+
[
|
|
106
|
+
"requestId": requestId,
|
|
107
|
+
"fov": fov,
|
|
108
|
+
"roiPosition": roiPosition.label,
|
|
109
|
+
"timestamp": timestamp,
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public var description: String {
|
|
114
|
+
"CameraFovResult(fov: \(fov), roiPosition: \(roiPosition.label))"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static func from(ack: SettingsAckEvent, fallback: CameraFov) throws -> CameraFovResult {
|
|
118
|
+
if ack.status == "error" {
|
|
119
|
+
throw BluetoothError(
|
|
120
|
+
code: ack.errorCode ?? "camera_fov_failed",
|
|
121
|
+
message: ack.errorMessage ?? "Camera FOV request failed."
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
if !ack.hardwareApplied {
|
|
125
|
+
throw BluetoothError(
|
|
126
|
+
code: "camera_fov_not_applied",
|
|
127
|
+
message: "Camera FOV was saved but not applied to hardware."
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return CameraFovResult(
|
|
132
|
+
requestId: ack.requestId,
|
|
133
|
+
fov: ack.fov ?? fallback.fov,
|
|
134
|
+
roiPosition: CameraRoiPosition.from(rawValue: ack.roiPosition ?? fallback.roiPosition.rawValue),
|
|
135
|
+
timestamp: ack.timestamp
|
|
136
|
+
)
|
|
60
137
|
}
|
|
61
138
|
}
|
|
62
139
|
|
|
@@ -68,6 +145,7 @@ public struct PhotoRequest {
|
|
|
68
145
|
public let authToken: String?
|
|
69
146
|
public let compress: PhotoCompression?
|
|
70
147
|
public let flash: Bool
|
|
148
|
+
public let save: Bool
|
|
71
149
|
public let sound: Bool
|
|
72
150
|
/// Sensor exposure time for this capture only (ns), or nil for auto exposure
|
|
73
151
|
public let exposureTimeNs: Double?
|
|
@@ -82,6 +160,7 @@ public struct PhotoRequest {
|
|
|
82
160
|
authToken: String? = nil,
|
|
83
161
|
compress: PhotoCompression? = nil,
|
|
84
162
|
flash: Bool = true,
|
|
163
|
+
save: Bool = false,
|
|
85
164
|
sound: Bool,
|
|
86
165
|
exposureTimeNs: Double? = nil,
|
|
87
166
|
iso: Int? = nil
|
|
@@ -93,6 +172,7 @@ public struct PhotoRequest {
|
|
|
93
172
|
self.authToken = authToken
|
|
94
173
|
self.compress = compress
|
|
95
174
|
self.flash = flash
|
|
175
|
+
self.save = save
|
|
96
176
|
self.sound = sound
|
|
97
177
|
self.exposureTimeNs = exposureTimeNs
|
|
98
178
|
self.iso = iso
|
|
@@ -144,11 +224,58 @@ public struct VideoRecordingRequest {
|
|
|
144
224
|
public let requestId: String
|
|
145
225
|
public let save: Bool
|
|
146
226
|
public let sound: Bool
|
|
227
|
+
// Optional per-recording overrides; 0 means "use the saved button-video default".
|
|
228
|
+
public let width: Int
|
|
229
|
+
public let height: Int
|
|
230
|
+
public let fps: Int
|
|
147
231
|
|
|
148
|
-
public init(
|
|
232
|
+
public init(
|
|
233
|
+
requestId: String, save: Bool, sound: Bool, width: Int = 0, height: Int = 0, fps: Int = 0
|
|
234
|
+
) {
|
|
149
235
|
self.requestId = requestId
|
|
150
236
|
self.save = save
|
|
151
237
|
self.sound = sound
|
|
238
|
+
self.width = width
|
|
239
|
+
self.height = height
|
|
240
|
+
self.fps = fps
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
public struct VideoRecordingStatusEvent: CustomStringConvertible {
|
|
245
|
+
public let values: [String: Any]
|
|
246
|
+
|
|
247
|
+
public init(values: [String: Any]) {
|
|
248
|
+
var values = values
|
|
249
|
+
values["type"] = "video_recording_status"
|
|
250
|
+
self.values = values
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public var requestId: String {
|
|
254
|
+
stringValue(values, "requestId") ?? ""
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
public var success: Bool {
|
|
258
|
+
boolValue(values, "success") ?? false
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
public var status: String {
|
|
262
|
+
stringValue(values, "status") ?? ""
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
public var details: String? {
|
|
266
|
+
stringValue(values, "details")
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
public var timestamp: Int {
|
|
270
|
+
intValue(values["timestamp"]) ?? Int(Date().timeIntervalSince1970 * 1000)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
public var data: [String: Any]? {
|
|
274
|
+
values["data"] as? [String: Any]
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public var description: String {
|
|
278
|
+
"VideoRecordingStatusEvent(requestId: \(requestId), status: \(status), success: \(success))"
|
|
152
279
|
}
|
|
153
280
|
}
|
|
154
281
|
|
|
@@ -158,24 +285,39 @@ public enum PhotoResponse: CustomStringConvertible, Equatable {
|
|
|
158
285
|
case error
|
|
159
286
|
}
|
|
160
287
|
|
|
161
|
-
case success(
|
|
288
|
+
case success(
|
|
289
|
+
requestId: String,
|
|
290
|
+
uploadUrl: String,
|
|
291
|
+
photoUrl: String?,
|
|
292
|
+
statusUrl: String?,
|
|
293
|
+
contentType: String?,
|
|
294
|
+
fileSizeBytes: Int?,
|
|
295
|
+
timestamp: Int
|
|
296
|
+
)
|
|
162
297
|
case error(requestId: String, errorCode: String?, errorMessage: String, timestamp: Int)
|
|
163
298
|
|
|
164
299
|
public init(values: [String: Any]) {
|
|
165
300
|
let requestId = stringValue(values, "requestId") ?? ""
|
|
166
301
|
let timestamp = intValue(values["timestamp"]) ?? Int(Date().timeIntervalSince1970 * 1000)
|
|
167
302
|
let state = stringValue(values, "state")?.lowercased()
|
|
168
|
-
|
|
303
|
+
let success = state == State.success.rawValue || boolValue(values, "success") == true
|
|
304
|
+
if success {
|
|
169
305
|
self = .success(
|
|
170
306
|
requestId: requestId,
|
|
171
307
|
uploadUrl: stringValue(values, "uploadUrl") ?? "",
|
|
308
|
+
photoUrl: stringValue(values, "photoUrl"),
|
|
309
|
+
statusUrl: stringValue(values, "statusUrl"),
|
|
310
|
+
contentType: stringValue(values, "contentType") ?? stringValue(values, "mimeType"),
|
|
311
|
+
fileSizeBytes: intValue(values["fileSizeBytes"]) ?? intValue(values["bytes"])
|
|
312
|
+
?? intValue(values["size"]),
|
|
172
313
|
timestamp: timestamp
|
|
173
314
|
)
|
|
174
315
|
} else {
|
|
175
316
|
self = .error(
|
|
176
317
|
requestId: requestId,
|
|
177
318
|
errorCode: stringValue(values, "errorCode"),
|
|
178
|
-
errorMessage: stringValue(values, "errorMessage") ?? "
|
|
319
|
+
errorMessage: stringValue(values, "errorMessage") ?? stringValue(values, "error")
|
|
320
|
+
?? "Unknown photo error",
|
|
179
321
|
timestamp: timestamp
|
|
180
322
|
)
|
|
181
323
|
}
|
|
@@ -192,27 +334,40 @@ public enum PhotoResponse: CustomStringConvertible, Equatable {
|
|
|
192
334
|
|
|
193
335
|
public var requestId: String {
|
|
194
336
|
switch self {
|
|
195
|
-
case let .success(requestId, _, _), let .error(requestId, _, _, _):
|
|
337
|
+
case let .success(requestId, _, _, _, _, _, _), let .error(requestId, _, _, _):
|
|
196
338
|
requestId
|
|
197
339
|
}
|
|
198
340
|
}
|
|
199
341
|
|
|
200
342
|
public var timestamp: Int {
|
|
201
343
|
switch self {
|
|
202
|
-
case let .success(_, _, timestamp), let .error(_, _, _, timestamp):
|
|
344
|
+
case let .success(_, _, _, _, _, _, timestamp), let .error(_, _, _, timestamp):
|
|
203
345
|
timestamp
|
|
204
346
|
}
|
|
205
347
|
}
|
|
206
348
|
|
|
207
349
|
public var values: [String: Any] {
|
|
208
350
|
switch self {
|
|
209
|
-
case let .success(requestId, uploadUrl, timestamp):
|
|
210
|
-
|
|
351
|
+
case let .success(requestId, uploadUrl, photoUrl, statusUrl, contentType, fileSizeBytes, timestamp):
|
|
352
|
+
var values: [String: Any] = [
|
|
211
353
|
"state": State.success.rawValue,
|
|
212
354
|
"requestId": requestId,
|
|
213
355
|
"uploadUrl": uploadUrl,
|
|
214
356
|
"timestamp": timestamp,
|
|
215
357
|
]
|
|
358
|
+
if let photoUrl, !photoUrl.isEmpty {
|
|
359
|
+
values["photoUrl"] = photoUrl
|
|
360
|
+
}
|
|
361
|
+
if let statusUrl, !statusUrl.isEmpty {
|
|
362
|
+
values["statusUrl"] = statusUrl
|
|
363
|
+
}
|
|
364
|
+
if let contentType, !contentType.isEmpty {
|
|
365
|
+
values["contentType"] = contentType
|
|
366
|
+
}
|
|
367
|
+
if let fileSizeBytes {
|
|
368
|
+
values["fileSizeBytes"] = fileSizeBytes
|
|
369
|
+
}
|
|
370
|
+
return values
|
|
216
371
|
case let .error(requestId, errorCode, errorMessage, timestamp):
|
|
217
372
|
var values: [String: Any] = [
|
|
218
373
|
"state": State.error.rawValue,
|
|
@@ -287,6 +442,18 @@ public struct PhotoStatusEvent: CustomStringConvertible {
|
|
|
287
442
|
values["resolvedConfig"] as? [String: Any]
|
|
288
443
|
}
|
|
289
444
|
|
|
445
|
+
public var requestedCaptureConfig: [String: Any]? {
|
|
446
|
+
values["requestedCaptureConfig"] as? [String: Any]
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
public var meteredPreview: [String: Any]? {
|
|
450
|
+
values["meteredPreview"] as? [String: Any]
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
public var captureMetadata: [String: Any]? {
|
|
454
|
+
values["captureMetadata"] as? [String: Any]
|
|
455
|
+
}
|
|
456
|
+
|
|
290
457
|
public var errorCode: String? {
|
|
291
458
|
stringValue(values, "errorCode")
|
|
292
459
|
}
|
|
@@ -299,3 +466,45 @@ public struct PhotoStatusEvent: CustomStringConvertible {
|
|
|
299
466
|
"PhotoStatusEvent(requestId: \(requestId), status: \(status))"
|
|
300
467
|
}
|
|
301
468
|
}
|
|
469
|
+
|
|
470
|
+
public struct GalleryStatusEvent: CustomStringConvertible {
|
|
471
|
+
public let values: [String: Any]
|
|
472
|
+
|
|
473
|
+
public init(values: [String: Any]) {
|
|
474
|
+
var values = values
|
|
475
|
+
values["type"] = "gallery_status"
|
|
476
|
+
self.values = values
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
public var photos: Int {
|
|
480
|
+
intValue(values["photos"]) ?? 0
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
public var videos: Int {
|
|
484
|
+
intValue(values["videos"]) ?? 0
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
public var total: Int {
|
|
488
|
+
intValue(values["total"]) ?? 0
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
public var totalSize: Int? {
|
|
492
|
+
intValue(values["totalSize"]) ?? intValue(values["total_size"])
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
public var hasContent: Bool {
|
|
496
|
+
boolValue(values, "hasContent", "has_content") ?? false
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
public var cameraBusy: Bool {
|
|
500
|
+
boolValue(values, "cameraBusy", "camera_busy") ?? false
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
public var cameraBusyReason: String? {
|
|
504
|
+
stringValue(values, "cameraBusyReason", "camera_busy")
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
public var description: String {
|
|
508
|
+
"GalleryStatusEvent(total: \(total), photos: \(photos), videos: \(videos))"
|
|
509
|
+
}
|
|
510
|
+
}
|
|
@@ -20,7 +20,7 @@ protocol ControllerManager {
|
|
|
20
20
|
|
|
21
21
|
func requestPhoto(
|
|
22
22
|
_ requestId: String, appId: String, size: String?, webhookUrl: String?, authToken: String?,
|
|
23
|
-
compress: String?, flash: Bool, sound: Bool, exposureTimeNs: Double?, iso: Int?
|
|
23
|
+
compress: String?, flash: Bool, save: Bool, sound: Bool, exposureTimeNs: Double?, iso: Int?
|
|
24
24
|
)
|
|
25
25
|
func startStream(_ message: [String: Any])
|
|
26
26
|
func stopStream()
|
|
@@ -41,7 +41,7 @@ protocol ControllerManager {
|
|
|
41
41
|
func clearDisplay()
|
|
42
42
|
func sendTextWall(_ text: String)
|
|
43
43
|
func sendDoubleTextWall(_ top: String, _ bottom: String)
|
|
44
|
-
func displayBitmap(base64ImageData: String) async -> Bool
|
|
44
|
+
func displayBitmap(base64ImageData: String, x: Int32?, y: Int32?, width: Int32?, height: Int32?) async -> Bool
|
|
45
45
|
func showDashboard()
|
|
46
46
|
func setDashboardPosition(_ height: Int, _ depth: Int)
|
|
47
47
|
|
|
@@ -154,7 +154,8 @@ extension ControllerManager {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
var voiceActivityDetectionEnabled: Bool {
|
|
157
|
-
DeviceStore.shared.get("glasses", "voiceActivityDetectionEnabled") as? Bool
|
|
157
|
+
DeviceStore.shared.get("glasses", "voiceActivityDetectionEnabled") as? Bool
|
|
158
|
+
?? BluetoothSdkDefaults.voiceActivityDetectionEnabled
|
|
158
159
|
}
|
|
159
160
|
|
|
160
161
|
var batteryLevel: Int {
|
|
@@ -506,7 +506,7 @@ class R1: NSObject, ControllerManager {
|
|
|
506
506
|
func sendJson(_: [String: Any], wakeUp _: Bool, requireAck _: Bool) {}
|
|
507
507
|
func requestPhoto(
|
|
508
508
|
_: String, appId _: String, size _: String?, webhookUrl _: String?, authToken _: String?,
|
|
509
|
-
compress _: String?, flash _: Bool, sound _: Bool, exposureTimeNs _: Double?, iso _: Int?
|
|
509
|
+
compress _: String?, flash _: Bool, save _: Bool, sound _: Bool, exposureTimeNs _: Double?, iso _: Int?
|
|
510
510
|
) {}
|
|
511
511
|
func startVideoRecording(requestId _: String, save _: Bool, flash _: Bool, sound _: Bool) {}
|
|
512
512
|
func stopVideoRecording(requestId _: String) {}
|
|
@@ -521,7 +521,7 @@ class R1: NSObject, ControllerManager {
|
|
|
521
521
|
func clearDisplay() {}
|
|
522
522
|
func sendTextWall(_: String) {}
|
|
523
523
|
func sendDoubleTextWall(_: String, _: String) {}
|
|
524
|
-
func displayBitmap(base64ImageData _: String) async -> Bool {
|
|
524
|
+
func displayBitmap(base64ImageData _: String, x _: Int32? = nil, y _: Int32? = nil, width _: Int32? = nil, height _: Int32? = nil) async -> Bool {
|
|
525
525
|
return false
|
|
526
526
|
}
|
|
527
527
|
|
|
@@ -767,7 +767,7 @@ extension R1: CBPeripheralDelegate {
|
|
|
767
767
|
) {
|
|
768
768
|
Bridge.log("R1: didUpdateValueFor1: \(characteristic.uuid)")
|
|
769
769
|
guard let data = characteristic.value, !data.isEmpty, error == nil else { return }
|
|
770
|
-
Bridge.log("R1: didUpdateValueFor: \(characteristic.uuid) data: \(data.
|
|
770
|
+
Bridge.log("R1: didUpdateValueFor: \(characteristic.uuid) data: \(data.hexEncodedString())")
|
|
771
771
|
|
|
772
772
|
DispatchQueue.main.async { [weak self] in
|
|
773
773
|
guard let self = self else { return }
|
|
@@ -49,7 +49,8 @@ public struct VoiceActivityDetectionStatusEvent: CustomStringConvertible {
|
|
|
49
49
|
public let values: [String: Any]
|
|
50
50
|
|
|
51
51
|
public init(values: [String: Any]) {
|
|
52
|
-
voiceActivityDetectionEnabled =
|
|
52
|
+
voiceActivityDetectionEnabled =
|
|
53
|
+
boolValue(values, "voiceActivityDetectionEnabled") ?? BluetoothSdkDefaults.voiceActivityDetectionEnabled
|
|
53
54
|
self.values = values
|
|
54
55
|
}
|
|
55
56
|
|
|
@@ -72,6 +73,166 @@ public struct SpeakingStatusEvent: CustomStringConvertible {
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
public struct OtaUpdateAvailableEvent: CustomStringConvertible {
|
|
77
|
+
public let versionCode: Int?
|
|
78
|
+
public let versionName: String?
|
|
79
|
+
public let updates: [String]
|
|
80
|
+
public let totalSize: Int?
|
|
81
|
+
public let cacheReady: Bool?
|
|
82
|
+
public let values: [String: Any]
|
|
83
|
+
|
|
84
|
+
public init(values: [String: Any]) {
|
|
85
|
+
versionCode = intValue(values["version_code"])
|
|
86
|
+
versionName = stringValue(values, "version_name")
|
|
87
|
+
updates = values["updates"] as? [String] ?? []
|
|
88
|
+
totalSize = intValue(values["total_size"])
|
|
89
|
+
cacheReady = boolValue(values, "cache_ready")
|
|
90
|
+
self.values = values
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public var description: String {
|
|
94
|
+
"OtaUpdateAvailableEvent(versionName: \(versionName ?? "unknown"), updates: \(updates.joined(separator: ",")))"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public struct OtaStartAckEvent: CustomStringConvertible {
|
|
99
|
+
public let timestamp: Int?
|
|
100
|
+
public let values: [String: Any]
|
|
101
|
+
|
|
102
|
+
public init(values: [String: Any]) {
|
|
103
|
+
timestamp = intValue(values["timestamp"])
|
|
104
|
+
self.values = values
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public var description: String {
|
|
108
|
+
"OtaStartAckEvent(timestamp: \(timestamp.map(String.init) ?? "unknown"))"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public struct OtaStatusEvent: CustomStringConvertible {
|
|
113
|
+
public let sessionId: String
|
|
114
|
+
public let totalSteps: Int
|
|
115
|
+
public let currentStep: Int
|
|
116
|
+
public let stepType: String
|
|
117
|
+
public let phase: String
|
|
118
|
+
public let stepPercent: Int
|
|
119
|
+
public let overallPercent: Int
|
|
120
|
+
public let status: String
|
|
121
|
+
public let errorMessage: String?
|
|
122
|
+
public let glassesTimeMs: Int?
|
|
123
|
+
public let values: [String: Any]
|
|
124
|
+
|
|
125
|
+
public init(values: [String: Any]) {
|
|
126
|
+
sessionId = stringValue(values, "session_id") ?? ""
|
|
127
|
+
totalSteps = intValue(values["total_steps"]) ?? 0
|
|
128
|
+
currentStep = intValue(values["current_step"]) ?? 0
|
|
129
|
+
stepType = stringValue(values, "step_type") ?? ""
|
|
130
|
+
phase = stringValue(values, "phase") ?? ""
|
|
131
|
+
stepPercent = intValue(values["step_percent"]) ?? 0
|
|
132
|
+
overallPercent = intValue(values["overall_percent"]) ?? 0
|
|
133
|
+
status = stringValue(values, "status") ?? ""
|
|
134
|
+
errorMessage = stringValue(values, "error_message")
|
|
135
|
+
glassesTimeMs = intValue(values["glasses_time_ms"])
|
|
136
|
+
self.values = values
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public var description: String {
|
|
140
|
+
"OtaStatusEvent(status: \(status), overallPercent: \(overallPercent))"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
public struct OtaQueryResult: CustomStringConvertible {
|
|
145
|
+
public let values: [String: Any]
|
|
146
|
+
|
|
147
|
+
public init(values: [String: Any]) {
|
|
148
|
+
self.values = values
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public var type: String {
|
|
152
|
+
stringValue(values, "type") ?? ""
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public var status: String? {
|
|
156
|
+
stringValue(values, "status")
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public var description: String {
|
|
160
|
+
"OtaQueryResult(type: \(type), status: \(status ?? "unknown"))"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public struct SettingsAckEvent: CustomStringConvertible {
|
|
165
|
+
public let values: [String: Any]
|
|
166
|
+
|
|
167
|
+
public init(values: [String: Any]) {
|
|
168
|
+
self.values = values
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public var requestId: String {
|
|
172
|
+
stringValue(values, "requestId") ?? ""
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public var setting: String {
|
|
176
|
+
stringValue(values, "setting") ?? ""
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public var status: String {
|
|
180
|
+
stringValue(values, "status") ?? "applied"
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public var timestamp: Int {
|
|
184
|
+
intValue(values["timestamp"]) ?? Int(Date().timeIntervalSince1970 * 1000)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public var fov: Int? {
|
|
188
|
+
intValue(values["fov"])
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public var roiPosition: Int? {
|
|
192
|
+
intValue(values["roiPosition"]) ?? intValue(values["roi_position"])
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
public var hardwareApplied: Bool {
|
|
196
|
+
boolValue(values, "hardwareApplied") ?? boolValue(values, "hardware_applied") ?? false
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public var errorCode: String? {
|
|
200
|
+
stringValue(values, "errorCode")
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
public var errorMessage: String? {
|
|
204
|
+
stringValue(values, "errorMessage")
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public var description: String {
|
|
208
|
+
"SettingsAckEvent(setting: \(setting), status: \(status))"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
public struct RgbLedControlResponseEvent: CustomStringConvertible {
|
|
213
|
+
public let values: [String: Any]
|
|
214
|
+
|
|
215
|
+
public init(values: [String: Any]) {
|
|
216
|
+
self.values = values
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public var requestId: String {
|
|
220
|
+
stringValue(values, "requestId") ?? ""
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
public var state: String {
|
|
224
|
+
stringValue(values, "state") ?? "error"
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public var errorCode: String? {
|
|
228
|
+
stringValue(values, "errorCode")
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
public var description: String {
|
|
232
|
+
"RgbLedControlResponseEvent(requestId: \(requestId), state: \(state))"
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
75
236
|
public enum BluetoothEvent: CustomStringConvertible {
|
|
76
237
|
case buttonPress(ButtonPressEvent)
|
|
77
238
|
case touch(TouchEvent)
|
|
@@ -82,8 +243,15 @@ public enum BluetoothEvent: CustomStringConvertible {
|
|
|
82
243
|
case hotspotError(HotspotErrorEvent)
|
|
83
244
|
case photoResponse(PhotoResponseEvent)
|
|
84
245
|
case photoStatus(PhotoStatusEvent)
|
|
246
|
+
case videoRecordingStatus(VideoRecordingStatusEvent)
|
|
247
|
+
case rgbLedControlResponse(RgbLedControlResponseEvent)
|
|
85
248
|
case streamStatus(StreamStatusEvent)
|
|
86
249
|
case keepAliveAck(KeepAliveAckEvent)
|
|
250
|
+
case otaUpdateAvailable(OtaUpdateAvailableEvent)
|
|
251
|
+
case otaStartAck(OtaStartAckEvent)
|
|
252
|
+
case otaStatus(OtaStatusEvent)
|
|
253
|
+
case settingsAck(SettingsAckEvent)
|
|
254
|
+
case versionInfo(VersionInfoResult)
|
|
87
255
|
case localTranscription(LocalTranscriptionEvent)
|
|
88
256
|
case raw(name: String, values: [String: Any])
|
|
89
257
|
|
|
@@ -107,10 +275,24 @@ public enum BluetoothEvent: CustomStringConvertible {
|
|
|
107
275
|
event.description
|
|
108
276
|
case let .photoStatus(event):
|
|
109
277
|
event.description
|
|
278
|
+
case let .videoRecordingStatus(event):
|
|
279
|
+
event.description
|
|
280
|
+
case let .rgbLedControlResponse(event):
|
|
281
|
+
event.description
|
|
110
282
|
case let .streamStatus(event):
|
|
111
283
|
event.description
|
|
112
284
|
case let .keepAliveAck(event):
|
|
113
285
|
event.description
|
|
286
|
+
case let .otaUpdateAvailable(event):
|
|
287
|
+
event.description
|
|
288
|
+
case let .otaStartAck(event):
|
|
289
|
+
event.description
|
|
290
|
+
case let .otaStatus(event):
|
|
291
|
+
event.description
|
|
292
|
+
case let .settingsAck(event):
|
|
293
|
+
event.description
|
|
294
|
+
case let .versionInfo(event):
|
|
295
|
+
event.description
|
|
114
296
|
case let .localTranscription(event):
|
|
115
297
|
event.description
|
|
116
298
|
case let .raw(name, values):
|