@stoprocent/noble 1.19.0 → 2.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.
Files changed (97) hide show
  1. package/README.md +393 -650
  2. package/examples/advertisement-discovery.js +57 -48
  3. package/examples/connect-address.js +59 -34
  4. package/examples/echo.js +59 -69
  5. package/examples/enter-exit.js +55 -49
  6. package/examples/multiple-bindings.js +53 -0
  7. package/examples/peripheral-explorer-async.js +39 -21
  8. package/examples/peripheral-explorer.ts +52 -0
  9. package/index.d.ts +249 -209
  10. package/index.js +4 -1
  11. package/jest.config.js +4 -0
  12. package/lib/characteristic.js +153 -127
  13. package/lib/{win/src/callbacks.h → common/include/Emit.h} +17 -14
  14. package/lib/common/include/Peripheral.h +31 -0
  15. package/lib/common/include/ThreadSafeCallback.h +95 -0
  16. package/lib/{win/src/callbacks.cc → common/src/Emit.cc} +111 -68
  17. package/lib/descriptor.js +57 -54
  18. package/lib/hci-socket/acl-stream.js +2 -4
  19. package/lib/hci-socket/bindings.js +96 -73
  20. package/lib/hci-socket/gap.js +2 -3
  21. package/lib/hci-socket/gatt.js +2 -5
  22. package/lib/hci-socket/hci.js +19 -7
  23. package/lib/hci-socket/signaling.js +2 -3
  24. package/lib/hci-socket/smp.js +2 -3
  25. package/lib/hci-socket/vs.js +1 -0
  26. package/lib/mac/binding.gyp +5 -7
  27. package/lib/mac/bindings.js +1 -3
  28. package/lib/mac/src/ble_manager.h +1 -8
  29. package/lib/mac/src/ble_manager.mm +87 -44
  30. package/lib/mac/src/napi_objc.h +1 -0
  31. package/lib/mac/src/napi_objc.mm +0 -6
  32. package/lib/mac/src/noble_mac.h +5 -3
  33. package/lib/mac/src/noble_mac.mm +99 -57
  34. package/lib/mac/src/objc_cpp.h +3 -2
  35. package/lib/mac/src/objc_cpp.mm +0 -6
  36. package/lib/noble.js +579 -488
  37. package/lib/peripheral.js +171 -174
  38. package/lib/resolve-bindings.js +37 -30
  39. package/lib/service.js +58 -55
  40. package/lib/win/binding.gyp +4 -11
  41. package/lib/win/bindings.js +1 -3
  42. package/lib/win/src/ble_manager.cc +291 -166
  43. package/lib/win/src/ble_manager.h +11 -13
  44. package/lib/win/src/napi_winrt.cc +1 -7
  45. package/lib/win/src/napi_winrt.h +1 -1
  46. package/lib/win/src/noble_winrt.cc +88 -61
  47. package/lib/win/src/noble_winrt.h +5 -3
  48. package/lib/win/src/notify_map.cc +0 -7
  49. package/lib/win/src/notify_map.h +1 -8
  50. package/lib/win/src/peripheral_winrt.cc +29 -11
  51. package/lib/win/src/peripheral_winrt.h +1 -1
  52. package/lib/win/src/radio_watcher.cc +79 -69
  53. package/lib/win/src/radio_watcher.h +30 -11
  54. package/lib/win/src/winrt_cpp.cc +1 -1
  55. package/lib/win/src/winrt_cpp.h +3 -0
  56. package/package.json +14 -17
  57. package/prebuilds/darwin-x64+arm64/@stoprocent+noble.node +0 -0
  58. package/prebuilds/win32-ia32/@stoprocent+noble.node +0 -0
  59. package/prebuilds/win32-x64/@stoprocent+noble.node +0 -0
  60. package/test/lib/characteristic.test.js +202 -322
  61. package/test/lib/descriptor.test.js +62 -95
  62. package/test/lib/hci-socket/acl-stream.test.js +112 -108
  63. package/test/lib/hci-socket/bindings.test.js +576 -365
  64. package/test/lib/hci-socket/hci.test.js +442 -473
  65. package/test/lib/hci-socket/signaling.test.js +45 -48
  66. package/test/lib/hci-socket/smp.test.js +144 -142
  67. package/test/lib/hci-socket/vs.test.js +193 -18
  68. package/test/lib/peripheral.test.js +492 -322
  69. package/test/lib/resolve-bindings.test.js +207 -82
  70. package/test/lib/service.test.js +79 -88
  71. package/test/noble.test.js +381 -1085
  72. package/.editorconfig +0 -11
  73. package/.nycrc.json +0 -4
  74. package/codecov.yml +0 -5
  75. package/examples/cache-gatt-discovery.js +0 -198
  76. package/examples/cache-gatt-reconnect.js +0 -164
  77. package/examples/ext-advertisement-discovery.js +0 -65
  78. package/examples/peripheral-explorer.js +0 -225
  79. package/examples/pizza/central.js +0 -194
  80. package/examples/pizza/pizza.js +0 -60
  81. package/examples/test/test.custom.js +0 -131
  82. package/examples/uart-bind-params.js +0 -28
  83. package/lib/distributed/bindings.js +0 -326
  84. package/lib/mac/src/callbacks.cc +0 -222
  85. package/lib/mac/src/callbacks.h +0 -84
  86. package/lib/mac/src/peripheral.h +0 -23
  87. package/lib/resolve-bindings-web.js +0 -9
  88. package/lib/webbluetooth/bindings.js +0 -368
  89. package/lib/websocket/bindings.js +0 -321
  90. package/lib/win/src/peripheral.h +0 -23
  91. package/test/lib/distributed/bindings.test.js +0 -918
  92. package/test/lib/webbluetooth/bindings.test.js +0 -190
  93. package/test/lib/websocket/bindings.test.js +0 -456
  94. package/test/mocha.setup.js +0 -0
  95. package/with-bindings.js +0 -5
  96. package/with-custom-binding.js +0 -6
  97. package/ws-slave.js +0 -404
