react-native-ble-manager 10.1.4 → 11.0.0

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.
@@ -0,0 +1,1185 @@
1
+ import Foundation
2
+ import CoreBluetooth
3
+
4
+
5
+ @objc(BleManager)
6
+ class BleManager: RCTEventEmitter, CBCentralManagerDelegate, CBPeripheralDelegate {
7
+
8
+ static var shared:BleManager?
9
+ static var sharedManager:CBCentralManager?
10
+
11
+ private var hasListeners:Bool = false
12
+
13
+ private var manager: CBCentralManager?
14
+ private var scanTimer: Timer?
15
+
16
+ private var peripherals: Dictionary<String, Peripheral>
17
+ private var connectCallbacks: Dictionary<String, [RCTResponseSenderBlock]>
18
+ private var readCallbacks: Dictionary<String, [RCTResponseSenderBlock]>
19
+ private var readRSSICallbacks: Dictionary<String, [RCTResponseSenderBlock]>
20
+ private var readDescriptorCallbacks: Dictionary<String, [RCTResponseSenderBlock]>
21
+ private var retrieveServicesCallbacks: Dictionary<String, [RCTResponseSenderBlock]>
22
+ private var writeCallbacks: Dictionary<String, [RCTResponseSenderBlock]>
23
+ private var writeQueue: Array<Any>
24
+ private var notificationCallbacks: Dictionary<String, [RCTResponseSenderBlock]>
25
+ private var stopNotificationCallbacks: Dictionary<String, [RCTResponseSenderBlock]>
26
+
27
+ private var connectedPeripherals: Set<String>
28
+
29
+ private var retrieveServicesLatches: Dictionary<String, Set<CBService>>
30
+ private var characteristicsLatches: Dictionary<String, Set<CBCharacteristic>>
31
+
32
+ private let serialQueue = DispatchQueue(label: "BleManager.serialQueue")
33
+
34
+ private var exactAdvertisingName: [String]
35
+
36
+ static var verboseLogging = false
37
+
38
+ private override init() {
39
+ peripherals = [:]
40
+ connectCallbacks = [:]
41
+ readCallbacks = [:]
42
+ readRSSICallbacks = [:]
43
+ readDescriptorCallbacks = [:]
44
+ retrieveServicesCallbacks = [:]
45
+ writeCallbacks = [:]
46
+ writeQueue = []
47
+ notificationCallbacks = [:]
48
+ stopNotificationCallbacks = [:]
49
+ retrieveServicesLatches = [:]
50
+ characteristicsLatches = [:]
51
+ exactAdvertisingName = []
52
+ connectedPeripherals = []
53
+
54
+ super.init()
55
+
56
+ NSLog("BleManager created");
57
+
58
+ BleManager.shared = self
59
+
60
+
61
+ NotificationCenter.default.addObserver(self, selector: #selector(bridgeReloading), name: NSNotification.Name(rawValue: "RCTBridgeWillReloadNotification"), object: nil)
62
+ }
63
+
64
+ @objc override static func requiresMainQueueSetup() -> Bool { return true }
65
+
66
+ @objc override func supportedEvents() -> [String]! {
67
+ return ["BleManagerDidUpdateValueForCharacteristic", "BleManagerStopScan", "BleManagerDiscoverPeripheral", "BleManagerConnectPeripheral", "BleManagerDisconnectPeripheral", "BleManagerDidUpdateState", "BleManagerCentralManagerWillRestoreState", "BleManagerDidUpdateNotificationStateFor"]
68
+ }
69
+
70
+ @objc override func startObserving() {
71
+ hasListeners = true
72
+ }
73
+
74
+ @objc override func stopObserving() {
75
+ hasListeners = false
76
+ }
77
+
78
+ @objc func bridgeReloading() {
79
+ if let manager = manager {
80
+ if let scanTimer = self.scanTimer {
81
+ scanTimer.invalidate()
82
+ self.scanTimer = nil
83
+ manager.stopScan()
84
+ }
85
+
86
+ manager.delegate = nil
87
+ }
88
+
89
+ serialQueue.sync {
90
+ for p in peripherals.values {
91
+ p.instance.delegate = nil
92
+ }
93
+ }
94
+
95
+ peripherals = [:]
96
+ }
97
+
98
+ // Helper method to find a peripheral by UUID
99
+ func findPeripheral(byUUID uuid: String) -> Peripheral? {
100
+ var foundPeripheral: Peripheral? = nil
101
+
102
+ serialQueue.sync {
103
+ if let peripheral = peripherals[uuid] {
104
+ foundPeripheral = peripheral;
105
+ }
106
+ }
107
+
108
+ return foundPeripheral
109
+ }
110
+
111
+ // Helper method to insert callback in different queues
112
+ func insertCallback(_ callback: @escaping RCTResponseSenderBlock, intoDictionary dictionary: inout Dictionary<String, [RCTResponseSenderBlock]>, withKey key: String) {
113
+ serialQueue.sync {
114
+ if var peripheralCallbacks = dictionary[key] {
115
+ peripheralCallbacks.append(callback)
116
+ } else {
117
+ var peripheralCallbacks = [RCTResponseSenderBlock]()
118
+ peripheralCallbacks.append(callback)
119
+ dictionary[key] = peripheralCallbacks
120
+ }
121
+
122
+ }
123
+ }
124
+
125
+ // Helper method to call the callbacks for a specific peripheral and clear the queue
126
+ func invokeAndClearDictionary(_ dictionary: inout Dictionary<String, [RCTResponseSenderBlock]>, withKey key: String, usingParameters parameters: [Any]) {
127
+ serialQueue.sync {
128
+
129
+ if let peripheralCallbacks = dictionary[key] {
130
+ for callback in peripheralCallbacks {
131
+ callback(parameters)
132
+ }
133
+
134
+ dictionary.removeValue(forKey: key)
135
+ }
136
+ }
137
+ }
138
+
139
+ @objc func getContext(_ peripheralUUIDString: String, serviceUUIDString: String, characteristicUUIDString: String, prop: CBCharacteristicProperties, callback: @escaping RCTResponseSenderBlock) -> BLECommandContext? {
140
+ let serviceUUID = CBUUID(string: serviceUUIDString)
141
+ let characteristicUUID = CBUUID(string: characteristicUUIDString)
142
+
143
+ guard let peripheral = peripherals[peripheralUUIDString] else {
144
+ let error = String(format: "Could not find peripheral with UUID %@", peripheralUUIDString)
145
+ NSLog(error)
146
+ callback([error])
147
+ return nil
148
+ }
149
+
150
+ guard let service = Helper.findService(fromUUID: serviceUUID, peripheral: peripheral.instance) else {
151
+ let error = String(format: "Could not find service with UUID %@ on peripheral with UUID %@",
152
+ serviceUUIDString,
153
+ peripheral.instance.uuidAsString())
154
+ NSLog(error)
155
+ callback([error])
156
+ return nil
157
+ }
158
+
159
+ var characteristic = Helper.findCharacteristic(fromUUID: characteristicUUID, service: service, prop: prop)
160
+
161
+ // Special handling for INDICATE. If characteristic with notify is not found, check for indicate.
162
+ if prop == CBCharacteristicProperties.notify && characteristic == nil {
163
+ characteristic = Helper.findCharacteristic(fromUUID: characteristicUUID, service: service, prop: CBCharacteristicProperties.indicate)
164
+ }
165
+
166
+ // As a last resort, try to find ANY characteristic with this UUID, even if it doesn't have the correct properties
167
+ if characteristic == nil {
168
+ characteristic = Helper.findCharacteristic(fromUUID: characteristicUUID, service: service)
169
+ }
170
+
171
+ guard let finalCharacteristic = characteristic else {
172
+ let error = String(format: "Could not find characteristic with UUID %@ on service with UUID %@ on peripheral with UUID %@",
173
+ characteristicUUIDString,
174
+ serviceUUIDString,
175
+ peripheral.instance.uuidAsString())
176
+ NSLog(error)
177
+ callback([error])
178
+ return nil
179
+ }
180
+
181
+ let context = BLECommandContext()
182
+ context.peripheral = peripheral
183
+ context.service = service
184
+ context.characteristic = finalCharacteristic
185
+ return context
186
+ }
187
+
188
+
189
+ @objc public func start(_ options: NSDictionary,
190
+ callback: RCTResponseSenderBlock) {
191
+ if BleManager.verboseLogging {
192
+ NSLog("BleManager initialized")
193
+ }
194
+ var initOptions = [String: Any]()
195
+
196
+ if let showAlert = options["showAlert"] as? Bool {
197
+ initOptions[CBCentralManagerOptionShowPowerAlertKey] = showAlert
198
+ }
199
+
200
+ var queue: DispatchQueue
201
+ if let queueIdentifierKey = options["queueIdentifierKey"] as? String {
202
+ queue = DispatchQueue(label: queueIdentifierKey, qos: DispatchQoS.background)
203
+ } else {
204
+ queue = DispatchQueue.main
205
+ }
206
+
207
+ if let restoreIdentifierKey = options["restoreIdentifierKey"] as? String {
208
+ initOptions[CBCentralManagerOptionRestoreIdentifierKey] = restoreIdentifierKey
209
+
210
+ if let sharedManager = BleManager.sharedManager {
211
+ manager = sharedManager
212
+ manager?.delegate = self
213
+ } else {
214
+ manager = CBCentralManager(delegate: self, queue: queue, options: initOptions)
215
+ BleManager.sharedManager = manager
216
+ }
217
+ } else {
218
+ manager = CBCentralManager(delegate: self, queue: queue, options: initOptions)
219
+ BleManager.sharedManager = manager
220
+ }
221
+
222
+ callback([])
223
+ }
224
+
225
+ @objc public func scan(_ serviceUUIDStrings: [Any],
226
+ timeoutSeconds: NSNumber,
227
+ allowDuplicates: Bool,
228
+ scanningOptions: NSDictionary,
229
+ callback:RCTResponseSenderBlock) {
230
+ if Int(truncating: timeoutSeconds) > 0 {
231
+ NSLog("scan with timeout \(timeoutSeconds)")
232
+ } else {
233
+ NSLog("scan")
234
+ }
235
+
236
+ // Clear the peripherals before scanning again, otherwise cannot connect again after disconnection
237
+ // Only clear peripherals that are not connected - otherwise connections fail silently (without any
238
+ // onDisconnect* callback).
239
+ serialQueue.sync {
240
+ let disconnectedPeripherals = peripherals.filter({ $0.value.instance.state != .connected && $0.value.instance.state != .connecting })
241
+ disconnectedPeripherals.forEach { (uuid, peripheral) in
242
+ peripheral.instance.delegate = nil
243
+ peripherals.removeValue(forKey: uuid)
244
+ }
245
+ }
246
+
247
+ var serviceUUIDs = [CBUUID]()
248
+ if let serviceUUIDStrings = serviceUUIDStrings as? [String] {
249
+ serviceUUIDs = serviceUUIDStrings.map { CBUUID(string: $0) }
250
+ }
251
+
252
+ var options: [String: Any]?
253
+ if allowDuplicates {
254
+ options = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
255
+ }
256
+
257
+ exactAdvertisingName.removeAll()
258
+ if let names = scanningOptions["exactAdvertisingName"] as? [String] {
259
+ exactAdvertisingName.append(contentsOf: names)
260
+ }
261
+
262
+ manager?.scanForPeripherals(withServices: serviceUUIDs, options: options)
263
+
264
+ if timeoutSeconds.doubleValue > 0 {
265
+ if let scanTimer = scanTimer {
266
+ scanTimer.invalidate()
267
+ self.scanTimer = nil
268
+ }
269
+ DispatchQueue.main.async {
270
+ self.scanTimer = Timer.scheduledTimer(timeInterval: timeoutSeconds.doubleValue, target: self, selector: #selector(self.stopTimer), userInfo: nil, repeats: false)
271
+ }
272
+ }
273
+
274
+ callback([])
275
+ }
276
+
277
+ @objc func stopTimer() {
278
+ NSLog("Stop scan");
279
+ scanTimer = nil;
280
+ manager?.stopScan()
281
+ if hasListeners {
282
+ sendEvent(withName: "BleManagerStopScan", body: ["status": 10])
283
+ }
284
+ }
285
+
286
+
287
+ @objc public func stopScan(_ callback: @escaping RCTResponseSenderBlock) {
288
+ if let scanTimer = self.scanTimer {
289
+ scanTimer.invalidate()
290
+ self.scanTimer = nil
291
+ }
292
+
293
+ manager?.stopScan()
294
+
295
+ if hasListeners {
296
+ sendEvent(withName: "BleManagerStopScan", body: ["status": 0])
297
+ }
298
+
299
+ callback([])
300
+ }
301
+
302
+
303
+ @objc func connect(_ peripheralUUID: String,
304
+ options: NSDictionary,
305
+ callback: @escaping RCTResponseSenderBlock) {
306
+
307
+ if let peripheral = peripherals[peripheralUUID] {
308
+ // Found the peripheral, connect to it
309
+ NSLog("Connecting to peripheral with UUID: \(peripheralUUID)")
310
+
311
+ insertCallback(callback, intoDictionary: &connectCallbacks, withKey: peripheral.instance.uuidAsString())
312
+ manager?.connect(peripheral.instance)
313
+ } else {
314
+ // Try to retrieve the peripheral
315
+ NSLog("Retrieving peripheral with UUID: \(peripheralUUID)")
316
+
317
+ if let uuid = UUID(uuidString: peripheralUUID) {
318
+ let peripheralArray = manager?.retrievePeripherals(withIdentifiers: [uuid])
319
+ if let retrievedPeripheral = peripheralArray?.first {
320
+ objc_sync_enter(peripherals)
321
+ peripherals[retrievedPeripheral.uuidAsString()] = Peripheral(peripheral:retrievedPeripheral)
322
+ objc_sync_exit(peripherals)
323
+ NSLog("Successfully retrieved and connecting to peripheral with UUID: \(peripheralUUID)")
324
+
325
+ // Connect to the retrieved peripheral
326
+ insertCallback(callback, intoDictionary: &connectCallbacks, withKey: retrievedPeripheral.uuidAsString())
327
+ manager?.connect(retrievedPeripheral, options: nil)
328
+ } else {
329
+ let error = "Could not find peripheral \(peripheralUUID)."
330
+ NSLog(error)
331
+ callback([error, NSNull()])
332
+ }
333
+ } else {
334
+ let error = "Wrong UUID format \(peripheralUUID)"
335
+ callback([error, NSNull()])
336
+ }
337
+ }
338
+ }
339
+
340
+ @objc func disconnect(_ peripheralUUID: String,
341
+ force: Bool,
342
+ callback: @escaping RCTResponseSenderBlock) {
343
+ if let peripheral = peripherals[peripheralUUID] {
344
+ NSLog("Disconnecting from peripheral with UUID: \(peripheralUUID)")
345
+
346
+ if let services = peripheral.instance.services {
347
+ for service in services {
348
+ if let characteristics = service.characteristics {
349
+ for characteristic in characteristics {
350
+ if characteristic.isNotifying {
351
+ NSLog("Remove notification from: \(characteristic.uuid)")
352
+ peripheral.instance.setNotifyValue(false, for: characteristic)
353
+ }
354
+ }
355
+ }
356
+ }
357
+ }
358
+
359
+ manager?.cancelPeripheralConnection(peripheral.instance)
360
+ callback([])
361
+
362
+ } else {
363
+ let error = "Could not find peripheral \(peripheralUUID)."
364
+ NSLog(error)
365
+ callback([error])
366
+ }
367
+ }
368
+
369
+ @objc func retrieveServices(_ peripheralUUID: String,
370
+ services: [String],
371
+ callback: @escaping RCTResponseSenderBlock) {
372
+ NSLog("retrieveServices \(services)")
373
+
374
+ if let peripheral = peripherals[peripheralUUID], peripheral.instance.state == .connected {
375
+ insertCallback(callback, intoDictionary: &retrieveServicesCallbacks, withKey: peripheral.instance.uuidAsString())
376
+
377
+ var uuids: [CBUUID] = []
378
+ for string in services {
379
+ let uuid = CBUUID(string: string)
380
+ uuids.append(uuid)
381
+ }
382
+
383
+ if !uuids.isEmpty {
384
+ peripheral.instance.discoverServices(uuids)
385
+ } else {
386
+ peripheral.instance.discoverServices(nil)
387
+ }
388
+
389
+ } else {
390
+ callback(["Peripheral not found or not connected"])
391
+ }
392
+ }
393
+
394
+ @objc func readRSSI(_ peripheralUUID: String,
395
+ callback: @escaping RCTResponseSenderBlock) {
396
+ NSLog("readRSSI")
397
+
398
+ if let peripheral = peripherals[peripheralUUID], peripheral.instance.state == .connected {
399
+ insertCallback(callback, intoDictionary: &readRSSICallbacks, withKey: peripheral.instance.uuidAsString())
400
+ peripheral.instance.readRSSI()
401
+ } else {
402
+ callback(["Peripheral not found or not connected"])
403
+ }
404
+ }
405
+
406
+ @objc func readDescriptor(_ peripheralUUID: String,
407
+ serviceUUID: String,
408
+ characteristicUUID: String,
409
+ descriptorUUID: String,
410
+ callback: @escaping RCTResponseSenderBlock) {
411
+ NSLog("readDescriptor")
412
+
413
+ guard let context = getContext(peripheralUUID, serviceUUIDString: serviceUUID, characteristicUUIDString: characteristicUUID, prop: CBCharacteristicProperties.read, callback: callback) else {
414
+ return
415
+ }
416
+
417
+ let peripheral = context.peripheral
418
+ let characteristic = context.characteristic
419
+
420
+ guard let descriptor = Helper.findDescriptor(fromUUID: CBUUID(string: descriptorUUID), characteristic: characteristic!) else {
421
+ let error = "Could not find descriptor with UUID \(descriptorUUID) on characteristic with UUID \(String(describing: characteristic?.uuid.uuidString)) on peripheral with UUID \(peripheralUUID)"
422
+ NSLog(error)
423
+ callback([error])
424
+ return
425
+ }
426
+
427
+ if let peripheral = peripheral?.instance {
428
+ let key = Helper.key(forPeripheral: peripheral, andCharacteristic: characteristic!, andDescriptor: descriptor)
429
+ insertCallback(callback, intoDictionary: &readDescriptorCallbacks, withKey: key)
430
+
431
+ }
432
+
433
+ peripheral?.instance.readValue(for: descriptor)
434
+ }
435
+
436
+ @objc func getDiscoveredPeripherals(_ callback: @escaping RCTResponseSenderBlock) {
437
+ NSLog("Get discovered peripherals")
438
+ var discoveredPeripherals: [[String: Any]] = []
439
+
440
+ serialQueue.sync {
441
+ for (_, peripheral) in peripherals {
442
+ discoveredPeripherals.append(peripheral.advertisingInfo())
443
+ }
444
+ }
445
+
446
+ callback([NSNull(), discoveredPeripherals])
447
+ }
448
+
449
+ @objc func getConnectedPeripherals(_ serviceUUIDStrings: [String],
450
+ callback: @escaping RCTResponseSenderBlock) {
451
+ NSLog("Get connected peripherals")
452
+ var serviceUUIDs: [CBUUID] = []
453
+
454
+ for uuidString in serviceUUIDStrings {
455
+ serviceUUIDs.append(CBUUID(string: uuidString))
456
+ }
457
+
458
+ var connectedPeripherals: [Peripheral] = []
459
+
460
+ if serviceUUIDs.isEmpty {
461
+ serialQueue.sync {
462
+ connectedPeripherals = peripherals.filter({ $0.value.instance.state == .connected }).map({ p in
463
+ p.value
464
+ })
465
+ }
466
+ } else {
467
+ let connectedCBPeripherals: [CBPeripheral] = manager?.retrieveConnectedPeripherals(withServices: serviceUUIDs) ?? []
468
+
469
+ serialQueue.sync {
470
+ for ph in connectedCBPeripherals {
471
+ if let peripheral = peripherals[ph.uuidAsString()] {
472
+ connectedPeripherals.append(peripheral)
473
+ } else {
474
+ peripherals[ph.uuidAsString()] = Peripheral(peripheral: ph)
475
+ }
476
+ }
477
+ }
478
+ }
479
+
480
+ var foundedPeripherals: [[String: Any]] = []
481
+
482
+ for peripheral in connectedPeripherals {
483
+ foundedPeripherals.append(peripheral.advertisingInfo())
484
+ }
485
+
486
+ callback([NSNull(), foundedPeripherals])
487
+ }
488
+
489
+ @objc func isPeripheralConnected(_ peripheralUUID: String,
490
+ callback: @escaping RCTResponseSenderBlock) {
491
+
492
+ if let peripheral = peripherals[peripheralUUID] {
493
+ callback([NSNull(), peripheral.instance.state == .connected])
494
+ } else {
495
+ callback(["Peripheral not found"])
496
+ }
497
+ }
498
+
499
+ @objc func checkState(_ callback: @escaping RCTResponseSenderBlock) {
500
+ if let manager = manager {
501
+ centralManagerDidUpdateState(manager)
502
+
503
+ let stateName = Helper.centralManagerStateToString(manager.state)
504
+ callback([stateName])
505
+ }
506
+ }
507
+
508
+ @objc func write(_ peripheralUUID: String,
509
+ serviceUUID: String,
510
+ characteristicUUID: String,
511
+ message: [UInt8],
512
+ maxByteSize: Int,
513
+ callback: @escaping RCTResponseSenderBlock) {
514
+ NSLog("write")
515
+
516
+ // TODO check if the queue is working
517
+
518
+ guard let context = getContext(peripheralUUID, serviceUUIDString: serviceUUID, characteristicUUIDString: characteristicUUID, prop: CBCharacteristicProperties.write, callback: callback) else {
519
+ return
520
+ }
521
+
522
+ let dataMessage = Data(message)
523
+
524
+ if let peripheral = context.peripheral, let characteristic = context.characteristic {
525
+ let key = Helper.key(forPeripheral:peripheral.instance, andCharacteristic: characteristic)
526
+ insertCallback(callback, intoDictionary: &writeCallbacks, withKey: key)
527
+
528
+ if BleManager.verboseLogging {
529
+ NSLog("Message to write(\(dataMessage.count)): \(dataMessage.hexadecimalString())")
530
+ }
531
+
532
+ if dataMessage.count > maxByteSize {
533
+ var count = 0
534
+ var offset = 0
535
+ while count < dataMessage.count, (dataMessage.count - count) > maxByteSize {
536
+ let splitMessage = dataMessage.subdata(in: offset..<offset + maxByteSize)
537
+ writeQueue.append(splitMessage)
538
+ count += maxByteSize
539
+ offset += maxByteSize
540
+ }
541
+
542
+ if count < dataMessage.count {
543
+ let splitMessage = dataMessage.subdata(in: offset..<dataMessage.count)
544
+ writeQueue.append(splitMessage)
545
+ }
546
+
547
+ if BleManager.verboseLogging {
548
+ NSLog("Queued splitted message: \(writeQueue.count)")
549
+ }
550
+
551
+ if case let firstMessage as Data = writeQueue.removeFirst() {
552
+ peripheral.instance.writeValue(firstMessage, for: characteristic, type: .withResponse)
553
+ }
554
+ } else {
555
+ peripheral.instance.writeValue(dataMessage, for: characteristic, type: .withResponse)
556
+ }
557
+ }
558
+ }
559
+
560
+ @objc func writeWithoutResponse(_ peripheralUUID: String,
561
+ serviceUUID: String,
562
+ characteristicUUID: String,
563
+ message: [UInt8],
564
+ maxByteSize: Int,
565
+ queueSleepTime: Int,
566
+ callback: @escaping RCTResponseSenderBlock) {
567
+ NSLog("writeWithoutResponse")
568
+
569
+ guard let context = getContext(peripheralUUID, serviceUUIDString: serviceUUID, characteristicUUIDString: characteristicUUID, prop: CBCharacteristicProperties.writeWithoutResponse, callback: callback) else {
570
+ return
571
+ }
572
+
573
+ let dataMessage = Data(message)
574
+
575
+ if BleManager.verboseLogging {
576
+ NSLog("Message to write(\(dataMessage.count)): \(dataMessage.hexadecimalString())")
577
+ }
578
+
579
+ if dataMessage.count > maxByteSize {
580
+ var offset = 0
581
+ let peripheral = context.peripheral
582
+ guard let characteristic = context.characteristic else { return }
583
+
584
+ repeat {
585
+ let thisChunkSize = min(maxByteSize, dataMessage.count - offset)
586
+ let chunk = dataMessage.subdata(in: offset..<offset + thisChunkSize)
587
+
588
+ offset += thisChunkSize
589
+ peripheral?.instance.writeValue(chunk, for: characteristic, type: .withoutResponse)
590
+
591
+ let sleepTimeSeconds = TimeInterval(queueSleepTime) / 1000
592
+ Thread.sleep(forTimeInterval: sleepTimeSeconds)
593
+ } while offset < dataMessage.count
594
+
595
+ callback([])
596
+ } else {
597
+ let peripheral = context.peripheral
598
+ guard let characteristic = context.characteristic else { return }
599
+
600
+ peripheral?.instance.writeValue(dataMessage, for: characteristic, type: .withoutResponse)
601
+ callback([])
602
+ }
603
+ }
604
+
605
+ @objc func read(_ peripheralUUID: String,
606
+ serviceUUID: String,
607
+ characteristicUUID: String,
608
+ callback: @escaping RCTResponseSenderBlock) {
609
+ NSLog("read")
610
+
611
+ guard let context = getContext(peripheralUUID, serviceUUIDString: serviceUUID, characteristicUUIDString: characteristicUUID, prop: CBCharacteristicProperties.read, callback: callback) else {
612
+ return
613
+ }
614
+
615
+ let peripheral = context.peripheral
616
+ let characteristic = context.characteristic
617
+
618
+ let key = Helper.key(forPeripheral:peripheral!.instance as CBPeripheral, andCharacteristic: characteristic!)
619
+ insertCallback(callback, intoDictionary: &readCallbacks, withKey: key)
620
+
621
+ peripheral?.instance.readValue(for: characteristic!) // callback sends value
622
+ }
623
+
624
+ @objc func startNotification(_ peripheralUUID: String,
625
+ serviceUUID: String,
626
+ characteristicUUID: String,
627
+ callback: @escaping RCTResponseSenderBlock) {
628
+ NSLog("startNotification")
629
+
630
+ guard let context = getContext(peripheralUUID, serviceUUIDString: serviceUUID, characteristicUUIDString: characteristicUUID, prop: CBCharacteristicProperties.notify, callback: callback) else {
631
+ return
632
+ }
633
+
634
+ guard let peripheral = context.peripheral else { return }
635
+ guard let characteristic = context.characteristic else { return }
636
+
637
+ let key = Helper.key(forPeripheral: (peripheral.instance as CBPeripheral?)!, andCharacteristic: characteristic)
638
+ insertCallback(callback, intoDictionary: &notificationCallbacks, withKey: key)
639
+
640
+ peripheral.instance.setNotifyValue(true, for: characteristic)
641
+ }
642
+
643
+ @objc func stopNotification(_ peripheralUUID: String,
644
+ serviceUUID: String,
645
+ characteristicUUID: String,
646
+ callback: @escaping RCTResponseSenderBlock) {
647
+ NSLog("stopNotification")
648
+
649
+ guard let context = getContext(peripheralUUID, serviceUUIDString: serviceUUID, characteristicUUIDString: characteristicUUID, prop: CBCharacteristicProperties.notify, callback: callback) else {
650
+ return
651
+ }
652
+
653
+ let peripheral = context.peripheral
654
+ guard let characteristic = context.characteristic else { return }
655
+
656
+ if characteristic.isNotifying {
657
+ let key = Helper.key(forPeripheral: (peripheral?.instance as CBPeripheral?)!, andCharacteristic: characteristic)
658
+ insertCallback(callback, intoDictionary: &stopNotificationCallbacks, withKey: key)
659
+ peripheral?.instance.setNotifyValue(false, for: characteristic)
660
+ NSLog("Characteristic stopped notifying")
661
+ } else {
662
+ NSLog("Characteristic is not notifying")
663
+ callback([])
664
+ }
665
+ }
666
+
667
+ @objc func getMaximumWriteValueLengthForWithoutResponse(_ peripheralUUID: String,
668
+ callback: @escaping RCTResponseSenderBlock) {
669
+ NSLog("getMaximumWriteValueLengthForWithoutResponse")
670
+
671
+ guard let peripheral = peripherals[peripheralUUID] else {
672
+ callback(["Peripheral not found or not connected"])
673
+ return
674
+ }
675
+
676
+ if peripheral.instance.state == .connected {
677
+ let max = NSNumber(value: peripheral.instance.maximumWriteValueLength(for: .withoutResponse))
678
+ callback([NSNull(), max])
679
+ } else {
680
+ callback(["Peripheral not found or not connected"])
681
+ }
682
+ }
683
+
684
+ @objc func getMaximumWriteValueLengthForWithResponse(_ peripheralUUID: String,
685
+ callback: @escaping RCTResponseSenderBlock) {
686
+ NSLog("getMaximumWriteValueLengthForWithResponse")
687
+
688
+ guard let peripheral = peripherals[peripheralUUID] else {
689
+ callback(["Peripheral not found or not connected"])
690
+ return
691
+ }
692
+
693
+ if peripheral.instance.state == .connected {
694
+ let max = NSNumber(value: peripheral.instance.maximumWriteValueLength(for: .withResponse))
695
+ callback([NSNull(), max])
696
+ } else {
697
+ callback(["Peripheral not found or not connected"])
698
+ }
699
+ }
700
+
701
+ func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
702
+ if let restoredPeripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral], restoredPeripherals.count > 0 {
703
+ serialQueue.sync {
704
+ var data = [[String: Any]]()
705
+ for peripheral in restoredPeripherals {
706
+ let p = Peripheral(peripheral:peripheral)
707
+ peripherals[peripheral.uuidAsString()] = p
708
+ data.append(p.advertisingInfo())
709
+ peripheral.delegate = self
710
+ }
711
+
712
+ NotificationCenter.default.post(name: Notification.Name("BleManagerCentralManagerWillRestoreState"), object: nil, userInfo: ["peripherals": data])
713
+ }
714
+ }
715
+ }
716
+
717
+
718
+ func centralManager(_ central: CBCentralManager,
719
+ didConnect peripheral: CBPeripheral) {
720
+ NSLog("Peripheral Connected: \(peripheral.uuidAsString() ?? "")")
721
+ peripheral.delegate = self
722
+
723
+ /*
724
+ The state of the peripheral isn't necessarily updated until a small
725
+ delay after didConnectPeripheral is called and in the meantime
726
+ didFailToConnectPeripheral may be called
727
+ */
728
+ DispatchQueue.main.async {
729
+ Timer.scheduledTimer(withTimeInterval: 0.002, repeats: false) { timer in
730
+ // didFailToConnectPeripheral should have been called already if not connected by now
731
+ self.invokeAndClearDictionary(&self.connectCallbacks, withKey: peripheral.uuidAsString(), usingParameters: [NSNull()])
732
+
733
+ if self.hasListeners {
734
+ self.connectedPeripherals.insert(peripheral.uuidAsString())
735
+ self.sendEvent(withName: "BleManagerConnectPeripheral", body: ["peripheral": peripheral.uuidAsString()])
736
+ }
737
+ }
738
+ }
739
+ }
740
+
741
+ func centralManager(_ central: CBCentralManager,
742
+ didFailToConnect peripheral: CBPeripheral,
743
+ error: Error?) {
744
+ let errorStr = "Peripheral connection failure: \(peripheral.uuidAsString() ?? "") (\(error?.localizedDescription ?? "")"
745
+ NSLog(errorStr)
746
+
747
+ invokeAndClearDictionary(&connectCallbacks, withKey: peripheral.uuidAsString(), usingParameters: [errorStr])
748
+ }
749
+
750
+ func centralManager(_ central: CBCentralManager,
751
+ didDisconnectPeripheral peripheral:
752
+ CBPeripheral, error: Error?) {
753
+ let peripheralUUIDString:String = peripheral.uuidAsString()
754
+ NSLog("Peripheral Disconnected: \(peripheralUUIDString)")
755
+
756
+ if let error = error {
757
+ NSLog("Error: \(error)")
758
+ }
759
+
760
+ let errorStr = "Peripheral did disconnect: \(peripheralUUIDString)"
761
+
762
+ invokeAndClearDictionary(&connectCallbacks, withKey: peripheralUUIDString, usingParameters: [errorStr])
763
+ invokeAndClearDictionary(&readRSSICallbacks, withKey: peripheralUUIDString, usingParameters: [errorStr])
764
+ invokeAndClearDictionary(&retrieveServicesCallbacks, withKey: peripheralUUIDString, usingParameters: [errorStr])
765
+
766
+
767
+ for key in readCallbacks.keys {
768
+ if let keyString = key as String?, keyString.hasPrefix(peripheralUUIDString) {
769
+ invokeAndClearDictionary(&readCallbacks, withKey: key, usingParameters: [errorStr])
770
+ }
771
+ }
772
+
773
+ for key in writeCallbacks.keys {
774
+ if let keyString = key as String?, keyString.hasPrefix(peripheralUUIDString) {
775
+ invokeAndClearDictionary(&writeCallbacks, withKey: key, usingParameters: [errorStr])
776
+ }
777
+ }
778
+
779
+ for key in notificationCallbacks.keys {
780
+ if let keyString = key as String?, keyString.hasPrefix(peripheralUUIDString) {
781
+ invokeAndClearDictionary(&notificationCallbacks, withKey: key, usingParameters: [errorStr])
782
+ }
783
+ }
784
+
785
+ for key in readDescriptorCallbacks.keys {
786
+ if let keyString = key as String?, keyString.hasPrefix(peripheralUUIDString) {
787
+ invokeAndClearDictionary(&readDescriptorCallbacks, withKey: key, usingParameters: [errorStr])
788
+ }
789
+ }
790
+
791
+ for key in stopNotificationCallbacks.keys {
792
+ if let keyString = key as String?, keyString.hasPrefix(peripheralUUIDString) {
793
+ invokeAndClearDictionary(&stopNotificationCallbacks, withKey: key, usingParameters: [errorStr])
794
+ }
795
+ }
796
+
797
+ if hasListeners {
798
+ connectedPeripherals.remove(peripheralUUIDString)
799
+ if let e:Error = error {
800
+ sendEvent(withName: "BleManagerDisconnectPeripheral", body: ["peripheral": peripheralUUIDString, "domain": e._domain, "code": e._code, "description": e.localizedDescription])
801
+ } else {
802
+ sendEvent(withName: "BleManagerDisconnectPeripheral", body: ["peripheral": peripheralUUIDString])
803
+ }
804
+ }
805
+ }
806
+
807
+
808
+ func centralManagerDidUpdateState(_ central: CBCentralManager) {
809
+ let stateName = Helper.centralManagerStateToString(central.state)
810
+ if hasListeners {
811
+ sendEvent(withName: "BleManagerDidUpdateState", body: ["state": stateName])
812
+ }
813
+ if stateName == "poweredOff" {
814
+ for peripheralUUID in connectedPeripherals {
815
+ if let peripheral = peripherals[peripheralUUID] {
816
+ if peripheral.instance.state == .disconnected {
817
+ self.centralManager(manager!, didDisconnectPeripheral:peripheral.instance, error: nil)
818
+ }
819
+ }
820
+ }
821
+ }
822
+ }
823
+
824
+ func handleDiscoveredPeripheral(_ peripheral: CBPeripheral,
825
+ advertisementData: [String : Any],
826
+ rssi : NSNumber) {
827
+ if BleManager.verboseLogging {
828
+ NSLog("Discover peripheral: \(peripheral.name ?? "NO NAME")");
829
+ }
830
+
831
+ var cp: Peripheral? = nil
832
+ serialQueue.sync {
833
+ if let p = peripherals[peripheral.uuidAsString()] {
834
+ cp = p
835
+ cp?.setRSSI(rssi)
836
+ cp?.setAdvertisementData(advertisementData)
837
+ } else {
838
+ cp = Peripheral(peripheral:peripheral, rssi:rssi, advertisementData:advertisementData)
839
+ peripherals[peripheral.uuidAsString()] = cp
840
+ }
841
+ }
842
+
843
+ if (hasListeners) {
844
+ sendEvent(withName: "BleManagerDiscoverPeripheral", body: cp?.advertisingInfo())
845
+ }
846
+ }
847
+
848
+ func centralManager(_ central: CBCentralManager,
849
+ didDiscover peripheral: CBPeripheral,
850
+ advertisementData: [String : Any],
851
+ rssi RSSI: NSNumber) {
852
+ if exactAdvertisingName.count > 0 {
853
+ if let peripheralName = peripheral.name {
854
+ if exactAdvertisingName.contains(peripheralName) {
855
+ handleDiscoveredPeripheral(peripheral, advertisementData: advertisementData, rssi: RSSI)
856
+ } else {
857
+ if let localName = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
858
+ if exactAdvertisingName.contains(localName) {
859
+ handleDiscoveredPeripheral(peripheral, advertisementData: advertisementData, rssi: RSSI)
860
+ }
861
+ }
862
+ }
863
+ }
864
+ } else {
865
+ handleDiscoveredPeripheral(peripheral, advertisementData: advertisementData, rssi: RSSI)
866
+ }
867
+
868
+
869
+ }
870
+
871
+ func peripheral(_ peripheral: CBPeripheral,
872
+ didDiscoverServices error: Error?) {
873
+ if let error = error {
874
+ NSLog("Error: \(error)")
875
+ return
876
+ }
877
+ if BleManager.verboseLogging {
878
+ NSLog("Services Discover")
879
+ }
880
+
881
+ var servicesForPeripheral = Set<CBService>()
882
+ servicesForPeripheral.formUnion(peripheral.services ?? [])
883
+ retrieveServicesLatches[peripheral.uuidAsString()] = servicesForPeripheral
884
+
885
+ if let services = peripheral.services {
886
+ for service in services {
887
+ if BleManager.verboseLogging {
888
+ NSLog("Service \(service.uuid.uuidString) \(service.description)")
889
+ }
890
+ peripheral.discoverIncludedServices(nil, for: service) // discover included services
891
+ peripheral.discoverCharacteristics(nil, for: service) // discover characteristics for service
892
+ }
893
+ }
894
+ }
895
+
896
+ func peripheral(_ peripheral: CBPeripheral,
897
+ didDiscoverIncludedServicesFor service: CBService,
898
+ error: Error?) {
899
+ if let error = error {
900
+ NSLog("Error: \(error)")
901
+ return
902
+ }
903
+ peripheral.discoverCharacteristics(nil, for: service) // discover characteristics for included service
904
+ }
905
+
906
+ func peripheral(_ peripheral: CBPeripheral,
907
+ didDiscoverCharacteristicsFor service: CBService,
908
+ error: Error?) {
909
+ if let error = error {
910
+ NSLog("Error: \(error)")
911
+ return
912
+ }
913
+ if BleManager.verboseLogging {
914
+ NSLog("Characteristics For Service Discover")
915
+ }
916
+
917
+ var characteristicsForService = Set<CBCharacteristic>()
918
+ characteristicsForService.formUnion(service.characteristics ?? [])
919
+ characteristicsLatches[service.uuid.uuidString] = characteristicsForService
920
+
921
+ if let characteristics = service.characteristics {
922
+ for characteristic in characteristics {
923
+ peripheral.discoverDescriptors(for: characteristic)
924
+ }
925
+ }
926
+ }
927
+
928
+ func peripheral(_ peripheral: CBPeripheral,
929
+ didDiscoverDescriptorsFor characteristic: CBCharacteristic,
930
+ error: Error?) {
931
+ if let error = error {
932
+ NSLog("Error: \(error)")
933
+ return
934
+ }
935
+ let peripheralUUIDString:String = peripheral.uuidAsString()
936
+ let serviceUUIDString:String = (characteristic.service?.uuid.uuidString)!
937
+
938
+ if BleManager.verboseLogging {
939
+ NSLog("Descriptor For Characteristic Discover \(serviceUUIDString) \(characteristic.uuid.uuidString)")
940
+ }
941
+
942
+ if var servicesLatch = retrieveServicesLatches[peripheralUUIDString], var characteristicsLatch = characteristicsLatches[serviceUUIDString] {
943
+
944
+ characteristicsLatch.remove(characteristic)
945
+ characteristicsLatches[serviceUUIDString] = characteristicsLatch
946
+
947
+ if characteristicsLatch.isEmpty {
948
+ // All characteristics for this service have been checked
949
+ servicesLatch.remove(characteristic.service!)
950
+ retrieveServicesLatches[peripheralUUIDString] = servicesLatch
951
+
952
+ if servicesLatch.isEmpty {
953
+ // All characteristics and services have been checked
954
+ if let peripheral = peripherals[peripheral.uuidAsString()] {
955
+ invokeAndClearDictionary(&retrieveServicesCallbacks, withKey: peripheralUUIDString, usingParameters: [NSNull(), peripheral.servicesInfo()])
956
+ }
957
+ characteristicsLatches.removeValue(forKey: serviceUUIDString)
958
+ retrieveServicesLatches.removeValue(forKey: peripheralUUIDString)
959
+ }
960
+ }
961
+
962
+ }
963
+ }
964
+
965
+ func peripheral(_ peripheral: CBPeripheral,
966
+ didReadRSSI RSSI: NSNumber,
967
+ error: Error?) {
968
+ if BleManager.verboseLogging {
969
+ print("didReadRSSI \(RSSI)")
970
+ }
971
+
972
+ if let error = error {
973
+ invokeAndClearDictionary(&readRSSICallbacks, withKey: peripheral.uuidAsString(), usingParameters: [error.localizedDescription, RSSI])
974
+ } else {
975
+ invokeAndClearDictionary(&readRSSICallbacks, withKey: peripheral.uuidAsString(), usingParameters: [NSNull(), RSSI])
976
+ }
977
+ }
978
+
979
+ func peripheral(_ peripheral: CBPeripheral,
980
+ didUpdateValueFor descriptor: CBDescriptor,
981
+ error: Error?) {
982
+ let key = Helper.key(forPeripheral: peripheral, andCharacteristic: descriptor.characteristic!, andDescriptor: descriptor)
983
+
984
+ if let error = error {
985
+ NSLog("Error reading descriptor value for \(descriptor.uuid) on characteristic \(descriptor.characteristic!.uuid) :\(error)")
986
+ invokeAndClearDictionary(&readDescriptorCallbacks, withKey: key, usingParameters: [error, NSNull()])
987
+ return
988
+ }
989
+
990
+ if let descriptorValue = descriptor.value as? Data {
991
+ NSLog("Read value [descriptor: \(descriptor.uuid), characteristic: \(descriptor.characteristic!.uuid)]: (\(descriptorValue.count)) \(descriptorValue.hexadecimalString())")
992
+ } else {
993
+ NSLog("Read value [descriptor: \(descriptor.uuid), characteristic: \(descriptor.characteristic!.uuid)]: \(String(describing: descriptor.value))")
994
+ }
995
+
996
+ if readDescriptorCallbacks[key] != nil {
997
+ // The most future proof way of doing this that I could find, other option would be running strcmp on CBUUID strings
998
+ // https://developer.apple.com/documentation/corebluetooth/cbuuid/characteristic_descriptors
999
+ if let descriptorValue = descriptor.value as? Data {
1000
+ if (BleManager.verboseLogging) {
1001
+ NSLog("Descriptor value is Data")
1002
+ }
1003
+ invokeAndClearDictionary(&readDescriptorCallbacks, withKey: key, usingParameters: [NSNull(), descriptorValue.toArray()])
1004
+ } else if let descriptorValue = descriptor.value as? NSNumber {
1005
+ if (BleManager.verboseLogging) {
1006
+ NSLog("Descriptor value is NSNumber")
1007
+ }
1008
+ var value = descriptorValue.uint64Value
1009
+ let byteData = Data(bytes: &value, count: MemoryLayout.size(ofValue: value))
1010
+ invokeAndClearDictionary(&readDescriptorCallbacks, withKey: key, usingParameters: [NSNull(), byteData.toArray()])
1011
+ } else if let descriptorValue = descriptor.value as? String {
1012
+ if (BleManager.verboseLogging) {
1013
+ NSLog("Descriptor value is String")
1014
+ }
1015
+ if let byteData = descriptorValue.data(using: .utf8) {
1016
+ invokeAndClearDictionary(&readDescriptorCallbacks, withKey: key, usingParameters: [NSNull(), byteData.toArray()])
1017
+ }
1018
+ } else {
1019
+ NSLog("Unrecognized type of descriptor: (UUID: \(descriptor.uuid), value type: \(type(of: descriptor.value)), value: \(String(describing: descriptor.value)))")
1020
+ if let descriptorValue = descriptor.value as? Data {
1021
+ invokeAndClearDictionary(&readDescriptorCallbacks, withKey: key, usingParameters: [NSNull(), descriptorValue.toArray()])
1022
+ }
1023
+ }
1024
+ }
1025
+ }
1026
+
1027
+ func peripheral(_ peripheral: CBPeripheral,
1028
+ didUpdateValueFor characteristic: CBCharacteristic,
1029
+ error: Error?) {
1030
+ let key = Helper.key(forPeripheral: peripheral, andCharacteristic: characteristic)
1031
+
1032
+ if let error = error {
1033
+ NSLog("Error \(characteristic.uuid) :\(error)")
1034
+ invokeAndClearDictionary(&readCallbacks, withKey: key, usingParameters: [error, NSNull()])
1035
+ return
1036
+ }
1037
+
1038
+ NSLog("Read value [\(characteristic.uuid)]: (\(String(describing: characteristic.value?.hexadecimalString()))")
1039
+
1040
+ if readCallbacks[key] != nil {
1041
+ invokeAndClearDictionary(&readCallbacks, withKey: key, usingParameters: [NSNull(), characteristic.value!])
1042
+ } else {
1043
+ if hasListeners {
1044
+ sendEvent(withName: "BleManagerDidUpdateValueForCharacteristic", body: [
1045
+ "peripheral": peripheral.uuidAsString(),
1046
+ "characteristic": characteristic.uuid.uuidString.lowercased(),
1047
+ "service": characteristic.service!.uuid.uuidString.lowercased(),
1048
+ "value": characteristic.value!.toArray()
1049
+ ])
1050
+ }
1051
+ }
1052
+ }
1053
+
1054
+ func peripheral(_ peripheral: CBPeripheral,
1055
+ didUpdateNotificationStateFor characteristic: CBCharacteristic,
1056
+ error: Error?) {
1057
+ if let error = error {
1058
+ NSLog("Error in didUpdateNotificationStateForCharacteristic: \(error)")
1059
+
1060
+ if hasListeners {
1061
+ sendEvent(withName: "BleManagerDidUpdateNotificationStateFor", body: [
1062
+ "peripheral": peripheral.uuidAsString(),
1063
+ "characteristic": characteristic.uuid.uuidString.lowercased(),
1064
+ "isNotifying": false,
1065
+ "domain": error._domain,
1066
+ "code": error._code
1067
+ ])
1068
+ }
1069
+ }
1070
+
1071
+ let key = Helper.key(forPeripheral: peripheral, andCharacteristic: characteristic)
1072
+
1073
+ if characteristic.isNotifying {
1074
+ if notificationCallbacks[key] != nil {
1075
+ if let error = error {
1076
+ invokeAndClearDictionary(&notificationCallbacks, withKey: key, usingParameters: [error])
1077
+ } else {
1078
+ if BleManager.verboseLogging {
1079
+ NSLog("Notification began on \(characteristic.uuid)")
1080
+ }
1081
+ invokeAndClearDictionary(&notificationCallbacks, withKey: key, usingParameters: [])
1082
+ }
1083
+ }
1084
+ } else {
1085
+ // Notification has stopped
1086
+ if stopNotificationCallbacks[key] != nil {
1087
+ if error != nil {
1088
+ invokeAndClearDictionary(&stopNotificationCallbacks, withKey: key, usingParameters: [error as Any])
1089
+ } else {
1090
+ if BleManager.verboseLogging {
1091
+ NSLog("Notification ended on \(characteristic.uuid)")
1092
+ }
1093
+ invokeAndClearDictionary(&stopNotificationCallbacks, withKey: key, usingParameters: [])
1094
+ }
1095
+ }
1096
+ }
1097
+ if hasListeners {
1098
+ sendEvent(withName: "BleManagerDidUpdateNotificationStateFor", body: [
1099
+ "peripheral": peripheral.uuidAsString(),
1100
+ "characteristic": characteristic.uuid.uuidString.lowercased(),
1101
+ "isNotifying": characteristic.isNotifying
1102
+ ])
1103
+ }
1104
+ }
1105
+
1106
+ func peripheral(_ peripheral: CBPeripheral,
1107
+ didWriteValueFor characteristic: CBCharacteristic,
1108
+ error: Error?) {
1109
+ NSLog("didWrite")
1110
+
1111
+ let key = Helper.key(forPeripheral:peripheral, andCharacteristic: characteristic)
1112
+ let peripheralWriteCallbacks = writeCallbacks[key]
1113
+
1114
+ if peripheralWriteCallbacks != nil {
1115
+ if let error = error {
1116
+ NSLog("\(error)")
1117
+ invokeAndClearDictionary(&writeCallbacks, withKey: key, usingParameters: [error.localizedDescription])
1118
+ } else {
1119
+ if writeQueue.isEmpty {
1120
+ invokeAndClearDictionary(&writeCallbacks, withKey: key, usingParameters: [])
1121
+ } else {
1122
+ // Rimuovi e scrivi il messaggio in coda
1123
+ let message = writeQueue.removeFirst() as! Data
1124
+ NSLog("Message to write \(message.hexadecimalString())")
1125
+ peripheral.writeValue(message, for: characteristic, type: .withResponse)
1126
+ }
1127
+ }
1128
+ }
1129
+ }
1130
+
1131
+
1132
+ static func getCentralManager() -> CBCentralManager? {
1133
+ return sharedManager
1134
+ }
1135
+
1136
+ static func getInstance() -> BleManager? {
1137
+ return shared
1138
+ }
1139
+
1140
+ @objc func enableBluetooth(_ callback: @escaping RCTResponseSenderBlock) {
1141
+ callback(["Not supported"])
1142
+ }
1143
+
1144
+ @objc func getBondedPeripherals(_ callback: @escaping RCTResponseSenderBlock) {
1145
+ callback(["Not supported"])
1146
+ }
1147
+
1148
+ @objc func createBond(_ peripheralUUID: String,
1149
+ devicePin: String,
1150
+ callback: @escaping RCTResponseSenderBlock) {
1151
+ callback(["Not supported"])
1152
+ }
1153
+
1154
+ @objc func removeBond(_ peripheralUUID: String,
1155
+ callback: @escaping RCTResponseSenderBlock) {
1156
+ callback(["Not supported"])
1157
+ }
1158
+
1159
+ @objc func removePeripheral(_ peripheralUUID: String,
1160
+ callback: @escaping RCTResponseSenderBlock) {
1161
+ callback(["Not supported"])
1162
+ }
1163
+
1164
+ @objc func requestMTU(_ peripheralUUID: String,
1165
+ mtu: Int,
1166
+ callback: @escaping RCTResponseSenderBlock) {
1167
+ callback(["Not supported"])
1168
+ }
1169
+
1170
+ @objc func requestConnectionPriority(_ peripheralUUID: String,
1171
+ mtu: Int,
1172
+ callback: @escaping RCTResponseSenderBlock) {
1173
+ callback(["Not supported"])
1174
+ }
1175
+
1176
+ @objc func refreshCache(_ peripheralUUID: String,
1177
+ callback: @escaping RCTResponseSenderBlock) {
1178
+ callback(["Not supported"])
1179
+ }
1180
+
1181
+ @objc func setName(_ name: String,
1182
+ callback: @escaping RCTResponseSenderBlock) {
1183
+ callback(["Not supported"])
1184
+ }
1185
+ }