@mentra/bluetooth-sdk 0.1.2 → 0.1.3
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 +33 -19
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +13 -13
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +42 -18
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +19 -21
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +4 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +118 -103
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +110 -38
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +4 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +6 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +3 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +18 -18
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +4 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/Constants.kt +6 -6
- package/build/BluetoothSdk.types.d.ts +126 -27
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_internal.d.ts +12 -0
- package/build/_internal.d.ts.map +1 -0
- package/build/_internal.js +11 -0
- package/build/_internal.js.map +1 -0
- package/build/{BluetoothSdkModule.d.ts → _private/BluetoothSdkModule.d.ts} +19 -8
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -0
- package/build/{BluetoothSdkModule.js → _private/BluetoothSdkModule.js} +41 -26
- package/build/_private/BluetoothSdkModule.js.map +1 -0
- package/build/index.d.ts +4 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -4
- package/build/index.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +14 -9
- package/ios/Source/Bridge.swift +44 -12
- package/ios/Source/DeviceManager.swift +27 -26
- package/ios/Source/DeviceStore.swift +4 -4
- package/ios/Source/MentraBluetoothSDK.swift +250 -132
- package/ios/Source/controllers/ControllerManager.swift +5 -5
- package/ios/Source/controllers/R1.swift +3 -3
- package/ios/Source/services/PhoneMic.swift +5 -5
- package/ios/Source/sgcs/Frame.swift +1 -1
- package/ios/Source/sgcs/G1.swift +1 -1
- package/ios/Source/sgcs/G2.swift +3 -3
- package/ios/Source/sgcs/Mach1.swift +1 -1
- package/ios/Source/sgcs/MentraLive.swift +31 -33
- package/ios/Source/sgcs/MentraNex.swift +2 -2
- package/ios/Source/sgcs/SGCManager.swift +5 -5
- package/ios/Source/sgcs/Simulated.swift +3 -3
- package/ios/Source/utils/Constants.swift +6 -6
- package/ios/Source/utils/JSCExperiment.swift +8 -8
- package/ios/Source/utils/TarBz2Extractor.swift +2 -2
- package/package.json +13 -1
- package/src/BluetoothSdk.types.ts +186 -28
- package/src/_internal.ts +11 -0
- package/src/{BluetoothSdkModule.ts → _private/BluetoothSdkModule.ts} +71 -38
- package/src/index.ts +80 -4
- package/build/BluetoothSdkModule.d.ts.map +0 -1
- package/build/BluetoothSdkModule.js.map +0 -1
|
@@ -54,8 +54,8 @@ protocol ControllerManager {
|
|
|
54
54
|
func sendShutdown()
|
|
55
55
|
func sendReboot()
|
|
56
56
|
func sendRgbLedControl(
|
|
57
|
-
requestId: String, packageName: String?, action: String, color: String?,
|
|
58
|
-
|
|
57
|
+
requestId: String, packageName: String?, action: String, color: String?, onDurationMs: Int,
|
|
58
|
+
offDurationMs: Int, count: Int
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
// MARK: - Connection Management
|
|
@@ -130,11 +130,11 @@ extension ControllerManager {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
var firmwareVersion: String {
|
|
133
|
-
DeviceStore.shared.get("glasses", "
|
|
133
|
+
DeviceStore.shared.get("glasses", "firmwareVersion") as? String ?? ""
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
var
|
|
137
|
-
DeviceStore.shared.get("glasses", "
|
|
136
|
+
var bluetoothMacAddress: String {
|
|
137
|
+
DeviceStore.shared.get("glasses", "bluetoothMacAddress") as? String ?? ""
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
var serialNumber: String {
|
|
@@ -259,7 +259,7 @@ class R1: NSObject, ControllerManager {
|
|
|
259
259
|
/// to WRITE_CHAR_2 (BAE80012-…). Reverse-engineered from the Even Realities mobile app
|
|
260
260
|
/// (BleRing1CmdProto::advStart -> BleRing1CmdPublicExt.sendCmd).
|
|
261
261
|
private func connectToGlasses() {
|
|
262
|
-
let glassesMac = (DeviceStore.shared.get("glasses", "
|
|
262
|
+
let glassesMac = (DeviceStore.shared.get("glasses", "bluetoothMacAddress") as? String)
|
|
263
263
|
?? UserDefaults.standard.string(forKey: "glasses_btMacAddress")
|
|
264
264
|
|
|
265
265
|
guard let glassesMac else {
|
|
@@ -530,8 +530,8 @@ class R1: NSObject, ControllerManager {
|
|
|
530
530
|
|
|
531
531
|
func sendReboot() {}
|
|
532
532
|
func sendRgbLedControl(
|
|
533
|
-
requestId _: String, packageName _: String?, action _: String, color _: String?,
|
|
534
|
-
|
|
533
|
+
requestId _: String, packageName _: String?, action _: String, color _: String?, onDurationMs _: Int,
|
|
534
|
+
offDurationMs _: Int, count _: Int
|
|
535
535
|
) {}
|
|
536
536
|
func requestWifiScan() {}
|
|
537
537
|
func sendWifiCredentials(_: String, _: String) {}
|
|
@@ -119,7 +119,7 @@ class PhoneMic {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/// Start recording with a specific microphone mode
|
|
122
|
-
/// - Parameter mode: One of MicTypes constants (PHONE_INTERNAL,
|
|
122
|
+
/// - Parameter mode: One of MicTypes constants (PHONE_INTERNAL, BLUETOOTH_CLASSIC, BLUETOOTH)
|
|
123
123
|
/// - Returns: true if successfully started recording, false otherwise
|
|
124
124
|
func startMode(_ mode: String) -> Bool {
|
|
125
125
|
// Check if already recording with this mode
|
|
@@ -150,7 +150,7 @@ class PhoneMic {
|
|
|
150
150
|
Bridge.log("MIC: Starting phone internal mic")
|
|
151
151
|
return startRecordingPhoneInternal()
|
|
152
152
|
|
|
153
|
-
// case MicTypes.
|
|
153
|
+
// case MicTypes.BLUETOOTH_CLASSIC:
|
|
154
154
|
// Bridge.log("MIC: Starting Bluetooth Classic (SCO)")
|
|
155
155
|
// guard isBluetoothScoAvailable() else {
|
|
156
156
|
// Bridge.log("MIC: Bluetooth SCO not available")
|
|
@@ -158,7 +158,7 @@ class PhoneMic {
|
|
|
158
158
|
// }
|
|
159
159
|
// return startRecordingBtClassic()
|
|
160
160
|
|
|
161
|
-
case MicTypes.
|
|
161
|
+
case MicTypes.BLUETOOTH:
|
|
162
162
|
Bridge.log("MIC: Starting high-quality Bluetooth mic")
|
|
163
163
|
guard isHighQualityBluetoothAvailable() else {
|
|
164
164
|
Bridge.log("MIC: High-quality Bluetooth not available")
|
|
@@ -248,7 +248,7 @@ class PhoneMic {
|
|
|
248
248
|
|
|
249
249
|
let success = startRecordingInternal()
|
|
250
250
|
if success {
|
|
251
|
-
currentMicMode = MicTypes.
|
|
251
|
+
currentMicMode = MicTypes.BLUETOOTH_CLASSIC
|
|
252
252
|
}
|
|
253
253
|
return success
|
|
254
254
|
|
|
@@ -284,7 +284,7 @@ class PhoneMic {
|
|
|
284
284
|
|
|
285
285
|
let success = startRecordingInternal()
|
|
286
286
|
if success {
|
|
287
|
-
currentMicMode = MicTypes.
|
|
287
|
+
currentMicMode = MicTypes.BLUETOOTH
|
|
288
288
|
}
|
|
289
289
|
return success
|
|
290
290
|
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
|
|
80
80
|
func exit() {}
|
|
81
81
|
|
|
82
|
-
func sendRgbLedControl(requestId: String, packageName _: String?, action _: String, color _: String?,
|
|
82
|
+
func sendRgbLedControl(requestId: String, packageName _: String?, action _: String, color _: String?, onDurationMs _: Int, offDurationMs _: Int, count _: Int) {
|
|
83
83
|
Bridge.sendRgbLedControlResponse(requestId: requestId, success: false, error: "device_not_supported")
|
|
84
84
|
}
|
|
85
85
|
|
package/ios/Source/sgcs/G1.swift
CHANGED
|
@@ -1446,7 +1446,7 @@ extension G1 {
|
|
|
1446
1446
|
|
|
1447
1447
|
func sendRgbLedControl(
|
|
1448
1448
|
requestId: String, packageName _: String?, action _: String, color _: String?,
|
|
1449
|
-
|
|
1449
|
+
onDurationMs _: Int, offDurationMs _: Int, count _: Int
|
|
1450
1450
|
) {
|
|
1451
1451
|
Bridge.log("sendRgbLedControl - not supported on G1")
|
|
1452
1452
|
Bridge.sendRgbLedControlResponse(
|
package/ios/Source/sgcs/G2.swift
CHANGED
|
@@ -2600,7 +2600,7 @@ class G2: NSObject, SGCManager {
|
|
|
2600
2600
|
|
|
2601
2601
|
func sendRgbLedControl(
|
|
2602
2602
|
requestId _: String, packageName _: String?, action _: String, color _: String?,
|
|
2603
|
-
|
|
2603
|
+
onDurationMs _: Int, offDurationMs _: Int, count _: Int
|
|
2604
2604
|
) {
|
|
2605
2605
|
// G2 doesn't have RGB LEDs
|
|
2606
2606
|
}
|
|
@@ -3310,7 +3310,7 @@ class G2: NSObject, SGCManager {
|
|
|
3310
3310
|
// Bridge.log("G2: Right firmware: \(rightVersion)")
|
|
3311
3311
|
DeviceStore.shared.apply("glasses", "rightFirmwareVersion", rightVersion)
|
|
3312
3312
|
// Use right version as the main version
|
|
3313
|
-
DeviceStore.shared.apply("glasses", "
|
|
3313
|
+
DeviceStore.shared.apply("glasses", "firmwareVersion", rightVersion)
|
|
3314
3314
|
}
|
|
3315
3315
|
}
|
|
3316
3316
|
|
|
@@ -3497,7 +3497,7 @@ extension G2: CBCentralManagerDelegate {
|
|
|
3497
3497
|
if let mac = extractMac(from: mfgData) {
|
|
3498
3498
|
if name.contains("_L_") {
|
|
3499
3499
|
DeviceStore.shared.apply("glasses", "leftMacAddress", mac)
|
|
3500
|
-
DeviceStore.shared.apply("glasses", "
|
|
3500
|
+
DeviceStore.shared.apply("glasses", "bluetoothMacAddress", mac)
|
|
3501
3501
|
} else if name.contains("_R_") {
|
|
3502
3502
|
DeviceStore.shared.apply("glasses", "rightMacAddress", mac)
|
|
3503
3503
|
}
|
|
@@ -53,7 +53,7 @@ class Mach1: UltraliteBaseViewController, SGCManager {
|
|
|
53
53
|
|
|
54
54
|
func sendRgbLedControl(
|
|
55
55
|
requestId: String, packageName _: String?, action _: String, color _: String?,
|
|
56
|
-
|
|
56
|
+
onDurationMs _: Int, offDurationMs _: Int, count _: Int
|
|
57
57
|
) {
|
|
58
58
|
Bridge.sendRgbLedControlResponse(
|
|
59
59
|
requestId: requestId, success: false, error: "device_not_supported"
|
|
@@ -2077,18 +2077,18 @@ class MentraLive: NSObject, SGCManager {
|
|
|
2077
2077
|
DeviceStore.shared.apply("glasses", "otaVersionUrl", otaVersionUrl)
|
|
2078
2078
|
}
|
|
2079
2079
|
if let firmwareVersion = fields["firmware_version"] as? String {
|
|
2080
|
-
DeviceStore.shared.apply("glasses", "
|
|
2080
|
+
DeviceStore.shared.apply("glasses", "firmwareVersion", firmwareVersion)
|
|
2081
2081
|
}
|
|
2082
|
-
if let
|
|
2083
|
-
DeviceStore.shared.apply("glasses", "
|
|
2082
|
+
if let besFirmwareVersion = fields["bes_fw_version"] as? String {
|
|
2083
|
+
DeviceStore.shared.apply("glasses", "besFirmwareVersion", besFirmwareVersion)
|
|
2084
2084
|
}
|
|
2085
|
-
if let
|
|
2085
|
+
if let mtkFirmwareVersion = fields["mtk_fw_version"] as? String {
|
|
2086
2086
|
// MTK firmware version (e.g., "20241130")
|
|
2087
2087
|
// Note: Stored separately from BES version for OTA patch matching
|
|
2088
|
-
DeviceStore.shared.apply("glasses", "
|
|
2088
|
+
DeviceStore.shared.apply("glasses", "mtkFirmwareVersion", mtkFirmwareVersion)
|
|
2089
2089
|
}
|
|
2090
|
-
if let
|
|
2091
|
-
DeviceStore.shared.apply("glasses", "
|
|
2090
|
+
if let bluetoothMacAddress = fields["bt_mac_address"] as? String {
|
|
2091
|
+
DeviceStore.shared.apply("glasses", "bluetoothMacAddress", bluetoothMacAddress)
|
|
2092
2092
|
}
|
|
2093
2093
|
|
|
2094
2094
|
// Send fields immediately to RN - no waiting for other chunks
|
|
@@ -2461,7 +2461,7 @@ class MentraLive: NSObject, SGCManager {
|
|
|
2461
2461
|
}
|
|
2462
2462
|
|
|
2463
2463
|
func sendGalleryMode() {
|
|
2464
|
-
let active = DeviceStore.shared.get("bluetooth", "
|
|
2464
|
+
let active = DeviceStore.shared.get("bluetooth", "galleryModeAuto") as! Bool
|
|
2465
2465
|
Bridge.log("LIVE: 📸 Sending gallery mode active to glasses: \(active)")
|
|
2466
2466
|
|
|
2467
2467
|
let json: [String: Any] = [
|
|
@@ -2520,8 +2520,8 @@ class MentraLive: NSObject, SGCManager {
|
|
|
2520
2520
|
// cannot leave a stale build number in RN (ASG is source of truth for PackageInfo).
|
|
2521
2521
|
DeviceStore.shared.apply("glasses", "buildNumber", "")
|
|
2522
2522
|
DeviceStore.shared.apply("glasses", "appVersion", "")
|
|
2523
|
-
DeviceStore.shared.apply("glasses", "
|
|
2524
|
-
DeviceStore.shared.apply("glasses", "
|
|
2523
|
+
DeviceStore.shared.apply("glasses", "besFirmwareVersion", "")
|
|
2524
|
+
DeviceStore.shared.apply("glasses", "mtkFirmwareVersion", "")
|
|
2525
2525
|
Bridge.log("LIVE: Cleared cached version_info fields before refresh")
|
|
2526
2526
|
|
|
2527
2527
|
// Perform SOC-dependent initialization
|
|
@@ -2587,13 +2587,13 @@ class MentraLive: NSObject, SGCManager {
|
|
|
2587
2587
|
let androidVersion = json["android_version"] as? String ?? ""
|
|
2588
2588
|
let otaVersionUrl = json["ota_version_url"] as? String ?? ""
|
|
2589
2589
|
let firmwareVersion = json["firmware_version"] as? String ?? ""
|
|
2590
|
-
let
|
|
2590
|
+
let bluetoothMacAddress = json["bt_mac_address"] as? String ?? ""
|
|
2591
2591
|
|
|
2592
2592
|
DeviceStore.shared.apply("glasses", "appVersion", appVersion)
|
|
2593
2593
|
DeviceStore.shared.apply("glasses", "buildNumber", buildNumber)
|
|
2594
2594
|
DeviceStore.shared.apply("glasses", "otaVersionUrl", otaVersionUrl)
|
|
2595
|
-
DeviceStore.shared.apply("glasses", "
|
|
2596
|
-
DeviceStore.shared.apply("glasses", "
|
|
2595
|
+
DeviceStore.shared.apply("glasses", "firmwareVersion", firmwareVersion)
|
|
2596
|
+
DeviceStore.shared.apply("glasses", "bluetoothMacAddress", bluetoothMacAddress)
|
|
2597
2597
|
isNewVersion = (Int(buildNumber) ?? 0) >= 5
|
|
2598
2598
|
DeviceStore.shared.apply("glasses", "deviceModel", deviceModel)
|
|
2599
2599
|
DeviceStore.shared.apply("glasses", "androidVersion", androidVersion)
|
|
@@ -2603,14 +2603,14 @@ class MentraLive: NSObject, SGCManager {
|
|
|
2603
2603
|
// hasMic = supportsLC3Audio
|
|
2604
2604
|
|
|
2605
2605
|
Bridge.log(
|
|
2606
|
-
"Glasses Version - App: \(appVersion), Build: \(buildNumber), Device: \(deviceModel), Android: \(androidVersion), Firmware: \(firmwareVersion), BT MAC: \(
|
|
2606
|
+
"Glasses Version - App: \(appVersion), Build: \(buildNumber), Device: \(deviceModel), Android: \(androidVersion), Firmware: \(firmwareVersion), BT MAC: \(bluetoothMacAddress), OTA URL: \(otaVersionUrl)"
|
|
2607
2607
|
)
|
|
2608
2608
|
Bridge.log("LIVE: LC3 Audio Support: \(supportsLC3Audio), Has Mic: \(hasMic)")
|
|
2609
2609
|
emitVersionInfo(
|
|
2610
2610
|
appVersion: appVersion, buildNumber: buildNumber, deviceModel: deviceModel,
|
|
2611
2611
|
androidVersion: androidVersion, otaVersionUrl: otaVersionUrl,
|
|
2612
2612
|
firmwareVersion: firmwareVersion,
|
|
2613
|
-
|
|
2613
|
+
bluetoothMacAddress: bluetoothMacAddress
|
|
2614
2614
|
)
|
|
2615
2615
|
}
|
|
2616
2616
|
|
|
@@ -3532,7 +3532,7 @@ class MentraLive: NSObject, SGCManager {
|
|
|
3532
3532
|
|
|
3533
3533
|
private func emitHotspotError(errorMessage: String, timestamp: Int64) {
|
|
3534
3534
|
let eventBody: [String: Any] = [
|
|
3535
|
-
"
|
|
3535
|
+
"errorMessage": errorMessage,
|
|
3536
3536
|
"timestamp": timestamp,
|
|
3537
3537
|
]
|
|
3538
3538
|
Bridge.sendTypedMessage("hotspot_error", body: eventBody)
|
|
@@ -3552,8 +3552,8 @@ class MentraLive: NSObject, SGCManager {
|
|
|
3552
3552
|
"photos": photoCount,
|
|
3553
3553
|
"videos": videoCount,
|
|
3554
3554
|
"total": totalCount,
|
|
3555
|
-
"
|
|
3556
|
-
"
|
|
3555
|
+
"totalSize": totalSize,
|
|
3556
|
+
"hasContent": hasContent,
|
|
3557
3557
|
] as [String: Any]
|
|
3558
3558
|
Bridge.sendTypedMessage("gallery_status", body: eventBody)
|
|
3559
3559
|
}
|
|
@@ -3763,9 +3763,7 @@ class MentraLive: NSObject, SGCManager {
|
|
|
3763
3763
|
private func emitStopScanEvent() {
|
|
3764
3764
|
// Use the standardized typed message function
|
|
3765
3765
|
let body = [
|
|
3766
|
-
"
|
|
3767
|
-
"device_model": "Mentra Live",
|
|
3768
|
-
],
|
|
3766
|
+
"deviceModel": "Mentra Live",
|
|
3769
3767
|
]
|
|
3770
3768
|
Bridge.sendTypedMessage("compatible_glasses_search_stop", body: body)
|
|
3771
3769
|
}
|
|
@@ -3811,7 +3809,7 @@ class MentraLive: NSObject, SGCManager {
|
|
|
3811
3809
|
|
|
3812
3810
|
private func emitVersionInfo(
|
|
3813
3811
|
appVersion: String, buildNumber: String, deviceModel: String, androidVersion: String,
|
|
3814
|
-
otaVersionUrl: String, firmwareVersion: String,
|
|
3812
|
+
otaVersionUrl: String, firmwareVersion: String, bluetoothMacAddress: String
|
|
3815
3813
|
) {
|
|
3816
3814
|
let eventBody: [String: Any] = [
|
|
3817
3815
|
"app_version": appVersion,
|
|
@@ -3820,7 +3818,7 @@ class MentraLive: NSObject, SGCManager {
|
|
|
3820
3818
|
"android_version": androidVersion,
|
|
3821
3819
|
"ota_version_url": otaVersionUrl,
|
|
3822
3820
|
"firmware_version": firmwareVersion,
|
|
3823
|
-
"bt_mac_address":
|
|
3821
|
+
"bt_mac_address": bluetoothMacAddress,
|
|
3824
3822
|
]
|
|
3825
3823
|
|
|
3826
3824
|
Bridge.sendTypedMessage("version_info", body: eventBody)
|
|
@@ -4106,7 +4104,7 @@ extension MentraLive {
|
|
|
4106
4104
|
glassesMediaVolumeLock.unlock()
|
|
4107
4105
|
if let c {
|
|
4108
4106
|
DispatchQueue.main.async {
|
|
4109
|
-
c(.success(["
|
|
4107
|
+
c(.success(["level": vol, "statusCode": status]))
|
|
4110
4108
|
}
|
|
4111
4109
|
}
|
|
4112
4110
|
}
|
|
@@ -4349,8 +4347,8 @@ extension MentraLive {
|
|
|
4349
4347
|
packageName: String?,
|
|
4350
4348
|
action: String,
|
|
4351
4349
|
color: String?,
|
|
4352
|
-
|
|
4353
|
-
|
|
4350
|
+
onDurationMs: Int,
|
|
4351
|
+
offDurationMs: Int,
|
|
4354
4352
|
count: Int
|
|
4355
4353
|
) {
|
|
4356
4354
|
guard connectionState == ConnTypes.CONNECTED, fullyBooted else {
|
|
@@ -4378,8 +4376,8 @@ extension MentraLive {
|
|
|
4378
4376
|
let ledIndex = ledIndex(for: color)
|
|
4379
4377
|
command["type"] = "rgb_led_control_on"
|
|
4380
4378
|
command["led"] = ledIndex
|
|
4381
|
-
command["ontime"] =
|
|
4382
|
-
command["offtime"] =
|
|
4379
|
+
command["ontime"] = onDurationMs
|
|
4380
|
+
command["offtime"] = offDurationMs
|
|
4383
4381
|
command["count"] = count
|
|
4384
4382
|
case "off":
|
|
4385
4383
|
command["type"] = "rgb_led_control_off"
|
|
@@ -4502,11 +4500,11 @@ extension MentraLive {
|
|
|
4502
4500
|
DeviceStore.shared.get("bluetooth", "button_video_settings") as? [String: Any] ?? [
|
|
4503
4501
|
"width": 1280,
|
|
4504
4502
|
"height": 720,
|
|
4505
|
-
"
|
|
4503
|
+
"frameRate": 30,
|
|
4506
4504
|
]
|
|
4507
4505
|
let width = settings["width"] as? Int ?? 1280
|
|
4508
4506
|
let height = settings["height"] as? Int ?? 720
|
|
4509
|
-
let fps = settings["
|
|
4507
|
+
let fps = settings["frameRate"] as? Int ?? 30
|
|
4510
4508
|
|
|
4511
4509
|
// Use defaults if not set
|
|
4512
4510
|
let finalWidth = width > 0 ? width : 1280
|
|
@@ -4584,11 +4582,11 @@ extension MentraLive {
|
|
|
4584
4582
|
}
|
|
4585
4583
|
|
|
4586
4584
|
func sendCameraFovSetting() {
|
|
4587
|
-
let settings = DeviceStore.shared.get("bluetooth", "camera_fov") as? [String: Any] ?? ["fov": 118, "
|
|
4585
|
+
let settings = DeviceStore.shared.get("bluetooth", "camera_fov") as? [String: Any] ?? ["fov": 118, "roiPosition": 0]
|
|
4588
4586
|
let fov = settings["fov"] as? Int ?? 118
|
|
4589
|
-
let roiPosition = settings["
|
|
4587
|
+
let roiPosition = settings["roiPosition"] as? Int ?? 0
|
|
4590
4588
|
|
|
4591
|
-
Bridge.log("Sending camera FOV setting: fov=\(fov),
|
|
4589
|
+
Bridge.log("Sending camera FOV setting: fov=\(fov), roiPosition=\(roiPosition)")
|
|
4592
4590
|
|
|
4593
4591
|
guard connectionState == ConnTypes.CONNECTED else {
|
|
4594
4592
|
Bridge.log("Cannot send camera FOV setting - not connected")
|
|
@@ -106,8 +106,8 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
|
|
|
106
106
|
func sendReboot() {}
|
|
107
107
|
|
|
108
108
|
func sendRgbLedControl(
|
|
109
|
-
requestId _: String, packageName _: String?, action _: String, color _: String?,
|
|
110
|
-
|
|
109
|
+
requestId _: String, packageName _: String?, action _: String, color _: String?, onDurationMs _: Int,
|
|
110
|
+
offDurationMs _: Int, count _: Int
|
|
111
111
|
) {}
|
|
112
112
|
|
|
113
113
|
func forget() {}
|
|
@@ -62,8 +62,8 @@ protocol SGCManager {
|
|
|
62
62
|
func sendShutdown()
|
|
63
63
|
func sendReboot()
|
|
64
64
|
func sendRgbLedControl(
|
|
65
|
-
requestId: String, packageName: String?, action: String, color: String?,
|
|
66
|
-
|
|
65
|
+
requestId: String, packageName: String?, action: String, color: String?, onDurationMs: Int,
|
|
66
|
+
offDurationMs: Int, count: Int
|
|
67
67
|
)
|
|
68
68
|
|
|
69
69
|
// MARK: - Connection Management
|
|
@@ -158,11 +158,11 @@ extension SGCManager {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
var firmwareVersion: String {
|
|
161
|
-
DeviceStore.shared.get("glasses", "
|
|
161
|
+
DeviceStore.shared.get("glasses", "firmwareVersion") as? String ?? ""
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
var
|
|
165
|
-
DeviceStore.shared.get("glasses", "
|
|
164
|
+
var bluetoothMacAddress: String {
|
|
165
|
+
DeviceStore.shared.get("glasses", "bluetoothMacAddress") as? String ?? ""
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
var serialNumber: String {
|
|
@@ -13,7 +13,7 @@ class Simulated: SGCManager {
|
|
|
13
13
|
DeviceStore.shared.apply("glasses", "connectionState", ConnTypes.CONNECTED)
|
|
14
14
|
DeviceStore.shared.apply("glasses", "micEnabled", false)
|
|
15
15
|
DeviceStore.shared.apply("glasses", "vadEnabled", false)
|
|
16
|
-
DeviceStore.shared.apply("glasses", "
|
|
16
|
+
DeviceStore.shared.apply("glasses", "bluetoothClassicConnected", false)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
// MARK: - Device Information
|
|
@@ -28,7 +28,7 @@ class Simulated: SGCManager {
|
|
|
28
28
|
var androidVersion: String = ""
|
|
29
29
|
var otaVersionUrl: String = ""
|
|
30
30
|
var firmwareVersion: String = ""
|
|
31
|
-
var
|
|
31
|
+
var bluetoothMacAddress: String = ""
|
|
32
32
|
var serialNumber: String = ""
|
|
33
33
|
var style: String = ""
|
|
34
34
|
var color: String = ""
|
|
@@ -176,7 +176,7 @@ class Simulated: SGCManager {
|
|
|
176
176
|
Bridge.log("sendReboot - not supported on Simulated")
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
func sendRgbLedControl(requestId: String, packageName _: String?, action _: String, color _: String?,
|
|
179
|
+
func sendRgbLedControl(requestId: String, packageName _: String?, action _: String, color _: String?, onDurationMs _: Int, offDurationMs _: Int, count _: Int) {
|
|
180
180
|
Bridge.log("sendRgbLedControl - not supported on Simulated")
|
|
181
181
|
Bridge.sendRgbLedControlResponse(requestId: requestId, success: false, error: "device_not_supported")
|
|
182
182
|
}
|
|
@@ -48,14 +48,14 @@ struct ConnTypes {
|
|
|
48
48
|
struct MicTypes {
|
|
49
49
|
static let PHONE_INTERNAL = "phone"
|
|
50
50
|
static let GLASSES_CUSTOM = "glasses"
|
|
51
|
-
static let
|
|
52
|
-
static let
|
|
51
|
+
static let BLUETOOTH_CLASSIC = "bluetoothClassic"
|
|
52
|
+
static let BLUETOOTH = "bluetooth"
|
|
53
53
|
|
|
54
54
|
static let ALL = [
|
|
55
55
|
PHONE_INTERNAL,
|
|
56
56
|
GLASSES_CUSTOM,
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
BLUETOOTH_CLASSIC,
|
|
58
|
+
BLUETOOTH,
|
|
59
59
|
]
|
|
60
60
|
|
|
61
61
|
/// Private init to prevent instantiation
|
|
@@ -65,10 +65,10 @@ struct MicTypes {
|
|
|
65
65
|
enum MicMap {
|
|
66
66
|
static var map: [String: [String]] = [
|
|
67
67
|
"auto": [
|
|
68
|
-
MicTypes.GLASSES_CUSTOM, MicTypes.PHONE_INTERNAL, MicTypes.
|
|
68
|
+
MicTypes.GLASSES_CUSTOM, MicTypes.PHONE_INTERNAL, MicTypes.BLUETOOTH, MicTypes.BLUETOOTH_CLASSIC,
|
|
69
69
|
],
|
|
70
70
|
"glasses": [MicTypes.GLASSES_CUSTOM],
|
|
71
71
|
"phone": [MicTypes.PHONE_INTERNAL, MicTypes.GLASSES_CUSTOM],
|
|
72
|
-
"bluetooth": [MicTypes.
|
|
72
|
+
"bluetooth": [MicTypes.BLUETOOTH, MicTypes.BLUETOOTH_CLASSIC, MicTypes.PHONE_INTERNAL, MicTypes.GLASSES_CUSTOM],
|
|
73
73
|
]
|
|
74
74
|
}
|
|
@@ -56,11 +56,11 @@ private func jlog(_ message: String) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
@objc
|
|
59
|
+
@objc class JSCExperiment: NSObject {
|
|
60
60
|
/// Called from BluetoothSdkModule init. If MENTRA_RUN_JSC_BENCH env var
|
|
61
61
|
/// is set, kick off the benchmark after a 5s settle window so the app
|
|
62
62
|
/// is fully booted (RN bridge up, Metro pull done if dev, etc).
|
|
63
|
-
@objc
|
|
63
|
+
@objc static func maybeAutoBenchmark() {
|
|
64
64
|
guard ProcessInfo.processInfo.environment["MENTRA_RUN_JSC_BENCH"] != nil else { return }
|
|
65
65
|
os_log("🧪 MENTRA_RUN_JSC_BENCH set — auto-running benchmark in 5s",
|
|
66
66
|
log: jscLog, type: .info)
|
|
@@ -75,7 +75,7 @@ private func jlog(_ message: String) {
|
|
|
75
75
|
|
|
76
76
|
/// Spawn N JSContexts at once. Each gets its own VM + a representative
|
|
77
77
|
/// idle workload. Returns the count successfully spawned.
|
|
78
|
-
@objc
|
|
78
|
+
@objc static func spawn(count: Int) -> Int {
|
|
79
79
|
let beforeMB = MemoryMonitor.currentMemoryMB()
|
|
80
80
|
jlog("🧪 JSCExperiment.spawn(\(count)) starting; baseline \(String(format: "%.1f", beforeMB)) MB")
|
|
81
81
|
var spawned = 0
|
|
@@ -92,7 +92,7 @@ private func jlog(_ message: String) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
/// Spawn one named context. Returns true on success.
|
|
95
|
-
@objc
|
|
95
|
+
@objc static func spawnOne(id: String) -> Bool {
|
|
96
96
|
return queue.sync {
|
|
97
97
|
// Each context gets its own VM = full heap isolation between miniapps.
|
|
98
98
|
// (JSContexts that share a VM share the heap; we want isolation.)
|
|
@@ -170,7 +170,7 @@ private func jlog(_ message: String) {
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
/// Tear down all contexts. Important: cancel timers, drop refs, force GC.
|
|
173
|
-
@objc
|
|
173
|
+
@objc static func killAll() {
|
|
174
174
|
queue.sync {
|
|
175
175
|
for (_, entry) in contexts {
|
|
176
176
|
entry.2.invalidate()
|
|
@@ -182,13 +182,13 @@ private func jlog(_ message: String) {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
/// How many contexts are alive right now.
|
|
185
|
-
@objc
|
|
185
|
+
@objc static func aliveCount() -> Int {
|
|
186
186
|
return queue.sync { contexts.count }
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
/// Convenience: spawn N + return memory delta vs baseline. Caller
|
|
190
190
|
/// records baseline via MemoryMonitor.currentMemoryMB() before calling.
|
|
191
|
-
@objc
|
|
191
|
+
@objc static func spawnAndMeasure(count: Int, baselineMB: Double) -> [String: Any] {
|
|
192
192
|
let beforeMB = MemoryMonitor.currentMemoryMB()
|
|
193
193
|
let spawned = spawn(count: count)
|
|
194
194
|
// Tiny settle delay so allocations complete before we read.
|
|
@@ -211,7 +211,7 @@ private func jlog(_ message: String) {
|
|
|
211
211
|
/// Run a full benchmark sweep: spawn 1, 5, 10, 25, 50 in waves with
|
|
212
212
|
/// 2s settle between, log resident MB before and after each. All
|
|
213
213
|
/// output via jlog so it reaches syslog in release builds.
|
|
214
|
-
@objc
|
|
214
|
+
@objc static func runBenchmark() {
|
|
215
215
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
216
216
|
killAll()
|
|
217
217
|
// Clear log file for a fresh run.
|
|
@@ -4,11 +4,11 @@ import Foundation
|
|
|
4
4
|
import SWCompression
|
|
5
5
|
|
|
6
6
|
@objc(TarBz2Extractor)
|
|
7
|
-
|
|
7
|
+
class TarBz2Extractor: NSObject {
|
|
8
8
|
private static let chunkSize = 1 << 16 // 64 KB
|
|
9
9
|
|
|
10
10
|
@objc
|
|
11
|
-
|
|
11
|
+
static func extractTarBz2From(
|
|
12
12
|
_ sourcePath: String,
|
|
13
13
|
to destinationPath: String,
|
|
14
14
|
error errorPointer: NSErrorPointer
|
package/package.json
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mentra/bluetooth-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "SDK for communicating with smart glasses",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
7
7
|
"app.plugin": "app.plugin.js",
|
|
8
8
|
"types": "build/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./build/index.d.ts",
|
|
12
|
+
"react-native": "./src/index.ts",
|
|
13
|
+
"default": "./build/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./_private/*": null,
|
|
16
|
+
"./build/*": null,
|
|
17
|
+
"./src/*": null,
|
|
18
|
+
"./app.plugin": "./app.plugin.js",
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
9
21
|
"files": [
|
|
10
22
|
"android",
|
|
11
23
|
"!android/.gradle",
|