munim-bluetooth 0.3.23 → 0.3.25

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 (28) hide show
  1. package/android/src/main/AndroidManifest.xml +10 -0
  2. package/android/src/main/java/com/munimbluetooth/HybridMunimBluetooth.kt +87 -0
  3. package/android/src/main/java/com/munimbluetooth/MunimBluetoothBackgroundService.kt +344 -0
  4. package/ios/HybridMunimBluetooth.swift +361 -47
  5. package/lib/commonjs/index.js +21 -0
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/module/index.js +19 -0
  8. package/lib/module/index.js.map +1 -1
  9. package/lib/typescript/src/index.d.ts +15 -2
  10. package/lib/typescript/src/index.d.ts.map +1 -1
  11. package/lib/typescript/src/specs/munim-bluetooth.nitro.d.ts +25 -3
  12. package/lib/typescript/src/specs/munim-bluetooth.nitro.d.ts.map +1 -1
  13. package/nitrogen/generated/android/c++/JBackgroundSessionOptions.hpp +107 -0
  14. package/nitrogen/generated/android/c++/JHybridMunimBluetoothSpec.cpp +12 -0
  15. package/nitrogen/generated/android/c++/JHybridMunimBluetoothSpec.hpp +2 -0
  16. package/nitrogen/generated/android/kotlin/com/margelo/nitro/munimbluetooth/BackgroundSessionOptions.kt +59 -0
  17. package/nitrogen/generated/android/kotlin/com/margelo/nitro/munimbluetooth/HybridMunimBluetoothSpec.kt +28 -20
  18. package/nitrogen/generated/ios/MunimBluetooth-Swift-Cxx-Umbrella.hpp +3 -0
  19. package/nitrogen/generated/ios/c++/HybridMunimBluetoothSpecSwift.hpp +15 -0
  20. package/nitrogen/generated/ios/swift/BackgroundSessionOptions.swift +154 -0
  21. package/nitrogen/generated/ios/swift/HybridMunimBluetoothSpec.swift +2 -0
  22. package/nitrogen/generated/ios/swift/HybridMunimBluetoothSpec_cxx.swift +43 -21
  23. package/nitrogen/generated/shared/c++/BackgroundSessionOptions.hpp +115 -0
  24. package/nitrogen/generated/shared/c++/HybridMunimBluetoothSpec.cpp +2 -0
  25. package/nitrogen/generated/shared/c++/HybridMunimBluetoothSpec.hpp +5 -0
  26. package/package.json +1 -1
  27. package/src/index.ts +23 -0
  28. package/src/specs/munim-bluetooth.nitro.ts +28 -3
@@ -10,6 +10,93 @@ import CoreBluetooth
10
10
  import NitroModules
11
11
  import React
12
12
 
