@glassly/bluetooth-sdk 0.1.0-dev.89 → 0.1.0-dev.96

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.
Files changed (26) hide show
  1. package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedChangelogCatalog.kt +1 -0
  2. package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt +3 -3
  3. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1.kt +8 -49
  4. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2.kt +3 -2
  5. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Mach1.kt +0 -13
  6. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLive.kt +11 -86
  7. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraNex.kt +1 -4
  8. package/android/src/main/java/com/glassly/bluetoothsdk/stt/VadGateSpeechPolicy.kt +0 -2
  9. package/build/generated/changelogCatalog.d.ts +3 -0
  10. package/build/generated/changelogCatalog.d.ts.map +1 -1
  11. package/build/generated/changelogCatalog.js +4 -0
  12. package/build/generated/changelogCatalog.js.map +1 -1
  13. package/build/generated/releaseMetadata.js +3 -3
  14. package/build/generated/releaseMetadata.js.map +1 -1
  15. package/ios/Source/BluetoothSdkDefaults.swift +1 -1
  16. package/ios/Source/DeviceManager.swift +5 -7
  17. package/ios/Source/GeneratedChangelogCatalog.swift +1 -0
  18. package/ios/Source/GeneratedReleaseMetadata.swift +3 -3
  19. package/ios/Source/sgcs/G2.swift +3 -10
  20. package/ios/Source/sgcs/MentraLive.swift +4 -4
  21. package/ios/Source/sgcs/MentraNex.swift +43 -44
  22. package/ios/Source/tts/TTSTools.swift +0 -4
  23. package/package.json +1 -1
  24. package/src/generated/changelogCatalog.ts +4 -0
  25. package/src/generated/releaseMetadata.ts +3 -3
  26. package/ios/Source/sgcs/Frame.swift +0 -649
@@ -424,24 +424,24 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
424
424
  private let INITIAL_CONNECTION_DELAY_MS: UInt64 = 350
425
425
  private let DELAY_BETWEEN_CHUNKS_SEND_MS: UInt64 = 10
426
426
 
427
- // Heartbeat tracking (like Java implementation)
427
+ // Heartbeat tracking
428
428
  private var heartbeatCount = 0
429
429
  private var lastHeartbeatSentTime: TimeInterval = 0
430
430
  private var lastHeartbeatReceivedTime: TimeInterval = 0
431
431
 
432
- // Microphone beat system (like Java implementation)
432
+ // Microphone beat system
433
433
  private var micBeatTimer: Timer?
434
434
  private var micBeatCount = 0
435
- private let MICBEAT_INTERVAL_MS: TimeInterval = 30 * 60 // 30 minutes like Java
435
+ private let MICBEAT_INTERVAL_MS: TimeInterval = 30 * 60 // 30 minutes
436
436
  private var shouldUseGlassesMic = true
437
437
  private var isMicrophoneEnabled = true
438
438
  private var microphoneStateBeforeDisconnection = false
439
439
 
440
- // Whitelist system (like Java implementation)
440
+ // Whitelist system
441
441
  private var whiteListedAlready = false
442
442
  private let WHITELIST_CMD: UInt8 = 0x04
443
443
 
444
- /// Protobuf version tracking (like Java implementation)
444
+ /// Protobuf version tracking
445
445
  private var protobufVersionPosted = false
446
446
 
447
447
  /// Device discovery cache (like MentraLive)
@@ -485,13 +485,13 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
485
485
  @Published var lastHeadGesture: String = ""
486
486
  @Published var headUpAngle: Int = 0
487
487
 
488
- // Enhanced device persistence (from Java implementation)
488
+ // Enhanced device persistence
489
489
  private let PREFS_DEVICE_NAME = "MentraNexLastConnectedDeviceName"
490
490
  private let PREFS_DEVICE_ADDRESS = "MentraNexLastConnectedDeviceAddress"
491
491
  private let PREFS_DEVICE_ID = "SavedNexIdKey"
492
492
  private let SHARED_PREFS_NAME = "NexGlassesPrefs"
493
493
 
494
- // Device state tracking (ported from Java)
494
+ // Device state tracking
495
495
  private var savedDeviceName: String?
