@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.
Files changed (69) hide show
  1. package/README.md +19 -5
  2. package/build/bluetooth-sdk/ota-transport.d.ts +2 -0
  3. package/build/bluetooth-sdk/ota-transport.d.ts.map +1 -0
  4. package/build/bluetooth-sdk/ota-transport.js +2 -0
  5. package/build/bluetooth-sdk/ota-transport.js.map +1 -0
  6. package/build/engine.d.ts +2 -2
  7. package/build/facades/ota.d.ts +4 -4
  8. package/build/facades/ota.d.ts.map +1 -1
  9. package/build/facades/ota.js +3 -4
  10. package/build/facades/ota.js.map +1 -1
  11. package/build/generated/releaseMetadata.js +4 -4
  12. package/build/generated/releaseMetadata.js.map +1 -1
  13. package/build/react/MentraLiveOtaFlow.d.ts +3 -2
  14. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -1
  15. package/build/react/MentraLiveOtaFlow.js +68 -345
  16. package/build/react/MentraLiveOtaFlow.js.map +1 -1
  17. package/build/react/index.d.ts +1 -0
  18. package/build/react/index.d.ts.map +1 -1
  19. package/build/react/index.js +1 -0
  20. package/build/react/index.js.map +1 -1
  21. package/build/react/useMentraLiveOta.d.ts +69 -0
  22. package/build/react/useMentraLiveOta.d.ts.map +1 -0
  23. package/build/react/useMentraLiveOta.js +485 -0
  24. package/build/react/useMentraLiveOta.js.map +1 -0
  25. package/build/services/GlassesStatusProjection.d.ts +15 -2
  26. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  27. package/build/services/GlassesStatusProjection.js +3 -3
  28. package/build/services/GlassesStatusProjection.js.map +1 -1
  29. package/build/services/HotspotOtaTransport.d.ts.map +1 -1
  30. package/build/services/HotspotOtaTransport.js +8 -7
  31. package/build/services/HotspotOtaTransport.js.map +1 -1
  32. package/build/services/OtaInstallCoordinator.d.ts +24 -3
  33. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  34. package/build/services/OtaInstallCoordinator.js +14 -12
  35. package/build/services/OtaInstallCoordinator.js.map +1 -1
  36. package/build/services/OtaService.d.ts.map +1 -1
  37. package/build/services/OtaService.js +1 -1
  38. package/build/services/OtaService.js.map +1 -1
  39. package/build/services/OtaUpdateCheckService.d.ts +1 -1
  40. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  41. package/build/services/OtaUpdateCheckService.js +6 -2
  42. package/build/services/OtaUpdateCheckService.js.map +1 -1
  43. package/build/services/asg/localNetworkTransport.d.ts.map +1 -1
  44. package/build/services/asg/localNetworkTransport.js +13 -12
  45. package/build/services/asg/localNetworkTransport.js.map +1 -1
  46. package/build/services/glassesClockSync.js +1 -1
  47. package/build/services/glassesClockSync.js.map +1 -1
  48. package/build/stores/core.d.ts +3 -3
  49. package/build/stores/core.d.ts.map +1 -1
  50. package/build/stores/core.js.map +1 -1
  51. package/build/stores/glasses.d.ts +10 -4
  52. package/build/stores/glasses.d.ts.map +1 -1
  53. package/build/stores/glasses.js.map +1 -1
  54. package/package.json +12 -6
  55. package/src/bluetooth-sdk/ota-transport.ts +1 -0
  56. package/src/facades/ota.ts +3 -4
  57. package/src/generated/releaseMetadata.ts +4 -4
  58. package/src/react/MentraLiveOtaFlow.tsx +116 -466
  59. package/src/react/index.ts +13 -0
  60. package/src/react/useMentraLiveOta.ts +619 -0
  61. package/src/services/GlassesStatusProjection.ts +7 -6
  62. package/src/services/HotspotOtaTransport.ts +8 -7
  63. package/src/services/OtaInstallCoordinator.ts +16 -13
  64. package/src/services/OtaService.ts +1 -2
  65. package/src/services/OtaUpdateCheckService.ts +8 -5
  66. package/src/services/asg/localNetworkTransport.ts +20 -19
  67. package/src/services/glassesClockSync.ts +1 -1
  68. package/src/stores/core.ts +4 -4
  69. package/src/stores/glasses.ts +13 -6
