@mentra/bluetooth-sdk 3.2.0-dev.265 → 3.2.1-beta.312
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 +28 -0
- package/android/lc3Lib/build.gradle +5 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +35 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +34 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +30 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +20 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedChangelogCatalog.kt +3 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +6 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +12 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +7 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.kt +4 -5
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +345 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +13 -0
- package/build/BluetoothSdk.types.d.ts +93 -1
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +32 -1
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +15 -1
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/generated/changelogCatalog.d.ts +5 -2
- package/build/generated/changelogCatalog.d.ts.map +1 -1
- package/build/generated/changelogCatalog.js +6 -2
- package/build/generated/changelogCatalog.js.map +1 -1
- package/build/generated/releaseMetadata.js +6 -6
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +60 -0
- package/ios/Source/BluetoothSdkDefaults.swift +1 -1
- package/ios/Source/Bridge.swift +27 -0
- package/ios/Source/DeviceManager.swift +52 -50
- package/ios/Source/DeviceStore.swift +6 -0
- package/ios/Source/GeneratedChangelogCatalog.swift +3 -2
- package/ios/Source/GeneratedReleaseMetadata.swift +6 -6
- package/ios/Source/MentraBluetoothSDK.swift +11 -0
- package/ios/Source/audio/PcmStreamPlayer.swift +12 -0
- package/ios/Source/events/BluetoothEvents.swift +15 -0
- package/ios/Source/services/PhoneMic.swift +1 -3
- package/ios/Source/sgcs/MentraLive.swift +247 -1
- package/ios/Source/sgcs/SGCManager.swift +32 -0
- package/ios/Source/utils/AudioRouteObservation.swift +54 -0
- package/ios/Source/utils/AudioSessionMonitor.swift +20 -6
- package/ios/Tests/AudioRouteObservationTests.swift +142 -0
- package/ios/Tests/BluetoothAudioRouteTests.swift +37 -0
- package/ios/Tests/GalleryServerCommandTests.swift +87 -0
- package/ios/Tests/WearTuningDispatchTests.swift +51 -0
- package/package.json +2 -2
- package/src/BluetoothSdk.types.ts +99 -0
- package/src/_private/BluetoothSdkModule.ts +64 -1
- package/src/generated/changelogCatalog.ts +6 -2
- package/src/generated/releaseMetadata.ts +6 -6
- package/src/index.ts +1 -0
package/README.md
CHANGED
|
@@ -478,6 +478,34 @@ await sdk.setDashboardContent("")
|
|
|
478
478
|
|
|
479
479
|
Settings commands that return `SettingsAckSuccessEvent` reject when the ASG reports an error ack. The SDK updates its local settings store only after that ASG ack resolves successfully, so observed SDK state reflects the acknowledged glasses state rather than a queued request. Raw `settings_ack` listener events still use `SettingsAckEvent` because they can include both success and failure statuses. `rgbLedControl(...)` resolves from a successful ASG `rgb_led_control_response` and rejects when the ASG reports `state: "error"`; raw `settings_ack` and `rgb_led_control_response` events remain available through listeners.
|
|
480
480
|
|
|
481
|
+
### Persistent HTTP gallery server (Mentra Live)
|
|
482
|
+
|
|
483
|
+
Use `setGalleryServerEnabled(true)` to keep the existing camera/gallery HTTP server available over the Wi-Fi network the glasses have already joined. This opt-in defaults off and persists across BLE reconnects and glasses restarts until explicitly disabled. It has no idle timeout and does not start or join a hotspot.
|
|
484
|
+
|
|
485
|
+
**This server uses HTTP without authentication. Any client that can reach the glasses can use the full camera/gallery API, including capture and deletion, while it is enabled.** Use it only where your network policy permits that access.
|
|
486
|
+
|
|
487
|
+
```ts
|
|
488
|
+
const server = await BluetoothSdk.setGalleryServerEnabled(true)
|
|
489
|
+
if (server.listening && server.url) {
|
|
490
|
+
const gallery = await fetch(`${server.url}/api/gallery`).then((response) => response.json())
|
|
491
|
+
console.log(gallery)
|
|
492
|
+
// Download using /api/download?file=<URL-encoded gallery filename>.
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Leave enabled for persistent access, or explicitly turn it off:
|
|
496
|
+
await BluetoothSdk.setGalleryServerEnabled(false)
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
Native Swift: `try await sdk.setGalleryServerEnabled(true)`; Kotlin: `sdk.setGalleryServerEnabled(true)`. Both return `SettingsAckEvent`, with `enabled`, `listening`, and `url` properties. React Native returns `SettingsAckSuccessEvent` with the same fields.
|
|
500
|
+
|
|
501
|
+
The acknowledgement confirms the saved setting. `enabled:true, listening:false` means the setting is enabled but no station endpoint is currently available, for example before Wi-Fi connects or while a bind is being retried. `url` is present only when the server is running and station Wi-Fi has an address. Repeat the same enable call to obtain a fresh endpoint without restarting a healthy server.
|
|
502
|
+
|
|
503
|
+
The same server listens on port 8089 on all local interfaces in persistent mode. Its complete HTTP API is unchanged: listing, downloads, sync, deletion, restore, camera control, and browser UI all work as on the hotspot. Existing response formats, resumable downloads, and in-progress-media filtering remain intact. No HTTP client changes are needed beyond choosing the site-network URL.
|
|
504
|
+
|
|
505
|
+
Disabling restores normal hotspot-only behavior: the server rebinds to an active hotspot address or stops if no hotspot is active. Changing binding modes can interrupt in-flight requests, so switch modes between transfers or retry interrupted requests.
|
|
506
|
+
|
|
507
|
+
Both the native SDK and ASG client need this command; older glasses firmware times out without claiming success. The client app must have local-network access and permit cleartext HTTP to the local device under its platform/MDM policy.
|
|
508
|
+
|
|
481
509
|
WiFi, hotspot, and version-info commands resolve from the ASG response path, not local dispatch:
|
|
482
510
|
`requestWifiScan()` resolves from the ASG `wifi_scan_result` completion response with the updated scan list, including `[]` when no networks are found. Intermediate `wifi_scan_result` events can arrive with `scanComplete: false` while the glasses stream discovered networks; the final event uses `scanComplete: true`. If older glasses stream non-empty scan results but never send the completion event, the request resolves with the accumulated scan list when the request times out. `sendWifiCredentials()` resolves when the requested SSID is connected, `forgetWifiNetwork()` returns a semantic `WifiForgetResult`, `getSavedWifiNetworks()` returns a semantic `SavedWifiNetworksResult`, `setHotspotState()` resolves when the requested hotspot state is reported, and `requestVersionInfo()` waits for all chunks declared by the correlated response's `chunkCount`, `chunkIndex`, and `final` metadata. Legacy single-message responses complete immediately; legacy chunked responses complete on `version_info_3` after `version_info_1`. Missing final chunks time out rather than returning partial data after a quiet period.
|
|
483
511
|
|
|
@@ -88,6 +88,11 @@ android {
|
|
|
88
88
|
namespace "com.mentra.lc3Lib"
|
|
89
89
|
compileSdk 33
|
|
90
90
|
|
|
91
|
+
// Reuse the host's NDK instead of downloading AGP's default alongside it.
|
|
92
|
+
if (rootProject.ext.has('ndkVersion')) {
|
|
93
|
+
ndkVersion rootProject.ext.ndkVersion
|
|
94
|
+
}
|
|
95
|
+
|
|
91
96
|
publishing {
|
|
92
97
|
singleVariant("release") {
|
|
93
98
|
withSourcesJar()
|
|
@@ -368,6 +368,10 @@ class BluetoothSdkModule : Module() {
|
|
|
368
368
|
"receive_command_from_ble",
|
|
369
369
|
"swipe_volume_status",
|
|
370
370
|
"switch_status",
|
|
371
|
+
"mic_tuning_state",
|
|
372
|
+
"mic_rms",
|
|
373
|
+
"wear_state",
|
|
374
|
+
"wear_tuning",
|
|
371
375
|
"rgb_led_control_response",
|
|
372
376
|
"settings_ack",
|
|
373
377
|
"version_info",
|
|
@@ -582,6 +586,33 @@ class BluetoothSdkModule : Module() {
|
|
|
582
586
|
// Stub on Android — iOS uses this for the jetsam stress test.
|
|
583
587
|
Function("getMemoryMB") { -> 0.0 }
|
|
584
588
|
|
|
589
|
+
// MARK: - Mic tuning (internal SDK surface only)
|
|
590
|
+
|
|
591
|
+
AsyncFunction("setMicRmsTelemetry") { enabled: Boolean ->
|
|
592
|
+
deviceManager?.sgc?.setMicRmsTelemetry(enabled)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Fire-and-forget: the answer arrives as a mic_tuning_state event, which
|
|
596
|
+
// the screen is subscribed to anyway.
|
|
597
|
+
AsyncFunction("requestMicTuningState") { deviceManager?.sgc?.requestMicTuningState() }
|
|
598
|
+
|
|
599
|
+
// MARK: - Wear detection (internal SDK surface only)
|
|
600
|
+
|
|
601
|
+
// All fire-and-forget; answers arrive as wear_state / wear_tuning events.
|
|
602
|
+
AsyncFunction("queryWearState") { deviceManager?.queryWearState() }
|
|
603
|
+
|
|
604
|
+
AsyncFunction("setWearReporting") { enabled: Boolean ->
|
|
605
|
+
deviceManager?.setWearReporting(enabled)
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
AsyncFunction("setWearTuning") { intervalMs: Int, count: Int, majority: Int ->
|
|
609
|
+
deviceManager?.setWearTuning(intervalMs, count, majority)
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
AsyncFunction("requestWearTuning") { deviceManager?.requestWearTuning() }
|
|
613
|
+
|
|
614
|
+
AsyncFunction("resetWearTuning") { deviceManager?.resetWearTuning() }
|
|
615
|
+
|
|
585
616
|
// MARK: - Incident Reporting
|
|
586
617
|
|
|
587
618
|
SdkAsyncFunction("sendIncidentId") { incidentId: String, apiBaseUrl: String? ->
|
|
@@ -629,6 +660,10 @@ class BluetoothSdkModule : Module() {
|
|
|
629
660
|
|
|
630
661
|
// MARK: - Gallery Commands
|
|
631
662
|
|
|
663
|
+
SdkCoroutineFunction("setGalleryServerEnabled") { enabled: Boolean ->
|
|
664
|
+
requireSdk().setGalleryServerEnabled(enabled).values
|
|
665
|
+
}
|
|
666
|
+
|
|
632
667
|
SdkCoroutineFunction("setGalleryModeEnabled") { enabled: Boolean ->
|
|
633
668
|
requireSdk().setGalleryModeEnabled(enabled).values
|
|
634
669
|
}
|
|
@@ -391,6 +391,40 @@ public class Bridge private constructor() {
|
|
|
391
391
|
sendTypedMessage("switch_status", body)
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
+
/**
|
|
395
|
+
* Mic tuning values the glasses report as actually in force (post-clamp),
|
|
396
|
+
* from sr_mictun / sr_micst.
|
|
397
|
+
*/
|
|
398
|
+
@JvmStatic
|
|
399
|
+
fun sendMicTuningState(state: Map<String, Any>) {
|
|
400
|
+
sendTypedMessage("mic_tuning_state", HashMap(state))
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** Wear state from sr_wrst, or from a wear transition on the glasses. */
|
|
404
|
+
@JvmStatic
|
|
405
|
+
fun sendWearState(worn: Boolean) {
|
|
406
|
+
val body = HashMap<String, Any>()
|
|
407
|
+
body["worn"] = worn
|
|
408
|
+
sendTypedMessage("wear_state", body)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** Wear vote config the glasses report as in force, from sr_weartun. */
|
|
412
|
+
@JvmStatic
|
|
413
|
+
fun sendWearTuningState(state: Map<String, Any>) {
|
|
414
|
+
sendTypedMessage("wear_tuning", HashMap(state))
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** Disposable mic RMS sample from sr_micrms. */
|
|
418
|
+
@JvmStatic
|
|
419
|
+
fun sendMicRms(rms: Int, gateOpen: Boolean, speakerElevated: Boolean, generation: Int) {
|
|
420
|
+
val body = HashMap<String, Any>()
|
|
421
|
+
body["rms"] = rms
|
|
422
|
+
body["gateOpen"] = gateOpen
|
|
423
|
+
body["speakerElevated"] = speakerElevated
|
|
424
|
+
body["generation"] = generation
|
|
425
|
+
sendTypedMessage("mic_rms", body)
|
|
426
|
+
}
|
|
427
|
+
|
|
394
428
|
@JvmStatic
|
|
395
429
|
fun sendPhotoError(requestId: String, errorCode: String, errorMessage: String) {
|
|
396
430
|
val timestamp = System.currentTimeMillis()
|
|
@@ -1883,6 +1883,31 @@ class DeviceManager {
|
|
|
1883
1883
|
sgc?.dbg2()
|
|
1884
1884
|
}
|
|
1885
1885
|
|
|
1886
|
+
fun queryWearState() {
|
|
1887
|
+
Bridge.log("MAN: queryWearState()")
|
|
1888
|
+
sgc?.queryWearState()
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
fun setWearReporting(enabled: Boolean) {
|
|
1892
|
+
Bridge.log("MAN: setWearReporting($enabled)")
|
|
1893
|
+
sgc?.setWearReporting(enabled)
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
fun setWearTuning(intervalMs: Int, count: Int, majority: Int) {
|
|
1897
|
+
Bridge.log("MAN: setWearTuning($intervalMs, $count, $majority)")
|
|
1898
|
+
sgc?.setWearTuning(intervalMs, count, majority)
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
fun requestWearTuning() {
|
|
1902
|
+
Bridge.log("MAN: requestWearTuning()")
|
|
1903
|
+
sgc?.requestWearTuning()
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
fun resetWearTuning() {
|
|
1907
|
+
Bridge.log("MAN: resetWearTuning()")
|
|
1908
|
+
sgc?.resetWearTuning()
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1886
1911
|
fun startStream(message: MutableMap<String, Any>) {
|
|
1887
1912
|
Bridge.log("MAN: startStream")
|
|
1888
1913
|
sgc?.startStream(message)
|
|
@@ -1976,6 +2001,11 @@ class DeviceManager {
|
|
|
1976
2001
|
ar99.sendFactoryReset()
|
|
1977
2002
|
}
|
|
1978
2003
|
|
|
2004
|
+
fun sendGalleryServerEnabled(requestId: String, enabled: Boolean) {
|
|
2005
|
+
val live = sgc as? MentraLive ?: throw IllegalStateException("unsupported_device")
|
|
2006
|
+
live.sendGalleryServerEnabled(requestId, enabled)
|
|
2007
|
+
}
|
|
2008
|
+
|
|
1979
2009
|
fun sendGalleryMode(requestId: String, enabled: Boolean) {
|
|
1980
2010
|
val live = sgc as? MentraLive ?: throw IllegalStateException("unsupported_device")
|
|
1981
2011
|
live.sendGalleryMode(requestId, enabled)
|
|
@@ -31,6 +31,16 @@ object DeviceStore {
|
|
|
31
31
|
JSONObject(mapOf("v" to newValue)).toString()
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Empty/`reset` mic tuning must still be written to the glasses. Native
|
|
36
|
+
* `update` drops null, and equal empty maps would otherwise skip BLE.
|
|
37
|
+
*/
|
|
38
|
+
private fun isMicTuningReset(value: Any): Boolean {
|
|
39
|
+
val map = value as? Map<*, *> ?: return true
|
|
40
|
+
if (map.isEmpty()) return true
|
|
41
|
+
return map.entries.none { (key, field) -> key != "reset" && field is Number }
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
private fun scheduleDashboardHeightToGlasses() {
|
|
35
45
|
pendingDashboardHeightRunnable?.let { dashboardBleHandler.removeCallbacks(it) }
|
|
36
46
|
val r = Runnable {
|
|
@@ -164,7 +174,10 @@ object DeviceStore {
|
|
|
164
174
|
fun apply(category: String, key: String, value: Any) {
|
|
165
175
|
val oldValue = store.get(category, key)
|
|
166
176
|
store.set(category, key, value)
|
|
167
|
-
|
|
177
|
+
val skipped = observableStoreWouldHaveSkipped(oldValue, value)
|
|
178
|
+
val forceMicReset =
|
|
179
|
+
category == ObservableStore.BLUETOOTH_CATEGORY && key == "mic_tuning" && isMicTuningReset(value)
|
|
180
|
+
if (skipped && !forceMicReset) {
|
|
168
181
|
return
|
|
169
182
|
}
|
|
170
183
|
|
|
@@ -278,6 +291,12 @@ object DeviceStore {
|
|
|
278
291
|
"bluetooth" to "loudness_gate_enabled" -> {
|
|
279
292
|
DeviceManager.getInstance().sgc?.sendLoudnessGateSetting()
|
|
280
293
|
}
|
|
294
|
+
// Deliberately has no seeded default above: the key starts absent so
|
|
295
|
+
// that a session where the engine has not authorized tuning can only
|
|
296
|
+
// ever send a reset.
|
|
297
|
+
"bluetooth" to "mic_tuning" -> {
|
|
298
|
+
DeviceManager.getInstance().sgc?.sendMicTuningSetting()
|
|
299
|
+
}
|
|
281
300
|
"bluetooth" to "nex_lc3_audio_playback" -> {
|
|
282
301
|
(value as? Boolean)?.let { enabled ->
|
|
283
302
|
Bridge.log("DeviceStore: nex_lc3_audio_playback changed to $enabled")
|
|
@@ -3,7 +3,8 @@ package com.mentra.bluetoothsdk
|
|
|
3
3
|
/** Generated from /changelogs. Do not edit directly. */
|
|
4
4
|
internal val GENERATED_RELEASE_CHANGELOGS: List<ReleaseChangelog> =
|
|
5
5
|
listOf(
|
|
6
|
+
ReleaseChangelog(version = "3.2.1", markdown = "This release is under active development. User-facing changes will be documented as they land."),
|
|
6
7
|
ReleaseChangelog(version = "3.2.0", markdown = "This release is under active development. User-facing changes will be documented as they land.\n\n- Breaking Bluetooth SDK change: `forgetWifiNetwork(ssid)` now returns `WifiForgetResult` instead of `WifiStatusChangeEvent`. Migrate status-only consumers to the semantic `outcome`; the requested network remains `ssid`, while optional post-command connectivity is reported by `connected`, `currentSsid`, and `localIp`."),
|
|
7
|
-
ReleaseChangelog(version = "3.1.1", markdown = "
|
|
8
|
-
ReleaseChangelog(version = "3.1.0", markdown = "
|
|
8
|
+
ReleaseChangelog(version = "3.1.1", markdown = "- Improved Google login on iOS.\n- Pairing no longer requires phone microphone access."),
|
|
9
|
+
ReleaseChangelog(version = "3.1.0", markdown = "**Mentra App and glasses**\n\n- Improved glasses pairing and reconnection, including on iPad.\n- Improved Android background reliability for captions and miniapps.\n- Added Xingyi AR99 support.\n- More reliable photo and video capture, with improved shutter sounds and privacy-light timing. Taking photos no longer interrupts your running miniapp.\n- Added video thumbnails and smoother gallery browsing.\n- Easier Mentra Live updates through your phone, with clearer progress and better recovery from interruptions.\n\n**Miniapp updates**\n\n- **Mentra AI:** Control whether photos are included with questions. Improved visual answers and connected-app follow-ups.\n- **Captions:** Added offline transcription settings and top/bottom positioning on supported displays.\n- **Translation:** Restored all 60 languages.\n- **Mentra Maps:** Clearer directions on G1/G2, less display flickering, and improved Android offline routing.\n- **Livestreamer:** More video-quality controls and custom streaming options, plus improved startup and sharing.\n- **Merge:** Tap to expand an insight; swipe down or back to dismiss it.\n- **Mentra Notes:** Smoother back navigation.\n- **Recorder:** Fixed audio sharing."),
|
|
9
10
|
)
|
|
@@ -2,10 +2,10 @@ package com.mentra.bluetoothsdk
|
|
|
2
2
|
|
|
3
3
|
/** Generated by release CI. Do not edit in a release checkout. */
|
|
4
4
|
internal object GeneratedReleaseMetadata {
|
|
5
|
-
const val FAMILY_BASE_VERSION: String = "3.2.
|
|
6
|
-
const val RELEASE_IDENTITY: String = "3.2.
|
|
7
|
-
const val RELEASE_SET_ID: String = "mentra-3.2.
|
|
8
|
-
const val SOURCE_COMMIT: String = "
|
|
9
|
-
const val OTA_MANIFEST_URL: String = "https://
|
|
10
|
-
const val OTA_MANIFEST_SHA256: String = "
|
|
5
|
+
const val FAMILY_BASE_VERSION: String = "3.2.1"
|
|
6
|
+
const val RELEASE_IDENTITY: String = "3.2.1-beta.312"
|
|
7
|
+
const val RELEASE_SET_ID: String = "mentra-3.2.1-beta.312"
|
|
8
|
+
const val SOURCE_COMMIT: String = "0e549d30e1de230cc9f22e77b80ca1704833cceb"
|
|
9
|
+
const val OTA_MANIFEST_URL: String = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.312.json"
|
|
10
|
+
const val OTA_MANIFEST_SHA256: String = "c7d7975d15ab271035e7e26431be200d91664cc4c85b761e373ed4bc4026a3ac"
|
|
11
11
|
}
|
|
@@ -601,6 +601,18 @@ class MentraBluetoothSdk private constructor(
|
|
|
601
601
|
DeviceStore.apply(ObservableStore.BLUETOOTH_CATEGORY, "screen_disabled", disabled)
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
+
/**
|
|
605
|
+
* Enable or disable persistent, unauthenticated HTTP gallery access on the glasses' Wi-Fi.
|
|
606
|
+
* Defaults off and survives glasses restarts. Only enable on a trusted network.
|
|
607
|
+
* The ack reports saved enabled state and current listening/url separately.
|
|
608
|
+
*/
|
|
609
|
+
suspend fun setGalleryServerEnabled(enabled: Boolean): SettingsAckEvent =
|
|
610
|
+
performSettingsCommand(
|
|
611
|
+
setting = "gallery_server",
|
|
612
|
+
updateStore = {},
|
|
613
|
+
send = { requestId -> deviceManager.sendGalleryServerEnabled(requestId, enabled) },
|
|
614
|
+
)
|
|
615
|
+
|
|
604
616
|
suspend fun setGalleryModeEnabled(enabled: Boolean): SettingsAckEvent =
|
|
605
617
|
performSettingsCommand(
|
|
606
618
|
setting = "gallery_mode",
|
|
@@ -125,6 +125,13 @@ data class SettingsAckEvent(
|
|
|
125
125
|
val hardwareApplied: Boolean get() = boolValue(values, "hardwareApplied", "hardware_applied") ?: false
|
|
126
126
|
val errorCode: String? get() = stringValue(values, "errorCode")
|
|
127
127
|
val errorMessage: String? get() = stringValue(values, "errorMessage")
|
|
128
|
+
/** Saved setting value, when included in the acknowledgement. */
|
|
129
|
+
val enabled: Boolean? get() = values["enabled"] as? Boolean
|
|
130
|
+
/** Whether the persistent gallery server is currently available over station Wi-Fi. */
|
|
131
|
+
val listening: Boolean? get() = values["listening"] as? Boolean
|
|
132
|
+
/** Current gallery base URL, available only with a running server and station Wi-Fi. */
|
|
133
|
+
val url: String? get() = stringValue(values, "url")
|
|
134
|
+
|
|
128
135
|
}
|
|
129
136
|
|
|
130
137
|
data class RgbLedControlResponseEvent(
|
|
@@ -703,9 +703,8 @@ class Mach1 : SGCManager() {
|
|
|
703
703
|
}
|
|
704
704
|
|
|
705
705
|
fun blankScreen() {
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
// }
|
|
706
|
+
ultraliteSdk?.screenOff()
|
|
707
|
+
screenIsClear = true
|
|
709
708
|
}
|
|
710
709
|
|
|
711
710
|
fun destroy() {
|
|
@@ -781,13 +780,13 @@ class Mach1 : SGCManager() {
|
|
|
781
780
|
}
|
|
782
781
|
|
|
783
782
|
fun changeUltraliteLayout(chosenLayout: Layout) {
|
|
783
|
+
ultraliteSdk!!.screenOn()
|
|
784
|
+
|
|
784
785
|
//don't update layout if it's already setup
|
|
785
786
|
if (currentUltraliteLayout != null && currentUltraliteLayout == chosenLayout) {
|
|
786
787
|
return
|
|
787
788
|
}
|
|
788
789
|
|
|
789
|
-
ultraliteSdk!!.screenOn()
|
|
790
|
-
|
|
791
790
|
currentUltraliteLayout = chosenLayout
|
|
792
791
|
ultraliteSdk!!.setLayout(chosenLayout, 0, true, false, 2)
|
|
793
792
|
|