@mentra/engine 3.1.0-dev.20 → 3.1.0-dev.22
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 +19 -5
- package/build/bluetooth-sdk/ota-transport.d.ts +2 -0
- package/build/bluetooth-sdk/ota-transport.d.ts.map +1 -0
- package/build/bluetooth-sdk/ota-transport.js +2 -0
- package/build/bluetooth-sdk/ota-transport.js.map +1 -0
- package/build/engine.d.ts +2 -2
- package/build/facades/ota.d.ts +4 -4
- package/build/facades/ota.d.ts.map +1 -1
- package/build/facades/ota.js +3 -4
- package/build/facades/ota.js.map +1 -1
- package/build/generated/releaseMetadata.js +4 -4
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/react/MentraLiveOtaFlow.d.ts +3 -2
- package/build/react/MentraLiveOtaFlow.d.ts.map +1 -1
- package/build/react/MentraLiveOtaFlow.js +68 -345
- package/build/react/MentraLiveOtaFlow.js.map +1 -1
- package/build/react/index.d.ts +1 -0
- package/build/react/index.d.ts.map +1 -1
- package/build/react/index.js +1 -0
- package/build/react/index.js.map +1 -1
- package/build/react/useMentraLiveOta.d.ts +69 -0
- package/build/react/useMentraLiveOta.d.ts.map +1 -0
- package/build/react/useMentraLiveOta.js +485 -0
- package/build/react/useMentraLiveOta.js.map +1 -0
- package/build/services/GlassesStatusProjection.d.ts +15 -2
- package/build/services/GlassesStatusProjection.d.ts.map +1 -1
- package/build/services/GlassesStatusProjection.js +3 -3
- package/build/services/GlassesStatusProjection.js.map +1 -1
- package/build/services/HotspotOtaTransport.d.ts.map +1 -1
- package/build/services/HotspotOtaTransport.js +8 -7
- package/build/services/HotspotOtaTransport.js.map +1 -1
- package/build/services/OtaInstallCoordinator.d.ts +24 -3
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +14 -12
- package/build/services/OtaInstallCoordinator.js.map +1 -1
- package/build/services/OtaService.d.ts.map +1 -1
- package/build/services/OtaService.js +1 -1
- package/build/services/OtaService.js.map +1 -1
- package/build/services/OtaUpdateCheckService.d.ts +1 -1
- package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
- package/build/services/OtaUpdateCheckService.js +6 -2
- package/build/services/OtaUpdateCheckService.js.map +1 -1
- package/build/services/asg/localNetworkTransport.d.ts.map +1 -1
- package/build/services/asg/localNetworkTransport.js +13 -12
- package/build/services/asg/localNetworkTransport.js.map +1 -1
- package/build/services/glassesClockSync.js +1 -1
- package/build/services/glassesClockSync.js.map +1 -1
- package/build/stores/core.d.ts +3 -3
- package/build/stores/core.d.ts.map +1 -1
- package/build/stores/core.js.map +1 -1
- package/build/stores/glasses.d.ts +10 -4
- package/build/stores/glasses.d.ts.map +1 -1
- package/build/stores/glasses.js.map +1 -1
- package/package.json +12 -6
- package/src/bluetooth-sdk/ota-transport.ts +1 -0
- package/src/facades/ota.ts +3 -4
- package/src/generated/releaseMetadata.ts +4 -4
- package/src/react/MentraLiveOtaFlow.tsx +116 -466
- package/src/react/index.ts +13 -0
- package/src/react/useMentraLiveOta.ts +619 -0
- package/src/services/GlassesStatusProjection.ts +7 -6
- package/src/services/HotspotOtaTransport.ts +8 -7
- package/src/services/OtaInstallCoordinator.ts +16 -13
- package/src/services/OtaService.ts +1 -2
- package/src/services/OtaUpdateCheckService.ts +8 -5
- package/src/services/asg/localNetworkTransport.ts +20 -19
- package/src/services/glassesClockSync.ts +1 -1
- package/src/stores/core.ts +4 -4
- package/src/stores/glasses.ts +13 -6
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import BluetoothSdk, {isEnabledHotspotStatus
|
|
1
|
+
import BluetoothSdk, {isEnabledHotspotStatus} from "@mentra/bluetooth-sdk"
|
|
2
|
+
import {otaServer} from "@mentra/bluetooth-sdk/ota-transport"
|
|
2
3
|
// One coordinator selects the native Android or iOS staging implementation at runtime.
|
|
3
4
|
// eslint-disable-next-line react-native/split-platform-components
|
|
4
5
|
import {PermissionsAndroid, Platform} from "react-native"
|
|
@@ -83,7 +84,7 @@ class HotspotOtaTransport {
|
|
|
83
84
|
let localAddress = scopedAddress
|
|
84
85
|
if (Platform.OS === "ios") {
|
|
85
86
|
try {
|
|
86
|
-
localAddress = await
|
|
87
|
+
localAddress = await otaServer.waitForWifiAddress(hotspot.localIp, 15_000)
|
|
87
88
|
} catch (error) {
|
|
88
89
|
throw new HotspotOtaTransportError(
|
|
89
90
|
"hotspot_join_failed",
|
|
@@ -94,10 +95,10 @@ class HotspotOtaTransport {
|
|
|
94
95
|
const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]))
|
|
95
96
|
// Start exactly one native listener to learn its selected port, then atomically replace
|
|
96
97
|
// the placeholder with the immutable rewritten manifest before ota_start is sent.
|
|
97
|
-
const server = await
|
|
98
|
+
const server = await otaServer.start("{}", artifactPaths, localAddress)
|
|
98
99
|
this.serverStarted = true
|
|
99
100
|
const manifest = rewriteManifestForLocalServer(checkResult.manifestBody, this.prepared, server.baseUrl)
|
|
100
|
-
const published = await
|
|
101
|
+
const published = await otaServer.start(manifest, artifactPaths, server.host)
|
|
101
102
|
if (published.manifestUrl !== server.manifestUrl) {
|
|
102
103
|
throw new Error("Local OTA server endpoint changed while publishing the manifest")
|
|
103
104
|
}
|
|
@@ -141,11 +142,11 @@ class HotspotOtaTransport {
|
|
|
141
142
|
destination: string,
|
|
142
143
|
onProgress?: (bytesWritten: number, contentLength: number) => void,
|
|
143
144
|
): Promise<{statusCode: number}> => {
|
|
144
|
-
const subscription =
|
|
145
|
+
const subscription = otaServer.onArtifactDownloadProgress((event) => {
|
|
145
146
|
if (event.destination === destination) onProgress?.(event.bytesWritten, event.contentLength)
|
|
146
147
|
})
|
|
147
148
|
try {
|
|
148
|
-
return await
|
|
149
|
+
return await otaServer.downloadArtifact(entry.url, destination)
|
|
149
150
|
} finally {
|
|
150
151
|
subscription.remove()
|
|
151
152
|
}
|
|
@@ -164,7 +165,7 @@ class HotspotOtaTransport {
|
|
|
164
165
|
console.warn("[OTA_PROGRESS] glasses hotspot shutdown was not confirmed after bounded retries")
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
|
-
if (this.serverStarted) await
|
|
168
|
+
if (this.serverStarted) await otaServer.stop().catch(() => {})
|
|
168
169
|
if (this.localNetworkConnected) await localNetworkTransport.disconnect().catch(() => {})
|
|
169
170
|
await cleanupArtifacts().catch(() => {})
|
|
170
171
|
this.prepared = []
|
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
* state written mid-pass queues a follow-up pass — the same way a setState
|
|
18
18
|
* during React effects scheduled a re-render after the current effect batch.
|
|
19
19
|
*/
|
|
20
|
-
import BluetoothSdk from "@mentra/bluetooth-sdk
|
|
21
|
-
import type {OtaProgress, OtaStatus} from "@mentra/bluetooth-sdk"
|
|
20
|
+
import BluetoothSdk, {type OtaProgress, type OtaStatus} from "@mentra/bluetooth-sdk"
|
|
22
21
|
import GlobalEventEmitter from "../utils/GlobalEventEmitter"
|
|
23
22
|
import {isGlassesConnected, useGlassesStore} from "../stores/glasses"
|
|
24
23
|
import {resolveOtaManifestUrl} from "./otaManifestUrl"
|
|
@@ -170,6 +169,8 @@ export interface OtaInstallSnapshot {
|
|
|
170
169
|
/** Pre-ota_start phone staging/join state for a hotspot attempt. */
|
|
171
170
|
hotspotPhase: HotspotOtaPhase
|
|
172
171
|
hotspotArtifactPercent: number | null
|
|
172
|
+
/** Transport selected from the checked glasses capabilities and Wi-Fi state. */
|
|
173
|
+
transport: "wifi" | "hotspot"
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
type OtaStartOutcome = "pending" | "acknowledged" | "rejected"
|
|
@@ -407,7 +408,7 @@ class OtaInstallCoordinator {
|
|
|
407
408
|
if (this.otaStartOwnership?.outcome === "pending") {
|
|
408
409
|
void this.sendOtaStartWithWatchdogs()
|
|
409
410
|
} else {
|
|
410
|
-
void BluetoothSdk.
|
|
411
|
+
void BluetoothSdk.queryOtaStatus().catch(() => {})
|
|
411
412
|
this.armQueryReplyFallback("retry")
|
|
412
413
|
}
|
|
413
414
|
}
|
|
@@ -449,16 +450,17 @@ class OtaInstallCoordinator {
|
|
|
449
450
|
* stays in the screen): clear the selected update, and after an APK step
|
|
450
451
|
* clear the stale build number so the next check re-reads version_info.
|
|
451
452
|
*/
|
|
452
|
-
finish(): void {
|
|
453
|
+
async finish(): Promise<void> {
|
|
453
454
|
if (this.otaStartOwnership?.outcome !== "pending") {
|
|
454
455
|
this.otaStartOwnership = null
|
|
455
456
|
}
|
|
456
457
|
useGlassesStore.getState().setOtaUpdateAvailable(null)
|
|
457
458
|
if (this.apkStepSeen) {
|
|
458
|
-
BluetoothSdk.updateGlasses({buildNumber: ""})
|
|
459
459
|
useGlassesStore.getState().setGlassesInfo({buildNumber: ""})
|
|
460
460
|
}
|
|
461
|
-
|
|
461
|
+
// The post-install check needs internet again. Do not let callers leave the
|
|
462
|
+
// terminal screen while Android still owns the no-internet hotspot route.
|
|
463
|
+
await this.teardownHotspotTransport()
|
|
462
464
|
}
|
|
463
465
|
|
|
464
466
|
/**
|
|
@@ -467,8 +469,8 @@ class OtaInstallCoordinator {
|
|
|
467
469
|
* deriveDisplayState doesn't resurrect the stale install when the host
|
|
468
470
|
* navigates away and back through /ota routes.
|
|
469
471
|
*/
|
|
470
|
-
discard(): void {
|
|
471
|
-
this.finish()
|
|
472
|
+
async discard(): Promise<void> {
|
|
473
|
+
await this.finish()
|
|
472
474
|
const store = useGlassesStore.getState()
|
|
473
475
|
store.setOtaStatus(null)
|
|
474
476
|
store.setOtaProgress(null)
|
|
@@ -505,6 +507,7 @@ class OtaInstallCoordinator {
|
|
|
505
507
|
versionChangePhase: this.deriveVersionChangePhase(connected),
|
|
506
508
|
hotspotPhase: this.hotspotPhase,
|
|
507
509
|
hotspotArtifactPercent: this.hotspotArtifactPercent,
|
|
510
|
+
transport: this.selectedTransport,
|
|
508
511
|
}
|
|
509
512
|
}
|
|
510
513
|
|
|
@@ -1065,7 +1068,7 @@ class OtaInstallCoordinator {
|
|
|
1065
1068
|
if (this.otaStartOwnership?.outcome === "pending") {
|
|
1066
1069
|
void this.sendOtaStartWithWatchdogs()
|
|
1067
1070
|
}
|
|
1068
|
-
void BluetoothSdk.
|
|
1071
|
+
void BluetoothSdk.queryOtaStatus()
|
|
1069
1072
|
this.armQueryReplyFallback("reconnect")
|
|
1070
1073
|
return true
|
|
1071
1074
|
}
|
|
@@ -1109,7 +1112,7 @@ class OtaInstallCoordinator {
|
|
|
1109
1112
|
if (noSessionYet) {
|
|
1110
1113
|
if (!isIdleStatus && this.otaStartOwnership?.outcome === "acknowledged") {
|
|
1111
1114
|
console.log("[OTA_PROGRESS] initial mount, acknowledged session has no cached status — reconciling")
|
|
1112
|
-
void BluetoothSdk.
|
|
1115
|
+
void BluetoothSdk.queryOtaStatus().catch(() => {})
|
|
1113
1116
|
this.armQueryReplyFallback("initial-mount")
|
|
1114
1117
|
return
|
|
1115
1118
|
}
|
|
@@ -1125,7 +1128,7 @@ class OtaInstallCoordinator {
|
|
|
1125
1128
|
void this.sendOtaStartWithWatchdogs()
|
|
1126
1129
|
} else {
|
|
1127
1130
|
console.log("[OTA_PROGRESS] initial mount, session exists, sending ota_query_status")
|
|
1128
|
-
void BluetoothSdk.
|
|
1131
|
+
void BluetoothSdk.queryOtaStatus()
|
|
1129
1132
|
this.armQueryReplyFallback("initial-mount")
|
|
1130
1133
|
}
|
|
1131
1134
|
}
|
|
@@ -1154,7 +1157,7 @@ class OtaInstallCoordinator {
|
|
|
1154
1157
|
this.clearProgressTimeout()
|
|
1155
1158
|
this.onFirstActivity()
|
|
1156
1159
|
this.onFirstNonZeroProgress()
|
|
1157
|
-
void BluetoothSdk.
|
|
1160
|
+
void BluetoothSdk.queryOtaStatus()
|
|
1158
1161
|
useGlassesStore.getState().setMtkUpdatedThisSession(true)
|
|
1159
1162
|
}
|
|
1160
1163
|
|
|
@@ -1345,7 +1348,7 @@ class OtaInstallCoordinator {
|
|
|
1345
1348
|
const s = useGlassesStore.getState().otaStatus
|
|
1346
1349
|
if (s?.stepType === "apk" && s.phase === "install" && s.status === "in_progress") {
|
|
1347
1350
|
this.apkInstallPollInFlight = true
|
|
1348
|
-
void BluetoothSdk.
|
|
1351
|
+
void BluetoothSdk.queryOtaStatus()
|
|
1349
1352
|
.catch(() => {})
|
|
1350
1353
|
.finally(() => {
|
|
1351
1354
|
this.apkInstallPollInFlight = false
|
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Started by `engine.start()`. Idempotent.
|
|
12
12
|
*/
|
|
13
|
-
import BluetoothSdk from "@mentra/bluetooth-sdk
|
|
14
|
-
import type {OtaStatus} from "@mentra/bluetooth-sdk/internal"
|
|
13
|
+
import BluetoothSdk, {type OtaStatus} from "@mentra/bluetooth-sdk"
|
|
15
14
|
import GlobalEventEmitter from "../utils/GlobalEventEmitter"
|
|
16
15
|
import {useGlassesStore} from "../stores/glasses"
|
|
17
16
|
import {handleOtaClockSkewFromGlasses} from "./glassesClockSync"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import BluetoothSdk from "@mentra/bluetooth-sdk
|
|
2
|
-
import type {OtaUpdateInfo} from "@mentra/bluetooth-sdk"
|
|
1
|
+
import BluetoothSdk, {type OtaUpdateInfo} from "@mentra/bluetooth-sdk"
|
|
3
2
|
import {getGlassesSystemTimeMs, isGlassesConnected, useGlassesStore, waitForGlassesState} from "../stores/glasses"
|
|
4
3
|
import {maybeFixGlassesClockFromVersionInfo} from "./glassesClockSync"
|
|
5
4
|
import {hasConfiguredModernOtaManifestPin, resolveOtaManifestUrl} from "./otaManifestUrl"
|
|
@@ -406,9 +405,13 @@ export async function checkCurrentGlassesForUpdate(
|
|
|
406
405
|
}
|
|
407
406
|
|
|
408
407
|
if (refreshVersionInfo) {
|
|
409
|
-
void BluetoothSdk.requestVersionInfo()
|
|
410
|
-
|
|
411
|
-
|
|
408
|
+
void BluetoothSdk.requestVersionInfo()
|
|
409
|
+
.then((versionInfo) => {
|
|
410
|
+
useGlassesStore.getState().setGlassesInfo(versionInfo)
|
|
411
|
+
})
|
|
412
|
+
.catch((error) => {
|
|
413
|
+
console.warn("OTA: Failed to request version_info from glasses:", error)
|
|
414
|
+
})
|
|
412
415
|
}
|
|
413
416
|
|
|
414
417
|
let buildNumber = useGlassesStore.getState().buildNumber
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as RNFS from "@dr.pogodin/react-native-fs"
|
|
2
|
-
import {
|
|
2
|
+
import {otaLocalNetwork, type OtaLocalNetworkDownloadProgress} from "@mentra/bluetooth-sdk/ota-transport"
|
|
3
3
|
import {Buffer} from "buffer"
|
|
4
4
|
import {Platform} from "react-native"
|
|
5
5
|
import WifiManager from "react-native-wifi-reborn"
|
|
@@ -17,7 +17,7 @@ export function shouldUseScopedLocalNetwork(os: string, moduleAvailable: boolean
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function supportsScopedConnection(): boolean {
|
|
20
|
-
return shouldUseScopedLocalNetwork(Platform.OS,
|
|
20
|
+
return shouldUseScopedLocalNetwork(Platform.OS, otaLocalNetwork.isAvailable())
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function normalizeHeaders(headers?: HeadersInit): Record<string, string> {
|
|
@@ -48,25 +48,25 @@ export const localNetworkTransport = {
|
|
|
48
48
|
await WifiManager.connectToProtectedSSID(ssid, password, false, false)
|
|
49
49
|
return undefined
|
|
50
50
|
}
|
|
51
|
-
const result = await
|
|
51
|
+
const result = await otaLocalNetwork.connect(ssid, password)
|
|
52
52
|
scopedConnectionActive = true
|
|
53
53
|
return result.localAddress
|
|
54
54
|
},
|
|
55
55
|
|
|
56
56
|
async disconnect(): Promise<void> {
|
|
57
57
|
if (supportsScopedConnection()) {
|
|
58
|
-
await
|
|
58
|
+
await otaLocalNetwork.disconnect().catch(() => {})
|
|
59
59
|
}
|
|
60
60
|
scopedConnectionActive = false
|
|
61
61
|
nativeJobs.clear()
|
|
62
62
|
},
|
|
63
63
|
|
|
64
64
|
async fetch(url: string | URL | Request, init?: RequestInit, timeoutMs = 30_000): Promise<Response> {
|
|
65
|
-
if (!scopedConnectionActive || !
|
|
65
|
+
if (!scopedConnectionActive || !otaLocalNetwork.isAvailable() || typeof url !== "string") {
|
|
66
66
|
return globalThis.fetch(url, init)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const nativeModule =
|
|
69
|
+
const nativeModule = otaLocalNetwork
|
|
70
70
|
const id = requestId("request")
|
|
71
71
|
const signal = init?.signal
|
|
72
72
|
const cancel = () => void nativeModule.cancel(id)
|
|
@@ -92,13 +92,13 @@ export const localNetworkTransport = {
|
|
|
92
92
|
},
|
|
93
93
|
|
|
94
94
|
downloadFile(options: DownloadOptions): DownloadHandle {
|
|
95
|
-
if (!scopedConnectionActive || !
|
|
95
|
+
if (!scopedConnectionActive || !otaLocalNetwork.isAvailable()) return RNFS.downloadFile(options)
|
|
96
96
|
|
|
97
97
|
const jobId = nextJobId++
|
|
98
98
|
const id = requestId("download")
|
|
99
99
|
let began = false
|
|
100
100
|
nativeJobs.set(jobId, id)
|
|
101
|
-
const subscription =
|
|
101
|
+
const subscription = otaLocalNetwork.onDownloadProgress((event: OtaLocalNetworkDownloadProgress) => {
|
|
102
102
|
if (event.requestId !== id) return
|
|
103
103
|
if (!began) {
|
|
104
104
|
began = true
|
|
@@ -116,14 +116,15 @@ export const localNetworkTransport = {
|
|
|
116
116
|
})
|
|
117
117
|
})
|
|
118
118
|
|
|
119
|
-
const promise =
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
119
|
+
const promise = otaLocalNetwork
|
|
120
|
+
.download(
|
|
121
|
+
id,
|
|
122
|
+
options.fromUrl,
|
|
123
|
+
options.toFile,
|
|
124
|
+
options.headers || {},
|
|
125
|
+
options.connectionTimeout || 30_000,
|
|
126
|
+
options.readTimeout || 30_000,
|
|
127
|
+
)
|
|
127
128
|
.then((result) => {
|
|
128
129
|
if (!began) {
|
|
129
130
|
options.begin?.({
|
|
@@ -154,16 +155,16 @@ export const localNetworkTransport = {
|
|
|
154
155
|
|
|
155
156
|
stopDownload(jobId: number): void {
|
|
156
157
|
const nativeId = nativeJobs.get(jobId)
|
|
157
|
-
if (nativeId &&
|
|
158
|
+
if (nativeId && otaLocalNetwork.isAvailable()) {
|
|
158
159
|
cancelledNativeJobs.add(jobId)
|
|
159
|
-
void
|
|
160
|
+
void otaLocalNetwork.cancel(nativeId)
|
|
160
161
|
return
|
|
161
162
|
}
|
|
162
163
|
RNFS.stopDownload(jobId)
|
|
163
164
|
},
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
|
|
167
|
+
otaLocalNetwork.onNetworkLost(() => {
|
|
167
168
|
scopedConnectionActive = false
|
|
168
169
|
nativeJobs.clear()
|
|
169
170
|
})
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Push phone time to glasses only when clock skew is detected (gallery sync, OTA, etc.).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import BluetoothSdk from "@mentra/bluetooth-sdk
|
|
5
|
+
import BluetoothSdk from "@mentra/bluetooth-sdk"
|
|
6
6
|
import {BgTimer} from "../utils/timers"
|
|
7
7
|
import {useGlassesStore} from "../stores/glasses"
|
|
8
8
|
|
package/src/stores/core.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {create} from "zustand"
|
|
2
2
|
import {subscribeWithSelector} from "zustand/middleware"
|
|
3
|
-
import type {
|
|
3
|
+
import type {PublicBluetoothStatus} from "@mentra/bluetooth-sdk"
|
|
4
4
|
|
|
5
|
-
export interface CoreState extends
|
|
6
|
-
setCoreInfo: (info: Partial<
|
|
5
|
+
export interface CoreState extends PublicBluetoothStatus {
|
|
6
|
+
setCoreInfo: (info: Partial<PublicBluetoothStatus>) => void
|
|
7
7
|
reset: () => void
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const initialState:
|
|
10
|
+
const initialState: PublicBluetoothStatus = {
|
|
11
11
|
// state:
|
|
12
12
|
searching: false,
|
|
13
13
|
searchingController: false,
|
package/src/stores/glasses.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
GlassesConnectionStatus,
|
|
3
|
-
GlassesStatus,
|
|
4
3
|
HotspotStatus,
|
|
5
4
|
OtaProgress,
|
|
6
5
|
OtaStatus,
|
|
7
6
|
OtaUpdateInfo,
|
|
7
|
+
PublicGlassesStatus,
|
|
8
8
|
WifiStatus,
|
|
9
|
-
} from "@mentra/bluetooth-sdk
|
|
9
|
+
} from "@mentra/bluetooth-sdk"
|
|
10
10
|
import {isGlassesConnected, isGlassesLinkLayerBusy, isGlassesReady} from "../services/GlassesReadiness"
|
|
11
11
|
import {create} from "zustand"
|
|
12
12
|
import {subscribeWithSelector} from "zustand/middleware"
|
|
@@ -20,7 +20,14 @@ export const selectGlassesConnected = (state: {connection: GlassesConnectionStat
|
|
|
20
20
|
|
|
21
21
|
export const selectGlassesReady = (state: {connection: GlassesConnectionStatus}) => isGlassesReady(state.connection)
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
type EngineGlassesStatus = PublicGlassesStatus & {
|
|
24
|
+
otaUpdateAvailable: OtaUpdateInfo | null
|
|
25
|
+
otaProgress: OtaProgress | null
|
|
26
|
+
otaInProgress: boolean
|
|
27
|
+
otaVersionUrl: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface GlassesState extends EngineGlassesStatus {
|
|
24
31
|
systemTimeMs: number
|
|
25
32
|
wifiStatusKnown: boolean
|
|
26
33
|
setGlassesInfo: (info: GlassesInfoUpdate) => void
|
|
@@ -53,7 +60,7 @@ type LegacyHotspotFields = {
|
|
|
53
60
|
hotspotLocalIp?: string
|
|
54
61
|
}
|
|
55
62
|
|
|
56
|
-
type GlassesInfoUpdate = Partial<
|
|
63
|
+
type GlassesInfoUpdate = Partial<EngineGlassesStatus> & LegacyWifiFields & LegacyHotspotFields
|
|
57
64
|
|
|
58
65
|
function wifiFromLegacyFields(info: LegacyWifiFields): WifiStatus | null {
|
|
59
66
|
if (info.wifiConnected === true) {
|
|
@@ -80,7 +87,7 @@ function hotspotFromLegacyFields(info: LegacyHotspotFields): HotspotStatus | nul
|
|
|
80
87
|
return null
|
|
81
88
|
}
|
|
82
89
|
|
|
83
|
-
export const getGlasesInfoPartial = (state:
|
|
90
|
+
export const getGlasesInfoPartial = (state: EngineGlassesStatus) => {
|
|
84
91
|
const wifi = state.wifi
|
|
85
92
|
const connected = isGlassesConnected(state.connection)
|
|
86
93
|
return {
|
|
@@ -98,7 +105,7 @@ export const getGlasesInfoPartial = (state: GlassesStatus) => {
|
|
|
98
105
|
}
|
|
99
106
|
}
|
|
100
107
|
|
|
101
|
-
interface GlassesStore extends
|
|
108
|
+
interface GlassesStore extends EngineGlassesStatus {
|
|
102
109
|
systemTimeMs: number
|
|
103
110
|
mtkUpdatedThisSession: boolean
|
|
104
111
|
wifiStatusKnown: boolean
|