@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.
- package/README.md +393 -650
- package/examples/advertisement-discovery.js +57 -48
- package/examples/connect-address.js +59 -34
- package/examples/echo.js +59 -69
- package/examples/enter-exit.js +55 -49
- package/examples/multiple-bindings.js +53 -0
- package/examples/peripheral-explorer-async.js +39 -21
- package/examples/peripheral-explorer.ts +52 -0
- package/index.d.ts +249 -209
- package/index.js +4 -1
- package/jest.config.js +4 -0
- package/lib/characteristic.js +153 -127
- package/lib/{win/src/callbacks.h → common/include/Emit.h} +17 -14
- package/lib/common/include/Peripheral.h +31 -0
- package/lib/common/include/ThreadSafeCallback.h +95 -0
- package/lib/{win/src/callbacks.cc → common/src/Emit.cc} +111 -68
- package/lib/descriptor.js +57 -54
- package/lib/hci-socket/acl-stream.js +2 -4
- package/lib/hci-socket/bindings.js +96 -73
- package/lib/hci-socket/gap.js +2 -3
- package/lib/hci-socket/gatt.js +2 -5
- package/lib/hci-socket/hci.js +19 -7
- package/lib/hci-socket/signaling.js +2 -3
- package/lib/hci-socket/smp.js +2 -3
- package/lib/hci-socket/vs.js +1 -0
- package/lib/mac/binding.gyp +5 -7
- package/lib/mac/bindings.js +1 -3
- package/lib/mac/src/ble_manager.h +1 -8
- package/lib/mac/src/ble_manager.mm +87 -44
- package/lib/mac/src/napi_objc.h +1 -0
- package/lib/mac/src/napi_objc.mm +0 -6
- package/lib/mac/src/noble_mac.h +5 -3
- package/lib/mac/src/noble_mac.mm +99 -57
- package/lib/mac/src/objc_cpp.h +3 -2
- package/lib/mac/src/objc_cpp.mm +0 -6
- package/lib/noble.js +579 -488
- package/lib/peripheral.js +171 -174
- package/lib/resolve-bindings.js +37 -30
- package/lib/service.js +58 -55
- package/lib/win/binding.gyp +4 -11
- package/lib/win/bindings.js +1 -3
- package/lib/win/src/ble_manager.cc +291 -166
- package/lib/win/src/ble_manager.h +11 -13
- package/lib/win/src/napi_winrt.cc +1 -7
- package/lib/win/src/napi_winrt.h +1 -1
- package/lib/win/src/noble_winrt.cc +88 -61
- package/lib/win/src/noble_winrt.h +5 -3
- package/lib/win/src/notify_map.cc +0 -7
- package/lib/win/src/notify_map.h +1 -8
- package/lib/win/src/peripheral_winrt.cc +29 -11
- package/lib/win/src/peripheral_winrt.h +1 -1
- package/lib/win/src/radio_watcher.cc +79 -69
- package/lib/win/src/radio_watcher.h +30 -11
- package/lib/win/src/winrt_cpp.cc +1 -1
- package/lib/win/src/winrt_cpp.h +3 -0
- package/package.json +14 -17
- package/prebuilds/darwin-x64+arm64/@stoprocent+noble.node +0 -0
- package/prebuilds/win32-ia32/@stoprocent+noble.node +0 -0
- package/prebuilds/win32-x64/@stoprocent+noble.node +0 -0
- package/test/lib/characteristic.test.js +202 -322
- package/test/lib/descriptor.test.js +62 -95
- package/test/lib/hci-socket/acl-stream.test.js +112 -108
- package/test/lib/hci-socket/bindings.test.js +576 -365
- package/test/lib/hci-socket/hci.test.js +442 -473
- package/test/lib/hci-socket/signaling.test.js +45 -48
- package/test/lib/hci-socket/smp.test.js +144 -142
- package/test/lib/hci-socket/vs.test.js +193 -18
- package/test/lib/peripheral.test.js +492 -322
- package/test/lib/resolve-bindings.test.js +207 -82
- package/test/lib/service.test.js +79 -88
- package/test/noble.test.js +381 -1085
- package/.editorconfig +0 -11
- package/.nycrc.json +0 -4
- package/codecov.yml +0 -5
- package/examples/cache-gatt-discovery.js +0 -198
- package/examples/cache-gatt-reconnect.js +0 -164
- package/examples/ext-advertisement-discovery.js +0 -65
- package/examples/peripheral-explorer.js +0 -225
- package/examples/pizza/central.js +0 -194
- package/examples/pizza/pizza.js +0 -60
- package/examples/test/test.custom.js +0 -131
- package/examples/uart-bind-params.js +0 -28
- package/lib/distributed/bindings.js +0 -326
- package/lib/mac/src/callbacks.cc +0 -222
- package/lib/mac/src/callbacks.h +0 -84
- package/lib/mac/src/peripheral.h +0 -23
- package/lib/resolve-bindings-web.js +0 -9
- package/lib/webbluetooth/bindings.js +0 -368
- package/lib/websocket/bindings.js +0 -321
- package/lib/win/src/peripheral.h +0 -23
- package/test/lib/distributed/bindings.test.js +0 -918
- package/test/lib/webbluetooth/bindings.test.js +0 -190
- package/test/lib/websocket/bindings.test.js +0 -456
- package/test/mocha.setup.js +0 -0
- package/with-bindings.js +0 -5
- package/with-custom-binding.js +0 -6
- package/ws-slave.js +0 -404
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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 ===
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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;
|
package/lib/hci-socket/gap.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const debug = require('debug')('gap');
|
|
2
2
|
|
|
3
|
-
const
|
|
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
|
-
|
|
36
|
+
Object.setPrototypeOf(Gap.prototype, EventEmitter.prototype);
|
|
38
37
|
|
|
39
38
|
Gap.prototype.setScanParameters = function (interval, window) {
|
|
40
39
|
this._hci.setScanParameters(interval, window);
|
package/lib/hci-socket/gatt.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const debug = require('debug')('att');
|
|
2
2
|
|
|
3
|
-
const
|
|
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
|
-
|
|
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
|
}
|
package/lib/hci-socket/hci.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
const debug = require('debug')('hci');
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const util = require('util');
|
|
3
|
+
const { EventEmitter } = require('events');
|
|
5
4
|
|
|
6
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
22
|
+
Object.setPrototypeOf(Signaling.prototype, EventEmitter.prototype);
|
|
24
23
|
|
|
25
24
|
Signaling.prototype.onAclStreamData = function (cid, data) {
|
|
26
25
|
if (cid !== SIGNALING_CID) {
|
package/lib/hci-socket/smp.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const
|
|
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
|
-
|
|
30
|
+
Object.setPrototypeOf(Smp.prototype, EventEmitter.prototype);
|
|
32
31
|
|
|
33
32
|
Smp.prototype.sendPairingRequest = function () {
|
|
34
33
|
this._preq = Buffer.from([
|
package/lib/hci-socket/vs.js
CHANGED
|
@@ -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 = {
|
package/lib/mac/binding.gyp
CHANGED
|
@@ -6,21 +6,19 @@
|
|
|
6
6
|
{
|
|
7
7
|
'target_name': 'binding',
|
|
8
8
|
'sources': [
|
|
9
|
-
'src
|
|
10
|
-
'src/
|
|
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': '
|
|
21
|
+
'MACOSX_DEPLOYMENT_TARGET': '11',
|
|
24
22
|
'CLANG_CXX_LIBRARY': 'libc++',
|
|
25
23
|
'OTHER_CFLAGS': [
|
|
26
24
|
'-fobjc-arc',
|
package/lib/mac/bindings.js
CHANGED
|
@@ -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
|
-
|
|
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 "
|
|
7
|
+
#include "Emit.h"
|
|
15
8
|
|
|
16
9
|
@interface BLEManager : NSObject <CBCentralManagerDelegate, CBPeripheralDelegate> {
|
|
17
10
|
Emit emit;
|