@mentra/bluetooth-sdk 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +26 -22
  2. package/android/.project +28 -0
  3. package/android/build.gradle +5 -9
  4. package/android/lc3Lib/.project +28 -0
  5. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +54 -33
  6. package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +48 -10
  7. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +27 -36
  8. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +8 -4
  9. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +170 -14
  10. package/android/src/main/java/com/mentra/bluetoothsdk/audio/AudioModels.kt +6 -6
  11. package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +69 -10
  12. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +5 -3
  13. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +2 -1
  14. package/android/src/main/java/com/mentra/bluetoothsdk/debug/BleTraceLogger.kt +149 -0
  15. package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +13 -0
  16. package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +297 -0
  17. package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/MentraPhotoReceiverModule.kt +120 -0
  18. package/android/src/main/java/com/mentra/bluetoothsdk/services/Foreground.kt +13 -0
  19. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +1 -1
  20. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +3 -1
  21. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +1 -1
  22. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +269 -28
  23. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +1 -1
  24. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +8 -3
  25. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +4 -1
  26. package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +14 -12
  27. package/android/src/main/java/com/mentra/bluetoothsdk/status/RuntimeState.kt +4 -2
  28. package/android/src/main/java/com/mentra/bluetoothsdk/streaming/StreamModels.kt +131 -6
  29. package/android/src/main/java/com/mentra/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +1 -3
  30. package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunkReassembler.java +105 -0
  31. package/build/BluetoothSdk.types.d.ts +107 -48
  32. package/build/BluetoothSdk.types.d.ts.map +1 -1
  33. package/build/BluetoothSdk.types.js +4 -0
  34. package/build/BluetoothSdk.types.js.map +1 -1
  35. package/build/_private/BluetoothSdkModule.d.ts +8 -6
  36. package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
  37. package/build/_private/BluetoothSdkModule.js +58 -9
  38. package/build/_private/BluetoothSdkModule.js.map +1 -1
  39. package/build/index.d.ts +2 -2
  40. package/build/index.d.ts.map +1 -1
  41. package/build/index.js +6 -5
  42. package/build/index.js.map +1 -1
  43. package/build/photo-receiver/MentraPhotoReceiver.types.d.ts +18 -0
  44. package/build/photo-receiver/MentraPhotoReceiver.types.d.ts.map +1 -0
  45. package/build/photo-receiver/MentraPhotoReceiver.types.js +2 -0
  46. package/build/photo-receiver/MentraPhotoReceiver.types.js.map +1 -0
  47. package/build/photo-receiver/MentraPhotoReceiverModule.d.ts +10 -0
  48. package/build/photo-receiver/MentraPhotoReceiverModule.d.ts.map +1 -0
  49. package/build/photo-receiver/MentraPhotoReceiverModule.js +3 -0
  50. package/build/photo-receiver/MentraPhotoReceiverModule.js.map +1 -0
  51. package/build/photo-receiver/MentraPhotoReceiverModule.web.d.ts +10 -0
  52. package/build/photo-receiver/MentraPhotoReceiverModule.web.d.ts.map +1 -0
  53. package/build/photo-receiver/MentraPhotoReceiverModule.web.js +12 -0
  54. package/build/photo-receiver/MentraPhotoReceiverModule.web.js.map +1 -0
  55. package/build/photo-receiver/index.d.ts +3 -0
  56. package/build/photo-receiver/index.d.ts.map +1 -0
  57. package/build/photo-receiver/index.js +3 -0
  58. package/build/photo-receiver/index.js.map +1 -0
  59. package/build/react/useMentraBluetooth.d.ts +5 -3
  60. package/build/react/useMentraBluetooth.d.ts.map +1 -1
  61. package/build/react/useMentraBluetooth.js +15 -4
  62. package/build/react/useMentraBluetooth.js.map +1 -1
  63. package/expo-module.config.json +5 -2
  64. package/ios/BluetoothSdkModule.swift +59 -26
  65. package/ios/LocalPhotoUploadServer.swift +411 -0
  66. package/ios/MentraBluetoothSDK.podspec +8 -5
  67. package/ios/MentraPhotoReceiverModule.swift +147 -0
  68. package/ios/Source/Audio/AudioModels.swift +10 -10
  69. package/ios/Source/Bridge.swift +42 -12
  70. package/ios/Source/Camera/CameraModels.swift +74 -19
  71. package/ios/Source/DeviceManager.swift +23 -98
  72. package/ios/Source/DeviceStore.swift +12 -4
  73. package/ios/Source/Events/BluetoothEvents.swift +37 -0
  74. package/ios/Source/MentraBluetoothSDK.swift +135 -14
  75. package/ios/Source/Status/DeviceStatus.swift +12 -4
  76. package/ios/Source/Status/RuntimeState.swift +22 -13
  77. package/ios/Source/Streaming/StreamModels.swift +239 -45
  78. package/ios/Source/controllers/ControllerManager.swift +3 -3
  79. package/ios/Source/controllers/R1.swift +9 -3
  80. package/ios/Source/sgcs/G1.swift +5 -4
  81. package/ios/Source/sgcs/G2.swift +5 -6
  82. package/ios/Source/sgcs/Mach1.swift +1 -1
  83. package/ios/Source/sgcs/MentraLive.swift +183 -22
  84. package/ios/Source/sgcs/MentraNex.swift +1 -1
  85. package/ios/Source/sgcs/SGCManager.swift +11 -3
  86. package/ios/Source/sgcs/Simulated.swift +2 -2
  87. package/ios/Source/stt/SherpaOnnxTranscriber.swift +1 -4
  88. package/ios/Source/utils/MessageChunkReassembler.swift +89 -0
  89. package/package.json +6 -1
  90. package/src/BluetoothSdk.types.ts +133 -62
  91. package/src/_private/BluetoothSdkModule.ts +79 -26
  92. package/src/index.ts +15 -8
  93. package/src/photo-receiver/MentraPhotoReceiver.types.ts +20 -0
  94. package/src/photo-receiver/MentraPhotoReceiverModule.ts +14 -0
  95. package/src/photo-receiver/MentraPhotoReceiverModule.web.ts +20 -0
  96. package/src/photo-receiver/index.ts +2 -0
  97. package/src/react/useMentraBluetooth.ts +19 -7
  98. package/android/src/main/java/com/mentra/bluetoothsdk/stt/VadGateSpeechPolicy.kt +0 -221
  99. package/ios/Packages/VAD/Common/VAD/VADQuality.swift +0 -41
  100. package/ios/Packages/VAD/Common/VAD/VADState.swift +0 -26
  101. package/ios/Packages/VAD/Common/VAD/VADStrategy.swift +0 -29
  102. package/ios/Packages/VAD/Common/VAD/VADType.swift +0 -14
  103. package/ios/Packages/VAD/Data/Configuration.swift +0 -68
  104. package/ios/Packages/VAD/Data/FrameSize.swift +0 -39
  105. package/ios/Packages/VAD/Data/Record.swift +0 -13
  106. package/ios/Packages/VAD/Data/Result.swift +0 -22
  107. package/ios/Packages/VAD/Data/SampleRate.swift +0 -48
  108. package/ios/Packages/VAD/Silero/Model/silero_vad.onnx +0 -0
  109. package/ios/Packages/VAD/Silero/SileroVAD.swift +0 -284
  110. package/ios/Packages/VAD/Silero/SileroVADStrategy.swift +0 -64
