munim-bluetooth 0.3.3 → 0.3.5

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.
@@ -10,7 +10,7 @@ import CoreBluetooth
10
10
  import NitroModules
11
11
  import React
12
12
 
13
- class HybridMunimBluetooth: HybridMunimBluetoothSpec {
13
+ class HybridMunimBluetooth: NSObject, HybridMunimBluetoothSpec {
14
14
  // Peripheral Manager
15
15
  private var peripheralManager: CBPeripheralManager?
16
16
  private var peripheralServices: [CBMutableService] = []
@@ -36,7 +36,7 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
36
36
 
37
37
  // MARK: - Peripheral Features
38
38
 
39
- override func startAdvertising(options: AdvertisingOptions) throws {
39
+ func startAdvertising(options: AdvertisingOptions) throws {
40
40
  guard let peripheralManager = peripheralManager,
41
41
  peripheralManager.state == .poweredOn else {
42
42
  throw NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Bluetooth is not powered on"])
@@ -70,7 +70,7 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
70
70
  peripheralManager.startAdvertising(advertisingData as? [String: Any])
71
71
  }
72
72
 
73
- override func updateAdvertisingData(advertisingData: AdvertisingDataTypes) throws {
73
+ func updateAdvertisingData(advertisingData: AdvertisingDataTypes) throws {
74
74
  guard let peripheralManager = peripheralManager,
75
75
  peripheralManager.state == .poweredOn else {
76
76
  throw NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Bluetooth is not powered on"])
@@ -85,18 +85,18 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
85
85
  peripheralManager.startAdvertising(newAdvertisingData as? [String: Any])
86
86
  }
87
87
 
88
- override func getAdvertisingData() throws -> Promise<AdvertisingDataTypes> {
88
+ func getAdvertisingData() throws -> Promise<AdvertisingDataTypes> {
89
89
  return Promise { resolver in
90
90
  resolver.resolve(self.currentAdvertisingData ?? AdvertisingDataTypes())
91
91
  }
92
92
  }
93
93
 
94
- override func stopAdvertising() throws {
94
+ func stopAdvertising() throws {
95
95
  peripheralManager?.stopAdvertising()
96
96
  currentAdvertisingData = nil
97
97
  }
98
98
 
99
- override func setServices(services: [GATTService]) throws {
99
+ func setServices(services: [GATTService]) throws {
100
100
  peripheralServices.removeAll()
101
101
 
102
102
  for service in services {
@@ -157,21 +157,21 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
157
157
 
158
158
  // MARK: - Central/Manager Features
159
159
 
160
- override func isBluetoothEnabled() throws -> Promise<Bool> {
160
+ func isBluetoothEnabled() throws -> Promise<Bool> {
161
161
  return Promise { resolver in
162
162
  let isEnabled = self.centralManager?.state == .poweredOn
163
163
  resolver.resolve(isEnabled ?? false)
164
164
  }
165
165
  }
166
166
 
167
- override func requestBluetoothPermission() throws -> Promise<Bool> {
167
+ func requestBluetoothPermission() throws -> Promise<Bool> {
168
168
  return Promise { resolver in
169
169
  // In iOS, permissions are handled by CBPeripheralManager/CBCentralManager
170
170
  resolver.resolve(true)
171
171
  }
172
172
  }
173
173
 
174
- override func startScan(options: ScanOptions?) throws {
174
+ func startScan(options: ScanOptions?) throws {
175
175
  guard let centralManager = centralManager,
176
176
  centralManager.state == .poweredOn else {
177
177
  throw NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Bluetooth is not powered on"])
@@ -188,12 +188,12 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
188
188
  centralManager.scanForPeripherals(withServices: nil, options: scanOptions as [String : Any])
189
189
  }
190
190
 
191
- override func stopScan() throws {
191
+ func stopScan() throws {
192
192
  centralManager?.stopScan()
193
193
  isScanning = false
194
194
  }
195
195
 
196
- override func connect(deviceId: String) throws -> Promise<Void> {
196
+ func connect(deviceId: String) throws -> Promise<Void> {
197
197
  return Promise { resolver in
198
198
  guard let peripheral = self.discoveredPeripherals[deviceId] else {
199
199
  resolver.reject(NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Device not found"]))
@@ -206,13 +206,13 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
206
206
  }
207
207
  }
208
208
 
209
- override func disconnect(deviceId: String) throws {
209
+ func disconnect(deviceId: String) throws {
210
210
  guard let peripheral = connectedPeripherals[deviceId] else { return }
211
211
  centralManager?.cancelPeripheralConnection(peripheral)
212
212
  connectedPeripherals.removeValue(forKey: deviceId)
213
213
  }
214
214
 
215
- override func discoverServices(deviceId: String) throws -> Promise<[GATTService]> {
215
+ func discoverServices(deviceId: String) throws -> Promise<[GATTService]> {
216
216
  return Promise { resolver in
217
217
  guard let peripheral = self.connectedPeripherals[deviceId] else {
218
218
  resolver.reject(NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Device not connected"]))
@@ -224,33 +224,33 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
224
224
  }
225
225
  }
226
226
 
227
- override func readCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String) throws -> Promise<CharacteristicValue> {
227
+ func readCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String) throws -> Promise<CharacteristicValue> {
228
228
  return Promise { resolver in
229
229
  resolver.reject(NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Not implemented"]))
230
230
  }
231
231
  }
232
232
 
233
- override func writeCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String, value: String, writeType: WriteType?) throws -> Promise<Void> {
233
+ func writeCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String, value: String, writeType: WriteType?) throws -> Promise<Void> {
234
234
  return Promise { resolver in
235
235
  resolver.reject(NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Not implemented"]))
236
236
  }
237
237
  }
238
238
 
239
- override func subscribeToCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String) throws {
239
+ func subscribeToCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String) throws {
240
240
  // Not implemented
241
241
  }
242
242
 
243
- override func unsubscribeFromCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String) throws {
243
+ func unsubscribeFromCharacteristic(deviceId: String, serviceUUID: String, characteristicUUID: String) throws {
244
244
  // Not implemented
245
245
  }
246
246
 
247
- override func getConnectedDevices() throws -> Promise<[String]> {
247
+ func getConnectedDevices() throws -> Promise<[String]> {
248
248
  return Promise { resolver in
249
249
  resolver.resolve(Array(self.connectedPeripherals.keys))
250
250
  }
251
251
  }
252
252
 
253
- override func readRSSI(deviceId: String) throws -> Promise<Double> {
253
+ func readRSSI(deviceId: String) throws -> Promise<Double> {
254
254
  return Promise { resolver in
255
255
  guard let peripheral = self.connectedPeripherals[deviceId] else {
256
256
  resolver.reject(NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Device not connected"]))
@@ -262,11 +262,11 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
262
262
  }
263
263
  }
264
264
 
265
- override func addListener(eventName: String) throws {
265
+ func addListener(eventName: String) throws {
266
266
  // Event management
267
267
  }
268
268
 
269
- override func removeListeners(count: Double) throws {
269
+ func removeListeners(count: Double) throws {
270
270
  // Event management
271
271
  }
272
272
 
@@ -307,161 +307,42 @@ class HybridMunimBluetooth: HybridMunimBluetoothSpec {
307
307
 
308
308
  // MARK: - CBPeripheralManagerDelegate
309
309
  extension HybridMunimBluetooth: CBPeripheralManagerDelegate {
310
- guard let peripheralManager = peripheralManager,
311
- peripheralManager.state == .poweredOn else {
312
- throw NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Bluetooth is not powered on"])
313
- }
314
-
315
- var advertisingData: [String: Any] = [:]
316
-
317
- // Process comprehensive advertising data
318
- if let advertisingDataDict = options["advertisingData"] as? [String: Any] {
319
- processAdvertisingData(advertisingDataDict, into: &advertisingData)
320
- }
321
-
322
- // Legacy support
323
- if let localName = options["localName"] as? String {
324
- advertisingData[CBAdvertisementDataLocalNameKey] = localName
325
- }
326
-
327
- if let serviceUUIDs = options["serviceUUIDs"] as? [String], !serviceUUIDs.isEmpty {
328
- let uuids = serviceUUIDs.compactMap { CBUUID(string: $0) }
329
- advertisingData[CBAdvertisementDataServiceUUIDsKey] = uuids
330
- }
331
-
332
- if let manufacturerData = options["manufacturerData"] as? String,
333
- let data = hexStringToData(manufacturerData) {
334
- advertisingData[CBAdvertisementDataManufacturerDataKey] = data
335
- }
336
-
337
- currentAdvertisingData = advertisingData
338
- peripheralManager.startAdvertising(advertisingData as? [String: Any])
339
- }
340
-
341
- func updateAdvertisingData(advertisingData: [String: Any]) throws {
342
- guard let peripheralManager = peripheralManager,
343
- peripheralManager.state == .poweredOn else {
344
- throw NSError(domain: "MunimBluetooth", code: 1, userInfo: [NSLocalizedDescriptionKey: "Bluetooth is not powered on"])
345
- }
346
-
347
- peripheralManager.stopAdvertising()
348
-
349
- var newAdvertisingData: [String: Any] = [:]
350
- processAdvertisingData(advertisingData, into: &newAdvertisingData)
351
-
352
- currentAdvertisingData = newAdvertisingData
353
- peripheralManager.startAdvertising(newAdvertisingData as? [String: Any])
354
- }
355
-
356
- func getAdvertisingData() throws -> [String: Any] {
357
- return currentAdvertisingData
358
- }
359
-
360
- func stopAdvertising() throws {
361
- peripheralManager?.stopAdvertising()
362
- currentAdvertisingData = [:]
363
- }
364
-
365
- func setServices(services: [[String: Any]]) throws {
366
- peripheralServices.removeAll()
367
-
368
- for serviceDict in services {
369
- guard let uuidString = serviceDict["uuid"] as? String else { continue }
370
-
371
- let serviceUUID = CBUUID(string: uuidString)
372
- let service = CBMutableService(type: serviceUUID, primary: true)
373
-
374
- var characteristics: [CBMutableCharacteristic] = []
375
-
376
- if let characteristicsArray = serviceDict["characteristics"] as? [[String: Any]] {
377
- for charDict in characteristicsArray {
378
- guard let charUUIDString = charDict["uuid"] as? String else { continue }
379
-
380
- let charUUID = CBUUID(string: charUUIDString)
381
- var properties: CBCharacteristicProperties = []
382
-
383
- if let propertiesArray = charDict["properties"] as? [String] {
384
- for prop in propertiesArray {
385
- switch prop {
386
- case "read":
387
- properties.insert(.read)
388
- case "write":
389
- properties.insert(.write)
390
- case "notify":
391
- properties.insert(.notify)
392
- case "indicate":
393
- properties.insert(.indicate)
394
- default:
395
- break
396
- }
397
- }
398
- }
399
-
400
- var value: Data?
401
- if let valueString = charDict["value"] as? String {
402
- value = valueString.data(using: .utf8)
403
- properties.insert(.read)
404
- }
405
-
406
- let permissions: CBAttributePermissions = value != nil ? .readable : [.readable, .writeable]
407
-
408
- let characteristic = CBMutableCharacteristic(
409
- type: charUUID,
410
- properties: properties,
411
- value: value,
412
- permissions: permissions
413
- )
414
-
415
- characteristics.append(characteristic)
416
- }
417
- }
418
-
419
- service.characteristics = characteristics
420
- peripheralServices.append(service)
421
- }
422
-
423
- peripheralManager?.removeAllServices()
424
- for service in peripheralServices {
425
- peripheralManager?.add(service)
426
- }
427
- }
428
-
429
- // MARK: - CBPeripheralManagerDelegate
430
- extension HybridMunimBluetooth: CBPeripheralManagerDelegate {
431
310
  func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
432
311
  // Handle state updates
433
312
  }
434
313
 
435
314
  func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
436
315
  if let error = error {
437
- // Emit error event
316
+ eventEmitter?.emit("advertisingError", ["error": error.localizedDescription])
317
+ } else {
318
+ eventEmitter?.emit("advertisingStarted", [:])
438
319
  }
439
320
  }
440
321
 
441
322
  func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
442
323
  if let error = error {
443
- // Emit error event
324
+ eventEmitter?.emit("serviceError", ["error": error.localizedDescription])
325
+ } else {
326
+ eventEmitter?.emit("serviceAdded", ["uuid": service.uuid.uuidString])
444
327
  }
445
328
  }
446
329
  }
447
330
 
448
331
  // MARK: - CBCentralManagerDelegate
449
-
450
332
  extension HybridMunimBluetooth: CBCentralManagerDelegate {
451
333
  func centralManagerDidUpdateState(_ central: CBCentralManager) {
452
- // Handle state updates
334
+ let state = central.state
335
+ eventEmitter?.emit("bluetoothStateChanged", ["state": state.rawValue])
453
336
  }
454
337
 
455
338
  func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
456
339
  let deviceId = peripheral.identifier.uuidString
457
340
  discoveredPeripherals[deviceId] = peripheral
458
341
 
459
- // Emit deviceFound event
460
342
  eventEmitter?.emit("deviceFound", [
461
343
  "id": deviceId,
462
344
  "name": peripheral.name ?? "",
463
- "rssi": RSSI.intValue,
464
- "advertisingData": advertisementData
345
+ "rssi": RSSI.intValue
465
346
  ])
466
347
  }
467
348
 
@@ -470,7 +351,6 @@ extension HybridMunimBluetooth: CBCentralManagerDelegate {
470
351
  connectedPeripherals[deviceId] = peripheral
471
352
  peripheral.delegate = self
472
353
 
473
- // Emit deviceConnected event
474
354
  eventEmitter?.emit("deviceConnected", ["id": deviceId])
475
355
  }
476
356
 
@@ -479,14 +359,11 @@ extension HybridMunimBluetooth: CBCentralManagerDelegate {
479
359
  connectedPeripherals.removeValue(forKey: deviceId)
480
360
  peripheralCharacteristics.removeValue(forKey: deviceId)
481
361
 
482
- // Emit deviceDisconnected event
483
362
  eventEmitter?.emit("deviceDisconnected", ["id": deviceId])
484
363
  }
485
364
 
486
365
  func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
487
366
  let deviceId = peripheral.identifier.uuidString
488
-
489
- // Emit connectionFailed event
490
367
  eventEmitter?.emit("connectionFailed", [
491
368
  "id": deviceId,
492
369
  "error": error?.localizedDescription ?? "Unknown error"
@@ -495,24 +372,17 @@ extension HybridMunimBluetooth: CBCentralManagerDelegate {
495
372
  }
496
373
 
497
374
  // MARK: - CBPeripheralDelegate
498
-
499
375
  extension HybridMunimBluetooth: CBPeripheralDelegate {
500
376
  func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
501
377
  let deviceId = peripheral.identifier.uuidString
502
378
 
503
379
  guard let services = peripheral.services else { return }
504
380
 
505
- var servicesArray: [[String: Any]] = []
506
381
  for service in services {
507
382
  peripheral.discoverCharacteristics(nil, for: service)
508
- servicesArray.append(["uuid": service.uuid.uuidString])
509
383
  }
510
384
 
511
- // Emit servicesDiscovered event
512
- eventEmitter?.emit("servicesDiscovered", [
513
- "id": deviceId,
514
- "services": servicesArray
515
- ])
385
+ eventEmitter?.emit("servicesDiscovered", ["id": deviceId])
516
386
  }
517
387
 
518
388
  func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
@@ -525,26 +395,7 @@ extension HybridMunimBluetooth: CBPeripheralDelegate {
525
395
  }
526
396
  peripheralCharacteristics[deviceId]?.append(contentsOf: characteristics)
527
397
 
528
- // Emit characteristicsDiscovered event
529
- var characteristicsArray: [[String: Any]] = []
530
- for characteristic in characteristics {
531
- var properties: [String] = []
532
- if characteristic.properties.contains(.read) { properties.append("read") }
533
- if characteristic.properties.contains(.write) { properties.append("write") }
534
- if characteristic.properties.contains(.notify) { properties.append("notify") }
535
- if characteristic.properties.contains(.indicate) { properties.append("indicate") }
536
-
537
- characteristicsArray.append([
538
- "uuid": characteristic.uuid.uuidString,
539
- "properties": properties
540
- ])
541
- }
542
-
543
- eventEmitter?.emit("characteristicsDiscovered", [
544
- "id": deviceId,
545
- "serviceUUID": service.uuid.uuidString,
546
- "characteristics": characteristicsArray
547
- ])
398
+ eventEmitter?.emit("characteristicsDiscovered", ["id": deviceId])
548
399
  }
549
400
 
550
401
  func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
@@ -554,7 +405,6 @@ extension HybridMunimBluetooth: CBPeripheralDelegate {
554
405
 
555
406
  let hexString = data.map { String(format: "%02x", $0) }.joined()
556
407
 
557
- // Emit characteristicValueChanged event
558
408
  eventEmitter?.emit("characteristicValueChanged", [
559
409
  "id": deviceId,
560
410
  "serviceUUID": characteristic.service?.uuid.uuidString ?? "",
@@ -569,29 +419,10 @@ extension HybridMunimBluetooth: CBPeripheralDelegate {
569
419
  if let error = error {
570
420
  eventEmitter?.emit("writeError", [
571
421
  "id": deviceId,
572
- "serviceUUID": characteristic.service?.uuid.uuidString ?? "",
573
- "characteristicUUID": characteristic.uuid.uuidString,
574
422
  "error": error.localizedDescription
575
423
  ])
576
424
  } else {
577
- eventEmitter?.emit("writeSuccess", [
578
- "id": deviceId,
579
- "serviceUUID": characteristic.service?.uuid.uuidString ?? "",
580
- "characteristicUUID": characteristic.uuid.uuidString
581
- ])
582
- }
583
- }
584
-
585
- func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
586
- let deviceId = peripheral.identifier.uuidString
587
-
588
- if let error = error {
589
- eventEmitter?.emit("subscriptionError", [
590
- "id": deviceId,
591
- "serviceUUID": characteristic.service?.uuid.uuidString ?? "",
592
- "characteristicUUID": characteristic.uuid.uuidString,
593
- "error": error.localizedDescription
594
- ])
425
+ eventEmitter?.emit("writeSuccess", ["id": deviceId])
595
426
  }
596
427
  }
597
428
 
@@ -599,21 +430,14 @@ extension HybridMunimBluetooth: CBPeripheralDelegate {
599
430
  let deviceId = peripheral.identifier.uuidString
600
431
 
601
432
  if let error = error {
602
- eventEmitter?.emit("rssiError", [
603
- "id": deviceId,
604
- "error": error.localizedDescription
605
- ])
433
+ eventEmitter?.emit("rssiError", ["error": error.localizedDescription])
606
434
  } else {
607
- eventEmitter?.emit("rssiUpdated", [
608
- "id": deviceId,
609
- "rssi": RSSI.intValue
610
- ])
435
+ eventEmitter?.emit("rssiUpdated", ["id": deviceId, "rssi": RSSI.intValue])
611
436
  }
612
437
  }
613
438
  }
614
439
 
615
- // MARK: - Event Emitter Helper
616
-
440
+ // MARK: - Helper Classes
617
441
  class NitroEventEmitter {
618
442
  private let moduleName: String
619
443
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "munim-bluetooth",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "A comprehensive React Native library for all your Bluetooth Low Energy (BLE) needs, supporting both peripheral and central roles with Expo support",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/module/index.js",