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