@mentra/bluetooth-sdk 3.2.1-beta.480 → 3.2.1-beta.498

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.
@@ -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.2.1"
6
- const val RELEASE_IDENTITY: String = "3.2.1-beta.480"
7
- const val RELEASE_SET_ID: String = "mentra-3.2.1-beta.480"
8
- const val SOURCE_COMMIT: String = "e7380c4149dfcc4bdd5d344bacede73f0a856213"
9
- const val OTA_MANIFEST_URL: String = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.480.json"
10
- const val OTA_MANIFEST_SHA256: String = "ead3ee204d941bdcea7d77c9ea1d55324fef1328e24a272ba6cf52512a8acae8"
6
+ const val RELEASE_IDENTITY: String = "3.2.1-beta.498"
7
+ const val RELEASE_SET_ID: String = "mentra-3.2.1-beta.498"
8
+ const val SOURCE_COMMIT: String = "d0b2fd5a107a817c0584a590e75e9b5e2de05786"
9
+ const val OTA_MANIFEST_URL: String = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.498.json"
10
+ const val OTA_MANIFEST_SHA256: String = "9e4e4204706f770ab58f656b3526b98a8d696230caaa0405cd3fcbf1f9abfa40"
11
11
  }
@@ -1,10 +1,10 @@
1
1
  export const BLUETOOTH_SDK_RELEASE_METADATA = Object.freeze({
2
2
  "schemaVersion": 1,
3
3
  "familyBaseVersion": "3.2.1",
4
- "releaseIdentity": "3.2.1-beta.480",
5
- "releaseSetId": "mentra-3.2.1-beta.480",
6
- "sourceCommit": "e7380c4149dfcc4bdd5d344bacede73f0a856213",
7
- "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.480.json",
8
- "otaManifestSha256": "ead3ee204d941bdcea7d77c9ea1d55324fef1328e24a272ba6cf52512a8acae8"
4
+ "releaseIdentity": "3.2.1-beta.498",
5
+ "releaseSetId": "mentra-3.2.1-beta.498",
6
+ "sourceCommit": "d0b2fd5a107a817c0584a590e75e9b5e2de05786",
7
+ "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.498.json",
8
+ "otaManifestSha256": "9e4e4204706f770ab58f656b3526b98a8d696230caaa0405cd3fcbf1f9abfa40"
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,gBAAgB;IACnC,cAAc,EAAE,uBAAuB;IACvC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,kIAAkI;IACpJ,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.2.1\",\n \"releaseIdentity\": \"3.2.1-beta.480\",\n \"releaseSetId\": \"mentra-3.2.1-beta.480\",\n \"sourceCommit\": \"e7380c4149dfcc4bdd5d344bacede73f0a856213\",\n \"otaManifestUrl\": \"https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.480.json\",\n \"otaManifestSha256\": \"ead3ee204d941bdcea7d77c9ea1d55324fef1328e24a272ba6cf52512a8acae8\"\n})\n"]}
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,gBAAgB;IACnC,cAAc,EAAE,uBAAuB;IACvC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,kIAAkI;IACpJ,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.2.1\",\n \"releaseIdentity\": \"3.2.1-beta.498\",\n \"releaseSetId\": \"mentra-3.2.1-beta.498\",\n \"sourceCommit\": \"d0b2fd5a107a817c0584a590e75e9b5e2de05786\",\n \"otaManifestUrl\": \"https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.498.json\",\n \"otaManifestSha256\": \"9e4e4204706f770ab58f656b3526b98a8d696230caaa0405cd3fcbf1f9abfa40\"\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.2.1-beta.480"
19
+ private static let swiftPackageSdkVersion = "3.2.1-beta.498"
20
20
  private static let swiftPackageSdkVersionPlaceholder = "__MENTRA" + "_BLUETOOTH_SDK_VERSION__"
21
21
 
