@mentra/bluetooth-sdk 0.1.21-beta.3 → 3.1.0-beta.100
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 +67 -25
- package/android/build.gradle +7 -4
- package/android/lc3Lib/build.gradle +18 -4
- package/android/silero/build.gradle +9 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +16 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +35 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +216 -23
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +2 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedChangelogCatalog.kt +7 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +11 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +127 -8
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraLocalNetworkModule.kt +93 -12
- package/android/src/main/java/com/mentra/bluetoothsdk/OtaManifest.kt +5 -7
- package/android/src/main/java/com/mentra/bluetoothsdk/ReleaseChangelog.kt +61 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/ScopedNetworkReadiness.kt +17 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/audio/AudioModels.kt +15 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +24 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/net/LocalIpv4.kt +57 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/otaserver/LocalOtaServer.kt +304 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/otaserver/MentraOtaServerModule.kt +120 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/MentraPhotoReceiverModule.kt +2 -49
- package/android/src/main/java/com/mentra/bluetoothsdk/services/Foreground.kt +61 -30
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +1393 -284
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLivePairingAdvertisement.kt +54 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +8 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +17 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/types/DeviceModels.kt +12 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BleJsonCompact.java +74 -79
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtils.java +3 -3
- package/android/src/test/java/com/mentra/bluetoothsdk/OtaStartResponsePolicyTest.kt +30 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/ReleaseChangelogTest.kt +13 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/ScopedNetworkReadinessTest.kt +39 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/otaserver/LocalOtaServerTest.kt +82 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/services/ForegroundServiceTypeTest.kt +69 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveGattCharacteristicsTest.kt +39 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLivePairingAdvertisementParserTest.kt +133 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/BleJsonCompactTest.java +148 -7
- package/build/BluetoothSdk.types.d.ts +84 -2
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_internal.d.ts +2 -0
- package/build/_internal.d.ts.map +1 -1
- package/build/_internal.js +2 -0
- package/build/_internal.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +4 -1
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +1 -1
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/_private/MentraLocalNetworkModule.d.ts +1 -0
- package/build/_private/MentraLocalNetworkModule.d.ts.map +1 -1
- package/build/_private/MentraLocalNetworkModule.js.map +1 -1
- package/build/_private/sdkOtaManifest.d.ts +3 -12
- package/build/_private/sdkOtaManifest.d.ts.map +1 -1
- package/build/_private/sdkOtaManifest.js +5 -17
- package/build/_private/sdkOtaManifest.js.map +1 -1
- package/build/changelogs.d.ts +7 -0
- package/build/changelogs.d.ts.map +1 -0
- package/build/changelogs.js +44 -0
- package/build/changelogs.js.map +1 -0
- package/build/generated/changelogCatalog.d.ts +6 -0
- package/build/generated/changelogCatalog.d.ts.map +1 -0
- package/build/generated/changelogCatalog.js +8 -0
- package/build/generated/changelogCatalog.js.map +1 -0
- package/build/generated/releaseMetadata.d.ts +12 -0
- package/build/generated/releaseMetadata.d.ts.map +1 -0
- package/build/generated/releaseMetadata.js +10 -0
- package/build/generated/releaseMetadata.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +24 -2
- package/build/index.js.map +1 -1
- package/build/ota-server/MentraOtaServer.types.d.ts +14 -0
- package/build/ota-server/MentraOtaServer.types.d.ts.map +1 -0
- package/build/ota-server/MentraOtaServer.types.js +2 -0
- package/build/ota-server/MentraOtaServer.types.js.map +1 -0
- package/build/ota-server/MentraOtaServerModule.d.ts +21 -0
- package/build/ota-server/MentraOtaServerModule.d.ts.map +1 -0
- package/build/ota-server/MentraOtaServerModule.js +3 -0
- package/build/ota-server/MentraOtaServerModule.js.map +1 -0
- package/build/ota-server/MentraOtaServerModule.web.d.ts +10 -0
- package/build/ota-server/MentraOtaServerModule.web.d.ts.map +1 -0
- package/build/ota-server/MentraOtaServerModule.web.js +12 -0
- package/build/ota-server/MentraOtaServerModule.web.js.map +1 -0
- package/build/ota-server/index.d.ts +3 -0
- package/build/ota-server/index.d.ts.map +1 -0
- package/build/ota-server/index.js +3 -0
- package/build/ota-server/index.js.map +1 -0
- package/build/ota-transport/index.d.ts +67 -0
- package/build/ota-transport/index.d.ts.map +1 -0
- package/build/ota-transport/index.js +58 -0
- package/build/ota-transport/index.js.map +1 -0
- package/expo-module.config.json +3 -2
- package/ios/BackgroundOtaArtifactDownloader.swift +125 -0
- package/ios/BluetoothSdkModule.swift +16 -2
- package/ios/LocalIPv4.swift +150 -0
- package/ios/LocalOtaServer.swift +309 -0
- package/ios/MentraBluetoothSDK.podspec +5 -1
- package/ios/MentraOtaServerModule.swift +147 -0
- package/ios/MentraPhotoReceiverModule.swift +1 -81
- package/ios/Source/BluetoothSdkDefaults.swift +4 -1
- package/ios/Source/Bridge.swift +43 -4
- package/ios/Source/DeviceManager.swift +154 -19
- package/ios/Source/DeviceStore.swift +2 -0
- package/ios/Source/GeneratedChangelogCatalog.swift +6 -0
- package/ios/Source/GeneratedReleaseMetadata.swift +11 -0
- package/ios/Source/MentraBluetoothSDK.swift +91 -6
- package/ios/Source/OtaManifest.swift +5 -7
- package/ios/Source/ReleaseChangelog.swift +65 -0
- package/ios/Source/audio/AudioModels.swift +17 -0
- package/ios/Source/camera/CameraModels.swift +1 -0
- package/ios/Source/events/BluetoothEvents.swift +27 -0
- package/ios/Source/sgcs/MentraLive.swift +512 -78
- package/ios/Source/sgcs/MentraLivePairingAdvertisement.swift +64 -0
- package/ios/Source/sgcs/SGCManager.swift +11 -0
- package/ios/Source/status/DeviceStatus.swift +23 -0
- package/ios/Source/types/DeviceModels.swift +23 -2
- package/ios/Source/utils/BleJsonCompact.swift +73 -71
- package/ios/Tests/MentraLivePairingAdvertisementTests.swift +160 -0
- package/ios/Tests/ReleaseChangelogTests.swift +13 -0
- package/package.json +10 -1
- package/plugin/build/withIos.d.ts +3 -1
- package/plugin/build/withIos.js +22 -10
- package/scripts/public-ota-api.test.mjs +37 -0
- package/scripts/verify-release-package.mjs +34 -0
- package/scripts/write-release-metadata.mjs +154 -0
- package/scripts/write-release-metadata.test.mjs +29 -0
- package/src/BluetoothSdk.types.ts +97 -3
- package/src/_internal.ts +2 -0
- package/src/_private/BluetoothSdkModule.ts +5 -5
- package/src/_private/MentraLocalNetworkModule.ts +1 -1
- package/src/_private/sdkOtaManifest.ts +5 -17
- package/src/changelogs.ts +44 -0
- package/src/generated/changelogCatalog.ts +9 -0
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +43 -2
- package/src/ota-server/MentraOtaServer.types.ts +10 -0
- package/src/ota-server/MentraOtaServerModule.ts +23 -0
- package/src/ota-server/MentraOtaServerModule.web.ts +17 -0
- package/src/ota-server/index.ts +2 -0
- package/src/ota-transport/index.ts +116 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type {ReleaseChangelog} from "./BluetoothSdk.types"
|
|
2
|
+
import {GENERATED_RELEASE_CHANGELOGS} from "./generated/changelogCatalog"
|
|
3
|
+
import {BLUETOOTH_SDK_RELEASE_METADATA} from "./generated/releaseMetadata"
|
|
4
|
+
|
|
5
|
+
const BASE_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:[-+].*)?$/
|
|
6
|
+
|
|
7
|
+
function baseVersion(version: string, label: string): string {
|
|
8
|
+
const match = BASE_VERSION_PATTERN.exec(version.trim())
|
|
9
|
+
if (!match) throw new Error(`${label} must be a semantic version such as 3.1.0, 3.1.0-dev.4, or 3.1.0-beta.2`)
|
|
10
|
+
return `${match[1]}.${match[2]}.${match[3]}`
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function compareVersions(left: string, right: string): number {
|
|
14
|
+
const a = left.split(".").map(Number)
|
|
15
|
+
const b = right.split(".").map(Number)
|
|
16
|
+
for (let index = 0; index < 3; index += 1) {
|
|
17
|
+
if (a[index] !== b[index]) return a[index] - b[index]
|
|
18
|
+
}
|
|
19
|
+
return 0
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Return authored release notes crossed between two product versions, newest first.
|
|
24
|
+
* The target release is always included, including transitions within one base train.
|
|
25
|
+
*/
|
|
26
|
+
export function getReleaseChangelogs(fromVersion?: string | null, toVersion?: string | null): ReleaseChangelog[] {
|
|
27
|
+
const fallbackTarget = BLUETOOTH_SDK_RELEASE_METADATA.familyBaseVersion ?? GENERATED_RELEASE_CHANGELOGS[0]?.version
|
|
28
|
+
if (!fallbackTarget && !toVersion) return []
|
|
29
|
+
const target = baseVersion(toVersion ?? fallbackTarget, "toVersion")
|
|
30
|
+
if (!GENERATED_RELEASE_CHANGELOGS.some(({version}) => version === target)) {
|
|
31
|
+
throw new Error(`No changelog is bundled for target version ${target}`)
|
|
32
|
+
}
|
|
33
|
+
if (!fromVersion) {
|
|
34
|
+
return GENERATED_RELEASE_CHANGELOGS.filter(({version}) => version === target).map((entry) => ({...entry}))
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const source = baseVersion(fromVersion, "fromVersion")
|
|
38
|
+
const direction = compareVersions(target, source)
|
|
39
|
+
return GENERATED_RELEASE_CHANGELOGS.filter(({version}) => {
|
|
40
|
+
if (direction === 0) return version === target
|
|
41
|
+
if (direction > 0) return compareVersions(version, source) > 0 && compareVersions(version, target) <= 0
|
|
42
|
+
return compareVersions(version, source) < 0 && compareVersions(version, target) >= 0
|
|
43
|
+
}).map((entry) => ({...entry}))
|
|
44
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Generated from /changelogs. Do not edit directly. */
|
|
2
|
+
export const GENERATED_RELEASE_CHANGELOGS = Object.freeze(
|
|
3
|
+
[
|
|
4
|
+
{
|
|
5
|
+
"version": "3.1.0",
|
|
6
|
+
"markdown": "Software updates are more reliable, with clearer progress and recovery when the glasses restart.\n\n- MentraOS, Mentra Engine, the Bluetooth SDK, and the glasses client now share one coordinated release version.\n- Mentra Live updates can continue across APK, system, and firmware restarts without asking the user to start the same update again.\n- Bluetooth photo capture and transfer diagnostics are more precise and less disruptive to normal glasses traffic."
|
|
7
|
+
}
|
|
8
|
+
] as const,
|
|
9
|
+
)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Generated by release CI. Do not edit in a release checkout. */
|
|
2
|
+
export interface BluetoothSdkReleaseMetadata {
|
|
3
|
+
schemaVersion: 1
|
|
4
|
+
familyBaseVersion: string | null
|
|
5
|
+
releaseIdentity: string | null
|
|
6
|
+
releaseSetId: string | null
|
|
7
|
+
sourceCommit: string | null
|
|
8
|
+
otaManifestUrl: string | null
|
|
9
|
+
otaManifestSha256: string | null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({
|
|
13
|
+
"schemaVersion": 1,
|
|
14
|
+
"familyBaseVersion": "3.1.0",
|
|
15
|
+
"releaseIdentity": "3.1.0-beta.100",
|
|
16
|
+
"releaseSetId": "mentra-3.1.0-beta.100",
|
|
17
|
+
"sourceCommit": "c7c90f50ce7fd83dadc9a005e152db1d88083e4f",
|
|
18
|
+
"otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.1.0/mentra-live-ota-3.1.0-beta.100.json",
|
|
19
|
+
"otaManifestSha256": "7fdf5b1f75d5d07007e45c929495cd4b6800c810c94e3c60c62bda99d1c61552"
|
|
20
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -3,8 +3,11 @@ import type {
|
|
|
3
3
|
BluetoothSdkEventListener,
|
|
4
4
|
BluetoothSdkEventName,
|
|
5
5
|
BluetoothSdkPublicModule,
|
|
6
|
+
PublicBluetoothStatus,
|
|
7
|
+
PublicGlassesStatus,
|
|
6
8
|
VideoRecordingDefaults,
|
|
7
9
|
} from "./BluetoothSdk.types"
|
|
10
|
+
import {getReleaseChangelogs} from "./changelogs"
|
|
8
11
|
|
|
9
12
|
const PUBLIC_EVENT_NAMES = new Set<BluetoothSdkEventName>([
|
|
10
13
|
"log",
|
|
@@ -36,12 +39,18 @@ const PUBLIC_EVENT_NAMES = new Set<BluetoothSdkEventName>([
|
|
|
36
39
|
"rgb_led_control_response",
|
|
37
40
|
"settings_ack",
|
|
38
41
|
"pair_failure",
|
|
42
|
+
"pairing_info",
|
|
43
|
+
"entering_pairing_mode",
|
|
44
|
+
"owner_replaced",
|
|
39
45
|
"audio_pairing_needed",
|
|
40
46
|
"audio_connected",
|
|
41
47
|
"audio_disconnected",
|
|
42
48
|
"mic_pcm",
|
|
43
49
|
"mic_lc3",
|
|
50
|
+
"mic_health",
|
|
44
51
|
"stream_status",
|
|
52
|
+
"mtk_update_complete",
|
|
53
|
+
"glasses_session_changed",
|
|
45
54
|
"ota_start_ack",
|
|
46
55
|
"ota_status",
|
|
47
56
|
"ar99_ota_status",
|
|
@@ -56,8 +65,12 @@ const addListener: BluetoothSdkPublicModule["addListener"] = (eventName, listene
|
|
|
56
65
|
return PrivateBluetoothSdkModule.addListener(eventName, listener as BluetoothSdkEventListener<BluetoothSdkEventName>)
|
|
57
66
|
}
|
|
58
67
|
|
|
59
|
-
const startOtaUpdate: BluetoothSdkPublicModule["startOtaUpdate"] = () => {
|
|
60
|
-
return PrivateBluetoothSdkModule.startOtaUpdate()
|
|
68
|
+
const startOtaUpdate: BluetoothSdkPublicModule["startOtaUpdate"] = (otaVersionUrl) => {
|
|
69
|
+
return PrivateBluetoothSdkModule.startOtaUpdate(otaVersionUrl)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const queryOtaStatus: BluetoothSdkPublicModule["queryOtaStatus"] = () => {
|
|
73
|
+
return PrivateBluetoothSdkModule.sendOtaQueryStatus()
|
|
61
74
|
}
|
|
62
75
|
|
|
63
76
|
const bindPublicMethod = <K extends keyof BluetoothSdkPublicModule>(name: K): BluetoothSdkPublicModule[K] => {
|
|
@@ -73,6 +86,12 @@ const bindPublicMethod = <K extends keyof BluetoothSdkPublicModule>(name: K): Bl
|
|
|
73
86
|
|
|
74
87
|
export const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({
|
|
75
88
|
addListener,
|
|
89
|
+
getGlassesStatus: bindPublicMethod("getGlassesStatus"),
|
|
90
|
+
getBluetoothStatus: bindPublicMethod("getBluetoothStatus"),
|
|
91
|
+
subscribeGlassesStatus: (listener: (changed: Partial<PublicGlassesStatus>) => void) =>
|
|
92
|
+
PrivateBluetoothSdkModule.onGlassesStatus(listener),
|
|
93
|
+
subscribeBluetoothStatus: (listener: (changed: Partial<PublicBluetoothStatus>) => void) =>
|
|
94
|
+
PrivateBluetoothSdkModule.onBluetoothStatus(listener),
|
|
76
95
|
getDefaultDevice: bindPublicMethod("getDefaultDevice"),
|
|
77
96
|
setDefaultDevice: bindPublicMethod("setDefaultDevice"),
|
|
78
97
|
clearDefaultDevice: bindPublicMethod("clearDefaultDevice"),
|
|
@@ -91,10 +110,13 @@ export const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({
|
|
|
91
110
|
setHeadUpAngle: bindPublicMethod("setHeadUpAngle"),
|
|
92
111
|
setImuEnabled: bindPublicMethod("setImuEnabled"),
|
|
93
112
|
setScreenDisabled: bindPublicMethod("setScreenDisabled"),
|
|
113
|
+
ping: bindPublicMethod("ping"),
|
|
94
114
|
requestWifiScan: bindPublicMethod("requestWifiScan"),
|
|
95
115
|
sendWifiCredentials: bindPublicMethod("sendWifiCredentials"),
|
|
96
116
|
forgetWifiNetwork: bindPublicMethod("forgetWifiNetwork"),
|
|
97
117
|
setHotspotState: bindPublicMethod("setHotspotState"),
|
|
118
|
+
setSystemTime: bindPublicMethod("setSystemTime"),
|
|
119
|
+
setWifiAdbState: bindPublicMethod("setWifiAdbState"),
|
|
98
120
|
setGalleryModeEnabled: bindPublicMethod("setGalleryModeEnabled"),
|
|
99
121
|
setVoiceActivityDetectionEnabled: bindPublicMethod("setVoiceActivityDetectionEnabled"),
|
|
100
122
|
setLoudnessGateEnabled: bindPublicMethod("setLoudnessGateEnabled"),
|
|
@@ -125,6 +147,7 @@ export const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({
|
|
|
125
147
|
stopCameraWarmUp: bindPublicMethod("stopCameraWarmUp"),
|
|
126
148
|
startVideoRecording: bindPublicMethod("startVideoRecording"),
|
|
127
149
|
stopVideoRecording: bindPublicMethod("stopVideoRecording"),
|
|
150
|
+
queryVideoRecordingStatus: bindPublicMethod("queryVideoRecordingStatus"),
|
|
128
151
|
startStream: bindPublicMethod("startStream"),
|
|
129
152
|
stopStream: bindPublicMethod("stopStream"),
|
|
130
153
|
setMicState: bindPublicMethod("setMicState"),
|
|
@@ -134,8 +157,12 @@ export const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({
|
|
|
134
157
|
setGlassesMediaVolume: bindPublicMethod("setGlassesMediaVolume"),
|
|
135
158
|
rgbLedControl: bindPublicMethod("rgbLedControl"),
|
|
136
159
|
requestVersionInfo: bindPublicMethod("requestVersionInfo"),
|
|
160
|
+
setOtaVersionUrl: bindPublicMethod("setOtaVersionUrl"),
|
|
161
|
+
getOtaVersionUrl: bindPublicMethod("getOtaVersionUrl"),
|
|
137
162
|
checkForOtaUpdate: bindPublicMethod("checkForOtaUpdate"),
|
|
163
|
+
getReleaseChangelogs,
|
|
138
164
|
startOtaUpdate,
|
|
165
|
+
queryOtaStatus,
|
|
139
166
|
startAr99OtaFromFile: bindPublicMethod("startAr99OtaFromFile"),
|
|
140
167
|
cancelAr99Ota: bindPublicMethod("cancelAr99Ota"),
|
|
141
168
|
sendAr99FactoryReset: bindPublicMethod("sendAr99FactoryReset"),
|
|
@@ -204,23 +231,37 @@ export type {
|
|
|
204
231
|
HotspotErrorEvent,
|
|
205
232
|
HotspotStatus,
|
|
206
233
|
HotspotStatusChangeEvent,
|
|
234
|
+
GlassesSessionChangedEvent,
|
|
235
|
+
KeepAliveAckEvent,
|
|
207
236
|
LocalTranscriptionEvent,
|
|
208
237
|
LogEvent,
|
|
209
238
|
MicLc3Event,
|
|
239
|
+
MicHealthEvent,
|
|
210
240
|
MicMode,
|
|
211
241
|
MicPcmEvent,
|
|
212
242
|
MicPreference,
|
|
213
243
|
OtaStartAckEvent,
|
|
244
|
+
OtaProgress,
|
|
245
|
+
OtaProgressStatus,
|
|
246
|
+
OtaStage,
|
|
214
247
|
OtaStatus,
|
|
215
248
|
OtaStatusEvent,
|
|
216
249
|
OtaQueryResult,
|
|
250
|
+
OtaUpdateInfo,
|
|
251
|
+
ReleaseChangelog,
|
|
252
|
+
MtkUpdateCompleteEvent,
|
|
217
253
|
PairFailureEvent,
|
|
254
|
+
PairingInfoEvent,
|
|
255
|
+
EnteringPairingModeEvent,
|
|
256
|
+
OwnerReplacedEvent,
|
|
218
257
|
PhotoCaptureMetadata,
|
|
219
258
|
PhotoResolvedConfig,
|
|
220
259
|
PhotoCompression,
|
|
221
260
|
PhotoFpsRange,
|
|
222
261
|
PhotoMeteredPreview,
|
|
223
262
|
PhotoMode,
|
|
263
|
+
PublicBluetoothStatus,
|
|
264
|
+
PublicGlassesStatus,
|
|
224
265
|
PhotoTransferMethod,
|
|
225
266
|
PhotoResponseEvent,
|
|
226
267
|
PhotoRequestedCaptureConfig,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type OtaServerResult = {
|
|
2
|
+
baseUrl: string
|
|
3
|
+
host: string
|
|
4
|
+
manifestUrl: string
|
|
5
|
+
port: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type MentraOtaServerModuleEvents = {
|
|
9
|
+
artifactDownloadProgress: (event: {destination: string; bytesWritten: number; contentLength: number}) => void
|
|
10
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {NativeModule, requireNativeModule} from "expo"
|
|
2
|
+
|
|
3
|
+
import type {MentraOtaServerModuleEvents, OtaServerResult} from "./MentraOtaServer.types"
|
|
4
|
+
|
|
5
|
+
declare class MentraOtaServerModule extends NativeModule<MentraOtaServerModuleEvents> {
|
|
6
|
+
/**
|
|
7
|
+
* Serve `manifestJson` at /version.json and `artifactPaths` (sha256 -> local file path)
|
|
8
|
+
* at /artifacts/<sha256>. Pass `host` when the caller knows the authoritative local
|
|
9
|
+
* address (e.g. from the scoped hotspot network); omit to fall back to interface
|
|
10
|
+
* scanning. Returns the URLs to hand to the glasses via ota_start.
|
|
11
|
+
*/
|
|
12
|
+
startOtaServer(
|
|
13
|
+
manifestJson: string,
|
|
14
|
+
artifactPaths: Record<string, string>,
|
|
15
|
+
host?: string | null,
|
|
16
|
+
): Promise<OtaServerResult>
|
|
17
|
+
stopOtaServer(): Promise<void>
|
|
18
|
+
/** Wait for iPhone Wi-Fi (`en0`) to acquire an address on the glasses gateway subnet. */
|
|
19
|
+
waitForWifiAddress(gateway: string, timeoutMs: number): Promise<string>
|
|
20
|
+
downloadArtifact(source: string, destination: string): Promise<{statusCode: number; bytesWritten: number}>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default requireNativeModule<MentraOtaServerModule>("MentraOtaServer")
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {NativeModule, registerWebModule} from "expo"
|
|
2
|
+
|
|
3
|
+
import type {MentraOtaServerModuleEvents, OtaServerResult} from "./MentraOtaServer.types"
|
|
4
|
+
|
|
5
|
+
class MentraOtaServerModule extends NativeModule<MentraOtaServerModuleEvents> {
|
|
6
|
+
async startOtaServer(): Promise<OtaServerResult> {
|
|
7
|
+
throw new Error("The OTA server is only available in native apps.")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async stopOtaServer(): Promise<void> {}
|
|
11
|
+
|
|
12
|
+
async waitForWifiAddress(): Promise<string> {
|
|
13
|
+
throw new Error("The OTA server is only available in native apps.")
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default registerWebModule(MentraOtaServerModule, "MentraOtaServer")
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// This public adapter is the package-owned boundary over its native implementation.
|
|
2
|
+
// eslint-disable-next-line no-restricted-imports
|
|
3
|
+
import MentraLocalNetwork from "../_private/MentraLocalNetworkModule"
|
|
4
|
+
// eslint-disable-next-line no-restricted-imports
|
|
5
|
+
import MentraOtaServer from "../ota-server"
|
|
6
|
+
|
|
7
|
+
export type OtaTransportSubscription = {remove(): void}
|
|
8
|
+
|
|
9
|
+
export type OtaLocalNetworkConnection = {
|
|
10
|
+
connected: boolean
|
|
11
|
+
ssid: string
|
|
12
|
+
localAddress?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type OtaLocalNetworkLostEvent = {ssid: string}
|
|
16
|
+
|
|
17
|
+
export type OtaLocalNetworkResponse = {
|
|
18
|
+
status: number
|
|
19
|
+
headers: Record<string, string>
|
|
20
|
+
bodyBase64: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type OtaLocalNetworkDownloadResult = {
|
|
24
|
+
statusCode: number
|
|
25
|
+
bytesWritten: number
|
|
26
|
+
headers: Record<string, string>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type OtaLocalNetworkDownloadProgress = {
|
|
30
|
+
requestId: string
|
|
31
|
+
bytesWritten: number
|
|
32
|
+
contentLength: number
|
|
33
|
+
statusCode?: number
|
|
34
|
+
headers?: Record<string, string>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type OtaArtifactDownloadProgress = {
|
|
38
|
+
destination: string
|
|
39
|
+
bytesWritten: number
|
|
40
|
+
contentLength: number
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type OtaServerResult = {
|
|
44
|
+
baseUrl: string
|
|
45
|
+
host: string
|
|
46
|
+
manifestUrl: string
|
|
47
|
+
port: number
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Scoped networking for traffic that must stay on a Mentra Live hotspot while
|
|
52
|
+
* the phone's default route remains on cellular or another Wi-Fi network.
|
|
53
|
+
*
|
|
54
|
+
* The module is optional because iOS uses its system Wi-Fi join flow instead.
|
|
55
|
+
*/
|
|
56
|
+
export const otaLocalNetwork = Object.freeze({
|
|
57
|
+
isAvailable: (): boolean => MentraLocalNetwork != null,
|
|
58
|
+
connect: async (ssid: string, password: string): Promise<OtaLocalNetworkConnection> => {
|
|
59
|
+
if (!MentraLocalNetwork) throw new Error("Scoped local networking is not available in this native build")
|
|
60
|
+
return MentraLocalNetwork.connect(ssid, password)
|
|
61
|
+
},
|
|
62
|
+
request: async (
|
|
63
|
+
requestId: string,
|
|
64
|
+
url: string,
|
|
65
|
+
method: string,
|
|
66
|
+
headers: Record<string, string>,
|
|
67
|
+
body: string | null,
|
|
68
|
+
timeoutMs: number,
|
|
69
|
+
): Promise<OtaLocalNetworkResponse> => {
|
|
70
|
+
if (!MentraLocalNetwork) throw new Error("Scoped local networking is not available in this native build")
|
|
71
|
+
return MentraLocalNetwork.request(requestId, url, method, headers, body, timeoutMs)
|
|
72
|
+
},
|
|
73
|
+
download: async (
|
|
74
|
+
requestId: string,
|
|
75
|
+
url: string,
|
|
76
|
+
destination: string,
|
|
77
|
+
headers: Record<string, string>,
|
|
78
|
+
connectionTimeoutMs: number,
|
|
79
|
+
readTimeoutMs: number,
|
|
80
|
+
): Promise<OtaLocalNetworkDownloadResult> => {
|
|
81
|
+
if (!MentraLocalNetwork) throw new Error("Scoped local networking is not available in this native build")
|
|
82
|
+
return MentraLocalNetwork.download(requestId, url, destination, headers, connectionTimeoutMs, readTimeoutMs)
|
|
83
|
+
},
|
|
84
|
+
cancel: async (requestId: string): Promise<void> => {
|
|
85
|
+
if (!MentraLocalNetwork) return
|
|
86
|
+
await MentraLocalNetwork.cancel(requestId)
|
|
87
|
+
},
|
|
88
|
+
disconnect: async (): Promise<void> => {
|
|
89
|
+
if (!MentraLocalNetwork) return
|
|
90
|
+
await MentraLocalNetwork.disconnect()
|
|
91
|
+
},
|
|
92
|
+
onDownloadProgress: (listener: (event: OtaLocalNetworkDownloadProgress) => void): OtaTransportSubscription => {
|
|
93
|
+
if (!MentraLocalNetwork) return {remove() {}}
|
|
94
|
+
return MentraLocalNetwork.addListener("downloadProgress", listener)
|
|
95
|
+
},
|
|
96
|
+
onNetworkLost: (listener: (event: OtaLocalNetworkLostEvent) => void): OtaTransportSubscription => {
|
|
97
|
+
if (!MentraLocalNetwork) return {remove() {}}
|
|
98
|
+
return MentraLocalNetwork.addListener("networkLost", listener)
|
|
99
|
+
},
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
/** Native HTTP server and artifact downloader used by the Engine OTA coordinator. */
|
|
103
|
+
export const otaServer = Object.freeze({
|
|
104
|
+
start: (
|
|
105
|
+
manifestJson: string,
|
|
106
|
+
artifactPaths: Record<string, string>,
|
|
107
|
+
host?: string | null,
|
|
108
|
+
): Promise<OtaServerResult> => MentraOtaServer.startOtaServer(manifestJson, artifactPaths, host),
|
|
109
|
+
stop: (): Promise<void> => MentraOtaServer.stopOtaServer(),
|
|
110
|
+
waitForWifiAddress: (gateway: string, timeoutMs: number): Promise<string> =>
|
|
111
|
+
MentraOtaServer.waitForWifiAddress(gateway, timeoutMs),
|
|
112
|
+
downloadArtifact: (source: string, destination: string): Promise<{statusCode: number; bytesWritten: number}> =>
|
|
113
|
+
MentraOtaServer.downloadArtifact(source, destination),
|
|
114
|
+
onArtifactDownloadProgress: (listener: (event: OtaArtifactDownloadProgress) => void): OtaTransportSubscription =>
|
|
115
|
+
MentraOtaServer.addListener("artifactDownloadProgress", listener),
|
|
116
|
+
})
|