@@ -1,17 +1,13 @@
1
- //
2
- // ble_manager.mm
3
- // noble-mac-native
4
- //
5
- // Created by Georg Vienna on 28.08.18.
6
- //
7
1
  #include "ble_manager.h"
2
+ #include "objc_cpp.h"
3
+ #include "Peripheral.h"
8
4
 
9
5
  #import <Foundation/Foundation.h>
10
6
 
11
- #include "objc_cpp.h"
12
-
13
7
  @implementation BLEManager
14
- - (instancetype)init: (const Napi::Value&) receiver with: (const Napi::Function&) callback {
8
+
9
+ - (instancetype)init: (const Napi::Value&) receiver with: (const Napi::Function&) callback
10
+ {
15
11
  if (self = [super init]) {
16
12
  pendingRead = false;
17
13
  // wrap cb before creating the CentralManager as it may call didUpdateState immediately
@@ -24,69 +20,90 @@
24
20
  return self;
25
21
  }
26
22
 
27
- - (void)centralManagerDidUpdateState:(CBCentralManager *)central {
23
+ - (void)centralManagerDidUpdateState:(CBCentralManager *)central
24
+ {
28
25
  auto state = stateToString(central.state);
29
26
  emit.RadioState(state);
30
27
  }
31
28
 
32
- - (void)scan: (NSArray<NSString*> *)serviceUUIDs allowDuplicates: (BOOL)allowDuplicates {
29
+ - (void)scan:(NSArray<NSString*> *)serviceUUIDs allowDuplicates:(BOOL)allowDuplicates {
30
+ [self.discovered removeAllObjects];
33
31
  NSMutableArray* advServicesUuid = [NSMutableArray arrayWithCapacity:[serviceUUIDs count]];
34
32
  [serviceUUIDs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
35
33
  [advServicesUuid addObject:[CBUUID UUIDWithString:obj]];
36
34
  }];
35
+
37
36
  NSDictionary *options = @{CBCentralManagerScanOptionAllowDuplicatesKey:[NSNumber numberWithBool:allowDuplicates]};
38
37
  [self.centralManager scanForPeripheralsWithServices:advServicesUuid options:options];
39
38
  emit.ScanState(true);
40
39
  }
41
40
 
42
- - (void)stopScan {
41
+ - (void)stopScan
42
+ {
43
43
  [self.centralManager stopScan];
44
- [self.discovered removeAllObjects];
45
44
  emit.ScanState(false);
46
45
  }
47
46
 
48
- - (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
47
+ - (void) centralManager:(CBCentralManager *)central
48
+ didDiscoverPeripheral:(CBPeripheral *)peripheral
49
+ advertisementData:(NSDictionary<NSString *,id> *)advertisementData
50
+ RSSI:(NSNumber *)RSSI
51
+ {
49
52
  std::string uuid = getUuid(peripheral);
50
53
  [self.discovered addObject:getNSUuid(peripheral)];
51
54
 
52
55
  Peripheral p;
53
56
  p.address = getAddress(uuid, &p.addressType);
57
+
54
58
  IF(NSNumber*, connect, [advertisementData objectForKey:CBAdvertisementDataIsConnectable]) {
55
59
  p.connectable = [connect boolValue];
56
60
  }
61
+
57
62
  IF(NSString*, dataLocalName, [advertisementData objectForKey:CBAdvertisementDataLocalNameKey]) {
58
- p.name = std::make_pair([dataLocalName UTF8String], true);
63
+ p.name = std::string([dataLocalName UTF8String]);
59
64
  }
60
- if(!std::get<1>(p.name)) {
65
+
66
+ if (!p.name) {
61
67
  IF(NSString*, name, [peripheral name]) {
62
- p.name = std::make_pair([name UTF8String], true);
68
+ p.name = std::string([name UTF8String]);
63
69
  }
64
70
  }
71
+
65
72
  IF(NSNumber*, txLevel, [advertisementData objectForKey:CBAdvertisementDataTxPowerLevelKey]) {
66
- p.txPowerLevel = std::make_pair([txLevel intValue], true);
73
+ p.txPowerLevel = [txLevel intValue];
67
74
  }
75
+
68
76
  IF(NSData*, data, [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey]) {
69
77
  const UInt8* bytes = (UInt8 *)[data bytes];
70
- std::get<0>(p.manufacturerData).assign(bytes, bytes+[data length]);
71
- std::get<1>(p.manufacturerData) = true;
78
+ Data manufacturerData;
79
+ manufacturerData.assign(bytes, bytes + [data length]);
80
+ p.manufacturerData = manufacturerData;
72
81
  }
82
+
73
83
  IF(NSDictionary*, dictionary, [advertisementData objectForKey:CBAdvertisementDataServiceDataKey]) {
84
+ std::vector<std::pair<std::string, Data>> serviceData;
74
85
  for (CBUUID* key in dictionary) {
75
86
  IF(NSData*, value, dictionary[key]) {
76
87
  auto serviceUuid = [[key UUIDString] UTF8String];
77
88
  Data sData;
78
89
  const UInt8* bytes = (UInt8 *)[value bytes];
79
- sData.assign(bytes, bytes+[value length]);
80
- std::get<0>(p.serviceData).push_back(std::make_pair(serviceUuid, sData));
90
+ sData.assign(bytes, bytes + [value length]);
91
+ serviceData.push_back(std::make_pair(serviceUuid, sData));
81
92
  }
82
93
  }
83
- std::get<1>(p.serviceData) = true;
94
+ if (!serviceData.empty()) {
95
+ p.serviceData = serviceData;
96
+ }
84
97
  }
98
+
85
99
  IF(NSArray*, services, [advertisementData objectForKey:CBAdvertisementDataServiceUUIDsKey]) {
100
+ std::vector<std::string> serviceUuids;
86
101
  for (CBUUID* service in services) {
87
- std::get<0>(p.serviceUuids).push_back([[service UUIDString] UTF8String]);
102
+ serviceUuids.push_back([[service UUIDString] UTF8String]);
103
+ }
104
+ if (!serviceUuids.empty()) {
105
+ p.serviceUuids = serviceUuids;
88
106
  }
89
- std::get<1>(p.serviceUuids) = true;
90
107
  }
91
108
 
92
109
  int rssi = [RSSI intValue];
@@ -157,17 +174,18 @@
157
174
  return NO;
158
175
  }
159
176
 
160
- - (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error {
177
+ - (void) peripheral:(CBPeripheral *) peripheral
178
+ didReadRSSI:(NSNumber *) RSSI
179
+ error:(NSError *) error
180
+ {
161
181
  std::string uuid = getUuid(peripheral);
162
- NSNumber* rssi = peripheral.RSSI;
163
- if(!error && rssi) {
164
- emit.RSSI(uuid, [rssi longValue]);
165
- }
182
+ int16_t rssi = [RSSI intValue];
183
+ emit.RSSI(uuid, rssi, error ? error.localizedDescription.UTF8String : "");
166
184
  }
167
185
 
168
186
  #pragma mark - Services
169
187
 
170
- -(BOOL) discoverServices:(NSString*) uuid serviceUuids:(NSArray<NSString*>*) services {
188
+ - (BOOL)discoverServices:(NSString*) uuid serviceUuids:(NSArray<NSString*>*) services {
171
189
  IF(CBPeripheral*, peripheral, [self.peripherals objectForKey:uuid]) {
172
190
  NSMutableArray* servicesUuid = nil;
173
191
  if(services) {
@@ -182,10 +200,10 @@
182
200
  return NO;
183
201
  }
184
202
 
185
- - (void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
203
+ - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
186
204
  std::string uuid = getUuid(peripheral);
187
205
  std::vector<std::string> services = getServices(peripheral.services);
188
- emit.ServicesDiscovered(uuid, services);
206
+ emit.ServicesDiscovered(uuid, services, error ? error.localizedDescription.UTF8String : "");
189
207
  }
190
208
 
191
209
  - (BOOL)discoverIncludedServices:(NSString*) uuid forService:(NSString*) serviceUuid services:(NSArray<NSString*>*) serviceUuids {
@@ -209,7 +227,7 @@
209
227
  std::string uuid = getUuid(peripheral);
210
228
  auto serviceUuid = [[service.UUID UUIDString] UTF8String];
211
229
  std::vector<std::string> services = getServices(service.includedServices);
212
- emit.IncludedServicesDiscovered(uuid, serviceUuid, services);
230
+ emit.IncludedServicesDiscovered(uuid, serviceUuid, services, error ? error.localizedDescription.UTF8String : "");
213
231
  }
214
232
 
215
233
  #pragma mark - Characteristics
@@ -218,7 +236,7 @@
218
236
  IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
219
237
  IF(CBService*, service, [self getService:peripheral service:serviceUuid]) {
220
238
  NSMutableArray* characteristicsUuid = nil;
221
- if(characteristics) {
239
+ if([characteristics count] > 0) {
222
240
  characteristicsUuid = [NSMutableArray arrayWithCapacity:[characteristics count]];
223
241
  [characteristics enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
224
242
  [characteristicsUuid addObject:[CBUUID UUIDWithString:obj]];
@@ -235,7 +253,7 @@
235
253
  std::string uuid = getUuid(peripheral);
236
254
  std::string serviceUuid = std::string([service.UUID.UUIDString UTF8String]);
237
255
  auto characteristics = getCharacteristics(service.characteristics);
238
- emit.CharacteristicsDiscovered(uuid, serviceUuid, characteristics);
256
+ emit.CharacteristicsDiscovered(uuid, serviceUuid, characteristics, error ? error.localizedDescription.UTF8String : "");
239
257
  }
240
258
 
241
259
  - (BOOL)read:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid {
@@ -258,7 +276,7 @@
258
276
  data.assign(bytes, bytes+[characteristic.value length]);
259
277
  bool isNotification = !pendingRead && characteristic.isNotifying;
260
278
  pendingRead = false;
261
- emit.Read(uuid, serviceUuid, characteristicUuid, data, isNotification);
279
+ emit.Read(uuid, serviceUuid, characteristicUuid, data, isNotification, error ? error.localizedDescription.UTF8String : "");
262
280
  }
263
281
 
264
282
  - (BOOL)write:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid data:(NSData*) data withoutResponse:(BOOL)withoutResponse {
@@ -279,7 +297,7 @@
279
297
  std::string uuid = getUuid(peripheral);
280
298
  std::string serviceUuid = [characteristic.service.UUID.UUIDString UTF8String];
281
299
  std::string characteristicUuid = [characteristic.UUID.UUIDString UTF8String];
282
- emit.Write(uuid, serviceUuid, characteristicUuid);
300
+ emit.Write(uuid, serviceUuid, characteristicUuid, error ? error.localizedDescription.UTF8String : "");
283
301
  }
284
302
 
285
303
  - (BOOL)notify:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid on:(BOOL)on {
@@ -296,7 +314,7 @@
296
314
  std::string uuid = getUuid(peripheral);
297
315
  std::string serviceUuid = [characteristic.service.UUID.UUIDString UTF8String];
298
316
  std::string characteristicUuid = [characteristic.UUID.UUIDString UTF8String];
299
- emit.Notify(uuid, serviceUuid, characteristicUuid, characteristic.isNotifying);
317
+ emit.Notify(uuid, serviceUuid, characteristicUuid, characteristic.isNotifying, error ? error.localizedDescription.UTF8String : "");
300
318
  }
301
319
 
302
320
  #pragma mark - Descriptors
@@ -316,7 +334,7 @@
316
334
  std::string serviceUuid = [characteristic.service.UUID.UUIDString UTF8String];
317
335
  std::string characteristicUuid = [characteristic.UUID.UUIDString UTF8String];
318
336
  std::vector<std::string> descriptors = getDescriptors(characteristic.descriptors);
319
- emit.DescriptorsDiscovered(uuid, serviceUuid, characteristicUuid, descriptors);
337
+ emit.DescriptorsDiscovered(uuid, serviceUuid, characteristicUuid, descriptors, error ? error.localizedDescription.UTF8String : "");
320
338
  }
321
339
 
322
340
  - (BOOL)readValue:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid descriptor:(NSString*) descriptorUuid {
@@ -334,13 +352,37 @@
334
352
  std::string serviceUuid = [descriptor.characteristic.service.UUID.UUIDString UTF8String];
335
353
  std::string characteristicUuid = [descriptor.characteristic.UUID.UUIDString UTF8String];
336
354
  std::string descriptorUuid = [descriptor.UUID.UUIDString UTF8String];
337
- const UInt8* bytes = (UInt8 *)[descriptor.value bytes];
355
+
338
356
  Data data;
339
- data.assign(bytes, bytes+[descriptor.value length]);
357
+
358
+ if (descriptor.value != nil) {
359
+ if ([descriptor.value isKindOfClass:[NSData class]]) {
360
+ // Handle NSData directly
361
+ NSData *valueData = (NSData *)descriptor.value;
362
+ const UInt8* bytes = (UInt8 *)[valueData bytes];
363
+ data.assign(bytes, bytes + [valueData length]);
364
+ }
365
+ else if ([descriptor.value isKindOfClass:[NSString class]]) {
366
+ // Convert NSString to bytes
367
+ NSString *valueString = (NSString *)descriptor.value;
368
+ NSData *valueData = [valueString dataUsingEncoding:NSUTF8StringEncoding];
369
+ const UInt8* bytes = (UInt8 *)[valueData bytes];
370
+ data.assign(bytes, bytes + [valueData length]);
371
+ }
372
+ else if ([descriptor.value isKindOfClass:[NSNumber class]]) {
373
+ // Convert NSNumber to bytes
374
+ NSNumber *valueNumber = (NSNumber *)descriptor.value;
375
+ NSData *valueData = [NSData dataWithBytes:valueNumber.stringValue.UTF8String
376
+ length:strlen(valueNumber.stringValue.UTF8String)];
377
+ const UInt8* bytes = (UInt8 *)[valueData bytes];
378
+ data.assign(bytes, bytes + [valueData length]);
379
+ }
380
+ }
381
+
340
382
  IF(NSNumber*, handle, [self getDescriptorHandle:descriptor]) {
341
383
  emit.ReadHandle(uuid, [handle intValue], data);
342
384
  }
343
- emit.ReadValue(uuid, serviceUuid, characteristicUuid, descriptorUuid, data);
385
+ emit.ReadValue(uuid, serviceUuid, characteristicUuid, descriptorUuid, data, error ? error.localizedDescription.UTF8String : "");
344
386
  }
345
387
 
346
388
  - (BOOL)writeValue:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid descriptor:(NSString*) descriptorUuid data:(NSData*) data {
@@ -361,7 +403,7 @@
361
403
  IF(NSNumber*, handle, [self getDescriptorHandle:descriptor]) {
362
404
  emit.WriteHandle(uuid, [handle intValue]);
363
405
  }
364
- emit.WriteValue(uuid, serviceUuid, characteristicUuid, descriptorUuid);
406
+ emit.WriteValue(uuid, serviceUuid, characteristicUuid, descriptorUuid, error ? error.localizedDescription.UTF8String : "");
365
407
  }
366
408
 
367
409
  - (BOOL)readHandle:(NSString*) uuid handle:(NSNumber*) handle {
@@ -450,3 +492,4 @@
450
492
  }
451
493
 
452
494
  @end
495
+
@@ -1,6 +1,7 @@
1
1
  #pragma once
2
2
 
3
3
  #include <napi.h>
4
+
4
5
  #import <Foundation/Foundation.h>
5
6
 
6
7
  NSArray* getUuidArray(const Napi::Value& value);
@@ -1,9 +1,3 @@
1
- //
2
- // napi_objc.mm
3
- // noble-mac-native
4
- //
5
- // Created by Georg Vienna on 30.08.18.
6
- //
7
1
  #include "napi_objc.h"
8
2
 
9
3
  NSString* napiToUuidString(Napi::String string) {
@@ -8,11 +8,13 @@ class NobleMac : public Napi::ObjectWrap<NobleMac>
8
8
  {
9
9
  public:
10
10
  NobleMac(const Napi::CallbackInfo&);
11
- Napi::Value Init(const Napi::CallbackInfo&);
11
+ Napi::Value Start(const Napi::CallbackInfo&);
12
+ Napi::Value Stop(const Napi::CallbackInfo&);
12
13
  Napi::Value Scan(const Napi::CallbackInfo&);
13
14
  Napi::Value StopScan(const Napi::CallbackInfo&);
14
15
  Napi::Value Connect(const Napi::CallbackInfo&);
15
16
  Napi::Value Disconnect(const Napi::CallbackInfo&);
17
+ Napi::Value CancelConnect(const Napi::CallbackInfo&);
16
18
  Napi::Value UpdateRSSI(const Napi::CallbackInfo&);
17
19
  Napi::Value DiscoverServices(const Napi::CallbackInfo&);
18
20
  Napi::Value DiscoverIncludedServices(const Napi::CallbackInfo& info);
@@ -25,9 +27,9 @@ public:
25
27
  Napi::Value WriteValue(const Napi::CallbackInfo& info);
26
28
  Napi::Value ReadHandle(const Napi::CallbackInfo& info);
27
29
  Napi::Value WriteHandle(const Napi::CallbackInfo& info);
28
- Napi::Value Stop(const Napi::CallbackInfo&);
30
+ Napi::Value AddressToId(const Napi::CallbackInfo& info);
29
31
 
30
- static Napi::Function GetClass(Napi::Env);
32
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
31
33
 
32
34
  private:
33
35
  BLEManager* manager;
@@ -1,11 +1,4 @@
1
- //
2
- // noble_mac.mm
3
- // noble-mac-native
4
- //
5
- // Created by Georg Vienna on 28.08.18.
6
- //
7
1
  #include "noble_mac.h"
8
-
9
2
  #include "napi_objc.h"
10
3
 
11
4
  #define THROW(msg) \
@@ -39,107 +32,134 @@ if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !inf
39
32
 
40
33
  #define CHECK_MANAGER() \
41
34
  if(!manager) { \
42
- THROW("BLEManager has already been cleaned up"); \
35
+ THROW(std::string(__FUNCTION__) + ": BLEManager has already been cleaned up"); \
43
36
  }
44
37
 
45
- NobleMac::NobleMac(const Napi::CallbackInfo& info) : ObjectWrap(info) {
46
- }
38
+ NobleMac::NobleMac(const Napi::CallbackInfo& info) : ObjectWrap(info) {}
47
39
 
48
- Napi::Value NobleMac::Init(const Napi::CallbackInfo& info) {
40
+ Napi::Value NobleMac::Start(const Napi::CallbackInfo& info)
41
+ {
49
42
  Napi::Function emit = info.This().As<Napi::Object>().Get("emit").As<Napi::Function>();
50
43
  manager = [[BLEManager alloc] init:info.This() with:emit];
51
44
  return Napi::Value();
52
45
  }
53
46
 
47
+ Napi::Value NobleMac::Stop(const Napi::CallbackInfo& info)
48
+ {
49
+ CHECK_MANAGER()
50
+ manager = nil;
51
+ return info.Env().Undefined();
52
+ }
53
+
54
54
  // startScanning(serviceUuids, allowDuplicates)
55
- Napi::Value NobleMac::Scan(const Napi::CallbackInfo& info) {
55
+ Napi::Value NobleMac::Scan(const Napi::CallbackInfo& info)
56
+ {
56
57
  CHECK_MANAGER()
57
58
  NSArray* array = getUuidArray(info[0]);
58
59
  // default value NO
59
60
  auto duplicates = getBool(info[1], NO);
60
61
  [manager scan:array allowDuplicates:duplicates];
61
- return Napi::Value();
62
+ return info.Env().Undefined();
62
63
  }
63
64
 
64
65
  // stopScanning()
65
- Napi::Value NobleMac::StopScan(const Napi::CallbackInfo& info) {
66
+ Napi::Value NobleMac::StopScan(const Napi::CallbackInfo& info)
67
+ {
66
68
  CHECK_MANAGER()
67
69
  [manager stopScan];
68
- return Napi::Value();
70
+ return info.Env().Undefined();
69
71
  }
70
72
 
71
73
  // connect(deviceUuid)
72
- Napi::Value NobleMac::Connect(const Napi::CallbackInfo& info) {
74
+ Napi::Value NobleMac::Connect(const Napi::CallbackInfo& info)
75
+ {
73
76
  CHECK_MANAGER()
74
77
  ARG1(String)
75
78
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
76
79
  [manager connect:uuid];
77
- return Napi::Value();
80
+ return info.Env().Undefined();
78
81
  }
79
82
 
80
83
  // disconnect(deviceUuid)
81
- Napi::Value NobleMac::Disconnect(const Napi::CallbackInfo& info) {
84
+ Napi::Value NobleMac::Disconnect(const Napi::CallbackInfo& info)
85
+ {
82
86
  CHECK_MANAGER()
83
87
  ARG1(String)
84
88
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
85
89
  [manager disconnect:uuid];
86
- return Napi::Value();
90
+ return info.Env().Undefined();
91
+ }
92
+
93
+ // cancelConnect(deviceUuid)
94
+ Napi::Value NobleMac::CancelConnect(const Napi::CallbackInfo& info)
95
+ {
96
+ CHECK_MANAGER()
97
+ ARG1(String)
98
+ auto uuid = napiToUuidString(info[0].As<Napi::String>());
99
+ [manager disconnect:uuid];
100
+ return info.Env().Undefined();
87
101
  }
88
102
 
89
103
  // updateRssi(deviceUuid)
90
- Napi::Value NobleMac::UpdateRSSI(const Napi::CallbackInfo& info) {
104
+ Napi::Value NobleMac::UpdateRSSI(const Napi::CallbackInfo& info)
105
+ {
91
106
  CHECK_MANAGER()
92
107
  ARG1(String)
93
108
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
94
109
  [manager updateRSSI:uuid];
95
- return Napi::Value();
110
+ return info.Env().Undefined();
96
111
  }
97
112
 
98
113
  // discoverServices(deviceUuid, uuids)
99
- Napi::Value NobleMac::DiscoverServices(const Napi::CallbackInfo& info) {
114
+ Napi::Value NobleMac::DiscoverServices(const Napi::CallbackInfo& info)
115
+ {
100
116
  CHECK_MANAGER()
101
117
  ARG1(String)
102
118
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
103
119
  NSArray* array = getUuidArray(info[1]);
104
120
  [manager discoverServices:uuid serviceUuids:array];
105
- return Napi::Value();
121
+ return info.Env().Undefined();
106
122
  }
107
123
 
108
124
  // discoverIncludedServices(deviceUuid, serviceUuid, serviceUuids)
109
- Napi::Value NobleMac::DiscoverIncludedServices(const Napi::CallbackInfo& info) {
125
+ Napi::Value NobleMac::DiscoverIncludedServices(const Napi::CallbackInfo& info)
126
+ {
110
127
  CHECK_MANAGER()
111
128
  ARG2(String, String)
112
129
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
113
130
  auto service = napiToUuidString(info[1].As<Napi::String>());
114
131
  NSArray* serviceUuids = getUuidArray(info[2]);
115
132
  [manager discoverIncludedServices:uuid forService:service services:serviceUuids];
116
- return Napi::Value();
133
+ return info.Env().Undefined();
117
134
  }
118
135
 
119
136
  // discoverCharacteristics(deviceUuid, serviceUuid, characteristicUuids)
120
- Napi::Value NobleMac::DiscoverCharacteristics(const Napi::CallbackInfo& info) {
137
+ Napi::Value NobleMac::DiscoverCharacteristics(const Napi::CallbackInfo& info)
138
+ {
121
139
  CHECK_MANAGER()
122
140
  ARG2(String, String)
123
141
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
124
142
  auto service = napiToUuidString(info[1].As<Napi::String>());
125
143
  NSArray* characteristics = getUuidArray(info[2]);
126
144
  [manager discoverCharacteristics:uuid forService:service characteristics:characteristics];
127
- return Napi::Value();
145
+ return info.Env().Undefined();
128
146
  }
129
147
 
130
148
  // read(deviceUuid, serviceUuid, characteristicUuid)
131
- Napi::Value NobleMac::Read(const Napi::CallbackInfo& info) {
149
+ Napi::Value NobleMac::Read(const Napi::CallbackInfo& info)
150
+ {
132
151
  CHECK_MANAGER()
133
152
  ARG3(String, String, String)
134
153
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
135
154
  auto service = napiToUuidString(info[1].As<Napi::String>());
136
155
  auto characteristic = napiToUuidString(info[2].As<Napi::String>());
137
156
  [manager read:uuid service:service characteristic:characteristic];
138
- return Napi::Value();
157
+ return info.Env().Undefined();
139
158
  }
140
159
 
141
160
  // write(deviceUuid, serviceUuid, characteristicUuid, data, withoutResponse)
142
- Napi::Value NobleMac::Write(const Napi::CallbackInfo& info) {
161
+ Napi::Value NobleMac::Write(const Napi::CallbackInfo& info)
162
+ {
143
163
  CHECK_MANAGER()
144
164
  ARG4(String, String, String, Buffer /*, Boolean */)
145
165
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
@@ -153,11 +173,12 @@ Napi::Value NobleMac::Write(const Napi::CallbackInfo& info) {
153
173
  }
154
174
 
155
175
  [manager write:uuid service:service characteristic:characteristic data:data withoutResponse:withoutResponse];
156
- return Napi::Value();
176
+ return info.Env().Undefined();
157
177
  }
158
178
 
159
179
  // notify(deviceUuid, serviceUuid, characteristicUuid, notify)
160
- Napi::Value NobleMac::Notify(const Napi::CallbackInfo& info) {
180
+ Napi::Value NobleMac::Notify(const Napi::CallbackInfo& info)
181
+ {
161
182
  CHECK_MANAGER()
162
183
  ARG4(String, String, String, Boolean)
163
184
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
@@ -165,22 +186,24 @@ Napi::Value NobleMac::Notify(const Napi::CallbackInfo& info) {
165
186
  auto characteristic = napiToUuidString(info[2].As<Napi::String>());
166
187
  auto on = info[3].As<Napi::Boolean>().Value();
167
188
  [manager notify:uuid service:service characteristic:characteristic on:on];
168
- return Napi::Value();
189
+ return info.Env().Undefined();
169
190
  }
170
191
 
171
192
  // discoverDescriptors(deviceUuid, serviceUuid, characteristicUuid)
172
- Napi::Value NobleMac::DiscoverDescriptors(const Napi::CallbackInfo& info) {
193
+ Napi::Value NobleMac::DiscoverDescriptors(const Napi::CallbackInfo& info)
194
+ {
173
195
  CHECK_MANAGER()
174
196
  ARG3(String, String, String)
175
197
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
176
198
  auto service = napiToUuidString(info[1].As<Napi::String>());
177
199
  auto characteristic = napiToUuidString(info[2].As<Napi::String>());
178
200
  [manager discoverDescriptors:uuid service:service characteristic:characteristic];
179
- return Napi::Value();
201
+ return info.Env().Undefined();
180
202
  }
181
203
 
182
204
  // readValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid)
183
- Napi::Value NobleMac::ReadValue(const Napi::CallbackInfo& info) {
205
+ Napi::Value NobleMac::ReadValue(const Napi::CallbackInfo& info)
206
+ {
184
207
  CHECK_MANAGER()
185
208
  ARG4(String, String, String, String)
186
209
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
@@ -188,11 +211,12 @@ Napi::Value NobleMac::ReadValue(const Napi::CallbackInfo& info) {
188
211
  auto characteristic = napiToUuidString(info[2].As<Napi::String>());
189
212
  auto descriptor = napiToUuidString(info[3].As<Napi::String>());
190
213
  [manager readValue:uuid service:service characteristic:characteristic descriptor:descriptor];
191
- return Napi::Value();
214
+ return info.Env().Undefined();
192
215
  }
193
216
 
194
217
  // writeValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid, data)
195
- Napi::Value NobleMac::WriteValue(const Napi::CallbackInfo& info) {
218
+ Napi::Value NobleMac::WriteValue(const Napi::CallbackInfo& info)
219
+ {
196
220
  CHECK_MANAGER()
197
221
  ARG5(String, String, String, String, Buffer)
198
222
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
@@ -201,44 +225,61 @@ Napi::Value NobleMac::WriteValue(const Napi::CallbackInfo& info) {
201
225
  auto descriptor = napiToUuidString(info[3].As<Napi::String>());
202
226
  auto data = napiToData(info[4].As<Napi::Buffer<Byte>>());
203
227
  [manager writeValue:uuid service:service characteristic:characteristic descriptor:descriptor data: data];
204
- return Napi::Value();
228
+ return info.Env().Undefined();
205
229
  }
206
230
 
207
231
  // readHandle(deviceUuid, handle)
208
- Napi::Value NobleMac::ReadHandle(const Napi::CallbackInfo& info) {
232
+ Napi::Value NobleMac::ReadHandle(const Napi::CallbackInfo& info)
233
+ {
209
234
  CHECK_MANAGER()
210
235
  ARG2(String, Number)
211
236
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
212
237
  auto handle = napiToNumber(info[1].As<Napi::Number>());
213
238
  [manager readHandle:uuid handle:handle];
214
- return Napi::Value();
239
+ return info.Env().Undefined();
215
240
  }
216
241
 
217
242
  // writeHandle(deviceUuid, handle, data, (unused)withoutResponse)
218
- Napi::Value NobleMac::WriteHandle(const Napi::CallbackInfo& info) {
243
+ Napi::Value NobleMac::WriteHandle(const Napi::CallbackInfo& info)
244
+ {
219
245
  CHECK_MANAGER()
220
246
  ARG3(String, Number, Buffer)
221
247
  auto uuid = napiToUuidString(info[0].As<Napi::String>());
222
248
  auto handle = napiToNumber(info[1].As<Napi::Number>());
223
249
  auto data = napiToData(info[2].As<Napi::Buffer<Byte>>());
224
250
  [manager writeHandle:uuid handle:handle data: data];
225
- return Napi::Value();
251
+ return info.Env().Undefined();
226
252
  }
227
253
 
228
- Napi::Value NobleMac::Stop(const Napi::CallbackInfo& info) {
229
- CHECK_MANAGER()
230
- CFRelease((__bridge CFTypeRef)manager);
231
- manager = nil;
232
- return Napi::Value();
254
+ // addressToId(address)
255
+ Napi::Value NobleMac::AddressToId(const Napi::CallbackInfo& info)
256
+ {
257
+ ARG1(String)
258
+ auto address = info[0].As<Napi::String>().Utf8Value();
259
+ NSMutableString * uuidString = [[NSMutableString alloc] initWithCString:address.c_str() encoding:NSASCIIStringEncoding];
260
+ if ([uuidString containsString:@"-"]) {
261
+ NSUUID* uuid = [[NSUUID alloc] initWithUUIDString:uuidString];
262
+ if (uuid) {
263
+ NSString* canonical = uuid.UUIDString;
264
+ NSString* result = [[canonical stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
265
+ return Napi::String::New(info.Env(), [result UTF8String]);
266
+ }
267
+ }
268
+ return info.Env().Null();
233
269
  }
234
270
 
235
- Napi::Function NobleMac::GetClass(Napi::Env env) {
236
- return DefineClass(env, "NobleMac", {
237
- NobleMac::InstanceMethod("init", &NobleMac::Init),
271
+ Napi::Object NobleMac::Init(Napi::Env env, Napi::Object exports)
272
+ {
273
+ Napi::HandleScope scope(env);
274
+
275
+ Napi::Function func = DefineClass(env, "NobleMac", {
276
+ NobleMac::InstanceMethod("start", &NobleMac::Start),
277
+ NobleMac::InstanceMethod("stop", &NobleMac::Stop),
238
278
  NobleMac::InstanceMethod("startScanning", &NobleMac::Scan),
239
279
  NobleMac::InstanceMethod("stopScanning", &NobleMac::StopScan),
240
280
  NobleMac::InstanceMethod("connect", &NobleMac::Connect),
241
281
  NobleMac::InstanceMethod("disconnect", &NobleMac::Disconnect),
282
+ NobleMac::InstanceMethod("cancelConnect", &NobleMac::CancelConnect),
242
283
  NobleMac::InstanceMethod("updateRssi", &NobleMac::UpdateRSSI),
243
284
  NobleMac::InstanceMethod("discoverServices", &NobleMac::DiscoverServices),
244
285
  NobleMac::InstanceMethod("discoverIncludedServices", &NobleMac::DiscoverIncludedServices),
@@ -251,14 +292,15 @@ Napi::Function NobleMac::GetClass(Napi::Env env) {
251
292
  NobleMac::InstanceMethod("writeValue", &NobleMac::WriteValue),
252
293
  NobleMac::InstanceMethod("readHandle", &NobleMac::ReadHandle),
253
294
  NobleMac::InstanceMethod("writeHandle", &NobleMac::WriteHandle),
254
- NobleMac::InstanceMethod("stop", &NobleMac::Stop),
295
+ NobleMac::InstanceMethod("addressToId", &NobleMac::AddressToId),
255
296
  });
256
- }
257
297
 
258
- Napi::Object Init(Napi::Env env, Napi::Object exports) {
259
- Napi::String name = Napi::String::New(env, "NobleMac");
260
- exports.Set(name, NobleMac::GetClass(env));
298
+ Napi::FunctionReference* constructor = new Napi::FunctionReference();
299
+ *constructor = Napi::Persistent(func);
300
+ env.SetInstanceData(constructor);
301
+
302
+ exports.Set("NobleMac", func);
261
303
  return exports;
262
304
  }
263
305
 
264
- NODE_API_MODULE(addon, Init)
306
+ NODE_API_NAMED_ADDON(addon, NobleMac);
@@ -2,9 +2,11 @@
2
2
 
3
3
  #include <string>
4
4
  #include <vector>
5
+
6
+ #include "Peripheral.h"
7
+
5
8
  #import <Foundation/Foundation.h>
6
9
  #import <CoreBluetooth/CoreBluetooth.h>
7
- #include "peripheral.h"
8
10
 
9
11
  #define IF(type, var, code) type var = code; if(var)
10
12
 
@@ -17,7 +19,6 @@
17
19
  std::string stateToString(CBCentralManagerState state);
18
20
  #endif
19
21
 
20
-
21
22
  NSString* getNSUuid(CBPeripheral* peripheral);
22
23
  std::string getUuid(CBPeripheral* peripheral);
23
24
  std::string getAddress(std::string uuid, AddressType* addressType);