@mentra/bluetooth-sdk 3.3.0-dev.418 → 3.3.0-dev.420
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/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +5 -5
- package/android/src/main/java/com/mentra/bluetoothsdk/debug/BleTraceLogger.kt +3 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +17 -1
- package/android/src/test/java/com/mentra/bluetoothsdk/debug/BleTraceLoggerTest.kt +69 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/MentraLiveWifiCredentialLogTest.kt +55 -0
- package/build/generated/releaseMetadata.js +5 -5
- package/build/generated/releaseMetadata.js.map +1 -1
- package/ios/Source/BluetoothSdkDefaults.swift +1 -1
- package/ios/Source/DeviceManager.swift +1 -1
- package/ios/Source/GeneratedReleaseMetadata.swift +5 -5
- package/ios/Source/sgcs/MentraLive.swift +5 -1
- package/ios/Tests/WifiCredentialLoggingTests.swift +42 -0
- package/package.json +2 -2
- package/src/generated/releaseMetadata.ts +5 -5
|
@@ -3,9 +3,9 @@ package com.mentra.bluetoothsdk
|
|
|
3
3
|
/** Generated by release CI. Do not edit in a release checkout. */
|
|
4
4
|
internal object GeneratedReleaseMetadata {
|
|
5
5
|
const val FAMILY_BASE_VERSION: String = "3.3.0"
|
|
6
|
-
const val RELEASE_IDENTITY: String = "3.3.0-dev.
|
|
7
|
-
const val RELEASE_SET_ID: String = "mentra-3.3.0-dev.
|
|
8
|
-
const val SOURCE_COMMIT: String = "
|
|
9
|
-
const val OTA_MANIFEST_URL: String = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.
|
|
10
|
-
const val OTA_MANIFEST_SHA256: String = "
|
|
6
|
+
const val RELEASE_IDENTITY: String = "3.3.0-dev.420"
|
|
7
|
+
const val RELEASE_SET_ID: String = "mentra-3.3.0-dev.420"
|
|
8
|
+
const val SOURCE_COMMIT: String = "cad421d261e3dc99f743ba902a7e0c4a0f42b095"
|
|
9
|
+
const val OTA_MANIFEST_URL: String = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.420.json"
|
|
10
|
+
const val OTA_MANIFEST_SHA256: String = "0bff87c1bcd2f19eb90079980fc42fe2dbd787ceb0a74bea56b8948f3b4190dc"
|
|
11
11
|
}
|
|
@@ -108,6 +108,9 @@ object BleTraceLogger {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
private fun sanitizeValue(key: String?, value: Any?): Any? {
|
|
111
|
+
// Scan security metadata is a boolean, not a credential. Keep the exact
|
|
112
|
+
// typed field while still redacting string/unknown values under this key.
|
|
113
|
+
if (key == "requiresPassword" && value is Boolean) return value
|
|
111
114
|
if (key != null && sensitiveKeyParts.any { key.contains(it, ignoreCase = true) }) {
|
|
112
115
|
return "<redacted>"
|
|
113
116
|
}
|
|
@@ -9493,7 +9493,11 @@ class MentraLive : SGCManager() {
|
|
|
9493
9493
|
}
|
|
9494
9494
|
} else {
|
|
9495
9495
|
// Normal single message transmission
|
|
9496
|
-
transportLog(
|
|
9496
|
+
transportLog(
|
|
9497
|
+
"LIVE: Sending data to glasses: " +
|
|
9498
|
+
loggableOutgoingPayload(wireData, commandTraceInfo.commandType),
|
|
9499
|
+
bridgeLogging
|
|
9500
|
+
)
|
|
9497
9501
|
|
|
9498
9502
|
// Pack the data using the centralized utility with the negotiated endianness
|
|
9499
9503
|
val packedData =
|
|
@@ -9795,6 +9799,18 @@ class MentraLive : SGCManager() {
|
|
|
9795
9799
|
}
|
|
9796
9800
|
}
|
|
9797
9801
|
|
|
9802
|
+
/**
|
|
9803
|
+
* Wi-Fi credentials are sent unchanged but never logged; the BLE trace records the command
|
|
9804
|
+
* with the password redacted.
|
|
9805
|
+
*/
|
|
9806
|
+
private fun loggableOutgoingPayload(payload: String, commandType: String): String =
|
|
9807
|
+
try {
|
|
9808
|
+
if (JSONObject(payload).has("password")) "<$commandType with credentials omitted>"
|
|
9809
|
+
else payload
|
|
9810
|
+
} catch (_: JSONException) {
|
|
9811
|
+
payload
|
|
9812
|
+
}
|
|
9813
|
+
|
|
9798
9814
|
private fun summarizeOutgoingMessage(payload: String?): String {
|
|
9799
9815
|
if (payload == null || payload.isEmpty()) {
|
|
9800
9816
|
return "type=unknown, requestId=none, appId=none, mode=none, transferMethod=none, bleImgId=none, exposureTimeNs=none, iso=none, mId=none"
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk.debug
|
|
2
|
+
|
|
3
|
+
import java.util.UUID
|
|
4
|
+
import org.json.JSONArray
|
|
5
|
+
import org.json.JSONObject
|
|
6
|
+
import org.junit.Assert.assertEquals
|
|
7
|
+
import org.junit.Assert.assertFalse
|
|
8
|
+
import org.junit.Test
|
|
9
|
+
import org.junit.runner.RunWith
|
|
10
|
+
import org.robolectric.RobolectricTestRunner
|
|
11
|
+
import org.robolectric.annotation.Config
|
|
12
|
+
import org.robolectric.shadows.ShadowLog
|
|
13
|
+
|
|
14
|
+
@RunWith(RobolectricTestRunner::class)
|
|
15
|
+
@Config(sdk = [28])
|
|
16
|
+
class BleTraceLoggerTest {
|
|
17
|
+
@Test
|
|
18
|
+
fun wifiScanPreservesBooleanSecurityWhileRedactingCredentials() {
|
|
19
|
+
val secret = UUID.randomUUID().toString()
|
|
20
|
+
val networks = JSONArray()
|
|
21
|
+
for (secured in listOf(true, false)) {
|
|
22
|
+
networks.put(
|
|
23
|
+
JSONObject()
|
|
24
|
+
.put("ssid", if (secured) "secured-fixture" else "open-fixture")
|
|
25
|
+
.put("requiresPassword", secured)
|
|
26
|
+
.put("signalStrength", -45)
|
|
27
|
+
.put("password", secret)
|
|
28
|
+
.put("token", secret)
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
ShadowLog.clear()
|
|
32
|
+
BleTraceLogger.logJson(
|
|
33
|
+
"glasses_to_phone",
|
|
34
|
+
"sdk_ble_event",
|
|
35
|
+
JSONObject().put("type", "wifi_scan_result").put("networks_neo", networks),
|
|
36
|
+
)
|
|
37
|
+
val message = ShadowLog.getLogsForTag("MentraBleTrace").single().msg
|
|
38
|
+
assertFalse(message.contains(secret))
|
|
39
|
+
val actual = JSONObject(message.substringAfter("payload=")).getJSONArray("networks_neo")
|
|
40
|
+
for ((index, secured) in listOf(true, false).withIndex()) {
|
|
41
|
+
val item = actual.getJSONObject(index)
|
|
42
|
+
assertEquals(secured, item.get("requiresPassword"))
|
|
43
|
+
assertEquals(-45, item.getInt("signalStrength"))
|
|
44
|
+
assertEquals("<redacted>", item.getString("password"))
|
|
45
|
+
assertEquals("<redacted>", item.getString("token"))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Test
|
|
50
|
+
fun exceptionDoesNotExposeNonBooleanOrOtherPasswordFields() {
|
|
51
|
+
val secret = UUID.randomUUID().toString()
|
|
52
|
+
ShadowLog.clear()
|
|
53
|
+
BleTraceLogger.logJson(
|
|
54
|
+
"glasses_to_phone",
|
|
55
|
+
"sdk_ble_event",
|
|
56
|
+
JSONObject()
|
|
57
|
+
.put("type", "wifi_scan_result")
|
|
58
|
+
.put("requiresPassword", secret)
|
|
59
|
+
.put("password", true)
|
|
60
|
+
.put("RequiresPassword", false),
|
|
61
|
+
)
|
|
62
|
+
val message = ShadowLog.getLogsForTag("MentraBleTrace").single().msg
|
|
63
|
+
assertFalse(message.contains(secret))
|
|
64
|
+
val actual = JSONObject(message.substringAfter("payload="))
|
|
65
|
+
for (key in listOf("requiresPassword", "password", "RequiresPassword")) {
|
|
66
|
+
assertEquals("<redacted>", actual.getString(key))
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk.sgcs
|
|
2
|
+
|
|
3
|
+
import android.os.Looper
|
|
4
|
+
import androidx.test.core.app.ApplicationProvider
|
|
5
|
+
import com.mentra.bluetoothsdk.Bridge
|
|
6
|
+
import java.nio.charset.StandardCharsets
|
|
7
|
+
import java.time.Duration
|
|
8
|
+
import java.util.UUID
|
|
9
|
+
import org.junit.Assert.assertFalse
|
|
10
|
+
import org.junit.Assert.assertTrue
|
|
11
|
+
import org.junit.Test
|
|
12
|
+
import org.junit.runner.RunWith
|
|
13
|
+
import org.robolectric.RobolectricTestRunner
|
|
14
|
+
import org.robolectric.Shadows.shadowOf
|
|
15
|
+
import org.robolectric.annotation.Config
|
|
16
|
+
import org.robolectric.annotation.LooperMode
|
|
17
|
+
import org.robolectric.shadows.ShadowLog
|
|
18
|
+
|
|
19
|
+
@RunWith(RobolectricTestRunner::class)
|
|
20
|
+
@Config(sdk = [33], shadows = [G1PairingTest.ShadowLc3Cpp::class], instrumentedPackages = ["com.mentra.lc3Lib"])
|
|
21
|
+
@LooperMode(LooperMode.Mode.PAUSED)
|
|
22
|
+
class MentraLiveWifiCredentialLogTest {
|
|
23
|
+
@Test fun `wifi credentials reach the BLE queue without being logged`() {
|
|
24
|
+
Bridge.initialize(ApplicationProvider.getApplicationContext())
|
|
25
|
+
val ssid = "synthetic-${UUID.randomUUID()}"
|
|
26
|
+
val password = UUID.randomUUID().toString()
|
|
27
|
+
val events = mutableListOf<String>()
|
|
28
|
+
val sink = Bridge.addEventSink { type, body -> if (type == "log") events.add(body["message"].toString()) }
|
|
29
|
+
val live = MentraLive()
|
|
30
|
+
try {
|
|
31
|
+
ShadowLog.clear()
|
|
32
|
+
live.sendWifiCredentials(ssid, password)
|
|
33
|
+
|
|
34
|
+
val logs = events + ShadowLog.getLogs().map { it.msg }
|
|
35
|
+
assertFalse("password logged", logs.any { it.contains(password) })
|
|
36
|
+
assertTrue(events.any { it.endsWith("LIVE: Sending data to glasses: <set_wifi_credentials with credentials omitted>") })
|
|
37
|
+
// The glasses still receive the unchanged credentials.
|
|
38
|
+
val wire = queuedWrites(live).joinToString("") { String(it, StandardCharsets.UTF_8) }
|
|
39
|
+
assertTrue(wire.contains("set_wifi_credentials"))
|
|
40
|
+
assertTrue(wire.contains(ssid))
|
|
41
|
+
assertTrue(wire.contains(password))
|
|
42
|
+
} finally {
|
|
43
|
+
Bridge.removeEventSink(sink)
|
|
44
|
+
live.destroy()
|
|
45
|
+
shadowOf(Looper.getMainLooper()).idleFor(Duration.ofSeconds(2))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private fun queuedWrites(live: MentraLive): List<ByteArray> {
|
|
50
|
+
val queue = MentraLive::class.java.getDeclaredField("sendQueue").apply { isAccessible = true }.get(live)
|
|
51
|
+
return (queue as Iterable<*>).map { write ->
|
|
52
|
+
write!!.javaClass.getDeclaredField("data").apply { isAccessible = true }.get(write) as ByteArray
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export const BLUETOOTH_SDK_RELEASE_METADATA = Object.freeze({
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"familyBaseVersion": "3.3.0",
|
|
4
|
-
"releaseIdentity": "3.3.0-dev.
|
|
5
|
-
"releaseSetId": "mentra-3.3.0-dev.
|
|
6
|
-
"sourceCommit": "
|
|
7
|
-
"otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.
|
|
8
|
-
"otaManifestSha256": "
|
|
4
|
+
"releaseIdentity": "3.3.0-dev.420",
|
|
5
|
+
"releaseSetId": "mentra-3.3.0-dev.420",
|
|
6
|
+
"sourceCommit": "cad421d261e3dc99f743ba902a7e0c4a0f42b095",
|
|
7
|
+
"otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.420.json",
|
|
8
|
+
"otaManifestSha256": "0bff87c1bcd2f19eb90079980fc42fe2dbd787ceb0a74bea56b8948f3b4190dc"
|
|
9
9
|
});
|
|
10
10
|
//# sourceMappingURL=releaseMetadata.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,8BAA8B,GAA0C,MAAM,CAAC,MAAM,CAAC;IACjG,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,eAAe;IAClC,cAAc,EAAE,sBAAsB;IACtC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,iIAAiI;IACnJ,mBAAmB,EAAE,kEAAkE;CACxF,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface BluetoothSdkReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.3.0\",\n \"releaseIdentity\": \"3.3.0-dev.
|
|
1
|
+
{"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,8BAA8B,GAA0C,MAAM,CAAC,MAAM,CAAC;IACjG,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,eAAe;IAClC,cAAc,EAAE,sBAAsB;IACtC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,iIAAiI;IACnJ,mBAAmB,EAAE,kEAAkE;CACxF,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface BluetoothSdkReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.3.0\",\n \"releaseIdentity\": \"3.3.0-dev.420\",\n \"releaseSetId\": \"mentra-3.3.0-dev.420\",\n \"sourceCommit\": \"cad421d261e3dc99f743ba902a7e0c4a0f42b095\",\n \"otaManifestUrl\": \"https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.420.json\",\n \"otaManifestSha256\": \"0bff87c1bcd2f19eb90079980fc42fe2dbd787ceb0a74bea56b8948f3b4190dc\"\n})\n"]}
|
|
@@ -16,7 +16,7 @@ enum BluetoothSdkDefaults {
|
|
|
16
16
|
/// silently disable it on every pair the app touches.
|
|
17
17
|
static let autoPowerOffEnabled = false
|
|
18
18
|
private static let infoSdkVersionKey = "MentraBluetoothSdkVersion"
|
|
19
|
-
private static let swiftPackageSdkVersion = "3.3.0-dev.
|
|
19
|
+
private static let swiftPackageSdkVersion = "3.3.0-dev.420"
|
|
20
20
|
private static let swiftPackageSdkVersionPlaceholder = "__MENTRA" + "_BLUETOOTH_SDK_VERSION__"
|
|
21
21
|
|
|
22
22
|
private static func normalizedSdkVersion(_ value: String?) -> String? {
|
|
@@ -1535,7 +1535,7 @@ struct ViewState {
|
|
|
1535
1535
|
}
|
|
1536
1536
|
|
|
1537
1537
|
func sendWifiCredentials(_ ssid: String, _ password: String) {
|
|
1538
|
-
Bridge.log("MAN: Sending wifi credentials: \(ssid)
|
|
1538
|
+
Bridge.log("MAN: Sending wifi credentials: \(ssid)")
|
|
1539
1539
|
sgc?.sendWifiCredentials(ssid, password)
|
|
1540
1540
|
}
|
|
1541
1541
|
|
|
@@ -3,9 +3,9 @@ import Foundation
|
|
|
3
3
|
/// Generated by release CI. Do not edit in a release checkout.
|
|
4
4
|
enum GeneratedReleaseMetadata {
|
|
5
5
|
static let familyBaseVersion = "3.3.0"
|
|
6
|
-
static let releaseIdentity = "3.3.0-dev.
|
|
7
|
-
static let releaseSetId = "mentra-3.3.0-dev.
|
|
8
|
-
static let sourceCommit = "
|
|
9
|
-
static let otaManifestUrl = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.
|
|
10
|
-
static let otaManifestSha256 = "
|
|
6
|
+
static let releaseIdentity = "3.3.0-dev.420"
|
|
7
|
+
static let releaseSetId = "mentra-3.3.0-dev.420"
|
|
8
|
+
static let sourceCommit = "cad421d261e3dc99f743ba902a7e0c4a0f42b095"
|
|
9
|
+
static let otaManifestUrl = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.420.json"
|
|
10
|
+
static let otaManifestSha256 = "0bff87c1bcd2f19eb90079980fc42fe2dbd787ceb0a74bea56b8948f3b4190dc"
|
|
11
11
|
}
|
|
@@ -5223,7 +5223,11 @@ class MentraLive: NSObject, SGCManager {
|
|
|
5223
5223
|
bridgeLogging: bridgeLogging
|
|
5224
5224
|
)
|
|
5225
5225
|
}
|
|
5226
|
-
|
|
5226
|
+
// Wi-Fi credentials are sent unchanged but never logged; the BLE trace
|
|
5227
|
+
// above records this command with the password redacted.
|
|
5228
|
+
let loggedPayload = json["password"] == nil
|
|
5229
|
+
? jsonString : "<\(commandInfo.commandType) with credentials omitted>"
|
|
5230
|
+
transportLog("LIVE: Sending data to glasses: \(loggedPayload)", bridgeLogging: bridgeLogging)
|
|
5227
5231
|
let packedData =
|
|
5228
5232
|
packJson(
|
|
5229
5233
|
jsonString,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
@testable import MentraBluetoothSDK
|
|
2
|
+
import XCTest
|
|
3
|
+
|
|
4
|
+
/// Captures packed BLE writes instead of sending them, so the real device dispatch,
|
|
5
|
+
/// command serialization and transport logging run without a radio.
|
|
6
|
+
@MainActor
|
|
7
|
+
private final class CapturingMentraLive: MentraLive {
|
|
8
|
+
var writes: [Data] = []
|
|
9
|
+
|
|
10
|
+
override func queueSend(_ data: Data, id _: String, trace _: BleWriteTrace?) {
|
|
11
|
+
writes.append(data)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@MainActor
|
|
16
|
+
final class WifiCredentialLoggingTests: XCTestCase {
|
|
17
|
+
func testWifiCredentialsReachTheBleQueueWithoutBeingLogged() {
|
|
18
|
+
let ssid = "synthetic-\(UUID().uuidString)"
|
|
19
|
+
let password = UUID().uuidString
|
|
20
|
+
var logs: [String] = []
|
|
21
|
+
let sink = Bridge.addEventSink { event, body in
|
|
22
|
+
if event == "log", let message = body["message"] as? String {
|
|
23
|
+
logs.append(message)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
defer { Bridge.removeEventSink(sink) }
|
|
27
|
+
let manager = DeviceManager()
|
|
28
|
+
let live = CapturingMentraLive()
|
|
29
|
+
manager.sgc = live
|
|
30
|
+
|
|
31
|
+
manager.sendWifiCredentials(ssid, password)
|
|
32
|
+
|
|
33
|
+
XCTAssertFalse(logs.contains { $0.contains(password) }, "password logged")
|
|
34
|
+
XCTAssertTrue(logs.contains("MAN: Sending wifi credentials: \(ssid)"))
|
|
35
|
+
XCTAssertTrue(logs.contains("LIVE: Sending data to glasses: <set_wifi_credentials with credentials omitted>"))
|
|
36
|
+
// The glasses still receive the unchanged credentials.
|
|
37
|
+
let wire = live.writes.map { String(decoding: $0, as: UTF8.self) }.joined()
|
|
38
|
+
XCTAssertTrue(wire.contains("set_wifi_credentials"))
|
|
39
|
+
XCTAssertTrue(wire.contains(ssid))
|
|
40
|
+
XCTAssertTrue(wire.contains(password))
|
|
41
|
+
}
|
|
42
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mentra/bluetooth-sdk",
|
|
3
|
-
"version": "3.3.0-dev.
|
|
3
|
+
"version": "3.3.0-dev.420",
|
|
4
4
|
"description": "SDK for communicating with smart glasses",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"registry": "https://registry.npmjs.org/"
|
|
115
115
|
},
|
|
116
116
|
"dependencies": {
|
|
117
|
-
"@mentra/cloud-protocol": "3.3.0-dev.
|
|
117
|
+
"@mentra/cloud-protocol": "3.3.0-dev.420"
|
|
118
118
|
},
|
|
119
119
|
"devDependencies": {
|
|
120
120
|
"@types/node": "^25.9.3",
|
|
@@ -12,9 +12,9 @@ export interface BluetoothSdkReleaseMetadata {
|
|
|
12
12
|
export const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({
|
|
13
13
|
"schemaVersion": 1,
|
|
14
14
|
"familyBaseVersion": "3.3.0",
|
|
15
|
-
"releaseIdentity": "3.3.0-dev.
|
|
16
|
-
"releaseSetId": "mentra-3.3.0-dev.
|
|
17
|
-
"sourceCommit": "
|
|
18
|
-
"otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.
|
|
19
|
-
"otaManifestSha256": "
|
|
15
|
+
"releaseIdentity": "3.3.0-dev.420",
|
|
16
|
+
"releaseSetId": "mentra-3.3.0-dev.420",
|
|
17
|
+
"sourceCommit": "cad421d261e3dc99f743ba902a7e0c4a0f42b095",
|
|
18
|
+
"otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.420.json",
|
|
19
|
+
"otaManifestSha256": "0bff87c1bcd2f19eb90079980fc42fe2dbd787ceb0a74bea56b8948f3b4190dc"
|
|
20
20
|
})
|