22
22
  private static func normalizedSdkVersion(_ value: String?) -> String? {
@@ -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.2.1"
6
- static let releaseIdentity = "3.2.1-beta.480"
7
- static let releaseSetId = "mentra-3.2.1-beta.480"
8
- static let sourceCommit = "e7380c4149dfcc4bdd5d344bacede73f0a856213"
9
- static let otaManifestUrl = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.480.json"
10
- static let otaManifestSha256 = "ead3ee204d941bdcea7d77c9ea1d55324fef1328e24a272ba6cf52512a8acae8"
6
+ static let releaseIdentity = "3.2.1-beta.498"
7
+ static let releaseSetId = "mentra-3.2.1-beta.498"
8
+ static let sourceCommit = "d0b2fd5a107a817c0584a590e75e9b5e2de05786"
9
+ static let otaManifestUrl = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.498.json"
10
+ static let otaManifestSha256 = "9e4e4204706f770ab58f656b3526b98a8d696230caaa0405cd3fcbf1f9abfa40"
11
11
  }
@@ -20,10 +20,6 @@ enum NimoBLE {
20
20
  static let CHAR_RX = CBUUID(string: "00002022-0000-1000-8000-00805F9B34FB")
21
21
  static let CHAR_MIC = CBUUID(string: "00002025-0000-1000-8000-00805F9B34FB")
22
22
 
23
- static let NAME_PREFIX = "nimo"
24
- /// iOS ANCS side-channel devices advertise "<name>_ble" — never the data channel.
25
- static let BLE_NAME_SUFFIX = "_ble"
26
-
27
23
  static let CHUNK_SIZE = 501
28
24
  static let INTER_FRAME_DELAY_MS = 5
29
25
  }
@@ -591,6 +587,27 @@ class Nimo: NSObject, SGCManager {
591
587
  private var rxChar: CBCharacteristic?
592
588
  private var micChar: CBCharacteristic?
593
589
  private var isDisconnecting = false
590
+ private var scanRequested = false
591
+ private lazy var discovery = NimoDiscovery<CBPeripheral>(
592
+ register: { [weak self] in
593
+ #if os(iOS)
594
+ self?.centralManager?.registerForConnectionEvents(options: [.serviceUUIDs: [NimoBLE.SERVICE_UUID]])
595
+ #endif
596
+ }, connected: { [weak self] in
597
+ self?.centralManager?.retrieveConnectedPeripherals(withServices: [NimoBLE.SERVICE_UUID]) ?? []
598
+ }, scan: { [weak self] in
599
+ self?.centralManager?.scanForPeripherals(
600
+ withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: false]
601
+ )
602
+ }, stop: { [weak self] in
603
+ self?.centralManager?.stopScan()
604
+ #if os(iOS)
605
+ self?.centralManager?.registerForConnectionEvents(options: [:])
606
+ #endif
607
+ }, name: { $0.name }, found: { [weak self] peripheral, name, rssi in
608
+ self?.onDeviceFound(peripheral, name: name, rssi: rssi)
609
+ }
610
+ )
594
611
 
595
612
  /// Device search
596
613
  private var DEVICE_SEARCH_ID = "NOT_SET"