13
+ private let centralRestoreIdentifier = "com.munimbluetooth.central"
14
+ private let peripheralRestoreIdentifier = "com.munimbluetooth.peripheral"
15
+
16
+ private final class PeripheralManagerDelegateProxy: NSObject, CBPeripheralManagerDelegate {
17
+ weak var owner: HybridMunimBluetooth?
18
+
19
+ init(owner: HybridMunimBluetooth) {
20
+ self.owner = owner
21
+ }
22
+
23
+ func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
24
+ owner?.handlePeripheralManagerDidUpdateState(peripheral)
25
+ }
26
+
27
+ func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
28
+ owner?.handlePeripheralManagerDidStartAdvertising(peripheral, error: error)
29
+ }
30
+
31
+ func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
32
+ owner?.handlePeripheralManagerDidAddService(peripheral, service: service, error: error)
33
+ }
34
+
35
+ func peripheralManager(_ peripheral: CBPeripheralManager, willRestoreState dict: [String : Any]) {
36
+ owner?.handlePeripheralManagerWillRestoreState(peripheral, state: dict)
37
+ }
38
+ }
39
+
40
+ private final class CentralManagerDelegateProxy: NSObject, CBCentralManagerDelegate {
41
+ weak var owner: HybridMunimBluetooth?
42
+
43
+ init(owner: HybridMunimBluetooth) {
44
+ self.owner = owner
45
+ }
46
+
47
+ func centralManagerDidUpdateState(_ central: CBCentralManager) {
48
+ owner?.handleCentralManagerDidUpdateState(central)
49
+ }
50
+
51
+ func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
52
+ owner?.handleCentralManagerWillRestoreState(central, state: dict)
53
+ }
54
+
55
+ func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
56
+ owner?.handleCentralManagerDidDiscover(central, peripheral: peripheral, advertisementData: advertisementData, rssi: RSSI)
57
+ }
58
+
59
+ func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
60
+ owner?.handleCentralManagerDidConnect(central, peripheral: peripheral)
61
+ }
62
+
63
+ func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
64
+ owner?.handleCentralManagerDidDisconnectPeripheral(central, peripheral: peripheral, error: error)
65
+ }
66
+
67
+ func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
68
+ owner?.handleCentralManagerDidFailToConnect(central, peripheral: peripheral, error: error)
69
+ }
70
+ }
71
+
72
+ private final class PeripheralDelegateProxy: NSObject, CBPeripheralDelegate {
73
+ weak var owner: HybridMunimBluetooth?
74
+
75
+ init(owner: HybridMunimBluetooth) {
76
+ self.owner = owner
77
+ }
78
+
79
+ func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
80
+ owner?.handlePeripheralDidDiscoverServices(peripheral, error: error)
81
+ }
82
+
83
+ func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
84
+ owner?.handlePeripheralDidDiscoverCharacteristics(peripheral, service: service, error: error)
85
+ }
86
+
87
+ func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
88
+ owner?.handlePeripheralDidUpdateValue(peripheral, characteristic: characteristic, error: error)
89
+ }
90
+
91
+ func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
92
+ owner?.handlePeripheralDidWriteValue(peripheral, characteristic: characteristic, error: error)
93
+ }
94
+
95
+ func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
96
+ owner?.handlePeripheralDidReadRSSI(peripheral, rssi: RSSI, error: error)
97
+ }
98
+ }
99
+
13
100
  class HybridMunimBluetooth: HybridMunimBluetoothSpec {
14
101
  // Peripheral Manager
15
102
  private var peripheralManager: CBPeripheralManager?
@@ -21,13 +108,34 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
21
108
  private var discoveredPeripherals: [String: CBPeripheral] = [:]
22
109
  private var connectedPeripherals: [String: CBPeripheral] = [:]
23
110
  private var peripheralCharacteristics: [String: [CBCharacteristic]] = [:]
111
+ private var pendingConnectionPromises: [String: Promise<Void>] = [:]
112
+ private var pendingServiceDiscoveryPromises: [String: Promise<[GATTService]>] = [:]
113
+ private var pendingCharacteristicDiscoveryCounts: [String: Int] = [:]
114
+ private var pendingReadPromises: [String: Promise<CharacteristicValue>] = [:]
115
+ private var pendingRSSIPromises: [String: Promise<Double>] = [:]
24
116
  private var scanOptions: ScanOptions?
25
117
  private var isScanning = false
118
+ private var isBackgroundSessionActive = false
119
+ private lazy var peripheralManagerDelegateProxy = PeripheralManagerDelegateProxy(owner: self)
120
+ private lazy var centralManagerDelegateProxy = CentralManagerDelegateProxy(owner: self)
121
+ private lazy var peripheralDelegateProxy = PeripheralDelegateProxy(owner: self)
26
122
 
27
123
  override init() {
28
124
  super.init()
29
- peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
30
- centralManager = CBCentralManager(delegate: self, queue: nil)
125
+ peripheralManager = CBPeripheralManager(
126
+ delegate: peripheralManagerDelegateProxy,
127
+ queue: nil,
128
+ options: [
129
+ CBPeripheralManagerOptionRestoreIdentifierKey: peripheralRestoreIdentifier
130
+ ]
131
+ )
132
+ centralManager = CBCentralManager(
133
+ delegate: centralManagerDelegateProxy,
134
+ queue: nil,
135
+ options: [
136
+ CBCentralManagerOptionRestoreIdentifierKey: centralRestoreIdentifier
137
+ ]
138
+ )
31
139
  }
32
140
 
33
141
  // MARK: - Event Emission
@@ -287,8 +395,12 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
287
395
  if let options = options {
288
396
  scanOptions[CBCentralManagerScanOptionAllowDuplicatesKey] = options.allowDuplicates ?? false
289
397
  }
290
-
291
- centralManager.scanForPeripherals(withServices: nil, options: scanOptions as [String : Any])
398
+
399
+ let serviceUUIDs = options?.serviceUUIDs?.map { CBUUID(string: $0) }
400
+ centralManager.scanForPeripherals(
401
+ withServices: serviceUUIDs?.isEmpty == false ? serviceUUIDs : nil,
402
+ options: scanOptions as [String : Any]
403
+ )
292
404
  }