@@ -4,18 +4,18 @@ public struct StreamVideoConfig {
4
4
  public let width: Int?
5
5
  public let height: Int?
6
6
  public let bitrate: Int?
7
- public let frameRate: Int?
7
+ public let fps: Int?
8
8
 
9
9
  public init(
10
10
  width: Int? = nil,
11
11
  height: Int? = nil,
12
12
  bitrate: Int? = nil,
13
- frameRate: Int? = nil
13
+ fps: Int? = nil
14
14
  ) {
15
15
  self.width = width
16
16
  self.height = height
17
17
  self.bitrate = bitrate
18
- self.frameRate = frameRate
18
+ self.fps = fps
19
19
  }
20
20
 
21
21
  var dictionary: [String: Any] {
@@ -23,7 +23,7 @@ public struct StreamVideoConfig {
23
23
  if let width { values["width"] = width }
24
24
  if let height { values["height"] = height }
25
25
  if let bitrate { values["bitrate"] = bitrate }
26
- if let frameRate { values["frameRate"] = frameRate }
26
+ if let fps { values["frameRate"] = fps }
27
27
  return values
28
28
  }
29
29
 
@@ -33,7 +33,7 @@ public struct StreamVideoConfig {
33
33
  width: intValue(values["width"]),
34
34
  height: intValue(values["height"]),
35
35
  bitrate: intValue(values["bitrate"]),
36
- frameRate: intValue(values["frameRate"])
36
+ fps: intValue(values["fps"])
37
37
  )
38
38
  }
39
39
  }