@@ -680,6 +697,8 @@ class Nimo: NSObject, SGCManager {
680
697
  func findCompatibleDevices() {
681
698
  Bridge.log("NIMO: findCompatibleDevices()")
682
699
  DEVICE_SEARCH_ID = "NOT_SET"
700
+ isDisconnecting = false
701
+ scanRequested = true
683
702
  DeviceStore.shared.apply("glasses", "connectionState", ConnTypes.SCANNING)
684
703
  startScan()
685
704
  }
@@ -687,6 +706,7 @@ class Nimo: NSObject, SGCManager {
687
706
  func connectById(_ id: String) {
688
707
  Bridge.log("NIMO: connectById(\(id))")
689
708
  DEVICE_SEARCH_ID = id
709
+ scanRequested = true
690
710
  DeviceStore.shared.apply("glasses", "connectionState", ConnTypes.CONNECTING)
691
711
  isDisconnecting = false
692
712
  startPairingTimeout()
@@ -694,7 +714,8 @@ class Nimo: NSObject, SGCManager {
694
714
  }
695
715
 
696
716
  func stopScan() {
697
- centralManager?.stopScan()
717
+ scanRequested = false
718
+ discovery.cancel()
698
719
  }
699
720
 
700
721
  func disconnect() {
@@ -1061,13 +1082,9 @@ class Nimo: NSObject, SGCManager {
1061
1082
 
1062
1083
  // MARK: - BLE Scanning
1063
1084
 
1064
- private func isNimoMainDevice(_ name: String) -> Bool {
1065
- let lower = name.lowercased()
1066
- return lower.hasPrefix(NimoBLE.NAME_PREFIX) && !lower.hasSuffix(NimoBLE.BLE_NAME_SUFFIX)
1067
- }
1068
-
1069
1085
  @discardableResult
1070
1086
  private func startScan() -> Bool {
1087
+ guard scanRequested, !isDisconnecting else { return false }
1071
1088
  Bridge.log("NIMO: startScan()")
1072
1089
  if centralManager == nil {
1073
1090
  centralManager = CBCentralManager(
@@ -1083,17 +1100,32 @@ class Nimo: NSObject, SGCManager {
1083
1100
 
1084
1101
  // Fast path: reconnect to the cached peripheral UUID.
1085
1102
  if connectByUUID() {
1103
+ stopScan()
1086
1104
  return true
1087
1105
  }
1088
1106
 
1089
- centralManager!.scanForPeripherals(
1090
- withServices: nil,
1091
- options: [CBCentralManagerScanOptionAllowDuplicatesKey: false]
1092
- )
1107
+ // NIMO's Companion service is GATT over BR/EDR. The main device must
1108
+ // first be paired in Settings; it does not appear in a BLE-only scan.
1109
+ discovery.start()
1093
1110
  return true
1094
1111
  }
1095
1112
 
1113
+ private func onDeviceFound(_ peripheral: CBPeripheral, name: String, rssi: Int?) {
1114
+ Bridge.log("NIMO: found Companion device: \(name)")
1115
+ Bridge.sendDiscoveredDevice(DeviceTypes.NIMO, name, rssi: rssi)
1116
+ guard DEVICE_SEARCH_ID != "NOT_SET", name == DEVICE_SEARCH_ID,
1117
+ self.peripheral == nil else { return }
1118
+ Bridge.log("NIMO: Connecting to \(name)")
1119
+ stopScan()
1120
+ lastDeviceName = name
1121
+ lastDeviceUUID = peripheral.identifier.uuidString
1122
+ self.peripheral = peripheral
1123
+ peripheral.delegate = self
1124
+ centralManager?.connect(peripheral, options: nil)
1125
+ }
1126
+
1096
1127
  private func connectByUUID() -> Bool {
1128
+ guard peripheral == nil else { return false }
1097
1129
  guard DEVICE_SEARCH_ID != "NOT_SET", !DEVICE_SEARCH_ID.isEmpty else { return false }
1098
1130
  guard lastDeviceName == DEVICE_SEARCH_ID,
1099
1131
  let uuidString = lastDeviceUUID,
@@ -1299,7 +1331,8 @@ class Nimo: NSObject, SGCManager {
1299
1331
  }
1300
1332
  Bridge.log("NIMO: Attempting reconnection...")
1301
1333
  await MainActor.run {
1302
- self.isDisconnecting = false
1334
+ guard !self.isDisconnecting else { return }
1335
+ self.scanRequested = true
1303
1336
  self.startScan()
1304
1337
  }
1305
1338
  return false
@@ -1564,37 +1597,29 @@ extension Nimo: CBCentralManagerDelegate {
1564
1597
  }
1565
1598
 
1566
1599
  nonisolated func centralManager(
1567
- _ central: CBCentralManager,
1600
+ _: CBCentralManager,
1568
1601
  didDiscover peripheral: CBPeripheral,
1569
1602
  advertisementData: [String: Any],
1570
1603
  rssi: NSNumber
1571
1604
  ) {
1572
- guard
1573
- let name = peripheral.name
1574
- ?? advertisementData[CBAdvertisementDataLocalNameKey] as? String
1575
- else { return }
1605
+ let advertisedName = advertisementData[CBAdvertisementDataLocalNameKey] as? String
1576
1606
  let rssiValue = rssi.intValue
1577
-
1578
1607
  DispatchQueue.main.async { [weak self] in
1579
- guard let self else { return }
1580
- guard self.isNimoMainDevice(name) else { return }
1581
-
1582
- Bridge.sendDiscoveredDevice(DeviceTypes.NIMO, name, rssi: rssiValue)
1583
-
1584
- guard self.DEVICE_SEARCH_ID != "NOT_SET" else { return }
1585
- guard name == self.DEVICE_SEARCH_ID else { return }
1586
- guard self.peripheral == nil else { return }
1587
-
1588
- Bridge.log("NIMO: Connecting to \(name)")
1589
- self.stopScan()
1590
- self.lastDeviceName = name
1591
- self.lastDeviceUUID = peripheral.identifier.uuidString
1592
- self.peripheral = peripheral
1593
- peripheral.delegate = self
1594
- central.connect(peripheral, options: nil)
1608
+ self?.discovery.receive(peripheral, advertisedName: advertisedName, rssi: rssiValue)
1595
1609
  }
1596
1610
  }
1597
1611
 
1612
+ #if os(iOS)
1613
+ nonisolated func centralManager(
1614
+ _: CBCentralManager, connectionEventDidOccur event: CBConnectionEvent, for peripheral: CBPeripheral
1615
+ ) {
1616
+ guard event == .peerConnected else { return }
1617
+ DispatchQueue.main.async { [weak self] in
1618
+ self?.discovery.receive(peripheral)
1619
+ }
1620
+ }
1621
+ #endif
1622
+
1598
1623
  nonisolated func centralManager(_: CBCentralManager, didConnect peripheral: CBPeripheral) {
1599
1624
  DispatchQueue.main.async { [weak self] in
1600
1625
  guard let self else { return }
@@ -0,0 +1,49 @@
1
+ import Foundation
2
+
3
+ /// Combines system-connected classic devices with incoming CoreBluetooth discoveries.
4
+ /// Kept independent of the radio so discovery can be exercised without hardware.
5
+ @MainActor
6
+ final class NimoDiscovery<Peripheral> {
7
+ private(set) var active = false
8
+ private let register: () -> Void
9
+ private let connected: () -> [Peripheral]
10
+ private let scan: () -> Void
11
+ private let stop: () -> Void
12
+ private let name: (Peripheral) -> String?
13
+ private let found: (Peripheral, String, Int?) -> Void
14
+
15
+ init(register: @escaping () -> Void, connected: @escaping () -> [Peripheral],
16
+ scan: @escaping () -> Void, stop: @escaping () -> Void,
17
+ name: @escaping (Peripheral) -> String?, found: @escaping (Peripheral, String, Int?) -> Void)
18
+ {
19
+ self.register = register
20
+ self.connected = connected
21
+ self.scan = scan
22
+ self.stop = stop
23
+ self.name = name
24
+ self.found = found
25
+ }
26
+
27
+ func start() {
28
+ active = true
29
+ // Register first so pairing in Settings cannot race the connected snapshot.
30
+ register()
31
+ for peripheral in connected() {
32
+ receive(peripheral)
33
+ }
34
+ if active { scan() }
35
+ }
36
+
37
+ func cancel() {
38
+ active = false
39
+ stop()
40
+ }
41
+
42
+ func receive(_ peripheral: Peripheral, advertisedName: String? = nil, rssi: Int? = nil) {
43
+ guard active, let name = advertisedName ?? name(peripheral) else { return }
44
+ let lower = name.lowercased()
45
+ // The separate ANCS peripheral does not host the Companion data service.
46
+ guard lower.hasPrefix("nimo"), !lower.hasSuffix("_ble") else { return }
47
+ found(peripheral, name, rssi)
48
+ }
49
+ }
@@ -0,0 +1,79 @@
1
+ @testable import MentraBluetoothSDK
2
+ import XCTest
3
+
4
+ @MainActor
5
+ final class NimoDiscoveryTests: XCTestCase {
6
+ @MainActor
7
+ private final class Radio {
8
+ var connected: [String] = []
9
+ var events: [String] = []
10
+ var found: [String] = []
11
+ var selected: String?
12
+ lazy var discovery: NimoDiscovery<String> = NimoDiscovery(
13
+ register: { [unowned self] in self.events.append("register") },
14
+ connected: { [unowned self] in self.events.append("retrieve"); return self.connected },
15
+ scan: { [unowned self] in self.events.append("scan") },
16
+ stop: { [unowned self] in self.events.append("stop") },
17
+ name: { $0 },
18
+ found: { [unowned self] _, name, _ in
19
+ found.append(name)
20
+ if selected == name { discovery.cancel() }
21
+ }
22
+ )
23
+ }
24
+
25
+ func testAlreadyConnectedClassicDeviceIsFoundWithoutAdvertisement() {
26
+ let radio = Radio()
27
+ radio.connected = ["NIMO_1234", "NIMO_1234_BLE", "Unrelated"]
28
+ radio.discovery.start()
29
+ XCTAssertEqual(radio.events, ["register", "retrieve", "scan"])
30
+ XCTAssertEqual(radio.found, ["NIMO_1234"])
31
+ }
32
+
33
+ func testPairingInSettingsAfterScanStartedDeliversDevice() {
34
+ let radio = Radio()
35
+ radio.discovery.start()
36
+ XCTAssertTrue(radio.found.isEmpty)
37
+ // Same entry point as connectionEventDidOccur(.peerConnected).
38
+ radio.discovery.receive("NIMO_5678")
39
+ XCTAssertEqual(radio.found, ["NIMO_5678"])
40
+ }
41
+
42
+ func testSelectionFromConnectedSnapshotStopsBeforeStartingBleScan() {
43
+ let radio = Radio()
44
+ radio.selected = "NIMO_5678"
45
+ radio.connected = ["NIMO_1234", "NIMO_5678", "NIMO_9999"]
46
+ radio.discovery.start()
47
+ XCTAssertEqual(radio.found, ["NIMO_1234", "NIMO_5678"])
48
+ XCTAssertEqual(radio.events, ["register", "retrieve", "stop"])
49
+ XCTAssertFalse(radio.discovery.active)
50
+ }
51
+
52
+ func testCancelledDiscoveryIgnoresQueuedEventsAndCanRestart() {
53
+ let radio = Radio()
54
+ radio.discovery.start()
55
+ radio.discovery.cancel()
56
+ radio.discovery.receive("NIMO_1234")
57
+ XCTAssertTrue(radio.found.isEmpty)
58
+ radio.connected = ["NIMO_1234"]
59
+ radio.discovery.start()
60
+ XCTAssertEqual(radio.found, ["NIMO_1234"])
61
+ }
62
+
63
+ func testBleFallbackUsesAdvertisementNameAndPreservesSignalStrength() {
64
+ var found: [String] = []
65
+ var signal: Int?
66
+ let discovery = NimoDiscovery<String>(
67
+ register: {}, connected: { [] }, scan: {}, stop: {}, name: { _ in nil },
68
+ found: { _, name, rssi in found.append(name); signal = rssi }
69
+ )
70
+ discovery.start()
71
+ discovery.receive("uuid", advertisedName: "NiMo_1234_bLe", rssi: -60)
72
+ discovery.receive("uuid", advertisedName: "Unrelated", rssi: -60)
73
+ discovery.receive("uuid")
74
+ XCTAssertTrue(found.isEmpty)
75
+ discovery.receive("uuid", advertisedName: "NiMo_1234", rssi: -55)
76
+ XCTAssertEqual(found, ["NiMo_1234"])
77
+ XCTAssertEqual(signal, -55)
78
+ }
79
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentra/bluetooth-sdk",
3
- "version": "3.2.1-beta.480",
3
+ "version": "3.2.1-beta.498",
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.2.1-beta.480"
117
+ "@mentra/cloud-protocol": "3.2.1-beta.498"
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.2.1",
15
- "releaseIdentity": "3.2.1-beta.480",
16
- "releaseSetId": "mentra-3.2.1-beta.480",
17
- "sourceCommit": "e7380c4149dfcc4bdd5d344bacede73f0a856213",
18
- "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.480.json",
19
- "otaManifestSha256": "ead3ee204d941bdcea7d77c9ea1d55324fef1328e24a272ba6cf52512a8acae8"
15
+ "releaseIdentity": "3.2.1-beta.498",
16
+ "releaseSetId": "mentra-3.2.1-beta.498",
17
+ "sourceCommit": "d0b2fd5a107a817c0584a590e75e9b5e2de05786",
18
+ "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.2.1/mentra-live-ota-3.2.1-beta.498.json",
19
+ "otaManifestSha256": "9e4e4204706f770ab58f656b3526b98a8d696230caaa0405cd3fcbf1f9abfa40"
20
20
  })