293
405
 
294
406
  func stopScan() throws {
@@ -298,14 +410,19 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
298
410
 
299
411
  func connect(deviceId: String) throws -> Promise<Void> {
300
412
  let promise = Promise<Void>()
413
+ if connectedPeripherals[deviceId] != nil {
414
+ promise.resolve(withResult: ())
415
+ return promise
416
+ }
417
+
301
418
  guard let peripheral = self.discoveredPeripherals[deviceId] else {
302
419
  promise.reject(withError: NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Device not found"]))
303
420
  return promise
304
421
  }
305
-
422
+
423
+ pendingConnectionPromises[deviceId] = promise
424
+ peripheral.delegate = peripheralDelegateProxy
306
425
  self.centralManager?.connect(peripheral, options: nil)
307
- self.connectedPeripherals[deviceId] = peripheral
308
- promise.resolve(withResult: ())
309
426
  return promise
310
427
  }
311
428
 
@@ -313,6 +430,7 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
313
430
  guard let peripheral = connectedPeripherals[deviceId] else { return }
314
431
  centralManager?.cancelPeripheralConnection(peripheral)
315
432
  connectedPeripherals.removeValue(forKey: deviceId)
433
+ rejectPendingOperations(for: deviceId, error: NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Disconnected from \(deviceId)"]))
316
434
  }
317
435
 
318
436
  func discoverServices(deviceId: String) throws -> Promise<[GATTService]> {
@@ -321,15 +439,37 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
321
439
  promise.reject(withError: NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Device not connected"]))
322
440
  return promise
323
441
  }
324
-
442
+
443
+ if let services = peripheral.services,
444
+ services.allSatisfy({ $0.characteristics != nil }) {
445
+ promise.resolve(withResult: buildGATTServices(from: services))
446
+ return promise
447
+ }
448
+
449
+ pendingServiceDiscoveryPromises[deviceId] = promise
325
450
  peripheral.discoverServices(nil)
326
- promise.resolve(withResult: [])
327
451
  return promise
328
452
  }
329
453
 
330
454
  func readCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String) throws -> Promise<CharacteristicValue> {
331
455
  let promise = Promise<CharacteristicValue>()
332
- promise.reject(withError: NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Not implemented"]))
456
+
457
+ guard let peripheral = connectedPeripherals[deviceId] else {
458
+ promise.reject(withError: NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Device not connected"]))
459
+ return promise
460
+ }
461
+
462
+ guard let characteristic = findCharacteristic(
463
+ deviceId: deviceId,
464
+ serviceUUID: serviceUUID,
465
+ characteristicUUID: characteristicUUID
466
+ ) else {
467
+ promise.reject(withError: NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Characteristic not found"]))
468
+ return promise
469
+ }
470
+
471
+ pendingReadPromises[characteristicKey(deviceId: deviceId, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID)] = promise
472
+ peripheral.readValue(for: characteristic)
333
473
  return promise
334
474
  }
335
475
 
@@ -359,11 +499,37 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
359
499
  promise.reject(withError: NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Device not connected"]))
360
500
  return promise
361
501
  }
362
-
502
+
503
+ pendingRSSIPromises[deviceId] = promise
363
504
  peripheral.readRSSI()
364
- promise.resolve(withResult: 0)
365
505
  return promise
366
506
  }
507
+
508
+ func startBackgroundSession(options: BackgroundSessionOptions) throws {
509
+ isBackgroundSessionActive = true
510
+
511
+ let advertisingOptions = AdvertisingOptions(
512
+ serviceUUIDs: options.serviceUUIDs,
513
+ localName: options.localName,
514
+ manufacturerData: nil,
515
+ advertisingData: nil
516
+ )
517
+
518
+ try startAdvertising(options: advertisingOptions)
519
+ try startScan(
520
+ options: ScanOptions(
521
+ serviceUUIDs: options.serviceUUIDs,
522
+ allowDuplicates: options.allowDuplicates,
523
+ scanMode: options.scanMode
524
+ )
525
+ )
526
+ }
527
+
528
+ func stopBackgroundSession() throws {
529
+ isBackgroundSessionActive = false
530
+ try stopScan()
531
+ try stopAdvertising()
532
+ }
367
533
 
368
534
  func addListener(eventName: String) throws {
369
535
  // Event management
@@ -406,15 +572,86 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
406
572
  advertisingData[CBAdvertisementDataTxPowerLevelKey] = txPowerLevel
407
573
  }
408
574
  }
409
- }
410
575
 
411
- // MARK: - CBPeripheralManagerDelegate Implementation
412
- extension HybridMunimBluetooth: CBPeripheralManagerDelegate {
413
- func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
576
+ private func characteristicKey(deviceId: String, serviceUUID: String, characteristicUUID: String) -> String {
577
+ "\(deviceId.lowercased())|\(serviceUUID.lowercased())|\(characteristicUUID.lowercased())"
578
+ }
579
+
580
+ private func buildGATTServices(from services: [CBService]) -> [GATTService] {
581
+ services.map { service in
582
+ GATTService(
583
+ uuid: service.uuid.uuidString,
584
+ characteristics: (service.characteristics ?? []).map { characteristic in
585
+ GATTCharacteristic(
586
+ uuid: characteristic.uuid.uuidString,
587
+ properties: mapProperties(characteristic.properties),
588
+ value: characteristic.value?.map { String(format: "%02x", $0) }.joined()
589
+ )
590
+ }
591
+ )
592
+ }
593
+ }
594
+
595
+ private func mapProperties(_ properties: CBCharacteristicProperties) -> [String] {
596
+ var result: [String] = []
597
+ if properties.contains(.read) {
598
+ result.append("read")
599
+ }
600
+ if properties.contains(.write) {
601
+ result.append("write")
602
+ }
603
+ if properties.contains(.writeWithoutResponse) {
604
+ result.append("writeWithoutResponse")
605
+ }
606
+ if properties.contains(.notify) {
607
+ result.append("notify")
608
+ }
609
+ if properties.contains(.indicate) {
610
+ result.append("indicate")
611
+ }
612
+ return result
613
+ }
614
+
615
+ private func findCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String) -> CBCharacteristic? {
616
+ guard let peripheral = connectedPeripherals[deviceId],
617
+ let services = peripheral.services else {
618
+ return nil
619
+ }
620
+
621
+ let matchingService = services.first {
622
+ $0.uuid.uuidString.caseInsensitiveCompare(serviceUUID) == .orderedSame
623
+ }
624
+ let matchingCharacteristic = matchingService?.characteristics?.first {
625
+ $0.uuid.uuidString.caseInsensitiveCompare(characteristicUUID) == .orderedSame
626
+ }
627
+ return matchingCharacteristic
628
+ }
629
+
630
+ private func rejectPendingOperations(for deviceId: String, error: Error) {
631
+ pendingConnectionPromises.removeValue(forKey: deviceId)?.reject(withError: error)
632
+ pendingServiceDiscoveryPromises.removeValue(forKey: deviceId)?.reject(withError: error)
633
+ pendingCharacteristicDiscoveryCounts.removeValue(forKey: deviceId)
634
+ pendingRSSIPromises.removeValue(forKey: deviceId)?.reject(withError: error)
635
+
636
+ let prefix = "\(deviceId.lowercased())|"
637
+ for key in pendingReadPromises.keys where key.hasPrefix(prefix) {
638
+ pendingReadPromises.removeValue(forKey: key)?.reject(withError: error)
639
+ }
640
+ }
641
+
642
+ // MARK: - CoreBluetooth Delegate Forwarding
643
+
644
+ func handlePeripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
414
645
  // Handle state updates
415
646
  }