@@ -76,6 +76,139 @@ public struct StreamAudioConfig {
76
76
  }
77
77
  }
78
78
 
79
+ public struct StreamResolvedVideoConfig: Equatable {
80
+ public let width: Int
81
+ public let height: Int
82
+ public let captureWidth: Int?
83
+ public let captureHeight: Int?
84
+ public let bitrate: Int
85
+ public let fps: Int
86
+
87
+ public init(
88
+ width: Int,
89
+ height: Int,
90
+ captureWidth: Int? = nil,
91
+ captureHeight: Int? = nil,
92
+ bitrate: Int,
93
+ fps: Int
94
+ ) {
95
+ self.width = width
96
+ self.height = height
97
+ self.captureWidth = captureWidth
98
+ self.captureHeight = captureHeight
99
+ self.bitrate = bitrate
100
+ self.fps = fps
101
+ }
102
+
103
+ init?(values: [String: Any]?) {
104
+ guard let values,
105
+ let width = intValue(values["width"]),
106
+ let height = intValue(values["height"]),
107
+ let bitrate = intValue(values["bitrate"]),
108
+ let fps = intValue(values["fps"])
109
+ else {
110
+ return nil
111
+ }
112
+ self.init(
113
+ width: width,
114
+ height: height,
115
+ captureWidth: intValue(values["captureWidth"]),
116
+ captureHeight: intValue(values["captureHeight"]),
117
+ bitrate: bitrate,
118
+ fps: fps
119
+ )
120
+ }
121
+
122
+ var values: [String: Any] {
123
+ var values: [String: Any] = [
124
+ "width": width,
125
+ "height": height,
126
+ "bitrate": bitrate,
127
+ "fps": fps,
128
+ ]
129
+ if let captureWidth { values["captureWidth"] = captureWidth }
130
+ if let captureHeight { values["captureHeight"] = captureHeight }
131
+ return values
132
+ }
133
+ }
134
+
135
+ public struct StreamResolvedAudioConfig: Equatable {
136
+ public let bitrate: Int?
137
+ public let sampleRate: Int?
138
+ public let echoCancellation: Bool?
139
+ public let noiseSuppression: Bool?
140
+
141
+ public init(
142
+ bitrate: Int? = nil,
143
+ sampleRate: Int? = nil,
144
+ echoCancellation: Bool? = nil,
145
+ noiseSuppression: Bool? = nil
146
+ ) {
147
+ self.bitrate = bitrate
148
+ self.sampleRate = sampleRate
149
+ self.echoCancellation = echoCancellation
150
+ self.noiseSuppression = noiseSuppression
151
+ }
152
+
153
+ init?(values: [String: Any]?) {
154
+ guard let values else { return nil }
155
+ self.init(
156
+ bitrate: intValue(values["bitrate"]),
157
+ sampleRate: intValue(values["sampleRate"]),
158
+ echoCancellation: boolValue(values, "echoCancellation"),
159
+ noiseSuppression: boolValue(values, "noiseSuppression")
160
+ )
161
+ }
162
+
163
+ var values: [String: Any] {
164
+ var values: [String: Any] = [:]
165
+ if let bitrate { values["bitrate"] = bitrate }
166
+ if let sampleRate { values["sampleRate"] = sampleRate }
167
+ if let echoCancellation { values["echoCancellation"] = echoCancellation }
168
+ if let noiseSuppression { values["noiseSuppression"] = noiseSuppression }
169
+ return values
170
+ }
171
+ }
172
+
173
+ public enum StreamTransport: String, Equatable {
174
+ case rtmp
175
+ case srt
176
+ case whip
177
+ }
178
+
179
+ public struct StreamResolvedConfig: Equatable {
180
+ public let transport: StreamTransport?
181
+ public let video: StreamResolvedVideoConfig?
182
+ public let audio: StreamResolvedAudioConfig?
183
+
184
+ public init(
185
+ transport: StreamTransport? = nil,
186
+ video: StreamResolvedVideoConfig? = nil,
187
+ audio: StreamResolvedAudioConfig? = nil
188
+ ) {
189
+ self.transport = transport
190
+ self.video = video
191
+ self.audio = audio
192
+ }
193
+
194
+ init?(values: [String: Any]?) {
195
+ guard let values else { return nil }
196
+ self.init(
197
+ transport: stringValue(values, "transport").flatMap(StreamTransport.init(rawValue:)),
198
+ video: StreamResolvedVideoConfig(values: values["video"] as? [String: Any]),
199
+ audio: StreamResolvedAudioConfig(values: values["audio"] as? [String: Any])
200
+ )
201
+ }
202
+
203
+ var values: [String: Any] {
204
+ var values: [String: Any] = [:]
205
+ if let transport { values["transport"] = transport.rawValue }
206
+ if let video { values["video"] = video.values }
207
+ if let audio { values["audio"] = audio.values }
208
+ return values
209
+ }
210
+ }
211
+
79
212
  public struct StreamRequest {
80
213
  public let streamUrl: String
81
214
  public let streamId: String
@@ -90,7 +223,7 @@ public struct StreamRequest {
90
223
  streamUrl: String,
91
224
  streamId: String = "",
92
225
  keepAlive: Bool = true,
93
- keepAliveIntervalSeconds: Int = 15,
226
+ keepAliveIntervalSeconds: Int = 5,
94
227
  sound: Bool = true,
95
228
  video: StreamVideoConfig? = nil,
96
229
  audio: StreamAudioConfig? = nil,
@@ -115,7 +248,7 @@ public struct StreamRequest {
115
248
  ?? "",
116
249
  streamId: values["streamId"] as? String ?? "",
117
250
  keepAlive: values["keepAlive"] as? Bool ?? true,
118
- keepAliveIntervalSeconds: intValue(values["keepAliveIntervalSeconds"]) ?? 15,
251
+ keepAliveIntervalSeconds: intValue(values["keepAliveIntervalSeconds"]) ?? 5,
119
252
  sound: values["sound"] as? Bool ?? true,
120
253
  video: StreamVideoConfig(values: values["video"] as? [String: Any]),
121
254
  audio: StreamAudioConfig(values: values["audio"] as? [String: Any]),
@@ -125,6 +258,7 @@ public struct StreamRequest {
125
258
 
126
259
  public var values: [String: Any] {
127
260
  var values = extraValues
261
+ values.removeValue(forKey: "keepAliveMode")
128
262
  values["type"] = "start_stream"
129
263
  values["streamUrl"] = streamUrl
130
264
  values["streamId"] = streamId
@@ -143,12 +277,18 @@ public struct StreamRequest {
143
277
  }
144
278
  }
145
279
 
146
- public struct StreamKeepAliveRequest {
147
- public let streamId: String
148
- public let ackId: String
149
- public let extraValues: [String: Any]
280
+ extension StreamRequest {
281
+ var isExternallyManagedKeepAlive: Bool {
282
+ stringValue(extraValues, "keepAliveMode") == "external"
283
+ }
284
+ }
285
+
286
+ struct StreamKeepAliveRequest {
287
+ let streamId: String
288
+ let ackId: String
289
+ let extraValues: [String: Any]
150
290
 
151
- public init(streamId: String, ackId: String, extraValues: [String: Any] = [:]) {
291
+ init(streamId: String, ackId: String, extraValues: [String: Any] = [:]) {
152
292
  self.streamId = streamId
153
293
  self.ackId = ackId
154
294
  self.extraValues = extraValues
@@ -162,7 +302,7 @@ public struct StreamKeepAliveRequest {
162
302
  )
163
303
  }
164
304
 
165
- public var values: [String: Any] {
305
+ var values: [String: Any] {
166
306
  var values = extraValues
167
307
  values["type"] = "keep_stream_alive"
168
308
  values["streamId"] = streamId
@@ -213,17 +353,33 @@ public enum StreamStatusKind: String, Equatable {
213
353
  }
214
354
 
215
355
  public enum StreamStatus: CustomStringConvertible, Equatable {
216
- case lifecycle(state: StreamState, streamId: String?, timestamp: Int?)
217
- case reconnecting(streamId: String?, attempt: Int, maxAttempts: Int, reason: String, timestamp: Int?)
218
- case reconnected(streamId: String?, attempt: Int, timestamp: Int?)
219
- case reconnectFailed(streamId: String?, maxAttempts: Int, timestamp: Int?)
220
- case error(streamId: String?, errorDetails: String, timestamp: Int?)
221
- case snapshot(state: StreamState, streaming: Bool, reconnecting: Bool, streamId: String?, attempt: Int?, timestamp: Int?)
356
+ case lifecycle(state: StreamState, streamId: String?, timestamp: Int?, resolvedConfig: StreamResolvedConfig?)
357
+ case reconnecting(
358
+ streamId: String?,
359
+ attempt: Int,
360
+ maxAttempts: Int,
361
+ reason: String,
362
+ timestamp: Int?,
363
+ resolvedConfig: StreamResolvedConfig?
364
+ )
365
+ case reconnected(streamId: String?, attempt: Int, timestamp: Int?, resolvedConfig: StreamResolvedConfig?)
366
+ case reconnectFailed(streamId: String?, maxAttempts: Int, timestamp: Int?, resolvedConfig: StreamResolvedConfig?)
367
+ case error(streamId: String?, errorDetails: String, timestamp: Int?, resolvedConfig: StreamResolvedConfig?)
368
+ case snapshot(
369
+ state: StreamState,
370
+ streaming: Bool,
371
+ reconnecting: Bool,
372
+ streamId: String?,
373
+ attempt: Int?,
374
+ timestamp: Int?,
375
+ resolvedConfig: StreamResolvedConfig?
376
+ )
222
377
 
223
378
  public init(values: [String: Any]) {
224
379
  let rawState = stringValue(values, "status")
225
380
  let streamId = stringValue(values, "streamId")
226
381
  let timestamp = intValue(values["timestamp"])
382
+ let resolvedConfig = StreamResolvedConfig(values: values["resolvedConfig"] as? [String: Any])
227
383
  let attempt = optionalIntValue(values, "attempt")
228
384
  let maxAttempts = optionalIntValue(values, "maxAttempts") ?? 0
229
385
 
@@ -237,7 +393,8 @@ public enum StreamStatus: CustomStringConvertible, Equatable {
237
393
  reconnecting: reconnecting,
238
394
  streamId: streamId,
239
395
  attempt: attempt,
240
- timestamp: timestamp
396
+ timestamp: timestamp,
397
+ resolvedConfig: resolvedConfig
241
398
  )
242
399
  return
243
400
  }
@@ -246,7 +403,8 @@ public enum StreamStatus: CustomStringConvertible, Equatable {
246
403
  self = .error(
247
404
  streamId: streamId,
248
405
  errorDetails: rawState.map { "Unknown stream status: \($0)" } ?? "Missing stream status",
249
- timestamp: timestamp
406
+ timestamp: timestamp,
407
+ resolvedConfig: resolvedConfig
250
408
  )
251
409
  return
252
410
  }
@@ -258,21 +416,38 @@ public enum StreamStatus: CustomStringConvertible, Equatable {
258
416
  attempt: attempt ?? 0,
259
417
  maxAttempts: maxAttempts,
260
418
  reason: stringValue(values, "reason") ?? "",
261
- timestamp: timestamp
419
+ timestamp: timestamp,
420
+ resolvedConfig: resolvedConfig
262
421
  )
263
422
  case .reconnected:
264
- self = .reconnected(streamId: streamId, attempt: attempt ?? 0, timestamp: timestamp)
423
+ self = .reconnected(
424
+ streamId: streamId,
425
+ attempt: attempt ?? 0,
426
+ timestamp: timestamp,
427
+ resolvedConfig: resolvedConfig
428
+ )
265
429
  case .reconnectFailed:
266
- self = .reconnectFailed(streamId: streamId, maxAttempts: maxAttempts, timestamp: timestamp)
430
+ self = .reconnectFailed(
431
+ streamId: streamId,
432
+ maxAttempts: maxAttempts,
433
+ timestamp: timestamp,
434
+ resolvedConfig: resolvedConfig
435
+ )
267
436
  case .error:
268
437
  self = .error(
269
438
  streamId: streamId,
270
439
  errorDetails: stringValue(values, "errorDetails")
271
440
  ?? (rawState == "error_not_streaming" ? "not_streaming" : "Unknown stream error"),
272
- timestamp: timestamp
441
+ timestamp: timestamp,
442
+ resolvedConfig: resolvedConfig
273
443
  )
274
444
  default:
275
- self = .lifecycle(state: state, streamId: streamId, timestamp: timestamp)
445
+ self = .lifecycle(
446
+ state: state,
447
+ streamId: streamId,
448
+ timestamp: timestamp,
449
+ resolvedConfig: resolvedConfig
450
+ )
276
451
  }
277
452
  }
278
453
 
@@ -291,7 +466,7 @@ public enum StreamStatus: CustomStringConvertible, Equatable {
291
466
 
292
467
  public var state: StreamState {
293
468
  switch self {
294
- case let .lifecycle(state, _, _):
469
+ case let .lifecycle(state, _, _, _):
295
470
  state
296
471
  case .reconnecting:
297
472
  .reconnecting
@@ -301,35 +476,47 @@ public enum StreamStatus: CustomStringConvertible, Equatable {
301
476
  .reconnectFailed
302
477
  case .error:
303
478
  .error
304
- case let .snapshot(state, _, _, _, _, _):
479
+ case let .snapshot(state, _, _, _, _, _, _):
305
480
  state
306
481
  }
307
482
  }
308
483
 
309
484
  public var streamId: String? {
310
485
  switch self {
311
- case let .lifecycle(_, streamId, _),
312
- let .reconnecting(streamId, _, _, _, _),
313
- let .reconnected(streamId, _, _),
314
- let .reconnectFailed(streamId, _, _),
315
- let .error(streamId, _, _),
316
- let .snapshot(_, _, _, streamId, _, _):
486
+ case let .lifecycle(_, streamId, _, _),
487
+ let .reconnecting(streamId, _, _, _, _, _),
488
+ let .reconnected(streamId, _, _, _),
489
+ let .reconnectFailed(streamId, _, _, _),
490
+ let .error(streamId, _, _, _),
491
+ let .snapshot(_, _, _, streamId, _, _, _):
317
492
  streamId
318
493
  }
319
494
  }
320
495
 
321
496
  public var timestamp: Int? {
322
497
  switch self {
323
- case let .lifecycle(_, _, timestamp),
324
- let .reconnecting(_, _, _, _, timestamp),
325
- let .reconnected(_, _, timestamp),
326
- let .reconnectFailed(_, _, timestamp),
327
- let .error(_, _, timestamp),
328
- let .snapshot(_, _, _, _, _, timestamp):
498
+ case let .lifecycle(_, _, timestamp, _),
499
+ let .reconnecting(_, _, _, _, timestamp, _),
500
+ let .reconnected(_, _, timestamp, _),
501
+ let .reconnectFailed(_, _, timestamp, _),
502
+ let .error(_, _, timestamp, _),
503
+ let .snapshot(_, _, _, _, _, timestamp, _):
329
504
  timestamp
330
505
  }
331
506
  }
332
507
 
508
+ public var resolvedConfig: StreamResolvedConfig? {
509
+ switch self {
510
+ case let .lifecycle(_, _, _, resolvedConfig),
511
+ let .reconnecting(_, _, _, _, _, resolvedConfig),
512
+ let .reconnected(_, _, _, resolvedConfig),
513
+ let .reconnectFailed(_, _, _, resolvedConfig),
514
+ let .error(_, _, _, resolvedConfig),
515
+ let .snapshot(_, _, _, _, _, _, resolvedConfig):
516
+ resolvedConfig
517
+ }
518
+ }
519
+
333
520
  public var values: [String: Any] {
334
521
  var values: [String: Any] = [
335
522
  "kind": kind.rawValue,
@@ -341,21 +528,24 @@ public enum StreamStatus: CustomStringConvertible, Equatable {
341
528
  if let timestamp {
342
529
  values["timestamp"] = timestamp
343
530
  }
531
+ if let resolvedConfig {
532
+ values["resolvedConfig"] = resolvedConfig.values
533
+ }
344
534
 
345
535
  switch self {
346
536
  case .lifecycle:
347
537
  break
348
- case let .reconnecting(_, attempt, maxAttempts, reason, _):
538
+ case let .reconnecting(_, attempt, maxAttempts, reason, _, _):
349
539
  values["attempt"] = attempt
350
540
  values["maxAttempts"] = maxAttempts
351
541
  values["reason"] = reason
352
- case let .reconnected(_, attempt, _):
542
+ case let .reconnected(_, attempt, _, _):
353
543
  values["attempt"] = attempt
354
- case let .reconnectFailed(_, maxAttempts, _):
544
+ case let .reconnectFailed(_, maxAttempts, _, _):
355
545
  values["maxAttempts"] = maxAttempts
356
- case let .error(_, errorDetails, _):
546
+ case let .error(_, errorDetails, _, _):
357
547
  values["errorDetails"] = errorDetails
358
- case let .snapshot(_, streaming, reconnecting, _, attempt, _):
548
+ case let .snapshot(_, streaming, reconnecting, _, attempt, _, _):
359
549
  values["streaming"] = streaming
360
550
  values["reconnecting"] = reconnecting
361
551
  if let attempt {
@@ -390,6 +580,10 @@ public struct StreamStatusEvent: CustomStringConvertible {
390
580
  status.streamId
391
581
  }
392
582
 
583
+ public var resolvedConfig: StreamResolvedConfig? {
584
+ status.resolvedConfig
585
+ }
586
+
393
587
  public var values: [String: Any] {
394
588
  var values = status.values
395
589
  values["type"] = "stream_status"
@@ -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
23
+ compress: String?, flash: Bool, sound: Bool, exposureTimeNs: Double?, iso: Int?
24
24
  )
25
25
  func startStream(_ message: [String: Any])
26
26
  func stopStream()
@@ -153,8 +153,8 @@ extension ControllerManager {
153
153
  DeviceStore.shared.get("glasses", "micEnabled") as? Bool ?? false
154
154
  }
155
155
 
156
- var vadEnabled: Bool {
157
- DeviceStore.shared.get("glasses", "vadEnabled") as? Bool ?? false
156
+ var voiceActivityDetectionEnabled: Bool {
157
+ DeviceStore.shared.get("glasses", "voiceActivityDetectionEnabled") as? Bool ?? true
158
158
  }
159
159
 
160
160
  var batteryLevel: Int {
@@ -499,11 +499,14 @@ class R1: NSObject, ControllerManager {
499
499
 
500
500
  func sendIncidentId(_: String, apiBaseUrl _: String?) {}
501
501
  func setMicEnabled(_: Bool) {}
502
- func sortMicRanking(list: [String]) -> [String] { return list }
502
+ func sortMicRanking(list: [String]) -> [String] {
503
+ return list
504
+ }
505
+
503
506
  func sendJson(_: [String: Any], wakeUp _: Bool, requireAck _: Bool) {}
504
507
  func requestPhoto(
505
508
  _: String, appId _: String, size _: String?, webhookUrl _: String?, authToken _: String?,
506
- compress _: String?, flash _: Bool, sound _: Bool
509
+ compress _: String?, flash _: Bool, sound _: Bool, exposureTimeNs _: Double?, iso _: Int?
507
510
  ) {}
508
511
  func startVideoRecording(requestId _: String, save _: Bool, flash _: Bool, sound _: Bool) {}
509
512
  func stopVideoRecording(requestId _: String) {}
@@ -518,7 +521,10 @@ class R1: NSObject, ControllerManager {
518
521
  func clearDisplay() {}
519
522
  func sendTextWall(_: String) {}
520
523
  func sendDoubleTextWall(_: String, _: String) {}
521
- func displayBitmap(base64ImageData _: String) async -> Bool { return false }
524
+ func displayBitmap(base64ImageData _: String) async -> Bool {
525
+ return false
526
+ }
527
+
522
528
  func showDashboard() {}
523
529
  func setDashboardPosition(_: Int, _: Int) {}
524
530
  func setHeadUpAngle(_: Int) {}
@@ -278,7 +278,7 @@ class G1: NSObject, SGCManager {
278
278
 
279
279
  func requestPhoto(
280
280
  _: String, appId _: String, size _: String?, webhookUrl _: String?, authToken _: String?,
281
- compress _: String?, flash _: Bool, sound _: Bool
281
+ compress _: String?, flash _: Bool, sound _: Bool, exposureTimeNs _: Double?, iso _: Int?
282
282
  ) {}
283
283
 
284
284
  func startStream(_: [String: Any]) {}
@@ -1813,7 +1813,8 @@ extension G1 {
1813
1813
  ctx.draw(cgImage, in: CGRect(x: offsetX, y: offsetY, width: scaledW, height: scaledH))
1814
1814
 
1815
1815
  guard let renderedImage = ctx.makeImage(),
1816
- let pixels = renderedImage.dataProvider?.data as Data? else {
1816
+ let pixels = renderedImage.dataProvider?.data as Data?
1817
+ else {
1817
1818
  Bridge.log("G1: convertToG1Bmp - failed to get pixel data")
1818
1819
  return nil
1819
1820
  }
@@ -1850,9 +1851,9 @@ extension G1 {
1850
1851
  bmp.append(contentsOf: [0xFF, 0xFF, 0xFF, 0x00]) // white
1851
1852
 
1852
1853
  // Pixel data (bottom-up row order for BMP)
1853
- for row in (0..<height).reversed() {
1854
+ for row in (0 ..< height).reversed() {
1854
1855
  var rowData = [UInt8](repeating: 0, count: rowBytes)
1855
- for col in 0..<width {
1856
+ for col in 0 ..< width {
1856
1857
  let pixelIndex = row * width + col
1857
1858
  let gray = pixels[pixelIndex]
1858
1859
  if gray >= 128 {
@@ -1454,8 +1454,7 @@ class G2: NSObject, SGCManager {
1454
1454
  DeviceStore.shared.apply("glasses", "bluetoothName", btName)
1455
1455
  DeviceStore.shared.apply("glasses", "deviceModel", DeviceTypes.G2)
1456
1456
 
1457
- DeviceStore.shared.apply("glasses", "connected", true)
1458
- DeviceStore.shared.apply("glasses", "fullyBooted", true)
1457
+ self.setFullyConnected()
1459
1458
 
1460
1459
  // connnect a controller if we have one:
1461
1460
  self.connectController()
@@ -2332,8 +2331,8 @@ class G2: NSObject, SGCManager {
2332
2331
  if useNativeDashboard && dashboardShowing > 0 {
2333
2332
  return
2334
2333
  }
2335
- if (!pageCreated || !pageHasTextContainer) {
2336
- DeviceManager.shared.sendCurrentState()// should re-create the page if needed
2334
+ if !pageCreated || !pageHasTextContainer {
2335
+ DeviceManager.shared.sendCurrentState() // should re-create the page if needed
2337
2336
  }
2338
2337
  let msg = EvenHubProto.audioControlMessage(enable: true)
2339
2338
  self.sendEvenHubCommand(msg)
@@ -2648,7 +2647,7 @@ class G2: NSObject, SGCManager {
2648
2647
 
2649
2648
  func requestPhoto(
2650
2649
  _: String, appId _: String, size _: String?, webhookUrl _: String?, authToken _: String?,
2651
- compress _: String?, flash _: Bool, sound _: Bool
2650
+ compress _: String?, flash _: Bool, sound _: Bool, exposureTimeNs _: Double?, iso _: Int?
2652
2651
  ) {}
2653
2652
  func startVideoRecording(requestId _: String, save _: Bool, flash _: Bool, sound _: Bool) {}
2654
2653
  func startStream(_: [String: Any]) {}
@@ -3442,7 +3441,7 @@ class G2: NSObject, SGCManager {
3442
3441
  }
3443
3442
  // do nothing this time since we just closed the dashboard
3444
3443
  dashboardShowing -= 1
3445
- if (dashboardShowing < 0) {
3444
+ if dashboardShowing < 0 {
3446
3445
  dashboardShowing = 0
3447
3446
  }
3448
3447
  }
@@ -17,7 +17,7 @@ class Mach1: UltraliteBaseViewController, SGCManager {
17
17
 
18
18
  func requestPhoto(
19
19
  _: String, appId _: String, size _: String?, webhookUrl _: String?, authToken _: String?,
20
- compress _: String?, flash _: Bool, sound _: Bool
20
+ compress _: String?, flash _: Bool, sound _: Bool, exposureTimeNs _: Double?, iso _: Int?
21
21
  ) {}
22
22
 
23
23
  func sendGalleryMode() {}