@@ -1,4 +1,5 @@
1
- import BluetoothSdk, {isEnabledHotspotStatus, MentraOtaServer} from "@mentra/bluetooth-sdk/internal"
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 MentraOtaServer.waitForWifiAddress(hotspot.localIp, 15_000)
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 MentraOtaServer.startOtaServer("{}", artifactPaths, localAddress)
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 MentraOtaServer.startOtaServer(manifest, artifactPaths, server.host)
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 = MentraOtaServer.addListener("artifactDownloadProgress", (event) => {
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 MentraOtaServer.downloadArtifact(entry.url, destination)
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 MentraOtaServer.stopOtaServer().catch(() => {})
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/internal"
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.sendOtaQueryStatus().catch(() => {})
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
- void this.teardownHotspotTransport()
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.sendOtaQueryStatus()
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.sendOtaQueryStatus().catch(() => {})
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.sendOtaQueryStatus()
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.sendOtaQueryStatus()
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.sendOtaQueryStatus()
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/internal"
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/internal"
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().catch((error) => {
410
- console.warn("OTA: Failed to request version_info from glasses:", error)
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 {MentraLocalNetwork, type LocalNetworkDownloadProgress} from "@mentra/bluetooth-sdk/internal"
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, MentraLocalNetwork != null)
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 MentraLocalNetwork!.connect(ssid, password)
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 MentraLocalNetwork!.disconnect().catch(() => {})
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 || !MentraLocalNetwork || typeof url !== "string") {
65
+ if (!scopedConnectionActive || !otaLocalNetwork.isAvailable() || typeof url !== "string") {
66
66
  return globalThis.fetch(url, init)
67
67
  }
68
68
 
69
- const nativeModule = MentraLocalNetwork
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 || !MentraLocalNetwork) return RNFS.downloadFile(options)
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 = MentraLocalNetwork.addListener("downloadProgress", (event: LocalNetworkDownloadProgress) => {
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 = MentraLocalNetwork.download(
120
- id,
121
- options.fromUrl,
122
- options.toFile,
123
- options.headers || {},
124
- options.connectionTimeout || 30_000,
125
- options.readTimeout || 30_000,
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 && MentraLocalNetwork) {
158
+ if (nativeId && otaLocalNetwork.isAvailable()) {
158
159
  cancelledNativeJobs.add(jobId)
159
- void MentraLocalNetwork.cancel(nativeId)
160
+ void otaLocalNetwork.cancel(nativeId)
160
161
  return
161
162
  }
162
163
  RNFS.stopDownload(jobId)
163
164
  },
164
165
  }
165
166
 
166
- MentraLocalNetwork?.addListener("networkLost", () => {
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/internal"
5
+ import BluetoothSdk from "@mentra/bluetooth-sdk"
6
6
  import {BgTimer} from "../utils/timers"
7
7
  import {useGlassesStore} from "../stores/glasses"
8
8
 
@@ -1,13 +1,13 @@
1
1
  import {create} from "zustand"
2
2
  import {subscribeWithSelector} from "zustand/middleware"
3
- import type {BluetoothStatus} from "@mentra/bluetooth-sdk/internal"
3
+ import type {PublicBluetoothStatus} from "@mentra/bluetooth-sdk"
4
4
 
5
- export interface CoreState extends BluetoothStatus {
6
- setCoreInfo: (info: Partial<BluetoothStatus>) => void
5
+ export interface CoreState extends PublicBluetoothStatus {
6
+ setCoreInfo: (info: Partial<PublicBluetoothStatus>) => void
7
7
  reset: () => void
8
8
  }
9
9
 
10
- const initialState: BluetoothStatus = {
10
+ const initialState: PublicBluetoothStatus = {
11
11
  // state:
12
12
  searching: false,
13
13
  searchingController: false,
@@ -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/internal"
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
- export interface GlassesState extends GlassesStatus {
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<GlassesStatus> & LegacyWifiFields & LegacyHotspotFields
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: GlassesStatus) => {
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 GlassesStatus {
108
+ interface GlassesStore extends EngineGlassesStatus {
102
109
  systemTimeMs: number
103
110
  mtkUpdatedThisSession: boolean
104
111
  wifiStatusKnown: boolean