@mentra/bluetooth-sdk 0.1.2 → 0.1.3
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 +33 -19
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +13 -13
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +42 -18
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +19 -21
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +4 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +118 -103
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +110 -38
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +4 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +6 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +3 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +18 -18
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +4 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/Constants.kt +6 -6
- package/build/BluetoothSdk.types.d.ts +126 -27
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_internal.d.ts +12 -0
- package/build/_internal.d.ts.map +1 -0
- package/build/_internal.js +11 -0
- package/build/_internal.js.map +1 -0
- package/build/{BluetoothSdkModule.d.ts → _private/BluetoothSdkModule.d.ts} +19 -8
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -0
- package/build/{BluetoothSdkModule.js → _private/BluetoothSdkModule.js} +41 -26
- package/build/_private/BluetoothSdkModule.js.map +1 -0
- package/build/index.d.ts +4 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -4
- package/build/index.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +14 -9
- package/ios/Source/Bridge.swift +44 -12
- package/ios/Source/DeviceManager.swift +27 -26
- package/ios/Source/DeviceStore.swift +4 -4
- package/ios/Source/MentraBluetoothSDK.swift +250 -132
- package/ios/Source/controllers/ControllerManager.swift +5 -5
- package/ios/Source/controllers/R1.swift +3 -3
- package/ios/Source/services/PhoneMic.swift +5 -5
- package/ios/Source/sgcs/Frame.swift +1 -1
- package/ios/Source/sgcs/G1.swift +1 -1
- package/ios/Source/sgcs/G2.swift +3 -3
- package/ios/Source/sgcs/Mach1.swift +1 -1
- package/ios/Source/sgcs/MentraLive.swift +31 -33
- package/ios/Source/sgcs/MentraNex.swift +2 -2
- package/ios/Source/sgcs/SGCManager.swift +5 -5
- package/ios/Source/sgcs/Simulated.swift +3 -3
- package/ios/Source/utils/Constants.swift +6 -6
- package/ios/Source/utils/JSCExperiment.swift +8 -8
- package/ios/Source/utils/TarBz2Extractor.swift +2 -2
- package/package.json +13 -1
- package/src/BluetoothSdk.types.ts +186 -28
- package/src/_internal.ts +11 -0
- package/src/{BluetoothSdkModule.ts → _private/BluetoothSdkModule.ts} +71 -38
- package/src/index.ts +80 -4
- package/build/BluetoothSdkModule.d.ts.map +0 -1
- package/build/BluetoothSdkModule.js.map +0 -1
package/README.md
CHANGED
|
@@ -23,8 +23,8 @@ Use a development build or production native build. Expo Go cannot load this pac
|
|
|
23
23
|
## Install
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
bun add @mentra/bluetooth-sdk
|
|
27
|
+
bunx expo install expo-build-properties
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
For Expo apps, add the plugin to `app.json` or `app.config.ts`:
|
|
@@ -62,10 +62,10 @@ For Expo apps, add the plugin to `app.json` or `app.config.ts`:
|
|
|
62
62
|
Then regenerate native projects and run a development build:
|
|
63
63
|
|
|
64
64
|
```sh
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
bunx expo prebuild
|
|
66
|
+
bunx expo run:ios
|
|
67
67
|
# or
|
|
68
|
-
|
|
68
|
+
bunx expo run:android
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
## Permissions
|
|
@@ -107,7 +107,7 @@ iOS apps should include usage descriptions:
|
|
|
107
107
|
|
|
108
108
|
## Minimal Usage
|
|
109
109
|
|
|
110
|
-
`
|
|
110
|
+
Use `scan()` when your app needs to show a picker. It calls `onResults` every time the discovered list changes, then resolves with the final list after the timeout.
|
|
111
111
|
|
|
112
112
|
```ts
|
|
113
113
|
import BluetoothSdk, {
|
|
@@ -119,7 +119,19 @@ const removeGlassesListener = BluetoothSdk.onGlassesStatus((status) => {
|
|
|
119
119
|
console.log('Glasses status changed', status)
|
|
120
120
|
})
|
|
121
121
|
|
|
122
|
-
await BluetoothSdk.
|
|
122
|
+
const devices = await BluetoothSdk.scan(DeviceModels.MentraLive, {
|
|
123
|
+
timeoutMs: 10_000,
|
|
124
|
+
onResults: (nextDevices) => {
|
|
125
|
+
console.log('Nearby glasses:', nextDevices)
|
|
126
|
+
},
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const device = devices[0]
|
|
130
|
+
if (!device) {
|
|
131
|
+
throw new Error('No Mentra Live glasses found')
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
await BluetoothSdk.connect(device)
|
|
123
135
|
|
|
124
136
|
const glasses = await BluetoothSdk.getGlassesStatus()
|
|
125
137
|
if (isReadyGlassesConnectionStatus(glasses.connection)) {
|
|
@@ -166,7 +178,6 @@ await saveDeviceToYourAppStorage(null)
|
|
|
166
178
|
```ts
|
|
167
179
|
await BluetoothSdk.clearDisplay()
|
|
168
180
|
await BluetoothSdk.showDashboard()
|
|
169
|
-
await BluetoothSdk.setBrightness(60, false)
|
|
170
181
|
await BluetoothSdk.setDashboardPosition(4, 2)
|
|
171
182
|
|
|
172
183
|
await BluetoothSdk.requestWifiScan()
|
|
@@ -195,19 +206,18 @@ await BluetoothSdk.rgbLedControl(
|
|
|
195
206
|
## Photo Upload
|
|
196
207
|
|
|
197
208
|
```ts
|
|
198
|
-
await BluetoothSdk.
|
|
209
|
+
await BluetoothSdk.requestPhoto(
|
|
199
210
|
`photo-${Date.now()}`,
|
|
200
211
|
'com.example.app',
|
|
201
212
|
'medium',
|
|
202
213
|
'https://api.example.com/mentra/photo',
|
|
203
214
|
'optional-token',
|
|
204
215
|
'medium',
|
|
205
|
-
false,
|
|
206
216
|
true,
|
|
207
217
|
)
|
|
208
218
|
```
|
|
209
219
|
|
|
210
|
-
The webhook should accept multipart form data with a `photo` file and `requestId`. If `authToken` is provided, the uploader adds `Authorization: Bearer <token>`.
|
|
220
|
+
The webhook should accept multipart form data with a `photo` file and `requestId`. If `authToken` is provided, the uploader adds `Authorization: Bearer <token>`. The camera light is always enabled for photo capture.
|
|
211
221
|
|
|
212
222
|
## Streaming
|
|
213
223
|
|
|
@@ -229,7 +239,7 @@ await BluetoothSdk.keepStreamAlive({
|
|
|
229
239
|
await BluetoothSdk.stopStream()
|
|
230
240
|
```
|
|
231
241
|
|
|
232
|
-
Use `rtmp://` or `rtmps://` for RTMP, `srt://` for SRT, and `http://` or `https://` for WHIP/WebRTC ingest. Send keep-alives about every 15 seconds while streaming.
|
|
242
|
+
Use `rtmp://` or `rtmps://` for RTMP, `srt://` for SRT, and `http://` or `https://` for WHIP/WebRTC ingest. Send keep-alives about every 15 seconds while streaming. The camera light is always enabled while streaming.
|
|
233
243
|
|
|
234
244
|
## Events
|
|
235
245
|
|
|
@@ -245,19 +255,23 @@ const subscriptions = [
|
|
|
245
255
|
subscriptions.forEach((subscription) => subscription.remove())
|
|
246
256
|
```
|
|
247
257
|
|
|
248
|
-
Common event names include `button_press`, `touch_event`, `head_up`, `battery_status`, `wifi_status_change`, `hotspot_status_change`, `photo_response`, `gallery_status`, `stream_status`, `keep_alive_ack`, `mic_pcm`, `mic_lc3`, `local_transcription`, `rgb_led_control_response`, `audio_connected`, `audio_disconnected`,
|
|
258
|
+
Common event names include `button_press`, `touch_event`, `head_up`, `battery_status`, `wifi_status_change`, `hotspot_status_change`, `photo_response`, `gallery_status`, `stream_status`, `keep_alive_ack`, `mic_pcm`, `mic_lc3`, `local_transcription`, `rgb_led_control_response`, `audio_connected`, `audio_disconnected`, and `log`.
|
|
259
|
+
|
|
260
|
+
React Native event payload fields use camelCase. For example, `touch_event` includes `gestureName`, `photo_response` success includes `uploadUrl`, and `gallery_status` includes `hasContent` and `cameraBusy`.
|
|
261
|
+
|
|
262
|
+
Only the documented root import is supported for partner apps. Package subpaths or symbols with a leading underscore are private implementation details and can change without notice.
|
|
249
263
|
|
|
250
264
|
## Local SDK Development
|
|
251
265
|
|
|
252
|
-
For normal app development, install the published
|
|
266
|
+
For normal app development, install the published JavaScript package. For SDK development before a package release, install a local checkout and point Metro/native resolution at the same path:
|
|
253
267
|
|
|
254
268
|
```sh
|
|
255
|
-
|
|
256
|
-
MENTRA_BLUETOOTH_SDK_PACKAGE_PATH=/path/to/MentraOS/mobile/modules/bluetooth-sdk
|
|
269
|
+
bun add --no-save /path/to/MentraOS/mobile/modules/bluetooth-sdk
|
|
270
|
+
MENTRA_BLUETOOTH_SDK_PACKAGE_PATH=/path/to/MentraOS/mobile/modules/bluetooth-sdk bunx expo run:ios
|
|
257
271
|
```
|
|
258
272
|
|
|
259
|
-
Use `
|
|
273
|
+
Use `bunx expo run:android` for Android. Keep local paths in your shell or CI environment, not in committed app config.
|
|
260
274
|
|
|
261
|
-
## Example App
|
|
275
|
+
## Starter Example App
|
|
262
276
|
|
|
263
|
-
The
|
|
277
|
+
The [Mentra Bluetooth SDK Starter Kit](https://github.com/Mentra-Community/Mentra-Bluetooth-SDK-Starter-Kit) includes starter example apps for Android, iOS, and React Native / Expo. The React Native starter demonstrates scan/connect, display, camera photo upload, RTMP/SRT/WebRTC streaming, Wi-Fi/hotspot, microphone PCM, RGB LED, gallery-button mode, and console event inspection.
|
|
@@ -40,7 +40,7 @@ class BluetoothSdkModule : Module() {
|
|
|
40
40
|
"compatible_glasses_search_stop",
|
|
41
41
|
mapOf(
|
|
42
42
|
"type" to "compatible_glasses_search_stop",
|
|
43
|
-
"
|
|
43
|
+
"deviceModel" to deviceModel,
|
|
44
44
|
)
|
|
45
45
|
)
|
|
46
46
|
}
|
|
@@ -294,6 +294,8 @@ class BluetoothSdkModule : Module() {
|
|
|
294
294
|
sdk?.startScan(DeviceModel.fromDeviceType(model))
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
AsyncFunction("stopScan") { sdk?.stopScan() }
|
|
298
|
+
|
|
297
299
|
AsyncFunction("cancelConnectionAttempt") { sdk?.cancelConnectionAttempt() }
|
|
298
300
|
|
|
299
301
|
AsyncFunction("showDashboard") { sdk?.showDashboard() }
|
|
@@ -346,14 +348,13 @@ class BluetoothSdkModule : Module() {
|
|
|
346
348
|
|
|
347
349
|
AsyncFunction("queryGalleryStatus") { sdk?.queryGalleryStatus() }
|
|
348
350
|
|
|
349
|
-
AsyncFunction("
|
|
351
|
+
AsyncFunction("requestPhoto") {
|
|
350
352
|
requestId: String,
|
|
351
353
|
appId: String,
|
|
352
354
|
size: String,
|
|
353
355
|
webhookUrl: String,
|
|
354
356
|
authToken: String?,
|
|
355
357
|
compress: String,
|
|
356
|
-
flash: Boolean,
|
|
357
358
|
sound: Boolean ->
|
|
358
359
|
sdk?.requestPhoto(
|
|
359
360
|
PhotoRequest(
|
|
@@ -363,7 +364,6 @@ class BluetoothSdkModule : Module() {
|
|
|
363
364
|
webhookUrl = webhookUrl,
|
|
364
365
|
authToken = authToken,
|
|
365
366
|
compress = PhotoCompression.fromValue(compress),
|
|
366
|
-
flash = flash,
|
|
367
367
|
sound = sound,
|
|
368
368
|
)
|
|
369
369
|
)
|
|
@@ -387,8 +387,8 @@ class BluetoothSdkModule : Module() {
|
|
|
387
387
|
|
|
388
388
|
// MARK: - Video Recording Commands
|
|
389
389
|
|
|
390
|
-
AsyncFunction("startVideoRecording") { requestId: String, save: Boolean,
|
|
391
|
-
sdk?.startVideoRecording(VideoRecordingRequest(requestId, save,
|
|
390
|
+
AsyncFunction("startVideoRecording") { requestId: String, save: Boolean, sound: Boolean ->
|
|
391
|
+
sdk?.startVideoRecording(VideoRecordingRequest(requestId, save, sound))
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
AsyncFunction("stopVideoRecording") { requestId: String ->
|
|
@@ -449,8 +449,8 @@ class BluetoothSdkModule : Module() {
|
|
|
449
449
|
packageName: String?,
|
|
450
450
|
action: String,
|
|
451
451
|
color: String?,
|
|
452
|
-
|
|
453
|
-
|
|
452
|
+
onDurationMs: Int,
|
|
453
|
+
offDurationMs: Int,
|
|
454
454
|
count: Int ->
|
|
455
455
|
sdk?.rgbLedControl(
|
|
456
456
|
RgbLedRequest(
|
|
@@ -458,8 +458,8 @@ class BluetoothSdkModule : Module() {
|
|
|
458
458
|
packageName = packageName,
|
|
459
459
|
action = RgbLedAction.fromValue(action),
|
|
460
460
|
color = RgbLedColor.fromValue(color),
|
|
461
|
-
|
|
462
|
-
|
|
461
|
+
onDurationMs = onDurationMs,
|
|
462
|
+
offDurationMs = offDurationMs,
|
|
463
463
|
count = count,
|
|
464
464
|
)
|
|
465
465
|
)
|
|
@@ -504,9 +504,9 @@ class BluetoothSdkModule : Module() {
|
|
|
504
504
|
|
|
505
505
|
private fun Map<String, Any>?.toMentraDevice(): Device? {
|
|
506
506
|
val values = this ?: return null
|
|
507
|
-
val model = values["model"] as? String ?:
|
|
508
|
-
val name = values["name"] as? String ?:
|
|
509
|
-
val address = values["address"] as? String
|
|
507
|
+
val model = values["model"] as? String ?: return null
|
|
508
|
+
val name = values["name"] as? String ?: return null
|
|
509
|
+
val address = values["address"] as? String
|
|
510
510
|
val rssi = (values["rssi"] as? Number)?.toInt()
|
|
511
511
|
val id = values["id"] as? String
|
|
512
512
|
return Device(
|
|
@@ -121,7 +121,7 @@ public class Bridge private constructor() {
|
|
|
121
121
|
@JvmStatic
|
|
122
122
|
fun sendAudioConnected(deviceName: String) {
|
|
123
123
|
val data = HashMap<String, Any>()
|
|
124
|
-
data["
|
|
124
|
+
data["deviceName"] = deviceName
|
|
125
125
|
sendTypedMessage("audio_connected", data as Map<String, Any>)
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -211,19 +211,41 @@ public class Bridge private constructor() {
|
|
|
211
211
|
}
|
|
212
212
|
rssi?.let { put("rssi", it) }
|
|
213
213
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
.asReversed()
|
|
218
|
-
.distinctBy {
|
|
219
|
-
val model = it["model"] ?: it["deviceModel"] ?: deviceModel
|
|
220
|
-
val name = it["name"] ?: it["deviceName"] ?: return@distinctBy null
|
|
221
|
-
"$model:$name"
|
|
222
|
-
}
|
|
223
|
-
.asReversed()
|
|
214
|
+
// Keep the public searchResults array stable as glasses are added or removed.
|
|
215
|
+
// Duplicate discoveries refresh their existing row; only new glasses append.
|
|
216
|
+
val uniqueResults = mergeStableSearchResults(searchResults, newResult, deviceModel)
|
|
224
217
|
DeviceStore.set("bluetooth", "searchResults", uniqueResults)
|
|
225
218
|
}
|
|
226
219
|
|
|
220
|
+
private fun mergeStableSearchResults(
|
|
221
|
+
currentResults: List<Map<String, Any>>,
|
|
222
|
+
newResult: Map<String, Any>,
|
|
223
|
+
fallbackModel: String
|
|
224
|
+
): List<Map<String, Any>> {
|
|
225
|
+
val newKey = searchResultKey(newResult, fallbackModel) ?: return currentResults
|
|
226
|
+
val nextResults = currentResults.toMutableList()
|
|
227
|
+
val existingIndex =
|
|
228
|
+
nextResults.indexOfFirst { result ->
|
|
229
|
+
searchResultKey(result, fallbackModel) == newKey
|
|
230
|
+
}
|
|
231
|
+
if (existingIndex >= 0) {
|
|
232
|
+
nextResults[existingIndex] = newResult
|
|
233
|
+
} else {
|
|
234
|
+
nextResults += newResult
|
|
235
|
+
}
|
|
236
|
+
return nextResults
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private fun searchResultKey(result: Map<String, Any>, fallbackModel: String): String? {
|
|
240
|
+
val id = result["id"] as? String
|
|
241
|
+
if (!id.isNullOrBlank()) {
|
|
242
|
+
return id
|
|
243
|
+
}
|
|
244
|
+
val model = result["model"] as? String ?: fallbackModel
|
|
245
|
+
val name = result["name"] as? String ?: return null
|
|
246
|
+
return "$model:$name"
|
|
247
|
+
}
|
|
248
|
+
|
|
227
249
|
// MARK: - Hardware Events
|
|
228
250
|
|
|
229
251
|
/** Send button press event to React Native - matches iOS implementation */
|
|
@@ -255,8 +277,9 @@ public class Bridge private constructor() {
|
|
|
255
277
|
source: Int? = null
|
|
256
278
|
) {
|
|
257
279
|
val body = HashMap<String, Any>()
|
|
258
|
-
body["
|
|
259
|
-
body["
|
|
280
|
+
body["type"] = "touch_event"
|
|
281
|
+
body["deviceModel"] = deviceModel
|
|
282
|
+
body["gestureName"] = gestureName
|
|
260
283
|
body["timestamp"] = timestamp
|
|
261
284
|
if (source != null) {
|
|
262
285
|
body["source"] = source
|
|
@@ -277,8 +300,8 @@ public class Bridge private constructor() {
|
|
|
277
300
|
@JvmStatic
|
|
278
301
|
fun sendSwitchStatus(switchType: Int, value: Int, timestamp: Long) {
|
|
279
302
|
val body = HashMap<String, Any>()
|
|
280
|
-
body["
|
|
281
|
-
body["
|
|
303
|
+
body["switchType"] = switchType
|
|
304
|
+
body["switchValue"] = value
|
|
282
305
|
body["timestamp"] = timestamp
|
|
283
306
|
sendTypedMessage("switch_status", body)
|
|
284
307
|
}
|
|
@@ -301,6 +324,7 @@ public class Bridge private constructor() {
|
|
|
301
324
|
if (requestId.isEmpty()) return
|
|
302
325
|
try {
|
|
303
326
|
val body = HashMap<String, Any>()
|
|
327
|
+
body["type"] = "rgb_led_control_response"
|
|
304
328
|
body["requestId"] = requestId
|
|
305
329
|
body["state"] = if (success) "success" else "error"
|
|
306
330
|
if (!success) {
|
|
@@ -405,8 +429,8 @@ public class Bridge private constructor() {
|
|
|
405
429
|
galleryData["photos"] = photoCount
|
|
406
430
|
galleryData["videos"] = videoCount
|
|
407
431
|
galleryData["total"] = totalCount
|
|
408
|
-
galleryData["
|
|
409
|
-
galleryData["
|
|
432
|
+
galleryData["totalSize"] = totalSize
|
|
433
|
+
galleryData["hasContent"] = hasContent
|
|
410
434
|
|
|
411
435
|
sendTypedMessage("gallery_status", galleryData as Map<String, Any>)
|
|
412
436
|
}
|
|
@@ -427,7 +451,7 @@ public class Bridge private constructor() {
|
|
|
427
451
|
@JvmStatic
|
|
428
452
|
fun sendHotspotError(errorMessage: String, timestamp: Long) {
|
|
429
453
|
val eventBody = HashMap<String, Any>()
|
|
430
|
-
eventBody["
|
|
454
|
+
eventBody["errorMessage"] = errorMessage
|
|
431
455
|
eventBody["timestamp"] = timestamp
|
|
432
456
|
|
|
433
457
|
sendTypedMessage("hotspot_error", eventBody as Map<String, Any>)
|
|
@@ -169,17 +169,17 @@ class DeviceManager {
|
|
|
169
169
|
set(value) = DeviceStore.apply("bluetooth", "dashboard_depth", value)
|
|
170
170
|
|
|
171
171
|
private var galleryMode: Boolean
|
|
172
|
-
get() = DeviceStore.store.get("bluetooth", "
|
|
173
|
-
set(value) = DeviceStore.apply("bluetooth", "
|
|
172
|
+
get() = DeviceStore.store.get("bluetooth", "galleryModeAuto") as? Boolean ?: true
|
|
173
|
+
set(value) = DeviceStore.apply("bluetooth", "galleryModeAuto", value)
|
|
174
174
|
|
|
175
175
|
// state:
|
|
176
176
|
private var searching: Boolean
|
|
177
177
|
get() = DeviceStore.store.get("bluetooth", "searching") as? Boolean ?: false
|
|
178
178
|
set(value) = DeviceStore.apply("bluetooth", "searching", value)
|
|
179
179
|
|
|
180
|
-
private var
|
|
181
|
-
get() = DeviceStore.store.get("glasses", "
|
|
182
|
-
set(value) = DeviceStore.apply("glasses", "
|
|
180
|
+
private var glassesBluetoothClassicConnected: Boolean
|
|
181
|
+
get() = DeviceStore.store.get("glasses", "bluetoothClassicConnected") as? Boolean ?: false
|
|
182
|
+
set(value) = DeviceStore.apply("glasses", "bluetoothClassicConnected", value)
|
|
183
183
|
|
|
184
184
|
public var micRanking: MutableList<String>
|
|
185
185
|
get() =
|
|
@@ -727,8 +727,8 @@ class DeviceManager {
|
|
|
727
727
|
|
|
728
728
|
for (micMode in micRanking) {
|
|
729
729
|
if (micMode == MicTypes.PHONE_INTERNAL ||
|
|
730
|
-
micMode == MicTypes.
|
|
731
|
-
micMode == MicTypes.
|
|
730
|
+
micMode == MicTypes.BLUETOOTH_CLASSIC ||
|
|
731
|
+
micMode == MicTypes.BLUETOOTH
|
|
732
732
|
) {
|
|
733
733
|
|
|
734
734
|
if (phoneMic?.isRecordingWithMode(micMode) == true) {
|
|
@@ -790,8 +790,8 @@ class DeviceManager {
|
|
|
790
790
|
}
|
|
791
791
|
|
|
792
792
|
if (micMode == MicTypes.PHONE_INTERNAL ||
|
|
793
|
-
micMode == MicTypes.
|
|
794
|
-
micMode == MicTypes.
|
|
793
|
+
micMode == MicTypes.BLUETOOTH_CLASSIC ||
|
|
794
|
+
micMode == MicTypes.BLUETOOTH
|
|
795
795
|
) {
|
|
796
796
|
phoneMic?.stopMode(micMode)
|
|
797
797
|
}
|
|
@@ -1221,6 +1221,7 @@ class DeviceManager {
|
|
|
1221
1221
|
|
|
1222
1222
|
fun startStream(message: MutableMap<String, Any>) {
|
|
1223
1223
|
Bridge.log("MAN: startStream")
|
|
1224
|
+
message["flash"] = true
|
|
1224
1225
|
sgc?.startStream(message)
|
|
1225
1226
|
}
|
|
1226
1227
|
|
|
@@ -1352,11 +1353,11 @@ class DeviceManager {
|
|
|
1352
1353
|
sgc?.sendReboot()
|
|
1353
1354
|
}
|
|
1354
1355
|
|
|
1355
|
-
fun startVideoRecording(requestId: String, save: Boolean,
|
|
1356
|
+
fun startVideoRecording(requestId: String, save: Boolean, sound: Boolean) {
|
|
1356
1357
|
Bridge.log(
|
|
1357
|
-
"MAN: onStartVideoRecording: requestId=$requestId, save=$save, flash
|
|
1358
|
+
"MAN: onStartVideoRecording: requestId=$requestId, save=$save, flash=true, sound=$sound"
|
|
1358
1359
|
)
|
|
1359
|
-
sgc?.startVideoRecording(requestId, save,
|
|
1360
|
+
sgc?.startVideoRecording(requestId, save, true, sound)
|
|
1360
1361
|
}
|
|
1361
1362
|
|
|
1362
1363
|
fun stopVideoRecording(requestId: String) {
|
|
@@ -1372,20 +1373,17 @@ class DeviceManager {
|
|
|
1372
1373
|
updateMicState()
|
|
1373
1374
|
}
|
|
1374
1375
|
|
|
1375
|
-
fun
|
|
1376
|
+
fun requestPhoto(
|
|
1376
1377
|
requestId: String,
|
|
1377
1378
|
appId: String,
|
|
1378
1379
|
size: String,
|
|
1379
1380
|
webhookUrl: String,
|
|
1380
1381
|
authToken: String?,
|
|
1381
1382
|
compress: String,
|
|
1382
|
-
flash: Boolean,
|
|
1383
1383
|
sound: Boolean
|
|
1384
1384
|
) {
|
|
1385
|
-
Bridge.log(
|
|
1386
|
-
|
|
1387
|
-
)
|
|
1388
|
-
sgc?.requestPhoto(requestId, appId, size, webhookUrl, authToken, compress, flash, sound)
|
|
1385
|
+
Bridge.log("MAN: requestPhoto: $requestId, $appId, $size, compress=$compress, flash=true, sound=$sound")
|
|
1386
|
+
sgc?.requestPhoto(requestId, appId, size, webhookUrl, authToken, compress, true, sound)
|
|
1389
1387
|
}
|
|
1390
1388
|
|
|
1391
1389
|
fun rgbLedControl(
|
|
@@ -1393,12 +1391,12 @@ class DeviceManager {
|
|
|
1393
1391
|
packageName: String?,
|
|
1394
1392
|
action: String,
|
|
1395
1393
|
color: String?,
|
|
1396
|
-
|
|
1397
|
-
|
|
1394
|
+
onDurationMs: Int,
|
|
1395
|
+
offDurationMs: Int,
|
|
1398
1396
|
count: Int
|
|
1399
1397
|
) {
|
|
1400
1398
|
Bridge.log("MAN: RGB LED control: action=$action, color=$color, requestId=$requestId")
|
|
1401
|
-
sgc?.sendRgbLedControl(requestId, packageName, action, color,
|
|
1399
|
+
sgc?.sendRgbLedControl(requestId, packageName, action, color, onDurationMs, offDurationMs, count)
|
|
1402
1400
|
}
|
|
1403
1401
|
|
|
1404
1402
|
fun connectDefault() {
|
|
@@ -66,7 +66,7 @@ object DeviceStore {
|
|
|
66
66
|
store.set("glasses", "deviceModel", "")
|
|
67
67
|
store.set("glasses", "firmwareVersion", "")
|
|
68
68
|
store.set("glasses", "micEnabled", false)
|
|
69
|
-
store.set("glasses", "
|
|
69
|
+
store.set("glasses", "bluetoothClassicConnected", false)
|
|
70
70
|
store.set("glasses", "caseRemoved", true)
|
|
71
71
|
store.set("glasses", "caseOpen", true)
|
|
72
72
|
store.set("glasses", "caseCharging", false)
|
|
@@ -121,12 +121,12 @@ object DeviceStore {
|
|
|
121
121
|
store.set("bluetooth", "dashboard_depth", 2)
|
|
122
122
|
store.set("bluetooth", "head_up_angle", 30)
|
|
123
123
|
store.set("bluetooth", "contextual_dashboard", true)
|
|
124
|
-
store.set("bluetooth", "
|
|
124
|
+
store.set("bluetooth", "galleryModeAuto", true)
|
|
125
125
|
store.set("bluetooth", "screen_disabled", false)
|
|
126
126
|
store.set("bluetooth", "button_photo_size", "medium")
|
|
127
127
|
store.set("bluetooth", "button_camera_led", true)
|
|
128
128
|
store.set("bluetooth", "button_max_recording_time", 10)
|
|
129
|
-
store.set("bluetooth", "camera_fov", mapOf("fov" to 118, "
|
|
129
|
+
store.set("bluetooth", "camera_fov", mapOf("fov" to 118, "roiPosition" to 0))
|
|
130
130
|
store.set("bluetooth", "button_video_width", 1280)
|
|
131
131
|
store.set("bluetooth", "button_video_height", 720)
|
|
132
132
|
store.set("bluetooth", "button_video_fps", 30)
|
|
@@ -239,7 +239,7 @@ object DeviceStore {
|
|
|
239
239
|
DeviceManager.getInstance().sgc?.setDashboardMenu(items)
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
|
-
"bluetooth" to "
|
|
242
|
+
"bluetooth" to "galleryModeAuto" -> {
|
|
243
243
|
DeviceManager.getInstance().sgc?.sendGalleryMode()
|
|
244
244
|
}
|
|
245
245
|
"bluetooth" to "screen_disabled" -> {
|