@mentra/engine 3.1.0-dev.10 → 3.1.0-dev.101
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 +24 -6
- 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 +5 -2
- package/build/engine.d.ts.map +1 -1
- package/build/facades/ota.d.ts +12 -7
- package/build/facades/ota.d.ts.map +1 -1
- package/build/facades/ota.js +10 -6
- package/build/facades/ota.js.map +1 -1
- package/build/facades/pairing.d.ts +4 -0
- package/build/facades/pairing.d.ts.map +1 -1
- package/build/facades/pairing.js +81 -7
- package/build/facades/pairing.js.map +1 -1
- package/build/generated/releaseMetadata.js +5 -5
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +3 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/react/MentraLiveOtaFlow.d.ts +8 -2
- package/build/react/MentraLiveOtaFlow.d.ts.map +1 -1
- package/build/react/MentraLiveOtaFlow.js +256 -354
- 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 +84 -0
- package/build/react/useMentraLiveOta.d.ts.map +1 -0
- package/build/react/useMentraLiveOta.js +627 -0
- package/build/react/useMentraLiveOta.js.map +1 -0
- package/build/services/BlobStore.d.ts +2 -0
- package/build/services/BlobStore.d.ts.map +1 -1
- package/build/services/BlobStore.js +63 -10
- package/build/services/BlobStore.js.map +1 -1
- package/build/services/DisplayProcessor.d.ts +3 -3
- package/build/services/DisplayProcessor.js +3 -3
- package/build/services/DisplayProcessor.js.map +1 -1
- 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/LocalDisplayManager.d.ts +2 -3
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +2 -3
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/OtaAutoChain.d.ts +9 -2
- package/build/services/OtaAutoChain.d.ts.map +1 -1
- package/build/services/OtaAutoChain.js +10 -2
- package/build/services/OtaAutoChain.js.map +1 -1
- package/build/services/OtaInstallCoordinator.d.ts +26 -3
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +35 -13
- 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 +4 -1
- package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
- package/build/services/OtaUpdateCheckService.js +21 -5
- package/build/services/OtaUpdateCheckService.js.map +1 -1
- package/build/services/PhonePhotoCoordinator.js +1 -1
- package/build/services/PhonePhotoCoordinator.js.map +1 -1
- package/build/services/StreamLifecycleController.d.ts +3 -3
- package/build/services/StreamLifecycleController.js +3 -3
- package/build/services/StreamLifecycleController.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/services/otaInstallPolicy.d.ts +4 -0
- package/build/services/otaInstallPolicy.d.ts.map +1 -1
- package/build/services/otaInstallPolicy.js +4 -0
- package/build/services/otaInstallPolicy.js.map +1 -1
- package/build/services/otaReleaseVersion.d.ts +10 -0
- package/build/services/otaReleaseVersion.d.ts.map +1 -0
- package/build/services/otaReleaseVersion.js +14 -0
- package/build/services/otaReleaseVersion.js.map +1 -0
- package/build/stores/appVisibility.d.ts +3 -0
- package/build/stores/appVisibility.d.ts.map +1 -0
- package/build/stores/appVisibility.js +3 -0
- package/build/stores/appVisibility.js.map +1 -0
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +7 -1
- package/build/stores/apps.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/build/types/applet.d.ts +1 -1
- package/build/types/applet.js +1 -1
- package/build/types/applet.js.map +1 -1
- package/build/types/capabilities/even-realities-g1.d.ts.map +1 -1
- package/build/types/capabilities/even-realities-g1.js +2 -0
- package/build/types/capabilities/even-realities-g1.js.map +1 -1
- package/build/types/capabilities/even-realities-g2.d.ts.map +1 -1
- package/build/types/capabilities/even-realities-g2.js +2 -0
- package/build/types/capabilities/even-realities-g2.js.map +1 -1
- package/build/types/capabilities/mentra-display.d.ts.map +1 -1
- package/build/types/capabilities/mentra-display.js +2 -0
- package/build/types/capabilities/mentra-display.js.map +1 -1
- package/build/types/capabilities/mentra-live.d.ts.map +1 -1
- package/build/types/capabilities/mentra-live.js +2 -0
- package/build/types/capabilities/mentra-live.js.map +1 -1
- package/build/types/capabilities/nimo.d.ts +9 -0
- package/build/types/capabilities/nimo.d.ts.map +1 -0
- package/build/types/capabilities/nimo.js +57 -0
- package/build/types/capabilities/nimo.js.map +1 -0
- package/build/types/capabilities/none.d.ts.map +1 -1
- package/build/types/capabilities/none.js +2 -0
- package/build/types/capabilities/none.js.map +1 -1
- package/build/types/capabilities/simulated-glasses.d.ts.map +1 -1
- package/build/types/capabilities/simulated-glasses.js +2 -0
- package/build/types/capabilities/simulated-glasses.js.map +1 -1
- package/build/types/capabilities/vuzix-z100.d.ts.map +1 -1
- package/build/types/capabilities/vuzix-z100.js +2 -0
- package/build/types/capabilities/vuzix-z100.js.map +1 -1
- package/build/types/enums.d.ts +2 -1
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -0
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +3 -2
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +3 -1
- package/build/types/hardware.js.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +1 -1
- package/build/types/index.js.map +1 -1
- package/build/utils/display/composer/ColumnComposer.d.ts +1 -1
- package/build/utils/display/composer/ColumnComposer.js +1 -1
- package/build/utils/display/composer/ColumnComposer.js.map +1 -1
- package/package.json +13 -6
- package/src/bluetooth-sdk/ota-transport.ts +1 -0
- package/src/facades/ota.ts +20 -7
- package/src/facades/pairing.ts +88 -12
- package/src/generated/releaseMetadata.ts +5 -5
- package/src/index.ts +3 -0
- package/src/react/MentraLiveOtaFlow.tsx +378 -480
- package/src/react/index.ts +14 -0
- package/src/react/useMentraLiveOta.ts +793 -0
- package/src/services/BlobStore.ts +57 -10
- package/src/services/DisplayProcessor.ts +3 -3
- package/src/services/GlassesStatusProjection.ts +7 -6
- package/src/services/HotspotOtaTransport.ts +8 -7
- package/src/services/LocalDisplayManager.ts +2 -3
- package/src/services/OtaAutoChain.ts +26 -2
- package/src/services/OtaInstallCoordinator.ts +37 -13
- package/src/services/OtaService.ts +1 -2
- package/src/services/OtaUpdateCheckService.ts +26 -8
- package/src/services/PhonePhotoCoordinator.ts +1 -1
- package/src/services/StreamLifecycleController.ts +3 -3
- package/src/services/asg/localNetworkTransport.ts +20 -19
- package/src/services/glassesClockSync.ts +1 -1
- package/src/services/otaInstallPolicy.ts +4 -0
- package/src/services/otaReleaseVersion.ts +22 -0
- package/src/stores/appVisibility.ts +3 -0
- package/src/stores/apps.ts +7 -1
- package/src/stores/core.ts +4 -4
- package/src/stores/glasses.ts +13 -6
- package/src/types/applet.ts +1 -1
- package/src/types/capabilities/even-realities-g1.ts +3 -0
- package/src/types/capabilities/even-realities-g2.ts +3 -0
- package/src/types/capabilities/mentra-display.ts +3 -0
- package/src/types/capabilities/mentra-live.ts +3 -0
- package/src/types/capabilities/nimo.ts +59 -0
- package/src/types/capabilities/none.ts +3 -0
- package/src/types/capabilities/simulated-glasses.ts +3 -0
- package/src/types/capabilities/vuzix-z100.ts +3 -0
- package/src/types/enums.ts +1 -0
- package/src/types/hardware.ts +4 -2
- package/src/types/index.ts +1 -0
- package/src/utils/display/composer/ColumnComposer.ts +1 -1
|
@@ -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
|
|
|
@@ -32,6 +32,8 @@ export const PING_INTERVAL_MS = 10_000
|
|
|
32
32
|
export const QUERY_REPLY_TIMEOUT_MS = 6000
|
|
33
33
|
/** 15s lockout on the Continue button after a BES restart, to prevent an accidental tap. */
|
|
34
34
|
export const BES_CONTINUE_LOCKOUT_MS = 15_000
|
|
35
|
+
/** Fail closed if a BES reboot never reconnects; normal restarts complete in a fraction of this window. */
|
|
36
|
+
export const BES_RESTART_TIMEOUT_MS = 120_000
|
|
35
37
|
|
|
36
38
|
// --- Legacy old-build (< MINIMUM_OTA_STATUS_BUILD) OTA policy (WP 8C) ---
|
|
37
39
|
//
|
|
@@ -51,6 +53,7 @@ export const LEGACY_MTK_INSTALL_TIMEOUT_MS = MTK_INSTALL_TIMEOUT_MS + LEGACY_EXT
|
|
|
51
53
|
export const LEGACY_GLOBAL_OTA_TIMEOUT_MS = GLOBAL_OTA_TIMEOUT_MS + LEGACY_EXTRA_TIMEOUT_MS
|
|
52
54
|
export const LEGACY_PING_INTERVAL_MS = PING_INTERVAL_MS + LEGACY_EXTRA_TIMEOUT_MS
|
|
53
55
|
export const LEGACY_BES_CONTINUE_LOCKOUT_MS = BES_CONTINUE_LOCKOUT_MS + LEGACY_EXTRA_TIMEOUT_MS
|
|
56
|
+
export const LEGACY_BES_RESTART_TIMEOUT_MS = BES_RESTART_TIMEOUT_MS + LEGACY_EXTRA_TIMEOUT_MS
|
|
54
57
|
/**
|
|
55
58
|
* After a legacy apk `install FINISHED` observed in-flight, the legacy screen held the
|
|
56
59
|
* completed state for 12s (+20s pad) so the ASG process restart settles (and fresh
|
|
@@ -122,6 +125,7 @@ export function selectOtaProtocolProfile(
|
|
|
122
125
|
export const OtaProgressMessages = {
|
|
123
126
|
stalledOrStuck: "Update may have failed. Ensure glasses have internet access and try again.",
|
|
124
127
|
globalTimeout: "Update took too long. Please try again.",
|
|
128
|
+
restartTimeout: "Glasses did not finish restarting. Restart them before trying the update again.",
|
|
125
129
|
sendOtaStartFailed: "Failed to communicate with glasses.",
|
|
126
130
|
hotspotArtifactDownloadFailed: "Could not download the update to your phone. Check phone internet and try again.",
|
|
127
131
|
hotspotArtifactVerifyFailed: "The update package could not be verified. Please try again later.",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const COORDINATED_RELEASE_VERSION = /^\d+\.\d+\.\d+(?:-(?:dev|beta)\.[1-9]\d*)?$/
|
|
2
|
+
|
|
3
|
+
type OtaReleaseVersionInput = {
|
|
4
|
+
manifestReleaseVersion?: string | null
|
|
5
|
+
manifestUrl: string
|
|
6
|
+
packagedManifestUrl?: string | null
|
|
7
|
+
packagedReleaseIdentity?: string | null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function validReleaseVersion(version: string | null | undefined): string | null {
|
|
11
|
+
const trimmed = version?.trim()
|
|
12
|
+
return trimmed && COORDINATED_RELEASE_VERSION.test(trimmed) ? trimmed : null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Resolve the label for the selected OTA pin, including stable promotion of exact beta OTA bytes. */
|
|
16
|
+
export function resolveOtaReleaseVersion(input: OtaReleaseVersionInput): string | null {
|
|
17
|
+
const packagedRelease = validReleaseVersion(input.packagedReleaseIdentity)
|
|
18
|
+
if (packagedRelease && input.packagedManifestUrl?.trim() === input.manifestUrl.trim()) {
|
|
19
|
+
return packagedRelease
|
|
20
|
+
}
|
|
21
|
+
return validReleaseVersion(input.manifestReleaseVersion)
|
|
22
|
+
}
|
package/src/stores/apps.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {islandNotifications} from "../services/NotificationsEmitter"
|
|
|
25
25
|
import sttModelManager from "../services/STTModelManager"
|
|
26
26
|
import {miniappLauncher} from "../services/MiniappLauncher"
|
|
27
27
|
import {miniappRunningRegistry} from "../services/MiniappRunningRegistry"
|
|
28
|
+
import {resolveHiddenStatus} from "./appVisibility"
|
|
28
29
|
import {SETTINGS, useSettingsStore} from "./settings"
|
|
29
30
|
import BluetoothSdk from "@mentra/bluetooth-sdk"
|
|
30
31
|
|
|
@@ -221,7 +222,12 @@ function projectApps(previousState: AppStatusState, localApps: ClientApp[]): Cli
|
|
|
221
222
|
...app,
|
|
222
223
|
screenshot: previousByPackage.get(app.packageName)?.screenshot ?? app.screenshot,
|
|
223
224
|
compatibility: HardwareCompatibility.checkCompatibility(app.hardwareRequirements, capabilities),
|
|
224
|
-
|
|
225
|
+
// A registry source can force an app off the primary home screen (for
|
|
226
|
+
// example, Miniapp Developer while its home-screen setting is disabled).
|
|
227
|
+
// Compose that gate with the user's persisted home-screen layout instead
|
|
228
|
+
// of replacing it, otherwise a default-false persisted value makes a
|
|
229
|
+
// source-hidden app visible again during projection.
|
|
230
|
+
hidden: resolveHiddenStatus(app.hidden, previousState.getHiddenStatus(app.packageName)),
|
|
225
231
|
// Derive the foreground flag from the store's single source of truth
|
|
226
232
|
// (`foregroundedPackage`), NOT from the previous snapshot. Carrying it over
|
|
227
233
|
// per-app meant a refresh that momentarily omitted an app (e.g. the
|
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
|
package/src/types/applet.ts
CHANGED
|
@@ -82,6 +82,9 @@ export const evenRealitiesG2: Capabilities = {
|
|
|
82
82
|
// WiFi capabilities - G2 does not support WiFi
|
|
83
83
|
hasWifi: false,
|
|
84
84
|
|
|
85
|
+
// OTA capabilities - G2 firmware updates are not driven by the ASG OTA flow
|
|
86
|
+
hasOta: false,
|
|
87
|
+
|
|
85
88
|
// Dashboard - G2 renders Even Realities' native dashboard in firmware, so
|
|
86
89
|
// MentraOS does not manage the dashboard or expose dashboard settings for it
|
|
87
90
|
hasNativeDashboard: true,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview NIMO hardware capabilities.
|
|
3
|
+
*
|
|
4
|
+
* NIMO uses framed UART-over-BLE for widget content and a separate Opus
|
|
5
|
+
* microphone channel.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {Capabilities} from "../hardware"
|
|
9
|
+
|
|
10
|
+
export const nimo: Capabilities = {
|
|
11
|
+
modelName: "NIMO",
|
|
12
|
+
hasCamera: false,
|
|
13
|
+
camera: null,
|
|
14
|
+
hasDisplay: true,
|
|
15
|
+
display: {
|
|
16
|
+
count: 2,
|
|
17
|
+
isColor: false,
|
|
18
|
+
color: "green",
|
|
19
|
+
canDisplayBitmap: true,
|
|
20
|
+
// Bitmaps render into the 160x160 2bpp navigation widget. The resolution
|
|
21
|
+
// below remains the existing text-display placeholder until hardware
|
|
22
|
+
// screen information is available.
|
|
23
|
+
resolution: {width: 640, height: 400},
|
|
24
|
+
maxTextLines: 5,
|
|
25
|
+
adjustBrightness: true,
|
|
26
|
+
},
|
|
27
|
+
hasMicrophone: true,
|
|
28
|
+
microphone: {
|
|
29
|
+
count: 2,
|
|
30
|
+
hasVAD: false,
|
|
31
|
+
},
|
|
32
|
+
hasSpeaker: false,
|
|
33
|
+
speaker: null,
|
|
34
|
+
hasIMU: true,
|
|
35
|
+
imu: null,
|
|
36
|
+
hasButton: true,
|
|
37
|
+
button: {
|
|
38
|
+
count: 2,
|
|
39
|
+
buttons: [
|
|
40
|
+
{
|
|
41
|
+
type: "press",
|
|
42
|
+
events: ["press", "double_press", "long_press"],
|
|
43
|
+
isCapacitive: true,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: "press",
|
|
47
|
+
events: ["press", "double_press", "long_press"],
|
|
48
|
+
isCapacitive: true,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
hasLight: false,
|
|
53
|
+
light: null,
|
|
54
|
+
power: {
|
|
55
|
+
hasExternalBattery: false,
|
|
56
|
+
},
|
|
57
|
+
hasWifi: false,
|
|
58
|
+
hasOta: false,
|
|
59
|
+
}
|
package/src/types/enums.ts
CHANGED
package/src/types/hardware.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { evenRealitiesG1 } from "./capabilities/even-realities-g1";
|
|
|
4
4
|
import { evenRealitiesG2 } from "./capabilities/even-realities-g2";
|
|
5
5
|
import { mentraDisplay } from "./capabilities/mentra-display";
|
|
6
6
|
import { mentraLive } from "./capabilities/mentra-live";
|
|
7
|
+
import { nimo } from "./capabilities/nimo";
|
|
7
8
|
import { simulatedGlasses } from "./capabilities/simulated-glasses";
|
|
8
9
|
import { vuzixZ100 } from "./capabilities/vuzix-z100";
|
|
9
10
|
import { none } from "./capabilities/none";
|
|
@@ -158,7 +159,7 @@ export interface Capabilities {
|
|
|
158
159
|
hasWifi: boolean;
|
|
159
160
|
|
|
160
161
|
// OTA capability
|
|
161
|
-
hasOta
|
|
162
|
+
hasOta: boolean;
|
|
162
163
|
|
|
163
164
|
// Native dashboard capability
|
|
164
165
|
// True when the device renders its own dashboard in firmware (e.g. Even
|
|
@@ -180,6 +181,7 @@ export const HARDWARE_CAPABILITIES: Record<string, Capabilities> = {
|
|
|
180
181
|
[mentraLive.modelName]: mentraLive,
|
|
181
182
|
[simulatedGlasses.modelName]: simulatedGlasses,
|
|
182
183
|
[vuzixZ100.modelName]: vuzixZ100,
|
|
184
|
+
[nimo.modelName]: nimo,
|
|
183
185
|
[DeviceTypes.MACH1]: vuzixZ100, // Mach1 uses same Vuzix Ultralite hardware as Z100
|
|
184
186
|
[DeviceTypes.AR99]: {
|
|
185
187
|
...evenRealitiesG1,
|
|
@@ -207,4 +209,4 @@ export const getModelCapabilities = (deviceType: DeviceTypes): Capabilities => {
|
|
|
207
209
|
};
|
|
208
210
|
|
|
209
211
|
// export * from "./capabilities"
|
|
210
|
-
export { simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, vuzixZ100, mentraDisplay };
|
|
212
|
+
export { simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, nimo, vuzixZ100, mentraDisplay };
|
package/src/types/index.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* 2. Merges columns line-by-line with pixel-precise space padding
|
|
12
12
|
* 3. Returns a single pre-composed string ready for native to chunk & send
|
|
13
13
|
*
|
|
14
|
-
* @see
|
|
14
|
+
* @see notes/miniapp-display-api-redesign.md for the current display design
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import type { DisplayProfile } from "../profiles/types";
|