496
496
  private var savedDeviceAddress: String?
497
497
  private var preferredDeviceId: String?
@@ -640,7 +640,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
640
640
  super.init()
641
641
  Bridge.log("NEX: 🚀 MentraNexSGC initialization started")
642
642
 
643
- // Load saved device information (from Java implementation)
643
+ // Load saved device information
644
644
  loadSavedDeviceInfo()
645
645
 
646
646
  // Using custom Bluetooth queue for better performance (like G1)
@@ -859,7 +859,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
859
859
  }
860
860
  }
861
861
 
862
- // MARK: - Device Persistence (ported from Java)
862
+ // MARK: - Device Persistence
863
863
 
864
864
  private func loadSavedDeviceInfo() {
865
865
  savedDeviceName = UserDefaults.standard.string(forKey: PREFS_DEVICE_NAME)
@@ -904,7 +904,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
904
904
  Bridge.log("NEX: 🗑️ Cleared all saved device information")
905
905
  }
906
906
 
907
- // MARK: - Enhanced Device Filtering (ported from Java)
907
+ // MARK: - Enhanced Device Filtering
908
908
 
909
909
  private func isCompatibleNexDevice(_ deviceName: String) -> Bool {
910
910
  // Keep in parity with Android MentraNex.kt scan filter.
@@ -924,7 +924,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
924
924
  }
925
925
 
