@stoprocent/noble 1.18.2 → 1.19.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/lib/hci-socket/bindings.js +19 -8
- package/lib/hci-socket/gatt.js +0 -1
- package/lib/hci-socket/hci.js +26 -25
- package/lib/noble.js +15 -8
- package/package.json +2 -2
- package/prebuilds/darwin-x64+arm64/@stoprocent+noble.node +0 -0
- package/prebuilds/linux-x64/@stoprocent+noble.musl.node +0 -0
- package/prebuilds/win32-ia32/@stoprocent+noble.node +0 -0
- package/prebuilds/win32-x64/@stoprocent+noble.node +0 -0
- package/test/lib/hci-socket/bindings.test.js +7 -3
|
@@ -105,7 +105,13 @@ NobleBindings.prototype.updateRssi = function (peripheralUuid) {
|
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
NobleBindings.prototype.init = function () {
|
|
108
|
-
|
|
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);
|
|
109
115
|
|
|
110
116
|
this._gap.on('scanParametersSet', this.onScanParametersSet.bind(this));
|
|
111
117
|
this._gap.on('scanStart', this.onScanStart.bind(this));
|
|
@@ -122,18 +128,12 @@ NobleBindings.prototype.init = function () {
|
|
|
122
128
|
this._hci.on('aclDataPkt', this.onAclDataPkt.bind(this));
|
|
123
129
|
|
|
124
130
|
this._hci.init();
|
|
125
|
-
|
|
126
|
-
/* Add exit handlers after `init()` has completed. If no adaptor
|
|
127
|
-
is present it can throw an exception - in which case we don't
|
|
128
|
-
want to try and clear up afterwards (issue #502) */
|
|
129
|
-
process.on('SIGINT', this.onSigIntBinded);
|
|
130
|
-
process.on('exit', this.stop.bind(this));
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
NobleBindings.prototype.onSigInt = function () {
|
|
134
134
|
const sigIntListeners = process.listeners('SIGINT');
|
|
135
135
|
|
|
136
|
-
if (sigIntListeners[sigIntListeners.length - 1] === this.
|
|
136
|
+
if (sigIntListeners[sigIntListeners.length - 1] === this._sigIntHandler) {
|
|
137
137
|
// we are the last listener, so exit
|
|
138
138
|
// this will trigger onExit, and clean up
|
|
139
139
|
process.exit(1);
|
|
@@ -141,6 +141,9 @@ NobleBindings.prototype.onSigInt = function () {
|
|
|
141
141
|
};
|
|
142
142
|
|
|
143
143
|
NobleBindings.prototype.stop = function () {
|
|
144
|
+
process.removeListener('exit', this._exitHandler);
|
|
145
|
+
process.removeListener('SIGINT', this._sigIntHandler);
|
|
146
|
+
|
|
144
147
|
this.stopScanning();
|
|
145
148
|
for (const handle in this._aclStreams) {
|
|
146
149
|
this._hci.disconnect(handle);
|
|
@@ -153,6 +156,14 @@ NobleBindings.prototype.onStateChange = function (state) {
|
|
|
153
156
|
if (this._state === state) {
|
|
154
157
|
return;
|
|
155
158
|
}
|
|
159
|
+
|
|
160
|
+
// If we are powered on and we are powered off, disconnect all connections
|
|
161
|
+
if (this._state === 'poweredOn' && state === 'poweredOff') {
|
|
162
|
+
for (const handle in this._handles) {
|
|
163
|
+
this.onDisconnComplete(handle, 0x03); // Hardward Failure
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
156
167
|
this._state = state;
|
|
157
168
|
|
|
158
169
|
if (state === 'unauthorized') {
|
package/lib/hci-socket/gatt.js
CHANGED
package/lib/hci-socket/hci.js
CHANGED
|
@@ -104,18 +104,19 @@ const Hci = function (options) {
|
|
|
104
104
|
this._isExtended = 'extended' in options && options.extended;
|
|
105
105
|
this._state = null;
|
|
106
106
|
this._bindParams = 'bindParams' in options ? options.bindParams : undefined;
|
|
107
|
-
|
|
108
107
|
this._handleBuffers = {};
|
|
109
|
-
|
|
110
108
|
this._aclBuffers = undefined;
|
|
111
109
|
this._resolveAclBuffers = undefined;
|
|
110
|
+
|
|
112
111
|
const aclBuffersPromise = new Promise((resolve) => {
|
|
113
112
|
this._resolveAclBuffers = resolve;
|
|
114
113
|
});
|
|
114
|
+
|
|
115
115
|
this.getAclBuffers = async function () {
|
|
116
116
|
if (this._aclBuffers) return this._aclBuffers;
|
|
117
117
|
return await aclBuffersPromise;
|
|
118
118
|
}.bind(this);
|
|
119
|
+
|
|
119
120
|
this.setAclBuffers = function (length, num) {
|
|
120
121
|
if (this._aclBuffers) {
|
|
121
122
|
this._aclBuffers.length = length;
|
|
@@ -130,7 +131,6 @@ const Hci = function (options) {
|
|
|
130
131
|
}.bind(this);
|
|
131
132
|
|
|
132
133
|
this._aclConnections = new Map();
|
|
133
|
-
|
|
134
134
|
this._aclQueue = [];
|
|
135
135
|
|
|
136
136
|
this._deviceId = options.deviceId != null
|
|
@@ -926,32 +926,28 @@ Hci.prototype.processCmdCompleteEvent = function (cmd, status, result) {
|
|
|
926
926
|
this.setLeEventMask();
|
|
927
927
|
this.readLocalVersion();
|
|
928
928
|
this.readBdAddr();
|
|
929
|
-
} else if (cmd === LE_READ_LOCAL_SUPPORTED_FEATURES) {
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
this._isExtended = !!(result.readUInt32LE(0) & (1 << 12));
|
|
929
|
+
} else if (cmd === LE_READ_LOCAL_SUPPORTED_FEATURES && status === 0) {
|
|
930
|
+
// Set _isExtended based on leExtendedAdvertising bit (12)
|
|
931
|
+
this._isExtended = !!(result.readUInt32LE(0) & (1 << 12));
|
|
933
932
|
|
|
934
|
-
|
|
933
|
+
this.emit('leFeatures', result);
|
|
935
934
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
}
|
|
939
|
-
this.setEventMask();
|
|
940
|
-
this.setLeEventMask();
|
|
941
|
-
this.readLocalVersion();
|
|
942
|
-
this.writeLeHostSupported();
|
|
943
|
-
this.readLeHostSupported();
|
|
944
|
-
this.readLeBufferSize();
|
|
945
|
-
this.readBdAddr();
|
|
935
|
+
if (this._isExtended) {
|
|
936
|
+
this.setCodedPhySupport();
|
|
946
937
|
}
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
938
|
+
this.setEventMask();
|
|
939
|
+
this.setLeEventMask();
|
|
940
|
+
this.readLocalVersion();
|
|
941
|
+
this.writeLeHostSupported();
|
|
942
|
+
this.readLeHostSupported();
|
|
943
|
+
this.readLeBufferSize();
|
|
944
|
+
this.readBdAddr();
|
|
945
|
+
} else if (cmd === READ_LE_HOST_SUPPORTED_CMD && status === 0) {
|
|
946
|
+
const le = result.readUInt8(0);
|
|
947
|
+
const simul = result.readUInt8(1);
|
|
951
948
|
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
}
|
|
949
|
+
debug(`\t\t\tle = ${le}`);
|
|
950
|
+
debug(`\t\t\tsimul = ${simul}`);
|
|
955
951
|
} else if (cmd === READ_LOCAL_VERSION_CMD) {
|
|
956
952
|
const hciVer = result.readUInt8(0);
|
|
957
953
|
const hciRev = result.readUInt16LE(1);
|
|
@@ -1289,6 +1285,11 @@ Hci.prototype.processCmdStatusEvent = function (cmd, status) {
|
|
|
1289
1285
|
};
|
|
1290
1286
|
|
|
1291
1287
|
Hci.prototype.onStateChange = function (state) {
|
|
1288
|
+
// If we are powered on and we are powered off, clean up
|
|
1289
|
+
if (this._state === 'poweredOn' && state === 'poweredOff') {
|
|
1290
|
+
this._aclConnections.clear();
|
|
1291
|
+
this._aclQueue = [];
|
|
1292
|
+
}
|
|
1292
1293
|
this._state = state;
|
|
1293
1294
|
};
|
|
1294
1295
|
|
package/lib/noble.js
CHANGED
|
@@ -14,11 +14,8 @@ function Noble (bindings) {
|
|
|
14
14
|
this.address = 'unknown';
|
|
15
15
|
this._state = 'unknown';
|
|
16
16
|
this._bindings = bindings;
|
|
17
|
-
|
|
18
|
-
this.
|
|
19
|
-
this._characteristics = {};
|
|
20
|
-
this._descriptors = {};
|
|
21
|
-
this._discoveredPeripheralUUids = {};
|
|
17
|
+
|
|
18
|
+
this._cleanupPeriperals();
|
|
22
19
|
|
|
23
20
|
this._bindings.on('stateChange', this.onStateChange.bind(this));
|
|
24
21
|
this._bindings.on('addressChange', this.onAddressChange.bind(this));
|
|
@@ -56,7 +53,6 @@ function Noble (bindings) {
|
|
|
56
53
|
this.on('newListener', (event) => {
|
|
57
54
|
if (event === 'stateChange' && !this.initialized) {
|
|
58
55
|
this.initialized = true;
|
|
59
|
-
|
|
60
56
|
process.nextTick(() => {
|
|
61
57
|
try {
|
|
62
58
|
this._bindings.init();
|
|
@@ -73,7 +69,6 @@ function Noble (bindings) {
|
|
|
73
69
|
get: function () {
|
|
74
70
|
if (!this.initialized) {
|
|
75
71
|
this.initialized = true;
|
|
76
|
-
|
|
77
72
|
this._bindings.init();
|
|
78
73
|
}
|
|
79
74
|
return this._state;
|
|
@@ -84,11 +79,23 @@ function Noble (bindings) {
|
|
|
84
79
|
|
|
85
80
|
util.inherits(Noble, events.EventEmitter);
|
|
86
81
|
|
|
82
|
+
Noble.prototype._cleanupPeriperals = function () {
|
|
83
|
+
this._peripherals = {};
|
|
84
|
+
this._services = {};
|
|
85
|
+
this._characteristics = {};
|
|
86
|
+
this._descriptors = {};
|
|
87
|
+
this._discoveredPeripheralUUids = {};
|
|
88
|
+
};
|
|
89
|
+
|
|
87
90
|
Noble.prototype.onStateChange = function (state) {
|
|
88
91
|
debug(`stateChange ${state}`);
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
// If the state is poweredOff and the previous state was poweredOn, clean up the peripherals
|
|
94
|
+
if (state === 'poweredOff' && this._state === 'poweredOn') {
|
|
95
|
+
this._cleanupPeriperals();
|
|
96
|
+
}
|
|
91
97
|
|
|
98
|
+
this._state = state;
|
|
92
99
|
this.emit('stateChange', state);
|
|
93
100
|
};
|
|
94
101
|
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"name": "@stoprocent/noble",
|
|
8
8
|
"description": "A Node.js BLE (Bluetooth Low Energy) central library.",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.19.0",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": "https://github.com/stoprocent/noble.git"
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"node-gyp-build": "^4.8.1"
|
|
35
35
|
},
|
|
36
36
|
"optionalDependencies": {
|
|
37
|
-
"@stoprocent/bluetooth-hci-socket": "^1.
|
|
37
|
+
"@stoprocent/bluetooth-hci-socket": "^1.5.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@commitlint/cli": "^19.3.0",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -78,13 +78,13 @@ describe('hci-socket bindings', () => {
|
|
|
78
78
|
describe('onSigInt', () => {
|
|
79
79
|
it('should exit', () => {
|
|
80
80
|
const sigIntListeners = process.listeners('SIGINT');
|
|
81
|
-
bindings.
|
|
81
|
+
bindings._sigIntHandler = sigIntListeners[sigIntListeners.length - 1];
|
|
82
82
|
bindings.onSigInt();
|
|
83
83
|
assert.calledOnceWithExactly(process.exit, 1);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
it('should not exit', () => {
|
|
87
|
-
bindings.
|
|
87
|
+
bindings._sigIntHandler = sinon.spy();
|
|
88
88
|
bindings.onSigInt();
|
|
89
89
|
assert.notCalled(process.exit);
|
|
90
90
|
});
|
|
@@ -292,7 +292,9 @@ describe('hci-socket bindings', () => {
|
|
|
292
292
|
bindings._gap.stopScanning = fake.resolves(null);
|
|
293
293
|
bindings._hci.reset = fake.resolves(null);
|
|
294
294
|
bindings._hci.stop = fake.resolves(null);
|
|
295
|
-
|
|
295
|
+
bindings._sigIntHandler = fake.resolves(null);
|
|
296
|
+
bindings._exitHandler = fake.resolves(null);
|
|
297
|
+
|
|
296
298
|
bindings.stop();
|
|
297
299
|
|
|
298
300
|
assert.calledOnce(bindings._gap.stopScanning);
|
|
@@ -305,6 +307,8 @@ describe('hci-socket bindings', () => {
|
|
|
305
307
|
bindings._hci.disconnect = fake.resolves(null);
|
|
306
308
|
bindings._hci.reset = fake.resolves(null);
|
|
307
309
|
bindings._hci.stop = fake.resolves(null);
|
|
310
|
+
bindings._sigIntHandler = fake.resolves(null);
|
|
311
|
+
bindings._exitHandler = fake.resolves(null);
|
|
308
312
|
|
|
309
313
|
bindings._aclStreams = [1, 2, 3];
|
|
310
314
|
|