@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,5 +1,4 @@
1
- const events = require('events');
2
- const util = require('util');
1
+ const { EventEmitter } = require('events');
3
2
 
4
3
  const AclStream = require('./acl-stream');
5
4
  const Gatt = require('./gatt');
@@ -10,7 +9,10 @@ const Signaling = require('./signaling');
10
9
  const NobleBindings = function (options) {
11
10
  this._state = null;
12
11
  this._isScanning = false;
12
+ this._isScanningStarted = false;
13
+ this._scanServiceUuids = [];
13
14
 
15
+ this._options = { ...options };
14
16
  this._addresses = {};
15
17
  this._addresseTypes = {};
16
18
  this._connectable = {};
@@ -25,11 +27,57 @@ const NobleBindings = function (options) {
25
27
  this._aclStreams = {};
26
28
  this._signalings = {};
27
29
 
28
- this._hci = new Hci(options);
30
+ this._hci = null;
31
+ this._gap = null;
32
+ };
33
+
34
+ Object.setPrototypeOf(NobleBindings.prototype, EventEmitter.prototype);
35
+
36
+ NobleBindings.prototype.start = function () {
37
+ /* Add exit handlers after `init()` has completed. If no adaptor
38
+ is present it can throw an exception - in which case we don't
39
+ want to try and clear up afterwards (issue #502) */
40
+ this._sigIntHandler = this.onSigInt.bind(this);
41
+ this._exitHandler = this.stop.bind(this);
42
+ process.on('SIGINT', this._sigIntHandler);
43
+ process.on('exit', this._exitHandler);
44
+
45
+ // Initialize the hci
46
+ this._hci = new Hci(this._options);
47
+
48
+ // Register event listeners for the hci
49
+ this._hci.on('stateChange', this.onStateChange.bind(this));
50
+ this._hci.on('addressChange', this.onAddressChange.bind(this));
51
+ this._hci.on('leConnComplete', this.onLeConnComplete.bind(this));
52
+ this._hci.on('leConnUpdateComplete', this.onLeConnUpdateComplete.bind(this));
53
+ this._hci.on('rssiRead', this.onRssiRead.bind(this));
54
+ this._hci.on('disconnComplete', this.onDisconnComplete.bind(this));
55
+ this._hci.on('encryptChange', this.onEncryptChange.bind(this));
56
+ this._hci.on('aclDataPkt', this.onAclDataPkt.bind(this));
57
+
58
+ // Initialize the gap
29
59
  this._gap = new Gap(this._hci);
60
+
61
+ // Register event listeners for the gap
62
+ this._gap.on('scanParametersSet', this.onScanParametersSet.bind(this));
63
+ this._gap.on('scanStart', this.onScanStart.bind(this));
64
+ this._gap.on('scanStop', this.onScanStop.bind(this));
65
+ this._gap.on('discover', this.onDiscover.bind(this));
66
+
67
+ // Initialize the hci
68
+ this._hci.init();
30
69
  };
31
70
 
32
- util.inherits(NobleBindings, events.EventEmitter);
71
+ NobleBindings.prototype.stop = function () {
72
+ process.removeListener('exit', this._exitHandler);
73
+ process.removeListener('SIGINT', this._sigIntHandler);
74
+
75
+ this.stopScanning();
76
+ for (const handle in this._aclStreams) {
77
+ this._hci.disconnect(handle);
78
+ }
79
+ this._hci.stop();
80
+ };
33
81
 
34
82
  NobleBindings.prototype.setScanParameters = function (interval, window) {
35
83
  this._gap.setScanParameters(interval, window);
@@ -43,13 +91,25 @@ NobleBindings.prototype.startScanning = function (
43
91
  serviceUuids,
44
92
  allowDuplicates
45
93
  ) {
94
+ if (this._isScanning) {
95
+ this.emit('scanStart');
96
+ return;
97
+ }
98
+ if (this._isScanningStarted) {
99
+ return;
100
+ }
101
+ this._isScanningStarted = true;
46
102
  this._scanServiceUuids = serviceUuids || [];
47
-
48
103
  this._gap.startScanning(allowDuplicates);
49
104
  };
50
105
 
51
106
  NobleBindings.prototype.stopScanning = function () {
52
- this._gap.stopScanning();
107
+ if (this._isScanning) {
108
+ this._gap.stopScanning();
109
+ }
110
+ else {
111
+ this.emit('scanStop');
112
+ }
53
113
  };
54
114
 
55
115
  NobleBindings.prototype.connect = function (peripheralUuid, parameters = {}) {
@@ -66,14 +126,14 @@ NobleBindings.prototype.connect = function (peripheralUuid, parameters = {}) {
66
126
  id: peripheralUuid,
67
127
  address,
68
128
  addressType,
69
- params: parameters
129
+ params: parameters
70
130
  });
71
131
 
72
132
  const processNextConnection = () => {
73
- if (this._connectionQueue.length === 0) return;
74
-
75
- const nextConn = this._connectionQueue[0]; // Look at next connection but don't remove yet
76
- this._hci.createLeConn(nextConn.address, nextConn.addressType, nextConn.params);
133
+ if (this._connectionQueue.length === 1) {
134
+ const nextConn = this._connectionQueue[0]; // Look at next connection but don't remove yet
135
+ this._hci.createLeConn(nextConn.address, nextConn.addressType, nextConn.params);
136
+ }
77
137
  };
78
138
 
79
139
  if (this._isScanning) {
@@ -96,62 +156,21 @@ NobleBindings.prototype.cancelConnect = function (peripheralUuid) {
96
156
  this._hci.cancelConnect(this._handles[peripheralUuid]);
97
157
  };
98
158
 
99
- NobleBindings.prototype.reset = function () {
100
- this._hci.reset();
101
- };
102
-
103
159
  NobleBindings.prototype.updateRssi = function (peripheralUuid) {
104
160
  this._hci.readRssi(this._handles[peripheralUuid]);
105
161
  };
106
162
 
107
- NobleBindings.prototype.init = function () {
108
- /* Add exit handlers after `init()` has completed. If no adaptor
109
- is present it can throw an exception - in which case we don't
110
- want to try and clear up afterwards (issue #502) */
111
- this._sigIntHandler = this.onSigInt.bind(this);
112
- this._exitHandler = this.stop.bind(this);
113
- process.on('SIGINT', this._sigIntHandler);
114
- process.on('exit', this._exitHandler);
115
-
116
- this._gap.on('scanParametersSet', this.onScanParametersSet.bind(this));
117
- this._gap.on('scanStart', this.onScanStart.bind(this));
118
- this._gap.on('scanStop', this.onScanStop.bind(this));
119
- this._gap.on('discover', this.onDiscover.bind(this));
120
-
121
- this._hci.on('stateChange', this.onStateChange.bind(this));
122
- this._hci.on('addressChange', this.onAddressChange.bind(this));
123
- this._hci.on('leConnComplete', this.onLeConnComplete.bind(this));
124
- this._hci.on('leConnUpdateComplete', this.onLeConnUpdateComplete.bind(this));
125
- this._hci.on('rssiRead', this.onRssiRead.bind(this));
126
- this._hci.on('disconnComplete', this.onDisconnComplete.bind(this));
127
- this._hci.on('encryptChange', this.onEncryptChange.bind(this));
128
- this._hci.on('aclDataPkt', this.onAclDataPkt.bind(this));
129
-
130
- this._hci.init();
131
- };
132
-
133
163
  NobleBindings.prototype.onSigInt = function () {
134
164
  const sigIntListeners = process.listeners('SIGINT');
135
165
 
136
166
  if (sigIntListeners[sigIntListeners.length - 1] === this._sigIntHandler) {
137
167
  // we are the last listener, so exit
138
168
  // this will trigger onExit, and clean up
169
+ // eslint-disable-next-line no-process-exit
139
170
  process.exit(1);
140
171
  }
141
172
  };
142
173
 
143
- NobleBindings.prototype.stop = function () {
144
- process.removeListener('exit', this._exitHandler);
145
- process.removeListener('SIGINT', this._sigIntHandler);
146
-
147
- this.stopScanning();
148
- for (const handle in this._aclStreams) {
149
- this._hci.disconnect(handle);
150
- }
151
- this._hci.reset();
152
- this._hci.stop();
153
- };
154
-
155
174
  NobleBindings.prototype.onStateChange = function (state) {
156
175
  if (this._state === state) {
157
176
  return;
@@ -202,6 +221,7 @@ NobleBindings.prototype.onScanStart = function (filterDuplicates) {
202
221
 
203
222
  NobleBindings.prototype.onScanStop = function () {
204
223
  this._isScanning = false;
224
+ this._isScanningStarted = false;
205
225
  this.emit('scanStop');
206
226
  };
207
227
 
@@ -242,7 +262,7 @@ NobleBindings.prototype.onDiscover = function (
242
262
  }
243
263
 
244
264
  if (hasScanServiceUuids) {
245
- const uuid = address.split(':').join('');
265
+ const uuid = this.addressToId(address);
246
266
  this._addresses[uuid] = address;
247
267
  this._addresseTypes[uuid] = addressType;
248
268
  this._connectable[uuid] = connectable;
@@ -281,7 +301,7 @@ NobleBindings.prototype.onLeConnComplete = function (
281
301
  let error = null;
282
302
 
283
303
  if (status === 0) {
284
- uuid = address.split(':').join('').toLowerCase();
304
+ uuid = this.addressToId(address);
285
305
 
286
306
  // Check if address is already known
287
307
  if (!this._addresses[uuid]) {
@@ -428,7 +448,7 @@ NobleBindings.prototype.onEncryptChange = function (handle, encrypt) {
428
448
  };
429
449
 
430
450
  NobleBindings.prototype.onMtu = function (address, mtu) {
431
- const uuid = address.split(':').join('').toLowerCase();
451
+ const uuid = this.addressToId(address);
432
452
 
433
453
  this.emit('onMtu', uuid, mtu);
434
454
  };
@@ -471,13 +491,13 @@ NobleBindings.prototype.onServicesDiscovered = function (
471
491
  address,
472
492
  serviceUuids
473
493
  ) {
474
- const uuid = address.split(':').join('').toLowerCase();
494
+ const uuid = this.addressToId(address);
475
495
 
476
496
  this.emit('servicesDiscover', uuid, serviceUuids);
477
497
  };
478
498
 
479
499
  NobleBindings.prototype.onServicesDiscoveredEX = function (address, services) {
480
- const uuid = address.split(':').join('').toLowerCase();
500
+ const uuid = this.addressToId(address);
481
501
 
482
502
  this.emit('servicesDiscovered', uuid, services);
483
503
  };
@@ -502,7 +522,7 @@ NobleBindings.prototype.onIncludedServicesDiscovered = function (
502
522
  serviceUuid,
503
523
  includedServiceUuids
504
524
  ) {
505
- const uuid = address.split(':').join('').toLowerCase();
525
+ const uuid = this.addressToId(address);
506
526
 
507
527
  this.emit(
508
528
  'includedServicesDiscover',
@@ -547,7 +567,7 @@ NobleBindings.prototype.onCharacteristicsDiscovered = function (
547
567
  serviceUuid,
548
568
  characteristics
549
569
  ) {
550
- const uuid = address.split(':').join('').toLowerCase();
570
+ const uuid = this.addressToId(address);
551
571
 
552
572
  this.emit('characteristicsDiscover', uuid, serviceUuid, characteristics);
553
573
  };
@@ -557,7 +577,7 @@ NobleBindings.prototype.onCharacteristicsDiscoveredEX = function (
557
577
  serviceUuid,
558
578
  characteristics
559
579
  ) {
560
- const uuid = address.split(':').join('').toLowerCase();
580
+ const uuid = this.addressToId(address);
561
581
 
562
582
  this.emit('characteristicsDiscovered', uuid, serviceUuid, characteristics);
563
583
  };
@@ -583,7 +603,7 @@ NobleBindings.prototype.onRead = function (
583
603
  characteristicUuid,
584
604
  data
585
605
  ) {
586
- const uuid = address.split(':').join('').toLowerCase();
606
+ const uuid = this.addressToId(address);
587
607
 
588
608
  this.emit('read', uuid, serviceUuid, characteristicUuid, data, false);
589
609
  };
@@ -610,7 +630,7 @@ NobleBindings.prototype.onWrite = function (
610
630
  serviceUuid,
611
631
  characteristicUuid
612
632
  ) {
613
- const uuid = address.split(':').join('').toLowerCase();
633
+ const uuid = this.addressToId(address);
614
634
 
615
635
  this.emit('write', uuid, serviceUuid, characteristicUuid);
616
636
  };
@@ -637,7 +657,7 @@ NobleBindings.prototype.onBroadcast = function (
637
657
  characteristicUuid,
638
658
  state
639
659
  ) {
640
- const uuid = address.split(':').join('').toLowerCase();
660
+ const uuid = this.addressToId(address);
641
661
 
642
662
  this.emit('broadcast', uuid, serviceUuid, characteristicUuid, state);
643
663
  };
@@ -650,7 +670,6 @@ NobleBindings.prototype.notify = function (
650
670
  ) {
651
671
  const handle = this._handles[peripheralUuid];
652
672
  const gatt = this._gatts[handle];
653
-
654
673
  if (gatt) {
655
674
  gatt.notify(serviceUuid, characteristicUuid, notify);
656
675
  } else {
@@ -664,7 +683,7 @@ NobleBindings.prototype.onNotify = function (
664
683
  characteristicUuid,
665
684
  state
666
685
  ) {
667
- const uuid = address.split(':').join('').toLowerCase();
686
+ const uuid = this.addressToId(address);
668
687
 
669
688
  this.emit('notify', uuid, serviceUuid, characteristicUuid, state);
670
689
  };
@@ -675,7 +694,7 @@ NobleBindings.prototype.onNotification = function (
675
694
  characteristicUuid,
676
695
  data
677
696
  ) {
678
- const uuid = address.split(':').join('').toLowerCase();
697
+ const uuid = this.addressToId(address);
679
698
 
680
699
  this.emit('read', uuid, serviceUuid, characteristicUuid, data, true);
681
700
  };
@@ -701,7 +720,7 @@ NobleBindings.prototype.onDescriptorsDiscovered = function (
701
720
  characteristicUuid,
702
721
  descriptorUuids
703
722
  ) {
704
- const uuid = address.split(':').join('').toLowerCase();
723
+ const uuid = this.addressToId(address);
705
724
 
706
725
  this.emit(
707
726
  'descriptorsDiscover',
@@ -735,7 +754,7 @@ NobleBindings.prototype.onValueRead = function (
735
754
  descriptorUuid,
736
755
  data
737
756
  ) {
738
- const uuid = address.split(':').join('').toLowerCase();
757
+ const uuid = this.addressToId(address);
739
758
 
740
759
  this.emit(
741
760
  'valueRead',
@@ -770,7 +789,7 @@ NobleBindings.prototype.onValueWrite = function (
770
789
  characteristicUuid,
771
790
  descriptorUuid
772
791
  ) {
773
- const uuid = address.split(':').join('').toLowerCase();
792
+ const uuid = this.addressToId(address);
774
793
 
775
794
  this.emit(
776
795
  'valueWrite',
@@ -793,7 +812,7 @@ NobleBindings.prototype.readHandle = function (peripheralUuid, attHandle) {
793
812
  };
794
813
 
795
814
  NobleBindings.prototype.onHandleRead = function (address, handle, data) {
796
- const uuid = address.split(':').join('').toLowerCase();
815
+ const uuid = this.addressToId(address);
797
816
 
798
817
  this.emit('handleRead', uuid, handle, data);
799
818
  };
@@ -815,13 +834,13 @@ NobleBindings.prototype.writeHandle = function (
815
834
  };
816
835
 
817
836
  NobleBindings.prototype.onHandleWrite = function (address, handle) {
818
- const uuid = address.split(':').join('').toLowerCase();
837
+ const uuid = this.addressToId(address);
819
838
 
820
839
  this.emit('handleWrite', uuid, handle);
821
840
  };
822
841
 
823
842
  NobleBindings.prototype.onHandleNotify = function (address, handle, data) {
824
- const uuid = address.split(':').join('').toLowerCase();
843
+ const uuid = this.addressToId(address);
825
844
 
826
845
  this.emit('handleNotify', uuid, handle, data);
827
846
  };
@@ -842,4 +861,8 @@ NobleBindings.prototype.onConnectionParameterUpdateRequest = function (
842
861
  );
843
862
  };
844
863
 
864
+ NobleBindings.prototype.addressToId = function (address) {
865
+ return address.replace(/:/g, '').toLowerCase();
866
+ };
867
+
845
868
  module.exports = NobleBindings;
@@ -1,8 +1,7 @@
1
1
  const debug = require('debug')('gap');
2
2
 
3
- const events = require('events');
3
+ const { EventEmitter } = require('events');
4
4
  const os = require('os');
5
- const util = require('util');
6
5
 
7
6
  const isChip = os.platform() === 'linux' && os.release().indexOf('-ntc') !== -1;
8
7
 
@@ -34,7 +33,7 @@ const Gap = function (hci) {
34
33
  this._hci.on('leScanEnableSetCmd', this.onLeScanEnableSetCmd.bind(this));
35
34
  };
36
35
 
37
- util.inherits(Gap, events.EventEmitter);
36
+ Object.setPrototypeOf(Gap.prototype, EventEmitter.prototype);
38
37
 
39
38
  Gap.prototype.setScanParameters = function (interval, window) {
40
39
  this._hci.setScanParameters(interval, window);
@@ -1,7 +1,6 @@
1
1
  const debug = require('debug')('att');
2
2
 
3
- const events = require('events');
4
- const util = require('util');
3
+ const { EventEmitter } = require('events');
5
4
 
6
5
  /* eslint-disable no-unused-vars */
7
6
  const ATT_OP_ERROR = 0x01;
@@ -83,7 +82,7 @@ const Gatt = function (address, aclStream) {
83
82
  this._aclStream.on('end', this.onAclStreamEndBinded);
84
83
  };
85
84
 
86
- util.inherits(Gatt, events.EventEmitter);
85
+ Object.setPrototypeOf(Gatt.prototype, EventEmitter.prototype);
87
86
 
88
87
  Gatt.prototype.onAclStreamData = function (cid, data) {
89
88
  if (cid !== ATT_CID) {
@@ -683,10 +682,8 @@ Gatt.prototype.notify = function (serviceUuid, characteristicUuid, notify) {
683
682
 
684
683
  const valueBuffer = Buffer.alloc(2);
685
684
  valueBuffer.writeUInt16LE(value, 0);
686
-
687
685
  this._queueCommand(this.writeRequest(handle, valueBuffer, false), data => {
688
686
  const opcode = data[0];
689
-
690
687
  if (opcode === ATT_OP_WRITE_RESP) {
691
688
  this.emit('notify', this._address, serviceUuid, characteristicUuid, notify);
692
689
  }
@@ -1,9 +1,8 @@
1
1
  const debug = require('debug')('hci');
2
2
 
3
- const events = require('events');
4
- const util = require('util');
3
+ const { EventEmitter } = require('events');
5
4
 
6
- const BluetoothHciSocket = require('@stoprocent/bluetooth-hci-socket');
5
+ const { loadDriver } = require('@stoprocent/bluetooth-hci-socket');
7
6
  const vendorSpecific = require('./vs');
8
7
 
9
8
  const HCI_COMMAND_PKT = 0x01;
@@ -99,7 +98,11 @@ const STATUS_MAPPER = require('./hci-status');
99
98
  const Hci = function (options) {
100
99
  options = options || {};
101
100
  this._manufacturer = null;
101
+
102
+ const BluetoothHciSocket = loadDriver(options.hciDriver || 'default');
102
103
  this._socket = new BluetoothHciSocket();
104
+
105
+ this._isStarted = false;
103
106
  this._isDevUp = null;
104
107
  this._isExtended = 'extended' in options && options.extended;
105
108
  this._state = null;
@@ -146,7 +149,7 @@ const Hci = function (options) {
146
149
  this.on('stateChange', this.onStateChange.bind(this));
147
150
  };
148
151
 
149
- util.inherits(Hci, events.EventEmitter);
152
+ Object.setPrototypeOf(Hci.prototype, EventEmitter.prototype);
150
153
 
151
154
  Hci.STATUS_MAPPER = STATUS_MAPPER;
152
155
 
@@ -166,7 +169,7 @@ Hci.prototype.init = function (options) {
166
169
  this._bound = true;
167
170
  }
168
171
  this._socket.start();
169
-
172
+ this._isStarted = true;
170
173
  this.reset();
171
174
  this.pollIsDevUp();
172
175
  }
@@ -193,8 +196,9 @@ Hci.prototype.pollIsDevUp = function () {
193
196
 
194
197
  this._isDevUp = isDevUp;
195
198
  }
196
-
197
- setTimeout(this.pollIsDevUp.bind(this), 1000);
199
+ if (this._isStarted) {
200
+ setTimeout(this.pollIsDevUp.bind(this), 1000);
201
+ }
198
202
  };
199
203
 
200
204
  Hci.prototype.setCodedPhySupport = function () {
@@ -287,6 +291,7 @@ Hci.prototype.reset = function () {
287
291
 
288
292
  Hci.prototype.stop = function () {
289
293
  this._socket.stop();
294
+ this._isStarted = false;
290
295
  };
291
296
 
292
297
  Hci.prototype.readSupportedCommands = function () {
@@ -926,6 +931,7 @@ Hci.prototype.processCmdCompleteEvent = function (cmd, status, result) {
926
931
  this.setLeEventMask();
927
932
  this.readLocalVersion();
928
933
  this.readBdAddr();
934
+ this.emit('reset');
929
935
  } else if (cmd === LE_READ_LOCAL_SUPPORTED_FEATURES && status === 0) {
930
936
  // Set _isExtended based on leExtendedAdvertising bit (12)
931
937
  this._isExtended = !!(result.readUInt32LE(0) & (1 << 12));
@@ -1054,6 +1060,9 @@ Hci.prototype.processLeMetaEvent = function (eventType, numReports, data) {
1054
1060
  };
1055
1061
 
1056
1062
  Hci.prototype.processLeConnComplete = function (status, data) {
1063
+ if (data.every(byte => byte === 0)) {
1064
+ return;
1065
+ }
1057
1066
  const handle = data.readUInt16LE(0);
1058
1067
  const role = data.readUInt8(2);
1059
1068
  const addressType = data.readUInt8(3) === 0x01 ? 'random' : 'public';
@@ -1094,6 +1103,9 @@ Hci.prototype.processLeConnComplete = function (status, data) {
1094
1103
  };
1095
1104
 
1096
1105
  Hci.prototype.processLeEnhancedConnComplete = function (status, data) {
1106
+ if (data.every(byte => byte === 0)) {
1107
+ return;
1108
+ }
1097
1109
  const handle = data.readUInt16LE(0);
1098
1110
  const role = data.readUInt8(2);
1099
1111
  const addressType = data.readUInt8(3) === 0x01 ? 'random' : 'public';
@@ -1,8 +1,7 @@
1
1
  const debug = require('debug')('signaling');
2
2
 
3
- const events = require('events');
3
+ const { EventEmitter } = require('events');
4
4
  const os = require('os');
5
- const util = require('util');
6
5
 
7
6
  const CONNECTION_PARAMETER_UPDATE_REQUEST = 0x12;
8
7
  const CONNECTION_PARAMETER_UPDATE_RESPONSE = 0x13;
@@ -20,7 +19,7 @@ const Signaling = function (handle, aclStream) {
20
19
  this._aclStream.on('end', this.onAclStreamEndBinded);
21
20
  };
22
21
 
23
- util.inherits(Signaling, events.EventEmitter);
22
+ Object.setPrototypeOf(Signaling.prototype, EventEmitter.prototype);
24
23
 
25
24
  Signaling.prototype.onAclStreamData = function (cid, data) {
26
25
  if (cid !== SIGNALING_CID) {
@@ -1,5 +1,4 @@
1
- const events = require('events');
2
- const util = require('util');
1
+ const { EventEmitter } = require('events');
3
2
 
4
3
  const crypto = require('./crypto');
5
4
 
@@ -28,7 +27,7 @@ const Smp = function (aclStream, localAddressType, localAddress, remoteAddressTy
28
27
  this._aclStream.on('end', this.onAclStreamEndBinded);
29
28
  };
30
29
 
31
- util.inherits(Smp, events.EventEmitter);
30
+ Object.setPrototypeOf(Smp.prototype, EventEmitter.prototype);
32
31
 
33
32
  Smp.prototype.sendPairingRequest = function () {
34
33
  this._preq = Buffer.from([
@@ -142,6 +142,7 @@ vendors.set(18, write_common_bd_addr(OCF_ZEEVO_WRITE_BD_ADDR));
142
142
  vendors.set(48, st_write_bd_addr);
143
143
  vendors.set(57, write_common_bd_addr(OCF_ERICSSON_WRITE_BD_ADDR));
144
144
  vendors.set(72, mrvl_write_bd_addr);
145
+ vendors.set(305, write_common_bd_addr(OCF_BCM_WRITE_BD_ADDR));
145
146
  vendors.set(1521, write_common_bd_addr(OCF_LINUX_FOUNDATION_WRITE_BD_ADDR));
146
147
 
147
148
  module.exports = {
@@ -6,21 +6,19 @@
6
6
  {
7
7
  'target_name': 'binding',
8
8
  'sources': [
9
- 'src/noble_mac.mm',
10
- 'src/napi_objc.mm',
11
- 'src/ble_manager.mm',
12
- 'src/objc_cpp.mm',
13
- 'src/callbacks.cc'
9
+ "<!@(node -p \"require('fs').readdirSync('src').filter(f=>new RegExp('.*\\\\.(c|cc|cpp|mm)$').test(f)).map(f=>'src/'+f).join(' ')\")",
10
+ "<!@(node -p \"require('fs').readdirSync('../common/src').filter(f=>new RegExp('.*\\\\.(c|cc|cpp)$').test(f)).map(f=>'../common/src/'+f).join(' ')\")"
14
11
  ],
15
12
  'include_dirs': [
16
- "<!(node -p \"require('node-addon-api').include_dir\")"
13
+ "<!(node -p \"require('node-addon-api').include_dir\")",
14
+ "../common/include"
17
15
  ],
18
16
  'cflags!': [ '-fno-exceptions' ],
19
17
  'cflags_cc!': [ '-fno-exceptions' ],
20
18
  "defines": ["NAPI_CPP_EXCEPTIONS"],
21
19
  'xcode_settings': {
22
20
  'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
23
- 'MACOSX_DEPLOYMENT_TARGET': '10.9',
21
+ 'MACOSX_DEPLOYMENT_TARGET': '11',
24
22
  'CLANG_CXX_LIBRARY': 'libc++',
25
23
  'OTHER_CFLAGS': [
26
24
  '-fobjc-arc',
@@ -1,11 +1,9 @@
1
1
  const { EventEmitter } = require('events');
2
- const { inherits } = require('util');
3
2
  const { resolve } = require('path');
4
3
  const dir = resolve(__dirname, '..', '..');
5
4
  const binding = require('node-gyp-build')(dir);
6
-
7
5
  const { NobleMac } = binding;
8
6
 
9
- inherits(NobleMac, EventEmitter);
7
+ Object.setPrototypeOf(NobleMac.prototype, EventEmitter.prototype);
10
8
 
11
9
  module.exports = NobleMac;
@@ -1,17 +1,10 @@
1
- //
2
- // ble_manager.h
3
- // noble-mac-native
4
- //
5
- // Created by Georg Vienna on 28.08.18.
6
- //
7
-
8
1
  #pragma once
9
2
 
10
3
  #import <Foundation/Foundation.h>
11
4
  #import <CoreBluetooth/CoreBluetooth.h>
12
5
  #include <dispatch/dispatch.h>
13
6
 
14
- #include "callbacks.h"
7
+ #include "Emit.h"
15
8
 
16
9
  @interface BLEManager : NSObject <CBCentralManagerDelegate, CBPeripheralDelegate> {
17
10
  Emit emit;