926
926
  private func extractDeviceId(from deviceName: String) -> String? {
927
- // Extract device ID pattern similar to Java implementation
927
+ // Extract device ID pattern
928
928
  let patterns = [
929
929
  "Glassly_([0-9A-Fa-f]+)",
930
930
  "NEX_([0-9A-Fa-f]+)",
@@ -2328,7 +2328,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2328
2328
  lastHeartbeatReceivedTime
2329
2329
  }
2330
2330
 
2331
- // MARK: - Java-Compatible Initialization Methods
2331
+ // MARK: - Initialization Methods
2332
2332
 
2333
2333
  private func startMicBeat() {
2334
2334
  Bridge.log("NEX: Starting micbeat (30 min interval)")
@@ -2340,7 +2340,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2340
2340
  sendSetMicEnabled(true, delaySeconds: 0.01)
2341
2341
  micBeatCount += 1
2342
2342
 
2343
- // Schedule periodic mic beat (like Java lines 1753-1762)
2343
+ // Schedule periodic mic beat
2344
2344
  micBeatTimer = Timer.scheduledTimer(withTimeInterval: MICBEAT_INTERVAL_MS, repeats: true) {
2345
2345
  [weak self] _ in
2346
2346
  guard let self else { return }
@@ -2372,18 +2372,18 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2372
2372
 
2373
2373
  Bridge.log("NEX: Sending whitelist command")
2374
2374
 
2375
- // Create whitelist JSON exactly like Java (lines 2642-2680)
2375
+ // Create whitelist JSON
2376
2376
  let whitelistJson = createWhitelistJson()
2377
2377
  let chunks = createWhitelistChunks(json: whitelistJson)
2378
2378
 
2379
- // Send chunks with delay like Java
2379
+ // Send chunks with delay
2380
2380
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { // 10ms delay
2381
2381
  self.queueChunks(chunks)
2382
2382
  }
2383
2383
  }
2384
2384
 
2385
2385
  private func createWhitelistJson() -> String {
2386
- // Exact JSON structure from Java implementation (lines 2653-2680)
2386
+ // Exact JSON structure
2387
2387
  let whitelistDict: [String: Any] = [
2388
2388
  "calendar_enable": false,
2389
2389
  "call_enable": false,
@@ -2411,7 +2411,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2411
2411
  }
2412
2412
 
2413
2413
  private func createWhitelistChunks(json: String) -> [[UInt8]] {
2414
- // Exact chunking logic from Java (lines 2703-2728)
2414
+ // Chunking must match the glasses' reassembly exactly.
2415
2415
  guard let jsonData = json.data(using: .utf8) else { return [] }
2416
2416
 
2417
2417
  let totalChunks = Int(ceil(Double(jsonData.count) / Double(maxChunkSize)))
@@ -2422,14 +2422,13 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2422
2422
  let end = min(start + maxChunkSize, jsonData.count)
2423
2423
  let payloadChunk = jsonData.subdata(in: start ..< end)
2424
2424
 
2425
- // Create header: [WHITELIST_CMD, total_chunks, chunk_index] (Java lines 2714-2717)
2425
+ // Create header: [WHITELIST_CMD, total_chunks, chunk_index]
2426
2426
  var header: [UInt8] = [
2427
2427
  WHITELIST_CMD, // Command ID (0x04)
2428
2428
  UInt8(totalChunks), // Total number of chunks
2429
2429
  UInt8(i), // Current chunk index
2430
2430
  ]
2431
2431
 
2432
- // Combine header and payload (Java lines 2720-2725)
2433
2432
  header.append(contentsOf: payloadChunk)
2434
2433
  chunks.append(header)
2435
2434
  }
@@ -2447,7 +2446,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2447
2446
 
2448
2447
  Bridge.log("NEX: 📋 Posting protobuf schema version info")
2449
2448
 
2450
- // Emit protobuf schema version event like Java (lines 3709-3728)
2449
+ // Emit protobuf schema version event
2451
2450
  let eventBody: [String: Any] = [
2452
2451
  "protobuf_schema_version": [
2453
2452
  "schema_version": 1, // Default version
@@ -2459,7 +2458,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2459
2458
  // emitEvent("ProtobufSchemaVersionEvent", body: eventBody)
2460
2459
  }
2461
2460
 
2462
- /// Save microphone state before disconnection (like Java implementation)
2461
+ /// Save microphone state before disconnection
2463
2462
  private func saveMicrophoneStateBeforeDisconnection() {
2464
2463
  UserDefaults.standard.set(isMicrophoneEnabled, forKey: "microphoneStateBeforeDisconnection")
2465
2464
  microphoneStateBeforeDisconnection = isMicrophoneEnabled
@@ -2501,7 +2500,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2501
2500
 
2502
2501
  private func finalizeDisconnect() {
2503
2502
  if let peripheral {
2504
- // Save microphone state before disconnection (like Java implementation)
2503
+ // Save microphone state before disconnection
2505
2504
  saveMicrophoneStateBeforeDisconnection()
2506
2505
 
2507
2506
  // Stop mic beat system
@@ -2519,7 +2518,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2519
2518
  stopTextWallDrain()
2520
2519
  }
2521
2520
 
2522
- // MARK: - Lifecycle Management (ported from Java)
2521
+ // MARK: - Lifecycle Management
2523
2522
 
2524
2523
  @objc func destroy() {
2525
2524
  // Route through the shared path so forget()/cleanup() also signal an
@@ -2534,10 +2533,10 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2534
2533
  isDisconnecting = true
2535
2534
 
2536
2535
  // Stop all timers
2537
- // Save microphone state before destruction (like Java implementation)
2536
+ // Save microphone state before destruction
2538
2537
  saveMicrophoneStateBeforeDisconnection()
2539
2538
 
2540
- // Stop mic beat system (like Java implementation)
2539
+ // Stop mic beat system
2541
2540
  stopMicBeat()
2542
2541
 
2543
2542
  stopReconnectionTimer()
@@ -2600,7 +2599,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2600
2599
  peripheralToConnectName = nil
2601
2600
 
2602
2601
  Bridge.log("NEX: ✅ Reset complete - ready for fresh pairing")
2603
- // Reset initialization flags (like Java implementation)
2602
+ // Reset initialization flags
2604
2603
  whiteListedAlready = false
2605
2604
  protobufVersionPosted = false
2606
2605
  heartbeatCount = 0
@@ -2723,7 +2722,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2723
2722
  // Always emit the discovered device for the UI list
2724
2723
  emitDiscoveredDevice(deviceName)
2725
2724
 
2726
- // Auto-connect logic based on target or saved device (from Java MentraNexSGC)
2725
+ // Auto-connect logic based on target or saved device
2727
2726
  var shouldConnect = false
2728
2727
  var connectionReason = ""
2729
2728
 
@@ -2780,7 +2779,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2780
2779
  connectionState = ConnTypes.CONNECTING
2781
2780
  DeviceStore.shared.apply("glasses", "connectionState", ConnTypes.CONNECTING)
2782
2781
 
2783
- // Use connection options for better reliability (from Java implementation)
2782
+ // Use connection options for better reliability
2784
2783
  let connectionOptions: [String: Any] = [
2785
2784
  CBConnectPeripheralOptionNotifyOnConnectionKey: true,
2786
2785
  CBConnectPeripheralOptionNotifyOnDisconnectionKey: true,
@@ -2798,7 +2797,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2798
2797
  peripheralUUID = peripheral.identifier // Persist UUID
2799
2798
  stopReconnectionTimer() // Successfully connected, stop trying to reconnect.
2800
2799
 
2801
- // Enhanced device info saving (from Java implementation)
2800
+ // Enhanced device info saving
2802
2801
  let deviceName = peripheral.name
2803
2802
  let deviceAddress = peripheral.identifier.uuidString
2804
2803
 
@@ -2861,7 +2860,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2861
2860
  currentLayoutId = nil
2862
2861
 
2863
2862
  // Reset connection state
2864
- // Save microphone state before disconnection (like Java implementation)
2863
+ // Save microphone state before disconnection
2865
2864
  saveMicrophoneStateBeforeDisconnection()
2866
2865
  setServicesReady(false)
2867
2866
  releaseServiceWaiters()
@@ -2869,10 +2868,10 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2869
2868
  resumePendingWrite()
2870
2869
  resumePendingAck()
2871
2870
 
2872
- // Reset protobuf version posted flag for next connection (like Java implementation)
2871
+ // Reset protobuf version posted flag for next connection
2873
2872
  protobufVersionPosted = false
2874
2873
 
2875
- // Stop mic beat system (like Java implementation)
2874
+ // Stop mic beat system
2876
2875
  stopMicBeat()
2877
2876
  stopTextWallDrain()
2878
2877
 
@@ -2915,7 +2914,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2915
2914
  if !isDisconnecting, !isKilled {
2916
2915
  Bridge.log("NEX-CONN: 🔄 Unintentional disconnect detected. Attempting reconnection...")
2917
2916
 
2918
- // Enhanced reconnection strategy from Java implementation
2917
+ // Enhanced reconnection strategy
2919
2918
  if let savedName = savedDeviceName {
2920
2919
  Bridge.log("NEX-CONN: 🎯 Will attempt to reconnect to saved device: \(savedName)")
2921
2920
  }
@@ -2962,7 +2961,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
2962
2961
  // Process MTU result immediately (iOS doesn't have callback like Android)
2963
2962
  onMTUNegotiated(mtu: validatedMTU, success: true)
2964
2963
 
2965
- // After MTU is set, start device initialization sequence (from Java implementation)
2964
+ // After MTU is set, start device initialization sequence
2966
2965
  initializeNexDevice()
2967
2966
  }
2968
2967
 
@@ -3022,20 +3021,20 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
3022
3021
  // emitDeviceReady()
3023
3022
  }
3024
3023
 
3025
- // MARK: - Device Initialization (ported from Java MentraNexSGC)
3024
+ // MARK: - Device Initialization
3026
3025
 
3027
3026
  private func initializeNexDevice() {
3028
3027
  Bridge.log("NEX-CONN: 🚀 Starting Nex device initialization (matching Java sequence)")
3029
3028
 
3030
- // Exact Java initialization sequence from lines 648-691:
3029
+ // Staggered init sequence; the glasses drop commands issued back-to-back.
3031
3030
 
3032
- // 1. Do first battery status query (Java line 650)
3033
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { // 10ms delay like Java
3031
+ // 1. Do first battery status query
3032
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { // 10ms delay
3034
3033
  Bridge.log("NEX: 🔋 Sending first battery status query")
3035
3034
  self.queryBatteryStatus()
3036
3035
  }
3037
3036
 
3038
- // 2. Restore previous microphone state (Java lines 657-665)
3037
+ // 2. Restore previous microphone state
3039
3038
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.02) { // 20ms delay
3040
3039
  let shouldRestoreMic = UserDefaults.standard.bool(
3041
3040
  forKey: "microphoneStateBeforeDisconnection"
@@ -3049,22 +3048,22 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
3049
3048
  }
3050
3049
  }
3051
3050
 
3052
- // 3. Enable AugmentOS notification key (Java line 668)
3051
+ // 3. Enable the notification whitelist key
3053
3052
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.03) { // 30ms delay
3054
3053
  self.sendWhiteListCommand()
3055
3054
  }
3056
3055
 
3057
- // 4. Show home screen to turn on the NexGlasses display (Java line 673)
3056
+ // 4. Show home screen to turn on the NexGlasses display
3058
3057
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { // 50ms delay
3059
3058
  self.showHomeScreen()
3060
3059
  }
3061
3060
 
3062
- // 5. Post protobuf schema version information (Java lines 684-687)
3061
+ // 5. Post protobuf schema version information
3063
3062
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // 100ms delay
3064
3063
  self.postProtobufSchemaVersionInfo()
3065
3064
  }
3066
3065
 
3067
- // 6. Version request is removed in current schema; Android sends no-op.
3066
+ // 6. No version request: the schema has no VersionRequest (Android no-ops too).
3068
3067
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
3069
3068
  Bridge.log("NEX: Skipping version request; schema removed VersionRequest")
3070
3069
  }
@@ -3146,7 +3145,7 @@ class MentraNexSGC: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, SG
3146
3145
  "NEX-CONN: ✅ All required characteristics discovered. Proceeding to MTU negotiation."
3147
3146
  )
3148
3147
 
3149
- // Start MTU negotiation like Java implementation
3148
+ // Start MTU negotiation implementation
3150
3149
  requestOptimalMTU(for: peripheral)
3151
3150
  }
3152
3151
  }
@@ -131,10 +131,6 @@ class TTSTools {
131
131
  let clampedSpeed = Float(min(max(speed, 0.5), 2.0))
132
132
  let lang = languageTagToSupertonicLang(getTtsModelLanguage())
133
133
 
134
- // generate(...) no longer accepts `extra`; that field moved onto
135
- // SherpaOnnxGenerationConfigSwift and is delivered via
136
- // generateWithConfig(...).
137
- //
138
134
  // numSteps controls the Supertonic flow-matching vocoder's
139
135
  // iteration count. The Swift wrapper defaults to 1, which produces
140
136
  // unintelligible robot audio — sherpa-onnx's actual C-side default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassly/bluetooth-sdk",
3
- "version": "0.1.0-dev.89",
3
+ "version": "0.1.0-dev.96",
4
4
  "description": "SDK for communicating with smart glasses",
5
5
  "main": "build/index.js",
6
6
  "react-native": "src/index.ts",
@@ -1,6 +1,10 @@
1
1
  /** Generated from /changelogs. Do not edit directly. */
2
2
  export const GENERATED_RELEASE_CHANGELOGS = Object.freeze(
3
3
  [
4
+ {
5
+ "version": "3.2.0",
6
+ "markdown": "This release is under active development. User-facing changes will be documented as they land."
7
+ },
4
8
  {
5
9
  "version": "3.1.0",
6
10
  "markdown": "Software updates are more reliable, with clearer progress and recovery when the glasses restart.\n\n- GlasslyOS, Glassly Engine, the Bluetooth SDK, and the glasses client now share one coordinated release version.\n- Mentra Live updates can continue across APK, system, and firmware restarts without asking the user to start the same update again.\n- Bluetooth photo capture and transfer diagnostics are more precise and less disruptive to normal glasses traffic."
@@ -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": "0.1.0",
15
- "releaseIdentity": "0.1.0-dev.89",
16
- "releaseSetId": "glassly-0.1.0-dev.89",
17
- "sourceCommit": "c66a621d66d70251e257f73c9a79ee1f8e079be9",
15
+ "releaseIdentity": "0.1.0-dev.96",
16
+ "releaseSetId": "glassly-0.1.0-dev.96",
17
+ "sourceCommit": "440518cf281588df779cd13d78922782db027ad4",
18
18
  "otaManifestUrl": null,
19
19
  "otaManifestSha256": null
20
20
  })