@mentra/bluetooth-sdk 0.1.21-beta.0 → 0.1.21-beta.2
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 +22 -11
- package/android/build.gradle +3 -0
- package/android/src/main/AndroidManifest.xml +3 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkAnalytics.kt +34 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkDefaults.kt +1 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +43 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +7 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +82 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +5 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +32 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/OtaManifest.kt +43 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +17 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/debug/BleTraceLogger.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/services/Foreground.kt +53 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Ar99.java +2653 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +161 -14
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +3 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ar99/ota/Ar99OtaManager.java +566 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ar99/ota/OtaByteUtils.java +18 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ar99/ota/OtaCommandConstants.java +35 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ar99/ota/OtaCrc32Util.java +13 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ar99/ota/OtaGattTransport.java +11 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ar99/ota/OtaProtocol.java +92 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/streaming/StreamModels.kt +41 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/types/DeviceModels.kt +7 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BleJsonCompact.java +8 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/Constants.kt +2 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/PhoneAudioMonitor.kt +45 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/Ar99OpusPcmDecoder.java +398 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/OtaManifestDowngradeTest.kt +86 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/StreamStatusEventTest.kt +29 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/camera/PhotoRequestTest.kt +30 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/Ar99AdvertisementMatcherTest.java +22 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/BleJsonCompactTest.java +20 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/PhoneAudioMonitorTest.kt +45 -0
- package/build/BluetoothSdk.types.d.ts +58 -25
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js +2 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_internal.d.ts +1 -0
- package/build/_internal.d.ts.map +1 -1
- package/build/_internal.js +1 -0
- package/build/_internal.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +8 -2
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +6 -3
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/_private/cameraRequestPayload.d.ts +1 -1
- package/build/_private/cameraRequestPayload.d.ts.map +1 -1
- package/build/_private/cameraRequestPayload.js +6 -0
- package/build/_private/cameraRequestPayload.js.map +1 -1
- package/build/_private/photoRequestPayload.d.ts.map +1 -1
- package/build/_private/photoRequestPayload.js +10 -1
- package/build/_private/photoRequestPayload.js.map +1 -1
- package/build/_private/sdkOtaManifest.d.ts +20 -0
- package/build/_private/sdkOtaManifest.d.ts.map +1 -0
- package/build/_private/sdkOtaManifest.js +28 -0
- package/build/_private/sdkOtaManifest.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +7 -1
- package/build/index.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +41 -2
- package/ios/Source/BluetoothSdkDefaults.swift +2 -1
- package/ios/Source/Bridge.swift +15 -3
- package/ios/Source/DeviceManager.swift +67 -17
- package/ios/Source/DeviceStore.swift +5 -1
- package/ios/Source/MentraBluetoothSDK.swift +37 -8
- package/ios/Source/OtaManifest.swift +47 -4
- package/ios/Source/camera/CameraModels.swift +20 -5
- package/ios/Source/internal/BleTraceLogger.swift +1 -1
- package/ios/Source/internal/BluetoothSdkAnalytics.swift +39 -0
- package/ios/Source/sgcs/Ar99.swift +2451 -0
- package/ios/Source/sgcs/MentraLive.swift +174 -38
- package/ios/Source/sgcs/SGCManager.swift +8 -0
- package/ios/Source/sgcs/ar99/ota/Ar99OtaManager.swift +637 -0
- package/ios/Source/streaming/StreamModels.swift +71 -7
- package/ios/Source/types/DeviceModels.swift +13 -0
- package/ios/Source/utils/BleJsonCompact.swift +8 -0
- package/ios/Source/utils/Constants.swift +2 -0
- package/ios/Source/utils/PhoneAudioMonitor.swift +4 -0
- package/package.json +1 -1
- package/src/BluetoothSdk.types.ts +61 -28
- package/src/_internal.ts +1 -0
- package/src/_private/BluetoothSdkModule.ts +20 -6
- package/src/_private/cameraRequestPayload.ts +8 -2
- package/src/_private/photoRequestPayload.ts +12 -2
- package/src/_private/sdkOtaManifest.ts +31 -0
- package/src/index.ts +9 -1
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
const PHOTO_TRANSFER_METHODS = new Set(["auto", "direct", "ble"]);
|
|
2
|
+
function photoTransferMethodForNative(value) {
|
|
3
|
+
if (value === undefined)
|
|
4
|
+
return "auto";
|
|
5
|
+
if (typeof value === "string" && PHOTO_TRANSFER_METHODS.has(value)) {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
throw new TypeError(`Invalid transferMethod ${JSON.stringify(value)}. Expected "auto", "direct", or "ble".`);
|
|
9
|
+
}
|
|
1
10
|
/** Maps unknown/legacy size strings to the current wire format. */
|
|
2
11
|
export function normalizePhotoSizeTier(size) {
|
|
3
12
|
switch (size) {
|
|
@@ -25,7 +34,7 @@ export function photoRequestParamsForNative(params) {
|
|
|
25
34
|
const payload = {
|
|
26
35
|
size: normalizePhotoSizeTier(params.size),
|
|
27
36
|
mode: params.mode ?? "photo",
|
|
28
|
-
transferMethod: params.transferMethod
|
|
37
|
+
transferMethod: photoTransferMethodForNative(params.transferMethod),
|
|
29
38
|
webhookUrl: params.webhookUrl ?? "",
|
|
30
39
|
compress: params.compress,
|
|
31
40
|
sound: params.sound,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"photoRequestPayload.js","sourceRoot":"","sources":["../../src/_private/photoRequestPayload.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,MAAM,UAAU,sBAAsB,CAAC,IAAwB;IAC7D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,KAAK,CAAA;QACd,KAAK,OAAO;YACV,OAAO,MAAM,CAAA;QACf,KAAK,MAAM;YACT,OAAO,KAAK,CAAA;QACd,KAAK,KAAK,CAAC;QACX,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM,CAAC;QACZ,KAAK,KAAK;YACR,OAAO,IAAI,CAAA;QACb;YACE,OAAO,QAAQ,CAAA;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAqB;IAC3C,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;IAC7B,OAAO,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5D,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,2BAA2B,CAAC,MAA0B;IACpE,MAAM,OAAO,GAA8C;QACzD,IAAI,EAAE,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC;QACzC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,OAAO;QAC5B,cAAc,EAAE,MAAM,CAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"photoRequestPayload.js","sourceRoot":"","sources":["../../src/_private/photoRequestPayload.ts"],"names":[],"mappings":"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","sourcesContent":["import type {PhotoRequestParams, PhotoSize, PhotoTransferMethod} from \"../BluetoothSdk.types\"\n\nconst PHOTO_TRANSFER_METHODS = new Set<PhotoTransferMethod>([\"auto\", \"direct\", \"ble\"])\n\nfunction photoTransferMethodForNative(value: unknown): PhotoTransferMethod {\n if (value === undefined) return \"auto\"\n if (typeof value === \"string\" && PHOTO_TRANSFER_METHODS.has(value as PhotoTransferMethod)) {\n return value as PhotoTransferMethod\n }\n throw new TypeError(`Invalid transferMethod ${JSON.stringify(value)}. Expected \"auto\", \"direct\", or \"ble\".`)\n}\n\n/** Maps unknown/legacy size strings to the current wire format. */\nexport function normalizePhotoSizeTier(size: string | undefined): PhotoSize {\n switch (size) {\n case \"small\":\n return \"low\"\n case \"large\":\n return \"high\"\n case \"full\":\n return \"max\"\n case \"low\":\n case \"medium\":\n case \"high\":\n case \"max\":\n return size\n default:\n return \"medium\"\n }\n}\n\nfunction nonBlankString(value?: string | null): string | undefined {\n const trimmed = value?.trim()\n return trimmed && trimmed.length > 0 ? trimmed : undefined\n}\n\n/** Expo Android bridge rejects null values in Map<String, Any> — omit optional nullish fields. */\nexport function photoRequestParamsForNative(params: PhotoRequestParams): Record<string, string | number | boolean> {\n const payload: Record<string, string | number | boolean> = {\n size: normalizePhotoSizeTier(params.size),\n mode: params.mode ?? \"photo\",\n transferMethod: photoTransferMethodForNative(params.transferMethod),\n webhookUrl: params.webhookUrl ?? \"\",\n compress: params.compress,\n sound: params.sound,\n }\n const requestId = nonBlankString(params.requestId)\n if (requestId != null) {\n payload.requestId = requestId\n }\n if (params.save != null) {\n payload.save = params.save\n }\n if (params.authToken != null && params.authToken.length > 0) {\n payload.authToken = params.authToken\n }\n const exposureTimeNs = params.exposureTimeNs\n const hasManualExposure = exposureTimeNs != null && Number.isFinite(exposureTimeNs) && exposureTimeNs > 0\n if (hasManualExposure) {\n payload.exposureTimeNs = exposureTimeNs\n }\n if (hasManualExposure && params.iso != null && Number.isFinite(params.iso) && params.iso > 0) {\n payload.iso = Math.round(params.iso)\n }\n if (params.aeExposureDivisor != null && params.aeExposureDivisor > 1) {\n payload.aeExposureDivisor = Math.round(params.aeExposureDivisor)\n }\n if (params.isoCap != null && params.isoCap > 0) {\n payload.isoCap = Math.round(params.isoCap)\n }\n if (params.noiseReduction != null) {\n payload.noiseReduction = params.noiseReduction\n }\n if (params.edgeEnhancement != null) {\n payload.edgeEnhancement = params.edgeEnhancement\n }\n if (params.mfnr != null) {\n payload.mfnr = params.mfnr\n }\n if (params.zsl != null) {\n payload.zsl = params.zsl\n }\n if (params.ispDigitalGain != null) {\n payload.ispDigitalGain = Math.round(params.ispDigitalGain)\n }\n if (params.ispAnalogGain != null && params.ispAnalogGain.length > 0) {\n payload.ispAnalogGain = params.ispAnalogGain\n }\n return payload\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK-pinned OTA manifest URL derivation.
|
|
3
|
+
*
|
|
4
|
+
* Each Bluetooth SDK release publishes an immutable manifest
|
|
5
|
+
* (`bluetooth-sdk-<version>-version.json`) pinning the exact ASG artifact paired with that SDK
|
|
6
|
+
* version. The URL is derived from this package's own version — the version is frozen into the
|
|
7
|
+
* published artifact, so this is equivalent to baking the URL at release time while keeping the
|
|
8
|
+
* manifest itself replaceable as an operational escape hatch (asset moves, CDN migration).
|
|
9
|
+
*
|
|
10
|
+
* Mirrors the native derivation in `OtaManifestDefaults.defaultOtaVersionUrl()` (Kotlin) /
|
|
11
|
+
* `BluetoothSdkDefaults` (Swift).
|
|
12
|
+
*/
|
|
13
|
+
/** This Bluetooth SDK package's own version, as published. */
|
|
14
|
+
export declare const BLUETOOTH_SDK_VERSION: string;
|
|
15
|
+
/**
|
|
16
|
+
* The immutable manifest URL pinning the ASG artifact paired with this SDK version, or null when
|
|
17
|
+
* the package version is unavailable (malformed workspace state).
|
|
18
|
+
*/
|
|
19
|
+
export declare function sdkPinnedOtaManifestUrl(): string | null;
|
|
20
|
+
//# sourceMappingURL=sdkOtaManifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdkOtaManifest.d.ts","sourceRoot":"","sources":["../../src/_private/sdkOtaManifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,8DAA8D;AAC9D,eAAO,MAAM,qBAAqB,EAAE,MAA2C,CAAA;AAE/E;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAKvD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK-pinned OTA manifest URL derivation.
|
|
3
|
+
*
|
|
4
|
+
* Each Bluetooth SDK release publishes an immutable manifest
|
|
5
|
+
* (`bluetooth-sdk-<version>-version.json`) pinning the exact ASG artifact paired with that SDK
|
|
6
|
+
* version. The URL is derived from this package's own version — the version is frozen into the
|
|
7
|
+
* published artifact, so this is equivalent to baking the URL at release time while keeping the
|
|
8
|
+
* manifest itself replaceable as an operational escape hatch (asset moves, CDN migration).
|
|
9
|
+
*
|
|
10
|
+
* Mirrors the native derivation in `OtaManifestDefaults.defaultOtaVersionUrl()` (Kotlin) /
|
|
11
|
+
* `BluetoothSdkDefaults` (Swift).
|
|
12
|
+
*/
|
|
13
|
+
const SDK_OTA_RELEASE_BASE_URL = "https://github.com/Mentra-Community/MentraOS/releases/download/bluetooth-sdk-ota";
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
15
|
+
const packageJson = require("../../package.json");
|
|
16
|
+
/** This Bluetooth SDK package's own version, as published. */
|
|
17
|
+
export const BLUETOOTH_SDK_VERSION = (packageJson.version ?? "").trim();
|
|
18
|
+
/**
|
|
19
|
+
* The immutable manifest URL pinning the ASG artifact paired with this SDK version, or null when
|
|
20
|
+
* the package version is unavailable (malformed workspace state).
|
|
21
|
+
*/
|
|
22
|
+
export function sdkPinnedOtaManifestUrl() {
|
|
23
|
+
if (!BLUETOOTH_SDK_VERSION) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return `${SDK_OTA_RELEASE_BASE_URL}/bluetooth-sdk-${BLUETOOTH_SDK_VERSION}-version.json`;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=sdkOtaManifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdkOtaManifest.js","sourceRoot":"","sources":["../../src/_private/sdkOtaManifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,wBAAwB,GAAG,kFAAkF,CAAA;AAEnH,8DAA8D;AAC9D,MAAM,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAuB,CAAA;AAEvE,8DAA8D;AAC9D,MAAM,CAAC,MAAM,qBAAqB,GAAW,CAAC,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;AAE/E;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACrC,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,GAAG,wBAAwB,kBAAkB,qBAAqB,eAAe,CAAA;AAC1F,CAAC","sourcesContent":["/**\n * SDK-pinned OTA manifest URL derivation.\n *\n * Each Bluetooth SDK release publishes an immutable manifest\n * (`bluetooth-sdk-<version>-version.json`) pinning the exact ASG artifact paired with that SDK\n * version. The URL is derived from this package's own version — the version is frozen into the\n * published artifact, so this is equivalent to baking the URL at release time while keeping the\n * manifest itself replaceable as an operational escape hatch (asset moves, CDN migration).\n *\n * Mirrors the native derivation in `OtaManifestDefaults.defaultOtaVersionUrl()` (Kotlin) /\n * `BluetoothSdkDefaults` (Swift).\n */\n\nconst SDK_OTA_RELEASE_BASE_URL = \"https://github.com/Mentra-Community/MentraOS/releases/download/bluetooth-sdk-ota\"\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst packageJson = require(\"../../package.json\") as {version?: string}\n\n/** This Bluetooth SDK package's own version, as published. */\nexport const BLUETOOTH_SDK_VERSION: string = (packageJson.version ?? \"\").trim()\n\n/**\n * The immutable manifest URL pinning the ASG artifact paired with this SDK version, or null when\n * the package version is unavailable (malformed workspace state).\n */\nexport function sdkPinnedOtaManifestUrl(): string | null {\n if (!BLUETOOTH_SDK_VERSION) {\n return null\n }\n return `${SDK_OTA_RELEASE_BASE_URL}/bluetooth-sdk-${BLUETOOTH_SDK_VERSION}-version.json`\n}\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ import type { BluetoothSdkPublicModule } from "./BluetoothSdk.types";
|
|
|
2
2
|
export declare const BluetoothSdk: BluetoothSdkPublicModule;
|
|
3
3
|
export default BluetoothSdk;
|
|
4
4
|
export { CAMERA_FOV_DEFAULT, CAMERA_FOV_MAX, CAMERA_FOV_MIN, DeviceModels, isBusyGlassesConnectionStatus, isConnectedGlassesConnectionStatus, isConnectedWifiStatus, isEnabledHotspotStatus, isReadyGlassesConnectionStatus, } from "./BluetoothSdk.types";
|
|
5
|
-
export type { AccelEvent, AudioConnectedEvent, AudioDisconnectedEvent, AudioPairingNeededEvent, BatteryStatusEvent, BluetoothSdkEvent, BluetoothSdkEventListener, BluetoothSdkEventMap, BluetoothSdkEventName, BluetoothSdkPublicModule as BluetoothSdkModule, BluetoothSdkSubscription, ButtonPhotoSize, PhotoCaptureDefaults, ButtonPressEvent, CameraFovPreset, CameraFovRequest, CameraFovResult, CameraRoiPosition, CompatibleGlassesSearchStopEvent, ConnectOptions, ConnectedGlassesConnectionStatus, ConnectedWifiStatus, Device, DeviceModel, EnabledHotspotStatus, GalleryStatusEvent, GlassesConnectionStatus, GlassesMediaVolumeGetResult, GlassesMediaVolumeSetResult, GlassesNotReadyEvent, HeadUpEvent, HotspotErrorEvent, HotspotStatus, HotspotStatusChangeEvent, LocalTranscriptionEvent, LogEvent, MicLc3Event, MicMode, MicPcmEvent, MicPreference, OtaStartAckEvent, OtaStatus, OtaStatusEvent, OtaQueryResult, PairFailureEvent, PhotoCaptureMetadata, PhotoResolvedConfig, PhotoCompression, PhotoFpsRange, PhotoMeteredPreview, PhotoMode, PhotoResponseEvent, PhotoRequestedCaptureConfig, PhotoRequestParams, PhotoSize, PhotoStatusEvent, PhotoStatusState, PhotoSuccessResponseEvent, RgbLedAction, RgbLedColor, RgbLedControlResponseEvent, RgbLedControlSuccessResponseEvent, ScanModelOptions, ScanOptions, ScanResultsCallback, SpeakingStatusEvent, SettingsAckEvent, SettingsAckSetting, SettingsAckSuccessEvent, SettingsAckSuccessStatus, SettingsAckStatus, StreamAudioConfig, StreamResolvedConfig, StreamStartRequest, StreamStatusEvent, StreamStatusLifecycleState, StreamStatusReconnectState, StreamStatusState, StreamVideoConfig, SwipeVolumeStatusEvent, SwitchStatusEvent, TouchEvent, VideoRecordingDefaults, VideoRecordingStartedStatusEvent, VideoRecordingStatusEvent, VideoRecordingStatusState, VideoRecordingStoppedStatusEvent, VideoRecordingSuccessStatusEvent, VersionInfoEvent, VersionInfoResult, WifiScanResultEvent, VoiceActivityDetectionStatusEvent, WifiSearchResult, WifiStatus, WifiStatusChangeEvent, } from "./BluetoothSdk.types";
|
|
5
|
+
export type { AccelEvent, Ar99OtaStatusEvent, AudioConnectedEvent, AudioDisconnectedEvent, AudioPairingNeededEvent, BatteryStatusEvent, BluetoothSdkEvent, BluetoothSdkEventListener, BluetoothSdkEventMap, BluetoothSdkEventName, BluetoothSdkPublicModule as BluetoothSdkModule, BluetoothSdkSubscription, ButtonPhotoSize, PhotoCaptureDefaults, ButtonPressEvent, CameraFovPreset, CameraFovRequest, CameraFovResult, CameraRoiPosition, CompatibleGlassesSearchStopEvent, ConnectOptions, ConnectedGlassesConnectionStatus, ConnectedWifiStatus, Device, DeviceModel, EnabledHotspotStatus, GalleryStatusEvent, GlassesConnectionStatus, GlassesMediaVolumeGetResult, GlassesMediaVolumeSetResult, GlassesNotReadyEvent, HeadUpEvent, HotspotErrorEvent, HotspotStatus, HotspotStatusChangeEvent, LocalTranscriptionEvent, LogEvent, MicLc3Event, MicMode, MicPcmEvent, MicPreference, OtaStartAckEvent, OtaStatus, OtaStatusEvent, OtaQueryResult, PairFailureEvent, PhotoCaptureMetadata, PhotoResolvedConfig, PhotoCompression, PhotoFpsRange, PhotoMeteredPreview, PhotoMode, PhotoTransferMethod, PhotoResponseEvent, PhotoRequestedCaptureConfig, PhotoRequestParams, PhotoSize, PhotoStatusEvent, PhotoStatusState, PhotoSuccessResponseEvent, RgbLedAction, RgbLedColor, RgbLedControlResponseEvent, RgbLedControlSuccessResponseEvent, ScanModelOptions, ScanOptions, ScanResultsCallback, SpeakingStatusEvent, SettingsAckEvent, SettingsAckSetting, SettingsAckSuccessEvent, SettingsAckSuccessStatus, SettingsAckStatus, StreamAudioConfig, StreamResolvedConfig, StreamStartRequest, StreamStatusEvent, StreamStatusLifecycleState, StreamStatusReconnectState, StreamStatusState, StreamVideoConfig, SwipeVolumeStatusEvent, SwitchStatusEvent, TouchEvent, VideoRecordingDefaults, VideoRecordingStartedStatusEvent, VideoRecordingStatusEvent, VideoRecordingStatusState, VideoRecordingStoppedStatusEvent, VideoRecordingSuccessStatusEvent, VersionInfoEvent, VersionInfoResult, WifiScanResultEvent, VoiceActivityDetectionStatusEvent, WifiSearchResult, WifiStatus, WifiStatusChangeEvent, } from "./BluetoothSdk.types";
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,wBAAwB,EAEzB,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,wBAAwB,EAEzB,MAAM,sBAAsB,CAAA;AAmE7B,eAAO,MAAM,YAAY,EAAE,wBAiFzB,CAAA;AAEF,eAAe,YAAY,CAAA;AAE3B,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,6BAA6B,EAC7B,kCAAkC,EAClC,qBAAqB,EACrB,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,sBAAsB,CAAA;AAE7B,YAAY,EACV,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,IAAI,kBAAkB,EAC9C,wBAAwB,EACxB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,gCAAgC,EAChC,cAAc,EACd,gCAAgC,EAChC,mBAAmB,EACnB,MAAM,EACN,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,EACvB,2BAA2B,EAC3B,2BAA2B,EAC3B,oBAAoB,EACpB,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,wBAAwB,EACxB,uBAAuB,EACvB,QAAQ,EACR,WAAW,EACX,OAAO,EACP,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,kBAAkB,EAClB,2BAA2B,EAC3B,kBAAkB,EAClB,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,YAAY,EACZ,WAAW,EACX,0BAA0B,EAC1B,iCAAiC,EACjC,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,sBAAsB,EACtB,gCAAgC,EAChC,yBAAyB,EACzB,yBAAyB,EACzB,gCAAgC,EAChC,gCAAgC,EAChC,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,iCAAiC,EACjC,gBAAgB,EAChB,UAAU,EACV,qBAAqB,GACtB,MAAM,sBAAsB,CAAA"}
|
package/build/index.js
CHANGED
|
@@ -37,6 +37,7 @@ const PUBLIC_EVENT_NAMES = new Set([
|
|
|
37
37
|
"stream_status",
|
|
38
38
|
"ota_start_ack",
|
|
39
39
|
"ota_status",
|
|
40
|
+
"ar99_ota_status",
|
|
40
41
|
"version_info",
|
|
41
42
|
"extraction_progress",
|
|
42
43
|
]);
|
|
@@ -84,9 +85,10 @@ export const BluetoothSdk = Object.freeze({
|
|
|
84
85
|
setHotspotState: bindPublicMethod("setHotspotState"),
|
|
85
86
|
setGalleryModeEnabled: bindPublicMethod("setGalleryModeEnabled"),
|
|
86
87
|
setVoiceActivityDetectionEnabled: bindPublicMethod("setVoiceActivityDetectionEnabled"),
|
|
88
|
+
setLoudnessGateEnabled: bindPublicMethod("setLoudnessGateEnabled"),
|
|
87
89
|
/**
|
|
88
90
|
* @deprecated Sticky action-button photo presets are deprecated. Prefer per-request
|
|
89
|
-
* `requestPhoto(...)` options (e.g. `mode: "text"` for
|
|
91
|
+
* `requestPhoto(...)` options (e.g. `mode: "text"` for text sensor size/crop, or explicit per-shot
|
|
90
92
|
* fields). Still functional until removed in a future release.
|
|
91
93
|
*/
|
|
92
94
|
setPhotoCaptureDefaults: bindPublicMethod("setPhotoCaptureDefaults"),
|
|
@@ -120,6 +122,10 @@ export const BluetoothSdk = Object.freeze({
|
|
|
120
122
|
requestVersionInfo: bindPublicMethod("requestVersionInfo"),
|
|
121
123
|
checkForOtaUpdate: bindPublicMethod("checkForOtaUpdate"),
|
|
122
124
|
startOtaUpdate,
|
|
125
|
+
startAr99OtaFromFile: bindPublicMethod("startAr99OtaFromFile"),
|
|
126
|
+
cancelAr99Ota: bindPublicMethod("cancelAr99Ota"),
|
|
127
|
+
sendAr99FactoryReset: bindPublicMethod("sendAr99FactoryReset"),
|
|
128
|
+
buildAr99OtaSignature: bindPublicMethod("buildAr99OtaSignature"),
|
|
123
129
|
setSttModelDetails: bindPublicMethod("setSttModelDetails"),
|
|
124
130
|
getSttModelPath: bindPublicMethod("getSttModelPath"),
|
|
125
131
|
checkSttModelAvailable: bindPublicMethod("checkSttModelAvailable"),
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import PrivateBluetoothSdkModule from \"./_private/BluetoothSdkModule\"\nimport type {\n BluetoothSdkEventListener,\n BluetoothSdkEventName,\n BluetoothSdkPublicModule,\n VideoRecordingDefaults,\n} from \"./BluetoothSdk.types\"\n\nconst PUBLIC_EVENT_NAMES = new Set<BluetoothSdkEventName>([\n \"log\",\n \"device_discovered\",\n \"default_device_changed\",\n \"glasses_not_ready\",\n \"button_press\",\n \"touch_event\",\n \"accel_event\",\n \"head_up\",\n \"voice_activity_detection_status\",\n \"speaking_status\",\n \"battery_status\",\n \"local_transcription\",\n \"wifi_status_change\",\n \"wifi_scan_result\",\n \"hotspot_status_change\",\n \"hotspot_error\",\n \"photo_response\",\n \"photo_status\",\n \"camera_status\",\n \"video_recording_status\",\n \"media_success\",\n \"media_error\",\n \"gallery_status\",\n \"compatible_glasses_search_stop\",\n \"swipe_volume_status\",\n \"switch_status\",\n \"rgb_led_control_response\",\n \"settings_ack\",\n \"pair_failure\",\n \"audio_pairing_needed\",\n \"audio_connected\",\n \"audio_disconnected\",\n \"mic_pcm\",\n \"mic_lc3\",\n \"stream_status\",\n \"ota_start_ack\",\n \"ota_status\",\n \"version_info\",\n \"extraction_progress\",\n])\n\nconst addListener: BluetoothSdkPublicModule[\"addListener\"] = (eventName, listener) => {\n if (!PUBLIC_EVENT_NAMES.has(eventName)) {\n throw new Error(`Unsupported BluetoothSdk event \"${eventName}\". Use @mentra/bluetooth-sdk/react for status state.`)\n }\n return PrivateBluetoothSdkModule.addListener(eventName, listener as BluetoothSdkEventListener<BluetoothSdkEventName>)\n}\n\nconst startOtaUpdate: BluetoothSdkPublicModule[\"startOtaUpdate\"] = () => {\n return PrivateBluetoothSdkModule.startOtaUpdate()\n}\n\nconst bindPublicMethod = <K extends keyof BluetoothSdkPublicModule>(name: K): BluetoothSdkPublicModule[K] => {\n const method = (PrivateBluetoothSdkModule as unknown as Record<string, unknown>)[name]\n if (typeof method === \"function\") {\n return method.bind(PrivateBluetoothSdkModule) as BluetoothSdkPublicModule[K]\n }\n\n return (async () => {\n throw new Error(`BluetoothSdk.${String(name)} is not available in this native build. Rebuild the app.`)\n }) as unknown as BluetoothSdkPublicModule[K]\n}\n\nexport const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({\n addListener,\n getDefaultDevice: bindPublicMethod(\"getDefaultDevice\"),\n setDefaultDevice: bindPublicMethod(\"setDefaultDevice\"),\n clearDefaultDevice: bindPublicMethod(\"clearDefaultDevice\"),\n startScan: bindPublicMethod(\"startScan\"),\n stopScan: bindPublicMethod(\"stopScan\"),\n scan: bindPublicMethod(\"scan\") as BluetoothSdkPublicModule[\"scan\"],\n connect: bindPublicMethod(\"connect\"),\n connectDefault: bindPublicMethod(\"connectDefault\"),\n cancelConnectionAttempt: bindPublicMethod(\"cancelConnectionAttempt\"),\n disconnect: bindPublicMethod(\"disconnect\"),\n forget: bindPublicMethod(\"forget\"),\n displayText: bindPublicMethod(\"displayText\"),\n clearDisplay: bindPublicMethod(\"clearDisplay\"),\n showDashboard: bindPublicMethod(\"showDashboard\"),\n setDashboardPosition: bindPublicMethod(\"setDashboardPosition\"),\n setHeadUpAngle: bindPublicMethod(\"setHeadUpAngle\"),\n setImuEnabled: bindPublicMethod(\"setImuEnabled\"),\n setScreenDisabled: bindPublicMethod(\"setScreenDisabled\"),\n requestWifiScan: bindPublicMethod(\"requestWifiScan\"),\n sendWifiCredentials: bindPublicMethod(\"sendWifiCredentials\"),\n forgetWifiNetwork: bindPublicMethod(\"forgetWifiNetwork\"),\n setHotspotState: bindPublicMethod(\"setHotspotState\"),\n setGalleryModeEnabled: bindPublicMethod(\"setGalleryModeEnabled\"),\n setVoiceActivityDetectionEnabled: bindPublicMethod(\"setVoiceActivityDetectionEnabled\"),\n /**\n * @deprecated Sticky action-button photo presets are deprecated. Prefer per-request\n * `requestPhoto(...)` options (e.g. `mode: \"text\"` for AE ÷3, or explicit per-shot\n * fields). Still functional until removed in a future release.\n */\n setPhotoCaptureDefaults: bindPublicMethod(\"setPhotoCaptureDefaults\"),\n setVideoRecordingDefaults: ({width, height, fps}: VideoRecordingDefaults) => {\n const method = (PrivateBluetoothSdkModule as unknown as Record<string, unknown>).setVideoRecordingDefaults\n if (typeof method !== \"function\") {\n return Promise.reject(\n new Error(\"BluetoothSdk.setVideoRecordingDefaults is not available in this native build. Rebuild the app.\"),\n )\n }\n return PrivateBluetoothSdkModule.setVideoRecordingDefaults(width, height, fps)\n },\n setMaxVideoRecordingDuration: bindPublicMethod(\"setMaxVideoRecordingDuration\"),\n setCameraFov: bindPublicMethod(\"setCameraFov\"),\n setLegacyCameraFov: bindPublicMethod(\"setLegacyCameraFov\"),\n setCameraFovOverride: bindPublicMethod(\"setCameraFovOverride\"),\n releaseCameraFovOverride: bindPublicMethod(\"releaseCameraFovOverride\"),\n setCameraTuningConfig: bindPublicMethod(\"setCameraTuningConfig\"),\n queryGalleryStatus: bindPublicMethod(\"queryGalleryStatus\"),\n requestPhoto: bindPublicMethod(\"requestPhoto\"),\n warmUpCamera: bindPublicMethod(\"warmUpCamera\"),\n stopCameraWarmUp: bindPublicMethod(\"stopCameraWarmUp\"),\n startVideoRecording: bindPublicMethod(\"startVideoRecording\"),\n stopVideoRecording: bindPublicMethod(\"stopVideoRecording\"),\n startStream: bindPublicMethod(\"startStream\"),\n stopStream: bindPublicMethod(\"stopStream\"),\n setMicState: bindPublicMethod(\"setMicState\"),\n setPreferredMic: bindPublicMethod(\"setPreferredMic\"),\n setOwnAppAudioPlaying: bindPublicMethod(\"setOwnAppAudioPlaying\"),\n getGlassesMediaVolume: bindPublicMethod(\"getGlassesMediaVolume\"),\n setGlassesMediaVolume: bindPublicMethod(\"setGlassesMediaVolume\"),\n rgbLedControl: bindPublicMethod(\"rgbLedControl\"),\n requestVersionInfo: bindPublicMethod(\"requestVersionInfo\"),\n checkForOtaUpdate: bindPublicMethod(\"checkForOtaUpdate\"),\n startOtaUpdate,\n setSttModelDetails: bindPublicMethod(\"setSttModelDetails\"),\n getSttModelPath: bindPublicMethod(\"getSttModelPath\"),\n checkSttModelAvailable: bindPublicMethod(\"checkSttModelAvailable\"),\n validateSttModel: bindPublicMethod(\"validateSttModel\"),\n extractTarBz2: bindPublicMethod(\"extractTarBz2\"),\n restartTranscriber: bindPublicMethod(\"restartTranscriber\"),\n setTtsModelDetails: bindPublicMethod(\"setTtsModelDetails\"),\n getTtsModelPath: bindPublicMethod(\"getTtsModelPath\"),\n getTtsModelLanguage: bindPublicMethod(\"getTtsModelLanguage\"),\n checkTtsModelAvailable: bindPublicMethod(\"checkTtsModelAvailable\"),\n validateTtsModel: bindPublicMethod(\"validateTtsModel\"),\n generateTtsAudio: bindPublicMethod(\"generateTtsAudio\"),\n})\n\nexport default BluetoothSdk\n\nexport {\n CAMERA_FOV_DEFAULT,\n CAMERA_FOV_MAX,\n CAMERA_FOV_MIN,\n DeviceModels,\n isBusyGlassesConnectionStatus,\n isConnectedGlassesConnectionStatus,\n isConnectedWifiStatus,\n isEnabledHotspotStatus,\n isReadyGlassesConnectionStatus,\n} from \"./BluetoothSdk.types\"\n\nexport type {\n AccelEvent,\n AudioConnectedEvent,\n AudioDisconnectedEvent,\n AudioPairingNeededEvent,\n BatteryStatusEvent,\n BluetoothSdkEvent,\n BluetoothSdkEventListener,\n BluetoothSdkEventMap,\n BluetoothSdkEventName,\n BluetoothSdkPublicModule as BluetoothSdkModule,\n BluetoothSdkSubscription,\n ButtonPhotoSize,\n PhotoCaptureDefaults,\n ButtonPressEvent,\n CameraFovPreset,\n CameraFovRequest,\n CameraFovResult,\n CameraRoiPosition,\n CompatibleGlassesSearchStopEvent,\n ConnectOptions,\n ConnectedGlassesConnectionStatus,\n ConnectedWifiStatus,\n Device,\n DeviceModel,\n EnabledHotspotStatus,\n GalleryStatusEvent,\n GlassesConnectionStatus,\n GlassesMediaVolumeGetResult,\n GlassesMediaVolumeSetResult,\n GlassesNotReadyEvent,\n HeadUpEvent,\n HotspotErrorEvent,\n HotspotStatus,\n HotspotStatusChangeEvent,\n LocalTranscriptionEvent,\n LogEvent,\n MicLc3Event,\n MicMode,\n MicPcmEvent,\n MicPreference,\n OtaStartAckEvent,\n OtaStatus,\n OtaStatusEvent,\n OtaQueryResult,\n PairFailureEvent,\n PhotoCaptureMetadata,\n PhotoResolvedConfig,\n PhotoCompression,\n PhotoFpsRange,\n PhotoMeteredPreview,\n PhotoMode,\n PhotoResponseEvent,\n PhotoRequestedCaptureConfig,\n PhotoRequestParams,\n PhotoSize,\n PhotoStatusEvent,\n PhotoStatusState,\n PhotoSuccessResponseEvent,\n RgbLedAction,\n RgbLedColor,\n RgbLedControlResponseEvent,\n RgbLedControlSuccessResponseEvent,\n ScanModelOptions,\n ScanOptions,\n ScanResultsCallback,\n SpeakingStatusEvent,\n SettingsAckEvent,\n SettingsAckSetting,\n SettingsAckSuccessEvent,\n SettingsAckSuccessStatus,\n SettingsAckStatus,\n StreamAudioConfig,\n StreamResolvedConfig,\n StreamStartRequest,\n StreamStatusEvent,\n StreamStatusLifecycleState,\n StreamStatusReconnectState,\n StreamStatusState,\n StreamVideoConfig,\n SwipeVolumeStatusEvent,\n SwitchStatusEvent,\n TouchEvent,\n VideoRecordingDefaults,\n VideoRecordingStartedStatusEvent,\n VideoRecordingStatusEvent,\n VideoRecordingStatusState,\n VideoRecordingStoppedStatusEvent,\n VideoRecordingSuccessStatusEvent,\n VersionInfoEvent,\n VersionInfoResult,\n WifiScanResultEvent,\n VoiceActivityDetectionStatusEvent,\n WifiSearchResult,\n WifiStatus,\n WifiStatusChangeEvent,\n} from \"./BluetoothSdk.types\"\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import PrivateBluetoothSdkModule from \"./_private/BluetoothSdkModule\"\nimport type {\n BluetoothSdkEventListener,\n BluetoothSdkEventName,\n BluetoothSdkPublicModule,\n VideoRecordingDefaults,\n} from \"./BluetoothSdk.types\"\n\nconst PUBLIC_EVENT_NAMES = new Set<BluetoothSdkEventName>([\n \"log\",\n \"device_discovered\",\n \"default_device_changed\",\n \"glasses_not_ready\",\n \"button_press\",\n \"touch_event\",\n \"accel_event\",\n \"head_up\",\n \"voice_activity_detection_status\",\n \"speaking_status\",\n \"battery_status\",\n \"local_transcription\",\n \"wifi_status_change\",\n \"wifi_scan_result\",\n \"hotspot_status_change\",\n \"hotspot_error\",\n \"photo_response\",\n \"photo_status\",\n \"camera_status\",\n \"video_recording_status\",\n \"media_success\",\n \"media_error\",\n \"gallery_status\",\n \"compatible_glasses_search_stop\",\n \"swipe_volume_status\",\n \"switch_status\",\n \"rgb_led_control_response\",\n \"settings_ack\",\n \"pair_failure\",\n \"audio_pairing_needed\",\n \"audio_connected\",\n \"audio_disconnected\",\n \"mic_pcm\",\n \"mic_lc3\",\n \"stream_status\",\n \"ota_start_ack\",\n \"ota_status\",\n \"ar99_ota_status\",\n \"version_info\",\n \"extraction_progress\",\n])\n\nconst addListener: BluetoothSdkPublicModule[\"addListener\"] = (eventName, listener) => {\n if (!PUBLIC_EVENT_NAMES.has(eventName)) {\n throw new Error(`Unsupported BluetoothSdk event \"${eventName}\". Use @mentra/bluetooth-sdk/react for status state.`)\n }\n return PrivateBluetoothSdkModule.addListener(eventName, listener as BluetoothSdkEventListener<BluetoothSdkEventName>)\n}\n\nconst startOtaUpdate: BluetoothSdkPublicModule[\"startOtaUpdate\"] = () => {\n return PrivateBluetoothSdkModule.startOtaUpdate()\n}\n\nconst bindPublicMethod = <K extends keyof BluetoothSdkPublicModule>(name: K): BluetoothSdkPublicModule[K] => {\n const method = (PrivateBluetoothSdkModule as unknown as Record<string, unknown>)[name]\n if (typeof method === \"function\") {\n return method.bind(PrivateBluetoothSdkModule) as BluetoothSdkPublicModule[K]\n }\n\n return (async () => {\n throw new Error(`BluetoothSdk.${String(name)} is not available in this native build. Rebuild the app.`)\n }) as unknown as BluetoothSdkPublicModule[K]\n}\n\nexport const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({\n addListener,\n getDefaultDevice: bindPublicMethod(\"getDefaultDevice\"),\n setDefaultDevice: bindPublicMethod(\"setDefaultDevice\"),\n clearDefaultDevice: bindPublicMethod(\"clearDefaultDevice\"),\n startScan: bindPublicMethod(\"startScan\"),\n stopScan: bindPublicMethod(\"stopScan\"),\n scan: bindPublicMethod(\"scan\") as BluetoothSdkPublicModule[\"scan\"],\n connect: bindPublicMethod(\"connect\"),\n connectDefault: bindPublicMethod(\"connectDefault\"),\n cancelConnectionAttempt: bindPublicMethod(\"cancelConnectionAttempt\"),\n disconnect: bindPublicMethod(\"disconnect\"),\n forget: bindPublicMethod(\"forget\"),\n displayText: bindPublicMethod(\"displayText\"),\n clearDisplay: bindPublicMethod(\"clearDisplay\"),\n showDashboard: bindPublicMethod(\"showDashboard\"),\n setDashboardPosition: bindPublicMethod(\"setDashboardPosition\"),\n setHeadUpAngle: bindPublicMethod(\"setHeadUpAngle\"),\n setImuEnabled: bindPublicMethod(\"setImuEnabled\"),\n setScreenDisabled: bindPublicMethod(\"setScreenDisabled\"),\n requestWifiScan: bindPublicMethod(\"requestWifiScan\"),\n sendWifiCredentials: bindPublicMethod(\"sendWifiCredentials\"),\n forgetWifiNetwork: bindPublicMethod(\"forgetWifiNetwork\"),\n setHotspotState: bindPublicMethod(\"setHotspotState\"),\n setGalleryModeEnabled: bindPublicMethod(\"setGalleryModeEnabled\"),\n setVoiceActivityDetectionEnabled: bindPublicMethod(\"setVoiceActivityDetectionEnabled\"),\n setLoudnessGateEnabled: bindPublicMethod(\"setLoudnessGateEnabled\"),\n /**\n * @deprecated Sticky action-button photo presets are deprecated. Prefer per-request\n * `requestPhoto(...)` options (e.g. `mode: \"text\"` for text sensor size/crop, or explicit per-shot\n * fields). Still functional until removed in a future release.\n */\n setPhotoCaptureDefaults: bindPublicMethod(\"setPhotoCaptureDefaults\"),\n setVideoRecordingDefaults: ({width, height, fps}: VideoRecordingDefaults) => {\n const method = (PrivateBluetoothSdkModule as unknown as Record<string, unknown>).setVideoRecordingDefaults\n if (typeof method !== \"function\") {\n return Promise.reject(\n new Error(\"BluetoothSdk.setVideoRecordingDefaults is not available in this native build. Rebuild the app.\"),\n )\n }\n return PrivateBluetoothSdkModule.setVideoRecordingDefaults(width, height, fps)\n },\n setMaxVideoRecordingDuration: bindPublicMethod(\"setMaxVideoRecordingDuration\"),\n setCameraFov: bindPublicMethod(\"setCameraFov\"),\n setLegacyCameraFov: bindPublicMethod(\"setLegacyCameraFov\"),\n setCameraFovOverride: bindPublicMethod(\"setCameraFovOverride\"),\n releaseCameraFovOverride: bindPublicMethod(\"releaseCameraFovOverride\"),\n setCameraTuningConfig: bindPublicMethod(\"setCameraTuningConfig\"),\n queryGalleryStatus: bindPublicMethod(\"queryGalleryStatus\"),\n requestPhoto: bindPublicMethod(\"requestPhoto\"),\n warmUpCamera: bindPublicMethod(\"warmUpCamera\"),\n stopCameraWarmUp: bindPublicMethod(\"stopCameraWarmUp\"),\n startVideoRecording: bindPublicMethod(\"startVideoRecording\"),\n stopVideoRecording: bindPublicMethod(\"stopVideoRecording\"),\n startStream: bindPublicMethod(\"startStream\"),\n stopStream: bindPublicMethod(\"stopStream\"),\n setMicState: bindPublicMethod(\"setMicState\"),\n setPreferredMic: bindPublicMethod(\"setPreferredMic\"),\n setOwnAppAudioPlaying: bindPublicMethod(\"setOwnAppAudioPlaying\"),\n getGlassesMediaVolume: bindPublicMethod(\"getGlassesMediaVolume\"),\n setGlassesMediaVolume: bindPublicMethod(\"setGlassesMediaVolume\"),\n rgbLedControl: bindPublicMethod(\"rgbLedControl\"),\n requestVersionInfo: bindPublicMethod(\"requestVersionInfo\"),\n checkForOtaUpdate: bindPublicMethod(\"checkForOtaUpdate\"),\n startOtaUpdate,\n startAr99OtaFromFile: bindPublicMethod(\"startAr99OtaFromFile\"),\n cancelAr99Ota: bindPublicMethod(\"cancelAr99Ota\"),\n sendAr99FactoryReset: bindPublicMethod(\"sendAr99FactoryReset\"),\n buildAr99OtaSignature: bindPublicMethod(\"buildAr99OtaSignature\"),\n setSttModelDetails: bindPublicMethod(\"setSttModelDetails\"),\n getSttModelPath: bindPublicMethod(\"getSttModelPath\"),\n checkSttModelAvailable: bindPublicMethod(\"checkSttModelAvailable\"),\n validateSttModel: bindPublicMethod(\"validateSttModel\"),\n extractTarBz2: bindPublicMethod(\"extractTarBz2\"),\n restartTranscriber: bindPublicMethod(\"restartTranscriber\"),\n setTtsModelDetails: bindPublicMethod(\"setTtsModelDetails\"),\n getTtsModelPath: bindPublicMethod(\"getTtsModelPath\"),\n getTtsModelLanguage: bindPublicMethod(\"getTtsModelLanguage\"),\n checkTtsModelAvailable: bindPublicMethod(\"checkTtsModelAvailable\"),\n validateTtsModel: bindPublicMethod(\"validateTtsModel\"),\n generateTtsAudio: bindPublicMethod(\"generateTtsAudio\"),\n})\n\nexport default BluetoothSdk\n\nexport {\n CAMERA_FOV_DEFAULT,\n CAMERA_FOV_MAX,\n CAMERA_FOV_MIN,\n DeviceModels,\n isBusyGlassesConnectionStatus,\n isConnectedGlassesConnectionStatus,\n isConnectedWifiStatus,\n isEnabledHotspotStatus,\n isReadyGlassesConnectionStatus,\n} from \"./BluetoothSdk.types\"\n\nexport type {\n AccelEvent,\n Ar99OtaStatusEvent,\n AudioConnectedEvent,\n AudioDisconnectedEvent,\n AudioPairingNeededEvent,\n BatteryStatusEvent,\n BluetoothSdkEvent,\n BluetoothSdkEventListener,\n BluetoothSdkEventMap,\n BluetoothSdkEventName,\n BluetoothSdkPublicModule as BluetoothSdkModule,\n BluetoothSdkSubscription,\n ButtonPhotoSize,\n PhotoCaptureDefaults,\n ButtonPressEvent,\n CameraFovPreset,\n CameraFovRequest,\n CameraFovResult,\n CameraRoiPosition,\n CompatibleGlassesSearchStopEvent,\n ConnectOptions,\n ConnectedGlassesConnectionStatus,\n ConnectedWifiStatus,\n Device,\n DeviceModel,\n EnabledHotspotStatus,\n GalleryStatusEvent,\n GlassesConnectionStatus,\n GlassesMediaVolumeGetResult,\n GlassesMediaVolumeSetResult,\n GlassesNotReadyEvent,\n HeadUpEvent,\n HotspotErrorEvent,\n HotspotStatus,\n HotspotStatusChangeEvent,\n LocalTranscriptionEvent,\n LogEvent,\n MicLc3Event,\n MicMode,\n MicPcmEvent,\n MicPreference,\n OtaStartAckEvent,\n OtaStatus,\n OtaStatusEvent,\n OtaQueryResult,\n PairFailureEvent,\n PhotoCaptureMetadata,\n PhotoResolvedConfig,\n PhotoCompression,\n PhotoFpsRange,\n PhotoMeteredPreview,\n PhotoMode,\n PhotoTransferMethod,\n PhotoResponseEvent,\n PhotoRequestedCaptureConfig,\n PhotoRequestParams,\n PhotoSize,\n PhotoStatusEvent,\n PhotoStatusState,\n PhotoSuccessResponseEvent,\n RgbLedAction,\n RgbLedColor,\n RgbLedControlResponseEvent,\n RgbLedControlSuccessResponseEvent,\n ScanModelOptions,\n ScanOptions,\n ScanResultsCallback,\n SpeakingStatusEvent,\n SettingsAckEvent,\n SettingsAckSetting,\n SettingsAckSuccessEvent,\n SettingsAckSuccessStatus,\n SettingsAckStatus,\n StreamAudioConfig,\n StreamResolvedConfig,\n StreamStartRequest,\n StreamStatusEvent,\n StreamStatusLifecycleState,\n StreamStatusReconnectState,\n StreamStatusState,\n StreamVideoConfig,\n SwipeVolumeStatusEvent,\n SwitchStatusEvent,\n TouchEvent,\n VideoRecordingDefaults,\n VideoRecordingStartedStatusEvent,\n VideoRecordingStatusEvent,\n VideoRecordingStatusState,\n VideoRecordingStoppedStatusEvent,\n VideoRecordingSuccessStatusEvent,\n VersionInfoEvent,\n VersionInfoResult,\n WifiScanResultEvent,\n VoiceActivityDetectionStatusEvent,\n WifiSearchResult,\n WifiStatus,\n WifiStatusChangeEvent,\n} from \"./BluetoothSdk.types\"\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import CryptoKit
|
|
1
2
|
import ExpoModulesCore
|
|
2
3
|
import Foundation
|
|
3
4
|
|
|
@@ -59,9 +60,11 @@ public class BluetoothSdkModule: Module, MentraBluetoothSDKDelegate {
|
|
|
59
60
|
"stream_status",
|
|
60
61
|
"keep_alive_ack",
|
|
61
62
|
"mtk_update_complete",
|
|
63
|
+
"glasses_session_changed",
|
|
62
64
|
"ota_progress",
|
|
63
65
|
"ota_start_ack",
|
|
64
66
|
"ota_status",
|
|
67
|
+
"ar99_ota_status",
|
|
65
68
|
"send_command_to_ble",
|
|
66
69
|
"receive_command_from_ble",
|
|
67
70
|
"miniapp_selected",
|
|
@@ -329,6 +332,11 @@ public class BluetoothSdkModule: Module, MentraBluetoothSDKDelegate {
|
|
|
329
332
|
try await sdk.setVoiceActivityDetectionEnabled(enabled)
|
|
330
333
|
}
|
|
331
334
|
|
|
335
|
+
AsyncFunction("setLoudnessGateEnabled") { (enabled: Bool) in
|
|
336
|
+
let sdk = await MainActor.run { self.bluetoothSdk() }
|
|
337
|
+
try await sdk.setLoudnessGateEnabled(enabled)
|
|
338
|
+
}
|
|
339
|
+
|
|
332
340
|
AsyncFunction("setPhotoCaptureDefaults") { (params: [String: Any]) in
|
|
333
341
|
let sdk = await MainActor.run { self.bluetoothSdk() }
|
|
334
342
|
return try await sdk.setPhotoCaptureDefaults(PhotoCaptureDefaults.from(params: params)).values
|
|
@@ -400,7 +408,7 @@ public class BluetoothSdkModule: Module, MentraBluetoothSDKDelegate {
|
|
|
400
408
|
}
|
|
401
409
|
|
|
402
410
|
AsyncFunction("requestPhoto") { (params: [String: Any]) in
|
|
403
|
-
let req = PhotoRequest.from(params: params)
|
|
411
|
+
let req = try PhotoRequest.from(params: params)
|
|
404
412
|
Bridge.log(
|
|
405
413
|
"NATIVE: PHOTO PIPELINE [3/6] BluetoothSdk.requestPhoto requestId=\(req.requestId) size=\(req.size.rawValue) compress=\(req.compress?.rawValue ?? "none") aeDivisor=\(req.aeExposureDivisor.map { String($0) } ?? "nil")"
|
|
406
414
|
)
|
|
@@ -428,6 +436,8 @@ public class BluetoothSdkModule: Module, MentraBluetoothSDKDelegate {
|
|
|
428
436
|
}
|
|
429
437
|
let durationRaw = intValue(params["durationMs"]) ?? 0
|
|
430
438
|
let durationMs = durationRaw > 0 ? durationRaw : 15000
|
|
439
|
+
let zsl = params["zsl"] as? Bool
|
|
440
|
+
let mfnr = params["mfnr"] as? Bool
|
|
431
441
|
|
|
432
442
|
let sdk = await MainActor.run { self.bluetoothSdk() }
|
|
433
443
|
return try await sdk.warmUpCamera(
|
|
@@ -435,7 +445,9 @@ public class BluetoothSdkModule: Module, MentraBluetoothSDKDelegate {
|
|
|
435
445
|
size: size,
|
|
436
446
|
mode: mode,
|
|
437
447
|
exposureTimeNs: exposureTimeNs,
|
|
438
|
-
durationMs: durationMs
|
|
448
|
+
durationMs: durationMs,
|
|
449
|
+
zsl: zsl,
|
|
450
|
+
mfnr: mfnr
|
|
439
451
|
).values
|
|
440
452
|
}
|
|
441
453
|
|
|
@@ -478,6 +490,27 @@ public class BluetoothSdkModule: Module, MentraBluetoothSDKDelegate {
|
|
|
478
490
|
return try await sdk.sendOtaQueryStatus().values
|
|
479
491
|
}
|
|
480
492
|
|
|
493
|
+
AsyncFunction("startAr99OtaFromFile") { (path: String) in
|
|
494
|
+
let sdk = await MainActor.run { self.bluetoothSdk() }
|
|
495
|
+
return try await MainActor.run { try sdk.startAr99OtaFromFile(path) }
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
AsyncFunction("cancelAr99Ota") {
|
|
499
|
+
let sdk = await MainActor.run { self.bluetoothSdk() }
|
|
500
|
+
await MainActor.run { sdk.cancelAr99Ota() }
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
AsyncFunction("sendAr99FactoryReset") {
|
|
504
|
+
let sdk = await MainActor.run { self.bluetoothSdk() }
|
|
505
|
+
try await MainActor.run { try sdk.sendAr99FactoryReset() }
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
Function("buildAr99OtaSignature") { (secret: String, appName: String, currentVersion: String, serialNumber: String, nonce: String) in
|
|
510
|
+
let raw = secret + appName + "juxinOTA" + currentVersion + serialNumber.trimmingCharacters(in: .whitespacesAndNewlines) + nonce
|
|
511
|
+
let digest = Insecure.MD5.hash(data: Data(raw.utf8))
|
|
512
|
+
return digest.map { String(format: "%02x", $0) }.joined()
|
|
513
|
+
}
|
|
481
514
|
// MARK: - Version Info Commands
|
|
482
515
|
|
|
483
516
|
AsyncFunction("requestVersionInfo") {
|
|
@@ -884,3 +917,9 @@ private extension ConnectOptions {
|
|
|
884
917
|
)
|
|
885
918
|
}
|
|
886
919
|
}
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
@@ -7,7 +7,8 @@ enum BluetoothSdkDefaults {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
static let voiceActivityDetectionEnabled = false
|
|
10
|
-
|
|
10
|
+
static let loudnessGateEnabled = true
|
|
11
|
+
private static let swiftPackageSdkVersion = "0.1.21-beta.2"
|
|
11
12
|
private static let swiftPackageSdkVersionPlaceholder = "__MENTRA" + "_BLUETOOTH_SDK_VERSION__"
|
|
12
13
|
|
|
13
14
|
private static func normalizedSdkVersion(_ value: String?) -> String? {
|
package/ios/Source/Bridge.swift
CHANGED
|
@@ -177,12 +177,15 @@ class Bridge {
|
|
|
177
177
|
_ deviceModel: String,
|
|
178
178
|
_ deviceName: String,
|
|
179
179
|
deviceAddress: String = "",
|
|
180
|
-
rssi: Int? = nil
|
|
180
|
+
rssi: Int? = nil,
|
|
181
|
+
projectName: String? = nil
|
|
181
182
|
) {
|
|
182
183
|
Task {
|
|
183
184
|
await MainActor.run {
|
|
184
185
|
let searchResults = DeviceStore.shared.get("bluetooth", "searchResults") as? [[String: Any]] ?? []
|
|
185
|
-
let id =
|
|
186
|
+
let id = [deviceModel, projectName?.isEmpty == false ? projectName! : nil, deviceName]
|
|
187
|
+
.compactMap { $0 }
|
|
188
|
+
.joined(separator: ":")
|
|
186
189
|
var newResult: [String: Any] = [
|
|
187
190
|
"id": id,
|
|
188
191
|
"model": deviceModel,
|
|
@@ -191,6 +194,9 @@ class Bridge {
|
|
|
191
194
|
if !deviceAddress.isEmpty {
|
|
192
195
|
newResult["address"] = deviceAddress
|
|
193
196
|
}
|
|
197
|
+
if let projectName, !projectName.isEmpty {
|
|
198
|
+
newResult["projectName"] = projectName
|
|
199
|
+
}
|
|
194
200
|
if let rssi {
|
|
195
201
|
newResult["rssi"] = rssi
|
|
196
202
|
}
|
|
@@ -495,7 +501,7 @@ class Bridge {
|
|
|
495
501
|
Bridge.sendTypedMessage("mtk_update_complete", body: eventBody)
|
|
496
502
|
}
|
|
497
503
|
|
|
498
|
-
/// Send ota_start_ack —
|
|
504
|
+
/// Send ota_start_ack —glasses confirmed receipt of ota_start command
|
|
499
505
|
static func sendOtaStartAck() {
|
|
500
506
|
let eventBody: [String: Any] = [
|
|
501
507
|
"timestamp": Int64(Date().timeIntervalSince1970 * 1000),
|
|
@@ -607,3 +613,9 @@ class Bridge {
|
|
|
607
613
|
return payload
|
|
608
614
|
}
|
|
609
615
|
}
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
@@ -22,7 +22,7 @@ struct ViewState {
|
|
|
22
22
|
var text: String
|
|
23
23
|
var data: String?
|
|
24
24
|
var animationData: [String: Any]?
|
|
25
|
-
// Optional container position/size
|
|
25
|
+
// Optional container position/size - used by bitmap_view and positioned_text (G2; ignored by others)
|
|
26
26
|
var bmpX: Int32? = nil
|
|
27
27
|
var bmpY: Int32? = nil
|
|
28
28
|
var bmpWidth: Int32? = nil
|
|
@@ -76,7 +76,7 @@ struct ViewState {
|
|
|
76
76
|
|
|
77
77
|
if isPaired {
|
|
78
78
|
// Device is paired! Don't activate it - let PhoneMic.swift activate when recording starts
|
|
79
|
-
Bridge.log("Audio:
|
|
79
|
+
Bridge.log("Audio: Mentra Live is paired (preserving A2DP for music)")
|
|
80
80
|
glassesBluetoothClassicConnected = true
|
|
81
81
|
} else {
|
|
82
82
|
glassesBluetoothClassicConnected = false
|
|
@@ -88,7 +88,7 @@ struct ViewState {
|
|
|
88
88
|
guard let self = self else { return }
|
|
89
89
|
|
|
90
90
|
if connected {
|
|
91
|
-
Bridge.log("Audio:
|
|
91
|
+
Bridge.log("Audio: Device paired and connected")
|
|
92
92
|
// Don't activate - let PhoneMic.swift handle that when recording starts
|
|
93
93
|
self.glassesBluetoothClassicConnected = true
|
|
94
94
|
} else {
|
|
@@ -320,7 +320,7 @@ struct ViewState {
|
|
|
320
320
|
),
|
|
321
321
|
]
|
|
322
322
|
|
|
323
|
-
// Scene slots
|
|
323
|
+
// Scene slots - one whole SceneFrame per view (main/dashboard), parallel to
|
|
324
324
|
// viewStates. When a slot holds a scene, viewStates carries a "scene"
|
|
325
325
|
// sentinel so sendCurrentState routes here. Holding the WHOLE frame keeps
|
|
326
326
|
// native re-dispatch coherent (dashboard exit re-applies a complete scene).
|
|
@@ -417,6 +417,10 @@ struct ViewState {
|
|
|
417
417
|
handlePcm(pcmData)
|
|
418
418
|
}
|
|
419
419
|
|
|
420
|
+
func reportGlassesAudioActivity() {
|
|
421
|
+
lastLc3Event = Date()
|
|
422
|
+
}
|
|
423
|
+
|
|
420
424
|
func handlePcm(_ pcmData: Data) {
|
|
421
425
|
handleSendingPcm(pcmData)
|
|
422
426
|
|
|
@@ -626,6 +630,8 @@ struct ViewState {
|
|
|
626
630
|
sgc = MentraLive()
|
|
627
631
|
} else if wearable.contains(DeviceTypes.NIMO) {
|
|
628
632
|
sgc = Nimo()
|
|
633
|
+
} else if wearable.contains(DeviceTypes.AR99) {
|
|
634
|
+
sgc = Ar99()
|
|
629
635
|
} else if wearable.contains(DeviceTypes.FRAME) {
|
|
630
636
|
// sgc = FrameManager()
|
|
631
637
|
}
|
|
@@ -722,7 +728,7 @@ struct ViewState {
|
|
|
722
728
|
)
|
|
723
729
|
case "positioned_text":
|
|
724
730
|
Bridge.log(
|
|
725
|
-
"MAN: positioned_text
|
|
731
|
+
"MAN: positioned_text -> text='\(currentViewState.text)' rect=\(currentViewState.bmpX ?? 0),\(currentViewState.bmpY ?? 0) \(currentViewState.bmpWidth ?? 576)x\(currentViewState.bmpHeight ?? 288)"
|
|
726
732
|
)
|
|
727
733
|
await sgc?.sendPositionedText(
|
|
728
734
|
currentViewState.text,
|
|
@@ -804,6 +810,11 @@ struct ViewState {
|
|
|
804
810
|
return
|
|
805
811
|
}
|
|
806
812
|
|
|
813
|
+
if PhoneAudioMonitor.getInstance().isOwnAppAudioPlaying() {
|
|
814
|
+
Bridge.log("MAN: Mentra audio is playing; skipping glasses mic recovery")
|
|
815
|
+
return
|
|
816
|
+
}
|
|
817
|
+
|
|
807
818
|
let timeSinceLastLc3Event = Date().timeIntervalSince(lastLc3Event ?? Date())
|
|
808
819
|
if timeSinceLastLc3Event > 5 {
|
|
809
820
|
Bridge.log("MAN: No audio activity in the last 5 seconds from glasses, reinitializing glasses mic")
|
|
@@ -861,7 +872,7 @@ struct ViewState {
|
|
|
861
872
|
let deviceName = session.availableInputs?.first(where: {
|
|
862
873
|
$0.portName.localizedCaseInsensitiveContains(audioDevicePattern)
|
|
863
874
|
})?.portName
|
|
864
|
-
Bridge.log("MAN:
|
|
875
|
+
Bridge.log("MAN: Successfully detected newly paired device '\(deviceName)'")
|
|
865
876
|
glassesBluetoothClassicConnected = true
|
|
866
877
|
} else {
|
|
867
878
|
glassesBluetoothClassicConnected = false
|
|
@@ -928,7 +939,7 @@ struct ViewState {
|
|
|
928
939
|
// stale/torn-down connection.
|
|
929
940
|
guard let sgc = self?.sgc else { return }
|
|
930
941
|
let h = DeviceStore.shared.get("bluetooth", "dashboard_height") as? Int ?? 4
|
|
931
|
-
// Fall back to the canonical default (2), matching DeviceStore
|
|
942
|
+
// Fall back to the canonical default (2), matching DeviceStore, not 1.
|
|
932
943
|
let rawDepth = DeviceStore.shared.get("bluetooth", "dashboard_depth") as? Int ?? 2
|
|
933
944
|
let d = min(max(rawDepth, 1), 4)
|
|
934
945
|
sgc.setDashboardPosition(h, d)
|
|
@@ -962,6 +973,10 @@ struct ViewState {
|
|
|
962
973
|
Bridge.saveSetting("default_wearable", defaultWearable)
|
|
963
974
|
Bridge.saveSetting("device_name", deviceName)
|
|
964
975
|
Bridge.saveSetting("device_address", deviceAddress)
|
|
976
|
+
if defaultWearable.contains(DeviceTypes.AR99) {
|
|
977
|
+
let projectName = (DeviceStore.shared.get("bluetooth", "project_name") as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
978
|
+
Bridge.saveSetting("project_name", projectName)
|
|
979
|
+
}
|
|
965
980
|
|
|
966
981
|
}
|
|
967
982
|
|
|
@@ -1168,7 +1183,7 @@ struct ViewState {
|
|
|
1168
1183
|
// Legacy→scene handoff: stale legacy content (e.g. a cloud app's
|
|
1169
1184
|
// text wall) must not linger under the scene's elements.
|
|
1170
1185
|
// clearDisplay is the per-device "wipe what's there" (blank-in-place
|
|
1171
|
-
// on G2
|
|
1186
|
+
// on G2 - no page rebuild).
|
|
1172
1187
|
let prevLegacyType = viewStates[stateIndex].layoutType
|
|
1173
1188
|
if !prevLegacyType.isEmpty, prevLegacyType != "clear_view", prevLegacyType != "scene" {
|
|
1174
1189
|
sgc?.clearDisplay()
|
|
@@ -1187,7 +1202,7 @@ struct ViewState {
|
|
|
1187
1202
|
}
|
|
1188
1203
|
|
|
1189
1204
|
// Store the REDISPATCH form: any later sendCurrentState (dashboard
|
|
1190
|
-
// exit, head-up return) must repaint the whole frame
|
|
1205
|
+
// exit, head-up return) must repaint the whole frame - the original
|
|
1191
1206
|
// annotations are only valid for the first dispatch right now.
|
|
1192
1207
|
sceneStates[stateIndex] = frame.asReplay()
|
|
1193
1208
|
viewStates[stateIndex] = ViewState(
|
|
@@ -1201,7 +1216,7 @@ struct ViewState {
|
|
|
1201
1216
|
}
|
|
1202
1217
|
}
|
|
1203
1218
|
|
|
1204
|
-
/// Guarded scene dispatch
|
|
1219
|
+
/// Guarded scene dispatch - mirrors sendCurrentState's send conditions.
|
|
1205
1220
|
private func dispatchSceneFrame(_ frame: SceneFrame) {
|
|
1206
1221
|
if screenDisabled { return }
|
|
1207
1222
|
if sgc?.type.contains(DeviceTypes.SIMULATED) ?? true { return }
|
|
@@ -1330,6 +1345,24 @@ struct ViewState {
|
|
|
1330
1345
|
(sgc as? MentraLive)?.sendOtaQueryStatus()
|
|
1331
1346
|
}
|
|
1332
1347
|
|
|
1348
|
+
func startAr99OtaFromFile(_ path: String) throws -> Bool {
|
|
1349
|
+
guard let ar99 = sgc as? Ar99 else {
|
|
1350
|
+
throw BluetoothSdkError(code: "unsupported_device", message: "This command requires AR99 glasses.")
|
|
1351
|
+
}
|
|
1352
|
+
return ar99.startOtaFromFile(path)
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
func cancelAr99Ota() {
|
|
1356
|
+
(sgc as? Ar99)?.cancelAr99Ota()
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
func sendAr99FactoryReset() throws {
|
|
1360
|
+
guard let ar99 = sgc as? Ar99 else {
|
|
1361
|
+
throw BluetoothSdkError(code: "unsupported_device", message: "This command requires AR99 glasses.")
|
|
1362
|
+
}
|
|
1363
|
+
ar99.sendFactoryReset()
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1333
1366
|
private func liveSgc() throws -> MentraLive {
|
|
1334
1367
|
guard let live = sgc as? MentraLive else {
|
|
1335
1368
|
throw BluetoothSdkError(code: "unsupported_device", message: "This command requires Mentra Live glasses.")
|
|
@@ -1409,7 +1442,9 @@ struct ViewState {
|
|
|
1409
1442
|
size: PhotoSize,
|
|
1410
1443
|
mode: PhotoMode = .photo,
|
|
1411
1444
|
exposureTimeNs: Double?,
|
|
1412
|
-
durationMs: Int
|
|
1445
|
+
durationMs: Int,
|
|
1446
|
+
zsl: Bool? = nil,
|
|
1447
|
+
mfnr: Bool? = nil
|
|
1413
1448
|
) throws {
|
|
1414
1449
|
guard let live = sgc as? MentraLive else {
|
|
1415
1450
|
// Fail fast like other camera commands so the SDK promise rejects immediately instead
|
|
@@ -1422,7 +1457,9 @@ struct ViewState {
|
|
|
1422
1457
|
size: size,
|
|
1423
1458
|
mode: mode,
|
|
1424
1459
|
exposureTimeNs: exposureTimeNs,
|
|
1425
|
-
durationMs: durationMs
|
|
1460
|
+
durationMs: durationMs,
|
|
1461
|
+
zsl: zsl,
|
|
1462
|
+
mfnr: mfnr
|
|
1426
1463
|
)
|
|
1427
1464
|
}
|
|
1428
1465
|
|
|
@@ -1498,7 +1535,7 @@ struct ViewState {
|
|
|
1498
1535
|
)
|
|
1499
1536
|
}
|
|
1500
1537
|
|
|
1501
|
-
/// Mentra Live only: K900 `cs_getvol` / `sr_getvol` (step volume 0
|
|
1538
|
+
/// Mentra Live only: K900 `cs_getvol` / `sr_getvol` (step volume 0-5).
|
|
1502
1539
|
func getGlassesMediaVolume() async throws -> [String: Any] {
|
|
1503
1540
|
guard let live = sgc as? MentraLive else {
|
|
1504
1541
|
throw NSError(
|
|
@@ -1561,7 +1598,7 @@ struct ViewState {
|
|
|
1561
1598
|
)
|
|
1562
1599
|
guard let sgc else {
|
|
1563
1600
|
Bridge.log(
|
|
1564
|
-
"MAN: PHOTO PIPELINE
|
|
1601
|
+
"MAN: PHOTO PIPELINE - sgc is null (glasses not connected); dropping requestId=\(routed.requestId)"
|
|
1565
1602
|
)
|
|
1566
1603
|
return
|
|
1567
1604
|
}
|
|
@@ -1573,13 +1610,19 @@ struct ViewState {
|
|
|
1573
1610
|
Bridge.log("MAN: No default wearable, returning")
|
|
1574
1611
|
return
|
|
1575
1612
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1613
|
+
let reconnectTarget =
|
|
1614
|
+
if defaultWearable.contains(DeviceTypes.AR99), !deviceAddress.isEmpty {
|
|
1615
|
+
deviceAddress
|
|
1616
|
+
} else {
|
|
1617
|
+
deviceName
|
|
1618
|
+
}
|
|
1619
|
+
if reconnectTarget.isEmpty {
|
|
1620
|
+
Bridge.log("MAN: No reconnect target, returning")
|
|
1578
1621
|
return
|
|
1579
1622
|
}
|
|
1580
1623
|
initSGC(defaultWearable)
|
|
1581
1624
|
searching = true
|
|
1582
|
-
sgc?.connectById(
|
|
1625
|
+
sgc?.connectById(reconnectTarget)
|
|
1583
1626
|
connectDefaultController()
|
|
1584
1627
|
}
|
|
1585
1628
|
|
|
@@ -1669,6 +1712,11 @@ struct ViewState {
|
|
|
1669
1712
|
shouldSendBootingMessage = true // Reset for next first connect
|
|
1670
1713
|
// clear glasses properties:
|
|
1671
1714
|
DeviceStore.shared.apply("glasses", "deviceModel", "")
|
|
1715
|
+
// A manufacturing serial is session-bound. Clear it on every disconnect so a
|
|
1716
|
+
// previously connected pair's serial can never be reported for the next
|
|
1717
|
+
// connection (e.g. switching from G1/Ar99, which populate it from the
|
|
1718
|
+
// advertisement, to a model that never writes it, like G2).
|
|
1719
|
+
DeviceStore.shared.apply("glasses", "serialNumber", "")
|
|
1672
1720
|
DeviceStore.shared.apply("glasses", "fullyBooted", false)
|
|
1673
1721
|
DeviceStore.shared.apply("glasses", "connected", false)
|
|
1674
1722
|
DeviceStore.shared.apply("glasses", "connectionState", ConnTypes.DISCONNECTED)
|
|
@@ -1700,6 +1748,7 @@ struct ViewState {
|
|
|
1700
1748
|
Bridge.saveSetting("default_wearable", "")
|
|
1701
1749
|
Bridge.saveSetting("device_name", "")
|
|
1702
1750
|
Bridge.saveSetting("device_address", "")
|
|
1751
|
+
Bridge.saveSetting("project_name", "")
|
|
1703
1752
|
}
|
|
1704
1753
|
|
|
1705
1754
|
func forgetController() {
|
|
@@ -1758,3 +1807,4 @@ struct ViewState {
|
|
|
1758
1807
|
cancellables.removeAll()
|
|
1759
1808
|
}
|
|
1760
1809
|
}
|
|
1810
|
+
|