647
+
648
+ func handlePeripheralManagerWillRestoreState(_ peripheral: CBPeripheralManager, state: [String: Any]) {
649
+ if peripheral.isAdvertising {
650
+ isBackgroundSessionActive = true
651
+ }
652
+ }
416
653
 
417
- func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
654
+ func handlePeripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
418
655
  if let error = error {
419
656
  NSLog("Bluetooth event")
420
657
  } else {
@@ -422,23 +659,32 @@ extension HybridMunimBluetooth: CBPeripheralManagerDelegate {
422
659
  }
423
660
  }
424
661
 
425
- func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
662
+ func handlePeripheralManagerDidAddService(_ peripheral: CBPeripheralManager, service: CBService, error: Error?) {
426
663
  if let error = error {
427
664
  NSLog("Bluetooth event")
428
665
  } else {
429
666
  NSLog("Bluetooth event")
430
667
  }
431
668
  }
432
- }
433
-
434
- // MARK: - CBCentralManagerDelegate Implementation
435
- extension HybridMunimBluetooth: CBCentralManagerDelegate {
436
- func centralManagerDidUpdateState(_ central: CBCentralManager) {
669
+
670
+ func handleCentralManagerDidUpdateState(_ central: CBCentralManager) {
437
671
  let state = central.state
438
672
  NSLog("Bluetooth event")
439
673
  }
674
+
675
+ func handleCentralManagerWillRestoreState(_ central: CBCentralManager, state: [String: Any]) {
676
+ if let scanServices = state[CBCentralManagerRestoredStateScanServicesKey] as? [CBUUID] {
677
+ scanOptions = ScanOptions(
678
+ serviceUUIDs: scanServices.map { $0.uuidString },
679
+ allowDuplicates: nil,
680
+ scanMode: nil
681
+ )
682
+ isScanning = true
683
+ isBackgroundSessionActive = true
684
+ }
685
+ }
440
686
 
441
- func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
687
+ func handleCentralManagerDidDiscover(_ central: CBCentralManager, peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
442
688
  let deviceId = peripheral.identifier.uuidString
443
689
  discoveredPeripherals[deviceId] = peripheral
444
690
 
@@ -448,35 +694,58 @@ extension HybridMunimBluetooth: CBCentralManagerDelegate {
448
694
  NSLog("Bluetooth: deviceFound - %@", deviceId)
449
695
  }
450
696
 
451
- func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
697
+ func handleCentralManagerDidConnect(_ central: CBCentralManager, peripheral: CBPeripheral) {
452
698
  let deviceId = peripheral.identifier.uuidString
453
699
  connectedPeripherals[deviceId] = peripheral
454
- peripheral.delegate = self
700
+ peripheral.delegate = peripheralDelegateProxy
701
+ pendingConnectionPromises.removeValue(forKey: deviceId)?.resolve(withResult: ())
455
702
 
456
703
  NSLog("Bluetooth event")
457
704
  }
458
705
 
459
- func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
706
+ func handleCentralManagerDidDisconnectPeripheral(_ central: CBCentralManager, peripheral: CBPeripheral, error: Error?) {
460
707
  let deviceId = peripheral.identifier.uuidString
461
708
  connectedPeripherals.removeValue(forKey: deviceId)
462
709
  peripheralCharacteristics.removeValue(forKey: deviceId)
710
+ rejectPendingOperations(
711
+ for: deviceId,
712
+ error: error ?? NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Disconnected from \(deviceId)"])
713
+ )
463
714
 
464
715
  NSLog("Bluetooth event")
465
716
  }
466
717
 
467
- func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
718
+ func handleCentralManagerDidFailToConnect(_ central: CBCentralManager, peripheral: CBPeripheral, error: Error?) {
468
719
  let deviceId = peripheral.identifier.uuidString
720
+ rejectPendingOperations(
721
+ for: deviceId,
722
+ error: error ?? NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to connect to \(deviceId)"])
723
+ )
469
724
  NSLog("Bluetooth: connectionFailed")
470
725
  }
471
- }
472
-
473
- // MARK: - CBPeripheralDelegate Implementation
474
- extension HybridMunimBluetooth: CBPeripheralDelegate {
475
- func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
726
+
727
+ func handlePeripheralDidDiscoverServices(_ peripheral: CBPeripheral, error: Error?) {
476
728
  let deviceId = peripheral.identifier.uuidString
477
-
478
- guard let services = peripheral.services else { return }
479
-
729
+
730
+ if let error = error {
731
+ pendingServiceDiscoveryPromises.removeValue(forKey: deviceId)?.reject(withError: error)
732
+ pendingCharacteristicDiscoveryCounts.removeValue(forKey: deviceId)
733
+ return
734
+ }
735
+
736
+ guard let services = peripheral.services else {
737
+ pendingServiceDiscoveryPromises.removeValue(forKey: deviceId)?.resolve(withResult: [])
738
+ pendingCharacteristicDiscoveryCounts.removeValue(forKey: deviceId)
739
+ return
740
+ }
741
+
742
+ if services.isEmpty {
743
+ pendingServiceDiscoveryPromises.removeValue(forKey: deviceId)?.resolve(withResult: [])
744
+ pendingCharacteristicDiscoveryCounts.removeValue(forKey: deviceId)
745
+ return
746
+ }
747
+
748
+ pendingCharacteristicDiscoveryCounts[deviceId] = services.count
480
749
  for service in services {
481
750
  peripheral.discoverCharacteristics(nil, for: service)
482
751
  }
@@ -484,30 +753,72 @@ extension HybridMunimBluetooth: CBPeripheralDelegate {
484
753
  NSLog("Bluetooth event")
485
754
  }
486
755
 
487
- func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
756
+ func handlePeripheralDidDiscoverCharacteristics(_ peripheral: CBPeripheral, service: CBService, error: Error?) {
488
757
  let deviceId = peripheral.identifier.uuidString
489
-
758
+
759
+ if let error = error {
760
+ pendingServiceDiscoveryPromises.removeValue(forKey: deviceId)?.reject(withError: error)
761
+ pendingCharacteristicDiscoveryCounts.removeValue(forKey: deviceId)
762
+ return
763
+ }
764
+
490
765
  guard let characteristics = service.characteristics else { return }
491
-
766
+
492
767
  if peripheralCharacteristics[deviceId] == nil {
493
768
  peripheralCharacteristics[deviceId] = []
494
769
  }
495
770
  peripheralCharacteristics[deviceId]?.append(contentsOf: characteristics)
771
+
772
+ if let remaining = pendingCharacteristicDiscoveryCounts[deviceId] {
773
+ let nextRemaining = max(remaining - 1, 0)
774
+ if nextRemaining == 0 {
775
+ pendingCharacteristicDiscoveryCounts.removeValue(forKey: deviceId)
776
+ pendingServiceDiscoveryPromises.removeValue(forKey: deviceId)?.resolve(
777
+ withResult: buildGATTServices(from: peripheral.services ?? [])
778
+ )
779
+ } else {
780
+ pendingCharacteristicDiscoveryCounts[deviceId] = nextRemaining
781
+ }
782
+ }
496
783
 
497
784
  NSLog("Bluetooth event")
498
785
  }
499
786
 
500
- func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
787
+ func handlePeripheralDidUpdateValue(_ peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
501
788
  let deviceId = peripheral.identifier.uuidString
502
-
789
+
790
+ if let error = error {
791
+ pendingReadPromises.removeValue(
792
+ forKey: characteristicKey(
793
+ deviceId: deviceId,
794
+ serviceUUID: characteristic.service.uuid.uuidString,
795
+ characteristicUUID: characteristic.uuid.uuidString
796
+ )
797
+ )?.reject(withError: error)
798
+ return
799
+ }
800
+
503
801
  guard let data = characteristic.value else { return }
504
-
802
+
505
803
  let hexString = data.map { String(format: "%02x", $0) }.joined()
804
+ pendingReadPromises.removeValue(
805
+ forKey: characteristicKey(
806
+ deviceId: deviceId,
807
+ serviceUUID: characteristic.service.uuid.uuidString,
808
+ characteristicUUID: characteristic.uuid.uuidString
809
+ )
810
+ )?.resolve(
811
+ withResult: CharacteristicValue(
812
+ value: hexString,
813
+ serviceUUID: characteristic.service.uuid.uuidString,
814
+ characteristicUUID: characteristic.uuid.uuidString
815
+ )
816
+ )
506
817
 
507
818
  NSLog("Bluetooth: characteristicValueChanged")
508
819
  }
509
820
 
510
- func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
821
+ func handlePeripheralDidWriteValue(_ peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
511
822
  let deviceId = peripheral.identifier.uuidString
512
823
 
513
824
  if let error = error {
@@ -517,13 +828,16 @@ extension HybridMunimBluetooth: CBPeripheralDelegate {
517
828
  }
518
829
  }
519
830
 
520
- func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
831
+ func handlePeripheralDidReadRSSI(_ peripheral: CBPeripheral, rssi RSSI: NSNumber, error: Error?) {
521
832
  let deviceId = peripheral.identifier.uuidString
522
-
833
+
523
834
  if let error = error {
835
+ pendingRSSIPromises.removeValue(forKey: deviceId)?.reject(withError: error)
524
836
  NSLog("Bluetooth event")
525
- } else {
526
- NSLog("Bluetooth event")
837
+ return
527
838
  }
839
+
840
+ pendingRSSIPromises.removeValue(forKey: deviceId)?.resolve(withResult: RSSI.doubleValue)
841
+ NSLog("Bluetooth event")
528
842
  }
529
843
  }
@@ -19,8 +19,10 @@ exports.removeListeners = removeListeners;
19
19
  exports.requestBluetoothPermission = requestBluetoothPermission;
20
20
  exports.setServices = setServices;
21
21
  exports.startAdvertising = startAdvertising;
22
+ exports.startBackgroundSession = startBackgroundSession;
22
23
  exports.startScan = startScan;
23
24
  exports.stopAdvertising = stopAdvertising;
25
+ exports.stopBackgroundSession = stopBackgroundSession;
24
26
  exports.stopScan = stopScan;
25
27
  exports.subscribeToCharacteristic = subscribeToCharacteristic;
26
28
  exports.unsubscribeFromCharacteristic = unsubscribeFromCharacteristic;
@@ -228,6 +230,23 @@ function readRSSI(deviceId) {
228
230
  return MunimBluetooth.readRSSI(deviceId);
229
231
  }
230
232
 
233
+ /**
234
+ * Start a best-effort background BLE session.
235
+ *
236
+ * Android uses a foreground service. iOS relies on the host app's Bluetooth
237
+ * background modes and state restoration.
238
+ */
239
+ function startBackgroundSession(options) {
240
+ return MunimBluetooth.startBackgroundSession(options);
241
+ }
242
+
243
+ /**
244
+ * Stop the active background BLE session.
245
+ */
246
+ function stopBackgroundSession() {
247
+ return MunimBluetooth.stopBackgroundSession();
248
+ }
249
+
231
250
  // ========== Event Management ==========
232
251
 
233
252
  /**
@@ -302,6 +321,8 @@ var _default = exports.default = {
302
321
  unsubscribeFromCharacteristic,
303
322
  getConnectedDevices,
304
323
  readRSSI,
324
+ startBackgroundSession,
325
+ stopBackgroundSession,
305
326
  // Events
306
327
  addDeviceFoundListener,
307
328
  addEventListener,
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNativeNitroModules","require","_reactNative","MunimBluetooth","NitroModules","createHybridObject","nativeEventModule","Platform","OS","NativeModules","MunimBluetoothEventEmitter","console","log","Object","keys","filter","key","includes","eventEmitter","DeviceEventEmitter","NativeEventEmitter","error","warn","startAdvertising","options","updateAdvertisingData","advertisingData","getAdvertisingData","stopAdvertising","setServices","services","isBluetoothEnabled","requestBluetoothPermission","startScan","stopScan","connect","deviceId","disconnect","discoverServices","readCharacteristic","serviceUUID","characteristicUUID","writeCharacteristic","value","writeType","subscribeToCharacteristic","unsubscribeFromCharacteristic","getConnectedDevices","readRSSI","addDeviceFoundListener","callback","subscription","addListener","remove","addEventListener","eventName","removeListeners","count","_default","exports","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_reactNativeNitroModules","require","_reactNative","MunimBluetooth","NitroModules","createHybridObject","nativeEventModule","Platform","OS","NativeModules","MunimBluetoothEventEmitter","console","log","Object","keys","filter","key","includes","eventEmitter","DeviceEventEmitter","NativeEventEmitter","error","warn","startAdvertising","options","updateAdvertisingData","advertisingData","getAdvertisingData","stopAdvertising","setServices","services","isBluetoothEnabled","requestBluetoothPermission","startScan","stopScan","connect","deviceId","disconnect","discoverServices","readCharacteristic","serviceUUID","characteristicUUID","writeCharacteristic","value","writeType","subscribeToCharacteristic","unsubscribeFromCharacteristic","getConnectedDevices","readRSSI","startBackgroundSession","stopBackgroundSession","addDeviceFoundListener","callback","subscription","addListener","remove","addEventListener","eventName","removeListeners","count","_default","exports","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
@@ -202,6 +202,23 @@ export function readRSSI(deviceId) {
202
202
  return MunimBluetooth.readRSSI(deviceId);
203
203
  }
204
204
 
205
+ /**
206
+ * Start a best-effort background BLE session.
207
+ *
208
+ * Android uses a foreground service. iOS relies on the host app's Bluetooth
209
+ * background modes and state restoration.
210
+ */
211
+ export function startBackgroundSession(options) {
212
+ return MunimBluetooth.startBackgroundSession(options);
213
+ }
214
+
215
+ /**
216
+ * Stop the active background BLE session.
217
+ */
218
+ export function stopBackgroundSession() {
219
+ return MunimBluetooth.stopBackgroundSession();
220
+ }
221
+
205
222
  // ========== Event Management ==========
206
223
 
207
224
  /**
@@ -277,6 +294,8 @@ export default {
277
294
  unsubscribeFromCharacteristic,
278
295
  getConnectedDevices,
279
296
  readRSSI,
297
+ startBackgroundSession,
298
+ stopBackgroundSession,
280
299
  // Events
281
300
  addDeviceFoundListener,
282
301
  addEventListener,