@stoprocent/noble 1.11.8 → 1.13.1
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 +52 -11
- package/binding.gyp +3 -0
- package/examples/uart-bind-params.js +28 -0
- package/lib/hci-socket/bindings.js +4 -0
- package/lib/hci-socket/hci.js +20 -21
- package/lib/hci-socket/vs.js +156 -0
- package/lib/mac/binding.gyp +23 -11
- package/lib/noble.js +8 -0
- package/lib/win/binding.gyp +25 -5
- package/package.json +13 -22
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/test/lib/hci-socket/hci.test.js +47 -7
- package/test/lib/hci-socket/vs.test.js +25 -0
- package/.eslintrc.js +0 -25
- package/.github/FUNDING.yml +0 -2
- package/.github/workflows/fediverse-action.yml +0 -16
- package/.github/workflows/nodepackage.yml +0 -68
- package/.github/workflows/npm-publish.yml +0 -26
- package/.github/workflows/prebuild.yml +0 -71
- package/CHANGELOG.md +0 -119
- package/MAINTAINERS.md +0 -1
- package/test.js +0 -131
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# 
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@stoprocent/noble)
|
|
4
|
+
[](https://www.npmjs.com/package/@stoprocent/noble)
|
|
5
|
+
[](https://travis-ci.org/stoprocent/noble)
|
|
6
6
|
[](https://gitter.im/abandonware/noble?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](#backers)
|
|
7
7
|
[](#sponsors)
|
|
8
8
|
|
|
9
9
|
A Node.js BLE (Bluetooth Low Energy) central module.
|
|
10
10
|
|
|
11
|
-
Want to implement a peripheral? Check out [bleno](https://github.com/
|
|
11
|
+
Want to implement a peripheral? Check out [bleno](https://github.com/stoprocent/bleno).
|
|
12
12
|
|
|
13
13
|
__Note:__ macOS / Mac OS X, Linux, FreeBSD and Windows are currently the only supported OSes.
|
|
14
14
|
|
|
@@ -25,7 +25,7 @@ __Note:__ macOS / Mac OS X, Linux, FreeBSD and Windows are currently the only su
|
|
|
25
25
|
```javascript
|
|
26
26
|
// Read the battery level of the first found peripheral exposing the Battery Level characteristic
|
|
27
27
|
|
|
28
|
-
const noble = require('@
|
|
28
|
+
const noble = require('@stoprocent/noble');
|
|
29
29
|
|
|
30
30
|
noble.on('stateChange', async (state) => {
|
|
31
31
|
if (state === 'poweredOn') {
|
|
@@ -48,7 +48,7 @@ noble.on('discover', async (peripheral) => {
|
|
|
48
48
|
## Use Noble With BLE5 Extended Features With HCI
|
|
49
49
|
|
|
50
50
|
```javascript
|
|
51
|
-
const noble = require('@
|
|
51
|
+
const noble = require('@stoprocent/noble/with-custom-binding')({extended: true});
|
|
52
52
|
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -72,6 +72,38 @@ const noble = require('@abandonware/noble/with-custom-binding')({extended: true}
|
|
|
72
72
|
|
|
73
73
|
Please refer to [https://github.com/stoprocent/node-bluetooth-hci-socket#uartserial-any-os](https://github.com/stoprocent/node-bluetooth-hci-socket#uartserial-any-os)
|
|
74
74
|
|
|
75
|
+
##### Example 1 (UART port spcified as enviromental variable)
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
$ export BLUETOOTH_HCI_SOCKET_UART_PORT=/dev/tty...
|
|
79
|
+
$ export BLUETOOTH_HCI_SOCKET_UART_BAUDRATE=1000000
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
__NOTE:__ `BLUETOOTH_HCI_SOCKET_UART_BAUDRATE` defaults to `1000000` so only needed if different.
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
const noble = require('@stoprocent/noble');
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
##### Example 2 (UART port spcified in `bindParams`)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
$ export BLUETOOTH_HCI_SOCKET_FORCE_UART=1
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const noble = require('@stoprocent/noble/with-custom-binding') ( {
|
|
96
|
+
bindParams: {
|
|
97
|
+
uart: {
|
|
98
|
+
port: '/dev/tty...',
|
|
99
|
+
baudRate: 1000000
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} );
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
__NOTE:__ There is a [UART code example](examples/uart-bind-params.js) in the `/examples` directory.
|
|
106
|
+
|
|
75
107
|
#### OS X
|
|
76
108
|
|
|
77
109
|
* Install [Xcode](https://itunes.apple.com/ca/app/xcode/id497799835?mt=12)
|
|
@@ -161,7 +193,7 @@ Make sure your container runs with `--network=host` options and all specific env
|
|
|
161
193
|
### Installing and using the package
|
|
162
194
|
|
|
163
195
|
```sh
|
|
164
|
-
npm install @
|
|
196
|
+
npm install @stoprocent/noble
|
|
165
197
|
```
|
|
166
198
|
|
|
167
199
|
In Windows OS add your custom hci-usb dongle to the process env
|
|
@@ -171,7 +203,7 @@ set BLUETOOTH_HCI_SOCKET_USB_PID=xxx
|
|
|
171
203
|
```
|
|
172
204
|
|
|
173
205
|
```javascript
|
|
174
|
-
const noble = require('@
|
|
206
|
+
const noble = require('@stoprocent/noble');
|
|
175
207
|
```
|
|
176
208
|
|
|
177
209
|
## API docs
|
|
@@ -208,6 +240,7 @@ API structure:
|
|
|
208
240
|
|
|
209
241
|
* [Scanning and discovery](#scanning-and-discovery)
|
|
210
242
|
* [_Event: Adapter state changed_](#event-adapter-state-changed)
|
|
243
|
+
* [Set address](#set-address)
|
|
211
244
|
* [Start scanning](#start-scanning)
|
|
212
245
|
* [_Event: Scanning started_](#event-scanning-started)
|
|
213
246
|
* [Stop scanning](#stop-scanning)
|
|
@@ -270,6 +303,14 @@ noble.on('stateChange', callback(state));
|
|
|
270
303
|
* `poweredOff`
|
|
271
304
|
* `poweredOn`
|
|
272
305
|
|
|
306
|
+
#### Set address
|
|
307
|
+
|
|
308
|
+
```javascript
|
|
309
|
+
noble.setAddress('00:11:22:33:44:55'); // set adapter's mac address
|
|
310
|
+
```
|
|
311
|
+
__NOTE:__ Curently this feature is only supported on HCI as it's using vendor specific commands. Source of the commands is based on the [BlueZ bdaddr.c](https://github.com/pauloborges/bluez/blob/master/tools/bdaddr.c).
|
|
312
|
+
__NOTE:__ `noble.state` must be `poweredOn` before address can be set. `noble.on('stateChange', callback(state));` can be used to listen for state change events.
|
|
313
|
+
|
|
273
314
|
#### Start scanning
|
|
274
315
|
|
|
275
316
|
```javascript
|
|
@@ -643,7 +684,7 @@ descriptor.once('valueWrite');
|
|
|
643
684
|
By default, noble will select appropriate Bluetooth device bindings based on your platform. You can provide custom bindings using the `with-bindings` module.
|
|
644
685
|
|
|
645
686
|
```javascript
|
|
646
|
-
var noble = require('@
|
|
687
|
+
var noble = require('@stoprocent/noble/with-bindings')(require('./my-custom-bindings'));
|
|
647
688
|
```
|
|
648
689
|
|
|
649
690
|
### Running without root/sudo (Linux-specific)
|
|
@@ -677,8 +718,8 @@ sudo NOBLE_HCI_DEVICE_ID=1 node <your file>.js
|
|
|
677
718
|
If you are using multiple HCI devices in one setup you can run two instances of noble with different binding configurations by initializing them seperatly in code:
|
|
678
719
|
|
|
679
720
|
```
|
|
680
|
-
const HCIBindings = require('@
|
|
681
|
-
const Noble = require('@
|
|
721
|
+
const HCIBindings = require('@stoprocent/noble/lib/hci-socket/bindings');
|
|
722
|
+
const Noble = require('@stoprocent/noble/lib/noble');
|
|
682
723
|
|
|
683
724
|
const params = {
|
|
684
725
|
deviceId: 0,
|
package/binding.gyp
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const noble = require('../with-custom-binding');
|
|
2
|
+
|
|
3
|
+
// Needs to export env: BLUETOOTH_HCI_SOCKET_FORCE_UART=1
|
|
4
|
+
|
|
5
|
+
const nobleUartA = noble({ bindParams: { uart: { port: '/dev/tty.usbmodem1...' } } });
|
|
6
|
+
const nobleUartB = noble({ bindParams: { uart: { port: '/dev/tty.usbmodem2...' } } });
|
|
7
|
+
|
|
8
|
+
nobleUartA.on('discover', peripheral => {
|
|
9
|
+
console.log('UART A', peripheral.address);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
nobleUartB.on('discover', peripheral => {
|
|
13
|
+
console.log('UART B', peripheral.address);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
nobleUartA.on('stateChange', state => {
|
|
17
|
+
if (state === 'poweredOn') {
|
|
18
|
+
nobleUartA.setAddress('00:11:22:33:44:01');
|
|
19
|
+
nobleUartA.startScanning();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
nobleUartB.on('stateChange', state => {
|
|
24
|
+
if (state === 'poweredOn') {
|
|
25
|
+
nobleUartB.setAddress('00:11:22:33:44:02');
|
|
26
|
+
nobleUartB.startScanning();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
@@ -34,6 +34,10 @@ NobleBindings.prototype.setScanParameters = function (interval, window) {
|
|
|
34
34
|
this._gap.setScanParameters(interval, window);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
NobleBindings.prototype.setAddress = function (address) {
|
|
38
|
+
this._hci.setAddress(address);
|
|
39
|
+
};
|
|
40
|
+
|
|
37
41
|
NobleBindings.prototype.startScanning = function (
|
|
38
42
|
serviceUuids,
|
|
39
43
|
allowDuplicates
|
package/lib/hci-socket/hci.js
CHANGED
|
@@ -4,6 +4,7 @@ const events = require('events');
|
|
|
4
4
|
const util = require('util');
|
|
5
5
|
|
|
6
6
|
const BluetoothHciSocket = require('@stoprocent/bluetooth-hci-socket');
|
|
7
|
+
const vendorSpecific = require('./vs');
|
|
7
8
|
|
|
8
9
|
const HCI_COMMAND_PKT = 0x01;
|
|
9
10
|
const HCI_ACLDATA_PKT = 0x02;
|
|
@@ -32,7 +33,6 @@ const OCF_DISCONNECT = 0x0006;
|
|
|
32
33
|
const OGF_HOST_CTL = 0x03;
|
|
33
34
|
const OCF_SET_EVENT_MASK = 0x0001;
|
|
34
35
|
const OCF_RESET = 0x0003;
|
|
35
|
-
const OCF_SET_RANDOM_MAC = 0x0005;
|
|
36
36
|
const OCF_SET_PHY = 0x0031;
|
|
37
37
|
const OCF_READ_LE_HOST_SUPPORTED = 0x006c;
|
|
38
38
|
const OCF_WRITE_LE_HOST_SUPPORTED = 0x006d;
|
|
@@ -96,10 +96,12 @@ const STATUS_MAPPER = require('./hci-status');
|
|
|
96
96
|
|
|
97
97
|
const Hci = function (options) {
|
|
98
98
|
options = options || {};
|
|
99
|
+
this._manufacturer = null;
|
|
99
100
|
this._socket = new BluetoothHciSocket();
|
|
100
101
|
this._isDevUp = null;
|
|
101
102
|
this._isExtended = 'extended' in options && options.extended;
|
|
102
103
|
this._state = null;
|
|
104
|
+
this._bindParams = 'bindParams' in options ? options.bindParams : undefined;
|
|
103
105
|
|
|
104
106
|
this._handleBuffers = {};
|
|
105
107
|
|
|
@@ -151,13 +153,13 @@ Hci.prototype.init = function (options) {
|
|
|
151
153
|
this._socket.on('error', this.onSocketError.bind(this));
|
|
152
154
|
|
|
153
155
|
if (this._userChannel) {
|
|
154
|
-
this._socket.bindUser(this._deviceId);
|
|
156
|
+
this._socket.bindUser(this._deviceId, this._bindParams);
|
|
155
157
|
this._socket.start();
|
|
156
158
|
|
|
157
159
|
this.reset();
|
|
158
160
|
} else {
|
|
159
161
|
if (!this._bound) {
|
|
160
|
-
this._socket.bindRaw(this._deviceId);
|
|
162
|
+
this._socket.bindRaw(this._deviceId, this._bindParams);
|
|
161
163
|
this._bound = true;
|
|
162
164
|
}
|
|
163
165
|
this._socket.start();
|
|
@@ -218,26 +220,20 @@ Hci.prototype.setCodedPhySupport = function () {
|
|
|
218
220
|
this._socket.write(cmd);
|
|
219
221
|
};
|
|
220
222
|
|
|
221
|
-
Hci.prototype.
|
|
222
|
-
|
|
223
|
+
Hci.prototype.setAddress = function (address) {
|
|
224
|
+
// Command
|
|
225
|
+
const addrCmd = vendorSpecific.setAddressCmd(this._manufacturer, address);
|
|
223
226
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
+
if (addrCmd !== null && Buffer.isBuffer(addrCmd)) {
|
|
228
|
+
// Make Command Buffer
|
|
229
|
+
const cmd = Buffer.alloc(1 + addrCmd.byteLength);
|
|
230
|
+
cmd.writeUInt8(HCI_COMMAND_PKT, 0);
|
|
231
|
+
addrCmd.copy(cmd, 1);
|
|
227
232
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
cmd.writeUInt8(0x05, 4); // mac 6 byte
|
|
233
|
-
cmd.writeUInt8(0x04, 5); // mac 5 byte
|
|
234
|
-
cmd.writeUInt8(0x03, 6); // mac 4 byte
|
|
235
|
-
cmd.writeUInt8(0x02, 7); // mac 3 byte
|
|
236
|
-
cmd.writeUInt8(0x01, 8); // mac 2 byte
|
|
237
|
-
cmd.writeUInt8(0x00, 9); // mac 1 byte
|
|
238
|
-
|
|
239
|
-
debug(`set random mac address - writing: ${cmd.toString('hex')}`);
|
|
240
|
-
this._socket.write(cmd);
|
|
233
|
+
debug(`set address - writing: ${cmd.toString('hex')}`);
|
|
234
|
+
this._socket.write(cmd);
|
|
235
|
+
this.readBdAddr();
|
|
236
|
+
}
|
|
241
237
|
};
|
|
242
238
|
|
|
243
239
|
Hci.prototype.setSocketFilter = function () {
|
|
@@ -938,6 +934,9 @@ Hci.prototype.processCmdCompleteEvent = function (cmd, status, result) {
|
|
|
938
934
|
this.setScanParameters();
|
|
939
935
|
}
|
|
940
936
|
|
|
937
|
+
// Update manufacturer
|
|
938
|
+
this._manufacturer = manufacturer;
|
|
939
|
+
|
|
941
940
|
this.emit(
|
|
942
941
|
'readLocalVersion',
|
|
943
942
|
hciVer,
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// This file is based on the bluez implementation
|
|
2
|
+
// https://github.com/bluez/bluez/blob/master/tools/bdaddr.c
|
|
3
|
+
|
|
4
|
+
const OGF_VENDOR_CMD = 0x3f;
|
|
5
|
+
|
|
6
|
+
const OCF_ERICSSON_WRITE_BD_ADDR = 0x000d;
|
|
7
|
+
const OCF_TI_WRITE_BD_ADDR = 0x0006;
|
|
8
|
+
const OCF_LINUX_FOUNDATION_WRITE_BD_ADDR = 0x0006;
|
|
9
|
+
const OCF_BCM_WRITE_BD_ADDR = 0x0001;
|
|
10
|
+
const OCF_ZEEVO_WRITE_BD_ADDR = 0x0001;
|
|
11
|
+
const OCF_MRVL_WRITE_BD_ADDR = 0x0022;
|
|
12
|
+
const OCF_ERICSSON_STORE_IN_FLASH = 0x0022;
|
|
13
|
+
const ERICSSON_STORE_IN_FLASH_CP_SIZE = 0xFF;
|
|
14
|
+
|
|
15
|
+
function parseAddress (address) {
|
|
16
|
+
// Parse MAC Address as in 00:00:00:00:00:00 into Buffer (needs to reverse byte order)
|
|
17
|
+
const macAddress = Buffer.from(address.split(':').reverse().join(''), 'hex');
|
|
18
|
+
|
|
19
|
+
if (Buffer.isBuffer(macAddress) && macAddress.byteLength !== 6) {
|
|
20
|
+
throw new Error('Invalid MAC Address. Should be formated as 00:00:00:00:00:00 string.');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return macAddress;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// eslint-disable-next-line camelcase
|
|
27
|
+
function csr_write_bd_addr (address) {
|
|
28
|
+
// Parse MAC Address
|
|
29
|
+
const macAddress = parseAddress(address);
|
|
30
|
+
|
|
31
|
+
if (macAddress === null) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Base command
|
|
36
|
+
const base = Buffer.from([
|
|
37
|
+
0x02, 0x00, 0x0c, 0x00, 0x11, 0x47, 0x03, 0x70,
|
|
38
|
+
0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
|
|
39
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
// Command
|
|
43
|
+
const cmd = Buffer.alloc(3 + base.byteLength);
|
|
44
|
+
|
|
45
|
+
cmd.writeUInt16LE(0x00 | OGF_VENDOR_CMD << 10, 0);
|
|
46
|
+
cmd.writeUInt8(0xC2, 2);
|
|
47
|
+
|
|
48
|
+
base.writeUint8(macAddress.readUInt8(2), 16);
|
|
49
|
+
base.writeUint8(0x00, 17);
|
|
50
|
+
base.writeUint8(macAddress.readUInt8(0), 18);
|
|
51
|
+
base.writeUint8(macAddress.readUInt8(1), 19);
|
|
52
|
+
base.writeUint8(macAddress.readUInt8(3), 20);
|
|
53
|
+
base.writeUint8(0x00, 21);
|
|
54
|
+
base.writeUint8(macAddress.readUInt8(4), 22);
|
|
55
|
+
base.writeUint8(macAddress.readUInt8(5), 23);
|
|
56
|
+
base.copy(cmd, 3);
|
|
57
|
+
|
|
58
|
+
return cmd;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// eslint-disable-next-line camelcase
|
|
62
|
+
function ericsson_store_in_flash (user_id, data) {
|
|
63
|
+
// Check Data
|
|
64
|
+
if (Buffer.isBuffer(data) === false || data.byteLength > OCF_ERICSSON_STORE_IN_FLASH - 2) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Command
|
|
69
|
+
const cmd = Buffer.alloc(3 + ERICSSON_STORE_IN_FLASH_CP_SIZE);
|
|
70
|
+
|
|
71
|
+
cmd.writeUInt16LE(OCF_ERICSSON_STORE_IN_FLASH | OGF_VENDOR_CMD << 10, 0);
|
|
72
|
+
cmd.writeUInt8(ERICSSON_STORE_IN_FLASH_CP_SIZE, 2);
|
|
73
|
+
cmd.writeUInt8(user_id, 3); // user_id
|
|
74
|
+
cmd.writeUInt8(data.byteLength, 4); // flash_length
|
|
75
|
+
data.copy(cmd, 5); // flash_data
|
|
76
|
+
|
|
77
|
+
return cmd;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// eslint-disable-next-line camelcase
|
|
81
|
+
function st_write_bd_addr (address) {
|
|
82
|
+
// Parse MAC Address
|
|
83
|
+
const macAddress = parseAddress(address);
|
|
84
|
+
|
|
85
|
+
if (macAddress === null) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return ericsson_store_in_flash(0xFE, macAddress);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// eslint-disable-next-line camelcase
|
|
93
|
+
function mrvl_write_bd_addr (address) {
|
|
94
|
+
// Parse MAC Address
|
|
95
|
+
const macAddress = parseAddress(address);
|
|
96
|
+
|
|
97
|
+
if (macAddress === null) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Command
|
|
102
|
+
const cmd = Buffer.alloc(11);
|
|
103
|
+
|
|
104
|
+
cmd.writeUInt16LE(OCF_MRVL_WRITE_BD_ADDR | OGF_VENDOR_CMD << 10, 0);
|
|
105
|
+
cmd.writeUInt8(0x08, 2);
|
|
106
|
+
cmd.writeUInt8(0xFE, 3); // parameter_id
|
|
107
|
+
cmd.writeUInt8(0x06, 4); // bdaddr_len
|
|
108
|
+
macAddress.copy(cmd, 5); // bdaddr
|
|
109
|
+
|
|
110
|
+
return cmd;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// eslint-disable-next-line camelcase
|
|
114
|
+
function write_common_bd_addr (OCF_VS_WRITE_BD_ADDR) {
|
|
115
|
+
// Return a function
|
|
116
|
+
return (address) => {
|
|
117
|
+
// Parse MAC Address
|
|
118
|
+
const macAddress = parseAddress(address);
|
|
119
|
+
|
|
120
|
+
if (macAddress === null) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Command
|
|
125
|
+
const cmd = Buffer.alloc(9);
|
|
126
|
+
|
|
127
|
+
cmd.writeUInt16LE(OCF_VS_WRITE_BD_ADDR | OGF_VENDOR_CMD << 10, 0);
|
|
128
|
+
cmd.writeUInt8(0x06, 2);
|
|
129
|
+
macAddress.copy(cmd, 3); // bdaddr
|
|
130
|
+
|
|
131
|
+
return cmd;
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const vendors = new Map();
|
|
136
|
+
|
|
137
|
+
vendors.set(0, write_common_bd_addr(OCF_ERICSSON_WRITE_BD_ADDR));
|
|
138
|
+
vendors.set(10, csr_write_bd_addr);
|
|
139
|
+
vendors.set(13, write_common_bd_addr(OCF_TI_WRITE_BD_ADDR));
|
|
140
|
+
vendors.set(15, write_common_bd_addr(OCF_BCM_WRITE_BD_ADDR));
|
|
141
|
+
vendors.set(18, write_common_bd_addr(OCF_ZEEVO_WRITE_BD_ADDR));
|
|
142
|
+
vendors.set(48, st_write_bd_addr);
|
|
143
|
+
vendors.set(57, write_common_bd_addr(OCF_ERICSSON_WRITE_BD_ADDR));
|
|
144
|
+
vendors.set(72, mrvl_write_bd_addr);
|
|
145
|
+
vendors.set(1521, write_common_bd_addr(OCF_LINUX_FOUNDATION_WRITE_BD_ADDR));
|
|
146
|
+
|
|
147
|
+
module.exports = {
|
|
148
|
+
// Vendor Specific Set Address
|
|
149
|
+
setAddressCmd: (manufacturer, address) => {
|
|
150
|
+
const generateCommand = vendors.get(manufacturer);
|
|
151
|
+
if (typeof generateCommand === 'function') {
|
|
152
|
+
return generateCommand(address) || null;
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
};
|
package/lib/mac/binding.gyp
CHANGED
|
@@ -1,26 +1,38 @@
|
|
|
1
1
|
{
|
|
2
|
+
'variables': {
|
|
3
|
+
'openssl_fips' : ''
|
|
4
|
+
},
|
|
2
5
|
'targets': [
|
|
3
6
|
{
|
|
4
7
|
'target_name': 'binding',
|
|
5
|
-
'sources': [
|
|
6
|
-
|
|
7
|
-
|
|
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'
|
|
14
|
+
],
|
|
15
|
+
'include_dirs': [
|
|
16
|
+
"<!(node -p \"require('node-addon-api').include_dir\")"
|
|
17
|
+
],
|
|
8
18
|
'cflags!': [ '-fno-exceptions' ],
|
|
9
19
|
'cflags_cc!': [ '-fno-exceptions' ],
|
|
20
|
+
"defines": ["NAPI_CPP_EXCEPTIONS"],
|
|
10
21
|
'xcode_settings': {
|
|
11
22
|
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
|
|
23
|
+
'MACOSX_DEPLOYMENT_TARGET': '10.9',
|
|
12
24
|
'CLANG_CXX_LIBRARY': 'libc++',
|
|
13
|
-
'MACOSX_DEPLOYMENT_TARGET': '10.7',
|
|
14
25
|
'OTHER_CFLAGS': [
|
|
15
|
-
|
|
26
|
+
'-fobjc-arc',
|
|
27
|
+
'-arch x86_64',
|
|
28
|
+
'-arch arm64'
|
|
16
29
|
],
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
'
|
|
30
|
+
'OTHER_LDFLAGS': [
|
|
31
|
+
'-framework CoreBluetooth',
|
|
32
|
+
'-arch x86_64',
|
|
33
|
+
'-arch arm64'
|
|
21
34
|
]
|
|
22
|
-
}
|
|
23
|
-
'product_dir': '../lib/mac/native',
|
|
35
|
+
}
|
|
24
36
|
}
|
|
25
37
|
]
|
|
26
38
|
}
|
package/lib/noble.js
CHANGED
|
@@ -110,6 +110,14 @@ Noble.prototype.onScanParametersSet = function () {
|
|
|
110
110
|
this.emit('scanParametersSet');
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
+
Noble.prototype.setAddress = function (address) {
|
|
114
|
+
if (this._bindings.setAddress) {
|
|
115
|
+
this._bindings.setAddress(address);
|
|
116
|
+
} else {
|
|
117
|
+
this.emit('warning', 'current binding does not implement setAddress method.');
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
113
121
|
const startScanning = function (serviceUuids, allowDuplicates, callback) {
|
|
114
122
|
if (typeof serviceUuids === 'function') {
|
|
115
123
|
this.emit('warning', 'calling startScanning(callback) is deprecated');
|
package/lib/win/binding.gyp
CHANGED
|
@@ -1,22 +1,42 @@
|
|
|
1
1
|
{
|
|
2
|
+
'variables': {
|
|
3
|
+
'openssl_fips' : ''
|
|
4
|
+
},
|
|
2
5
|
'targets': [
|
|
3
6
|
{
|
|
4
7
|
'target_name': 'binding',
|
|
5
|
-
'sources': [
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
'sources': [
|
|
9
|
+
'src/noble_winrt.cc',
|
|
10
|
+
'src/napi_winrt.cc',
|
|
11
|
+
'src/peripheral_winrt.cc',
|
|
12
|
+
'src/radio_watcher.cc',
|
|
13
|
+
'src/notify_map.cc',
|
|
14
|
+
'src/ble_manager.cc',
|
|
15
|
+
'src/winrt_cpp.cc',
|
|
16
|
+
'src/winrt_guid.cc',
|
|
17
|
+
'src/callbacks.cc'
|
|
18
|
+
],
|
|
19
|
+
'include_dirs': [
|
|
20
|
+
"<!(node -p \"require('node-addon-api').include_dir\")",
|
|
21
|
+
"<!@(node -p \"require('napi-thread-safe-callback').include\")"
|
|
22
|
+
],
|
|
8
23
|
'cflags!': [ '-fno-exceptions' ],
|
|
9
24
|
'cflags_cc!': [ '-fno-exceptions' ],
|
|
10
25
|
'msvs_settings': {
|
|
11
26
|
'VCCLCompilerTool': {
|
|
12
27
|
'ExceptionHandling': 1,
|
|
13
|
-
'AdditionalOptions': [
|
|
28
|
+
'AdditionalOptions': [
|
|
29
|
+
'/await',
|
|
30
|
+
'/std:c++latest'
|
|
31
|
+
],
|
|
14
32
|
},
|
|
15
33
|
},
|
|
16
34
|
'msvs_target_platform_version':'10.0.18362.0',
|
|
17
35
|
'msvs_target_platform_minversion':'10.0.18362.0',
|
|
18
36
|
'conditions': [
|
|
19
|
-
['OS=="win"', {
|
|
37
|
+
['OS=="win"', {
|
|
38
|
+
'defines': [ '_HAS_EXCEPTIONS=1' ]
|
|
39
|
+
}]
|
|
20
40
|
],
|
|
21
41
|
}
|
|
22
42
|
]
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"author": "Sandeep Mistry",
|
|
2
|
+
"author": "Sandeep Mistry <sandeep.mistry@gmail.com>",
|
|
3
3
|
"maintainers": [
|
|
4
|
-
"
|
|
5
|
-
"Luis Montes"
|
|
4
|
+
"Marek Serafin <marek@serafin.email>"
|
|
6
5
|
],
|
|
7
6
|
"license": "MIT",
|
|
8
7
|
"name": "@stoprocent/noble",
|
|
9
8
|
"description": "A Node.js BLE (Bluetooth Low Energy) central library.",
|
|
10
|
-
"version": "1.
|
|
9
|
+
"version": "1.13.1",
|
|
11
10
|
"repository": {
|
|
12
11
|
"type": "git",
|
|
13
12
|
"url": "https://github.com/stoprocent/noble.git"
|
|
@@ -28,12 +27,6 @@
|
|
|
28
27
|
"engines": {
|
|
29
28
|
"node": ">=6"
|
|
30
29
|
},
|
|
31
|
-
"os": [
|
|
32
|
-
"darwin",
|
|
33
|
-
"linux",
|
|
34
|
-
"freebsd",
|
|
35
|
-
"win32"
|
|
36
|
-
],
|
|
37
30
|
"dependencies": {
|
|
38
31
|
"debug": "^4.3.4",
|
|
39
32
|
"napi-thread-safe-callback": "^0.0.6",
|
|
@@ -41,9 +34,10 @@
|
|
|
41
34
|
"node-gyp-build": "^4.5.0"
|
|
42
35
|
},
|
|
43
36
|
"optionalDependencies": {
|
|
44
|
-
"@stoprocent/bluetooth-hci-socket": "^
|
|
37
|
+
"@stoprocent/bluetooth-hci-socket": "^1.1.3"
|
|
45
38
|
},
|
|
46
39
|
"devDependencies": {
|
|
40
|
+
"@semantic-release/exec": "^6.0.3",
|
|
47
41
|
"async": "^3.2.4",
|
|
48
42
|
"cross-env": "^7.0.3",
|
|
49
43
|
"eslint": "^8.31.0",
|
|
@@ -53,12 +47,13 @@
|
|
|
53
47
|
"eslint-plugin-n": "^15.6.0",
|
|
54
48
|
"eslint-plugin-promise": "^6.1.1",
|
|
55
49
|
"mocha": "^10.2.0",
|
|
56
|
-
"node-gyp": "^9.
|
|
50
|
+
"node-gyp": "^9.4.0",
|
|
57
51
|
"nyc": "^15.1.0",
|
|
58
52
|
"prebuildify": "^5.0.1",
|
|
59
|
-
"prebuildify-
|
|
53
|
+
"prebuildify-cross": "5.0.0",
|
|
60
54
|
"prettier": "^2.8.1",
|
|
61
55
|
"proxyquire": "^2.1.3",
|
|
56
|
+
"semantic-release": "21.1.0",
|
|
62
57
|
"should": "~13.2.3",
|
|
63
58
|
"sinon": "^15.0.1",
|
|
64
59
|
"ws": "^8.11.0"
|
|
@@ -67,11 +62,9 @@
|
|
|
67
62
|
"install": "node-gyp-build",
|
|
68
63
|
"lint": "eslint \"**/*.js\"",
|
|
69
64
|
"lint-fix": "eslint \"**/*.js\" --fix",
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"prebuild-linux": "prebuildify --napi --strip",
|
|
74
|
-
"prebuild-download": "prebuildify-ci download",
|
|
65
|
+
"prebuildify": "prebuildify --napi --target 14.0.0 --force --strip --verbose",
|
|
66
|
+
"prebuildify-cross": "prebuildify-cross --napi --target 14.0.0 --force --strip --verbose",
|
|
67
|
+
"semantic-release": "semantic-release",
|
|
75
68
|
"pretest": "npm run rebuild",
|
|
76
69
|
"rebuild": "node-gyp rebuild",
|
|
77
70
|
"coverage": "nyc npm test && nyc report --reporter=text-lcov > .nyc_output/lcov.info",
|
|
@@ -80,9 +73,7 @@
|
|
|
80
73
|
"browser": {
|
|
81
74
|
"./lib/resolve-bindings.js": "./lib/resolve-bindings-web.js"
|
|
82
75
|
},
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
4
|
|
86
|
-
]
|
|
76
|
+
"publishConfig": {
|
|
77
|
+
"access": "public"
|
|
87
78
|
}
|
|
88
79
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -22,6 +22,7 @@ describe('hci-socket hci', () => {
|
|
|
22
22
|
Socket.prototype.isDevUp = sinon.stub();
|
|
23
23
|
Socket.prototype.removeAllListeners = sinon.stub();
|
|
24
24
|
Socket.prototype.setFilter = sinon.stub();
|
|
25
|
+
Socket.prototype.setAddress = sinon.stub();
|
|
25
26
|
Socket.prototype.write = sinon.stub();
|
|
26
27
|
|
|
27
28
|
hci = new Hci({});
|
|
@@ -43,7 +44,7 @@ describe('hci-socket hci', () => {
|
|
|
43
44
|
assert.calledWithMatch(hci._socket.on, 'data', sinon.match.func);
|
|
44
45
|
assert.calledWithMatch(hci._socket.on, 'error', sinon.match.func);
|
|
45
46
|
|
|
46
|
-
assert.calledOnceWithExactly(hci._socket.bindUser, deviceId);
|
|
47
|
+
assert.calledOnceWithExactly(hci._socket.bindUser, deviceId, undefined);
|
|
47
48
|
assert.calledOnceWithExactly(hci._socket.start);
|
|
48
49
|
|
|
49
50
|
assert.calledOnceWithExactly(hci.reset);
|
|
@@ -60,7 +61,7 @@ describe('hci-socket hci', () => {
|
|
|
60
61
|
assert.calledWithMatch(hci._socket.on, 'data', sinon.match.func);
|
|
61
62
|
assert.calledWithMatch(hci._socket.on, 'error', sinon.match.func);
|
|
62
63
|
|
|
63
|
-
assert.calledOnceWithExactly(hci._socket.bindRaw, deviceId);
|
|
64
|
+
assert.calledOnceWithExactly(hci._socket.bindRaw, deviceId, undefined);
|
|
64
65
|
assert.calledOnceWithExactly(hci._socket.start);
|
|
65
66
|
|
|
66
67
|
assert.calledOnceWithExactly(hci.pollIsDevUp);
|
|
@@ -230,11 +231,6 @@ describe('hci-socket hci', () => {
|
|
|
230
231
|
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x31, 0x20, 0x03, 0x00, 0x05, 0x05]));
|
|
231
232
|
});
|
|
232
233
|
|
|
233
|
-
it('should write randomMAC command', () => {
|
|
234
|
-
hci.setRandomMAC();
|
|
235
|
-
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x05, 0x20, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00]));
|
|
236
|
-
});
|
|
237
|
-
|
|
238
234
|
it('should setSocketFilter', () => {
|
|
239
235
|
hci.setSocketFilter();
|
|
240
236
|
assert.calledOnceWithExactly(hci._socket.setFilter, Buffer.from([0x16, 0, 0, 0, 0x20, 0xc1, 0x08, 0, 0, 0, 0, 0x40, 0, 0]));
|
|
@@ -270,6 +266,50 @@ describe('hci-socket hci', () => {
|
|
|
270
266
|
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 9, 0x10, 0]));
|
|
271
267
|
});
|
|
272
268
|
|
|
269
|
+
describe('setAddress', () => {
|
|
270
|
+
it('should write vendor specific (Linux Foundation) command based on read local version response', () => {
|
|
271
|
+
hci.readBdAddr = sinon.spy();
|
|
272
|
+
hci.setScanEnabled = sinon.spy();
|
|
273
|
+
hci.setScanParameters = sinon.spy();
|
|
274
|
+
|
|
275
|
+
const cmd = 4097;
|
|
276
|
+
const status = 0;
|
|
277
|
+
// hciVer=12, hciRev=0, lmpVer=12, manufacturer=1521, lmpSubVer=65535
|
|
278
|
+
const result = Buffer.from([0x0C, 0x00, 0x00, 0x0C, 0xF1, 0x05, 0xFF, 0xFF]);
|
|
279
|
+
|
|
280
|
+
hci.processCmdCompleteEvent(cmd, status, result);
|
|
281
|
+
|
|
282
|
+
hci.setAddress('11:22:33:44:55:66');
|
|
283
|
+
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x06, 0xfc, 0x06, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]));
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should write vendor specific (Ericsson) command based on manufacturer value (', () => {
|
|
287
|
+
hci._manufacturer = 0;
|
|
288
|
+
hci.readBdAddr = sinon.spy();
|
|
289
|
+
hci.setAddress('11:22:33:44:55:66');
|
|
290
|
+
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x0d, 0xfc, 0x06, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]));
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('should write vendor specific (Texas Instrument) command based on manufacturer value', () => {
|
|
294
|
+
hci._manufacturer = 13;
|
|
295
|
+
hci.readBdAddr = sinon.spy();
|
|
296
|
+
hci.setAddress('11:22:33:44:55:66');
|
|
297
|
+
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x06, 0xfc, 0x06, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]));
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('should write vendor specific (BCM) command based on manufacturer value', () => {
|
|
301
|
+
hci._manufacturer = 15;
|
|
302
|
+
hci.readBdAddr = sinon.spy();
|
|
303
|
+
hci.setAddress('11:22:33:44:55:66');
|
|
304
|
+
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x01, 0xfc, 0x06, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]));
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should not write vendor specific command', () => {
|
|
308
|
+
hci.setAddress('11:22:33:44:55:66');
|
|
309
|
+
assert.notCalled(hci._socket.write);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
273
313
|
describe('setLeEventMask', () => {
|
|
274
314
|
it('should setLeEventMask', () => {
|
|
275
315
|
hci.setLeEventMask();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const should = require('should');
|
|
2
|
+
const sinon = require('sinon');
|
|
3
|
+
const proxyquire = require('proxyquire').noCallThru();
|
|
4
|
+
|
|
5
|
+
const fakeOs = {};
|
|
6
|
+
const { assert } = sinon;
|
|
7
|
+
const vendorSpecific = proxyquire('../../../lib/hci-socket/vs', { os: fakeOs });
|
|
8
|
+
|
|
9
|
+
describe('hci-socket vs', () => {
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
sinon.reset();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('parseAddress', () => {
|
|
15
|
+
it('should convert to Buffer', () => {
|
|
16
|
+
assert.match(vendorSpecific.setAddressCmd(0, '00:11:22:33:44:55').slice(3), Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should not convert to Buffer and throw an Error', () => {
|
|
20
|
+
should.throws(function () {
|
|
21
|
+
vendorSpecific.setAddressCmd(0, '00:11:22:33:44');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
package/.eslintrc.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
root: true,
|
|
3
|
-
extends: ['eslint:recommended', 'semistandard'],
|
|
4
|
-
parserOptions: {
|
|
5
|
-
ecmaVersion: 2017
|
|
6
|
-
},
|
|
7
|
-
env: {
|
|
8
|
-
browser: true,
|
|
9
|
-
mocha: true,
|
|
10
|
-
node: true
|
|
11
|
-
},
|
|
12
|
-
globals: {
|
|
13
|
-
Promise: true
|
|
14
|
-
},
|
|
15
|
-
rules: {
|
|
16
|
-
'space-before-function-paren': ['error', 'always'],
|
|
17
|
-
'no-unused-vars': [
|
|
18
|
-
'error',
|
|
19
|
-
{
|
|
20
|
-
args: 'none'
|
|
21
|
-
}
|
|
22
|
-
],
|
|
23
|
-
semi: 'error'
|
|
24
|
-
}
|
|
25
|
-
};
|
package/.github/FUNDING.yml
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# YAML
|
|
2
|
-
---
|
|
3
|
-
name: fediverse-action
|
|
4
|
-
on: [push]
|
|
5
|
-
jobs:
|
|
6
|
-
post:
|
|
7
|
-
runs-on: ubuntu-latest
|
|
8
|
-
steps:
|
|
9
|
-
- uses: actions/checkout@v3
|
|
10
|
-
- id: log
|
|
11
|
-
run: echo "::set-output name=message::$(git log --no-merges -1 --oneline)"
|
|
12
|
-
- if: "contains(steps.log.outputs.message, 'Release ')"
|
|
13
|
-
uses: rzr/fediverse-action@master
|
|
14
|
-
with:
|
|
15
|
-
access-token: ${{ secrets.MASTODON_ACCESS_TOKEN }}
|
|
16
|
-
message: "https://github.com/${{ github.repository }}/commit/${{ steps.log.outputs.message }} ~ #FediVerseAction"
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
name: Node.js package
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
branches:
|
|
6
|
-
- master
|
|
7
|
-
push:
|
|
8
|
-
branches:
|
|
9
|
-
- master
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
build:
|
|
13
|
-
runs-on: ${{ matrix.os }}
|
|
14
|
-
strategy:
|
|
15
|
-
matrix:
|
|
16
|
-
os: [ubuntu-20.04, ubuntu-latest, macos-latest, windows-2019]
|
|
17
|
-
node: [12, 14, 16, 18]
|
|
18
|
-
steps:
|
|
19
|
-
- uses: actions/checkout@v3
|
|
20
|
-
- uses: actions/setup-node@v3
|
|
21
|
-
with:
|
|
22
|
-
node-version: ${{ matrix.node }}
|
|
23
|
-
- name: Install dependencies (ubuntu-latest)
|
|
24
|
-
if: ${{ matrix.os == 'ubuntu-latest' }}
|
|
25
|
-
run: |
|
|
26
|
-
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
|
27
|
-
sudo apt -qq update
|
|
28
|
-
sudo apt install -y g++-9
|
|
29
|
-
export CC="g++-9"
|
|
30
|
-
- name: Install NPM packages
|
|
31
|
-
run: |
|
|
32
|
-
npm install
|
|
33
|
-
- name: Run tests
|
|
34
|
-
run: |
|
|
35
|
-
npm test
|
|
36
|
-
- name: Lint
|
|
37
|
-
run: |
|
|
38
|
-
npm run lint
|
|
39
|
-
|
|
40
|
-
quality:
|
|
41
|
-
name: Quality phase
|
|
42
|
-
runs-on: ubuntu-latest
|
|
43
|
-
steps:
|
|
44
|
-
- name: ⬇️ Checkout code
|
|
45
|
-
uses: actions/checkout@v3
|
|
46
|
-
- name: 💽 Setup nodejs
|
|
47
|
-
uses: actions/setup-node@v3
|
|
48
|
-
with:
|
|
49
|
-
node-version: '14'
|
|
50
|
-
- name: 📇 Use npm cache
|
|
51
|
-
uses: c-hive/gha-npm-cache@v1
|
|
52
|
-
- name: Install dependencies (ubuntu-latest)
|
|
53
|
-
run: |
|
|
54
|
-
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
|
55
|
-
sudo apt -qq update
|
|
56
|
-
sudo apt install -y g++-9
|
|
57
|
-
export CC="g++-9"
|
|
58
|
-
- name: 📦 Install NPM packages
|
|
59
|
-
run: |
|
|
60
|
-
npm install
|
|
61
|
-
- name: ✅ Test with coverage
|
|
62
|
-
run: |
|
|
63
|
-
npm run coverage
|
|
64
|
-
- name: 📄 Codecov report upload
|
|
65
|
-
uses: codecov/codecov-action@v2
|
|
66
|
-
with:
|
|
67
|
-
fail_ci_if_error: true
|
|
68
|
-
file: .nyc_output/lcov.info
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
name: npm-publish
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- master # Change this to your default branch
|
|
6
|
-
jobs:
|
|
7
|
-
npm-publish:
|
|
8
|
-
name: npm-publish
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
steps:
|
|
11
|
-
- uses: actions/checkout@master
|
|
12
|
-
- id: log
|
|
13
|
-
run: echo "::set-output name=message::$(git log --no-merges -1 --oneline)"
|
|
14
|
-
- if: "contains(steps.log.outputs.message, 'Release ')"
|
|
15
|
-
uses: actions/setup-node@master
|
|
16
|
-
with:
|
|
17
|
-
node-version: 16.0.0
|
|
18
|
-
- if: "contains(steps.log.outputs.message, 'Release ')"
|
|
19
|
-
uses: pascalgn/npm-publish-action@1.3.9
|
|
20
|
-
with: # All of these inputs are optional
|
|
21
|
-
tag_name: "v%s"
|
|
22
|
-
tag_message: "v%s"
|
|
23
|
-
commit_pattern: "^Release (\\S+)"
|
|
24
|
-
env: # More info about the environment variables in the README
|
|
25
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Leave this as is, it's automatically generated
|
|
26
|
-
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} # You need to set this in your repo settings
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
name: prebuild
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- master
|
|
7
|
-
tags:
|
|
8
|
-
- '*'
|
|
9
|
-
pull_request:
|
|
10
|
-
branches:
|
|
11
|
-
- master
|
|
12
|
-
workflow_dispatch:
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
prebuild:
|
|
16
|
-
strategy:
|
|
17
|
-
matrix:
|
|
18
|
-
include:
|
|
19
|
-
- name: darwin
|
|
20
|
-
os: macos-11
|
|
21
|
-
node: x64
|
|
22
|
-
- name: linux
|
|
23
|
-
os: ubuntu-latest
|
|
24
|
-
- name: win32
|
|
25
|
-
os: windows-2019
|
|
26
|
-
name: Build ${{ matrix.name }}
|
|
27
|
-
runs-on: ${{ matrix.os }}
|
|
28
|
-
steps:
|
|
29
|
-
- if: matrix.node
|
|
30
|
-
uses: actions/setup-node@v3
|
|
31
|
-
with:
|
|
32
|
-
node-version: 14.x
|
|
33
|
-
architecture: ${{ matrix.node }}
|
|
34
|
-
- uses: actions/checkout@v3
|
|
35
|
-
- name: Install dependencies (ubuntu-latest)
|
|
36
|
-
# Use g++-9 only on versions after 'ubuntu-18.04'
|
|
37
|
-
if: ${{ matrix.os == 'ubuntu-latest' }}
|
|
38
|
-
run: |
|
|
39
|
-
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
|
40
|
-
sudo apt -qq update
|
|
41
|
-
sudo apt install -y g++-9
|
|
42
|
-
export CC="g++-9"
|
|
43
|
-
- run: npm install --ignore-scripts
|
|
44
|
-
- run: npm run prebuild-${{ matrix.name }}
|
|
45
|
-
- run: tar -zcvf ${{ matrix.name }}.tar.gz -C prebuilds .
|
|
46
|
-
- uses: actions/upload-artifact@v3
|
|
47
|
-
with:
|
|
48
|
-
name: build-artifacts
|
|
49
|
-
path: prebuilds/
|
|
50
|
-
if-no-files-found: error
|
|
51
|
-
- if: failure()
|
|
52
|
-
run: npx shx ls -lA
|
|
53
|
-
release:
|
|
54
|
-
needs: prebuild
|
|
55
|
-
name: Release
|
|
56
|
-
runs-on: ubuntu-latest
|
|
57
|
-
steps:
|
|
58
|
-
- uses: actions/checkout@v3
|
|
59
|
-
- uses: actions/download-artifact@v3
|
|
60
|
-
with:
|
|
61
|
-
name: build-artifacts
|
|
62
|
-
path: prebuilds
|
|
63
|
-
- uses: actions/setup-node@v3
|
|
64
|
-
with:
|
|
65
|
-
node-version: 18.x
|
|
66
|
-
- run: npm ci
|
|
67
|
-
- run: npm run build
|
|
68
|
-
- run: npm run semantic-release
|
|
69
|
-
env:
|
|
70
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
71
|
-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
## Version 1.9.1
|
|
2
|
-
|
|
3
|
-
* Don't forget previously discovered services and characteristics ([@elafargue](https://github.com/elafargue))
|
|
4
|
-
* Fixed peripheral-explorer example with newer async versions
|
|
5
|
-
* web socket binding: various fixes ([@hadrienk](https://github.com/hadrienk))
|
|
6
|
-
* Fix multiple init of bindings with multiple stateChange listeners added or noble.state is accessed
|
|
7
|
-
|
|
8
|
-
## Version 1.9.0
|
|
9
|
-
|
|
10
|
-
* Don't initialize bindings until first state change listener added
|
|
11
|
-
* webble: hooked up disconnect event
|
|
12
|
-
* webble: clear cached services on reconnect
|
|
13
|
-
* hci-socket: Added upport 32-bit and 128-bit service data UUIDs ([@arekzelechowski](https://github.com/arekzelechowski))
|
|
14
|
-
* Update 'connectable' property upon discovery ([@dimitrisx](https://github.com/dimitrisx))
|
|
15
|
-
* macOS: Added support for High Sierra
|
|
16
|
-
* webble: remove subscribe listeners on disconnect
|
|
17
|
-
|
|
18
|
-
## Version 1.8.1
|
|
19
|
-
|
|
20
|
-
* easier install instructions for Windows ([@don](https://github.com/don))
|
|
21
|
-
* hci-socket binding: more descriptive error outputs ([@mbifulco](https://github.com/mbifulco))
|
|
22
|
-
* hci-socket binding: report non-connectable advertisements without scan response
|
|
23
|
-
* Corrected deprecated `read` event for characteristics no emitting for notifications
|
|
24
|
-
|
|
25
|
-
## Version 1.8.0
|
|
26
|
-
|
|
27
|
-
* hci-socket binding: always set scan parameters before scanning ([@Lahorde](https://github.com/Lahorde))
|
|
28
|
-
* hci-socket binding: add L2CAP signaling layer for non-Linux or Linux user channel mode
|
|
29
|
-
* hci-socket binding: Workarounds for scanning with N.T.C. C.H.I.P
|
|
30
|
-
* hci-socket binding: if `init()` fails we don't want to try and clear up ([@gfwilliams](https://github.com/gfwilliams))
|
|
31
|
-
* Fix read events firing for notifications ([@zkiiito](https://github.com/zkiiito))
|
|
32
|
-
* Add FreeBSD support ([@myfreeweb](https://github.com/myfreeweb))
|
|
33
|
-
* Fix startScanning callback calling setting error to try ([@MarSoft](https://github.com/MarSoft))
|
|
34
|
-
* New Web Bluetooth API shim ([@monteslu](https://github.com/monteslu))
|
|
35
|
-
|
|
36
|
-
## Version 1.7.0
|
|
37
|
-
|
|
38
|
-
* hci-socket binding: now supports "long writes" ([@projectgus](https://github.com/projectgus))
|
|
39
|
-
* hci-socket binding: use latest bluetooth-hci-socket dependency (~0.5.1)
|
|
40
|
-
* hci-socket binding: add support to extract service solicitation UUID's from advertisement ([@smartyw](https://github.com/smartyw))
|
|
41
|
-
* web-socket binding: fixed write handle not working ([@christopherhex](https://github.com/christopherhex))
|
|
42
|
-
* hci-socket binding: initial bindUser support via HCI_CHANNEL_USER environment variable
|
|
43
|
-
|
|
44
|
-
## Version 1.6.0
|
|
45
|
-
|
|
46
|
-
* hci-socket binding: use latest bluetooth-hci-socket dependency (~0.4.4)
|
|
47
|
-
* Added characteristic.subscribe and characteristic.unsubscribe API's (characteristic.notify is now deprecated)
|
|
48
|
-
* hci-socket binding: use OCF_LE_SET_EVENT_MASK for LE_SET_EVENT_MASK_CMD
|
|
49
|
-
* hci-socket binding: check READ_LE_HOST_SUPPORTED_CMD status before parsing result
|
|
50
|
-
|
|
51
|
-
## Version 1.5.0
|
|
52
|
-
|
|
53
|
-
* hci-socket binding: add NOBLE_MULTI_ROLE flag for ignoring peripheral role commands ([@popasquat89](https://github.com/bradjc))
|
|
54
|
-
* Fix variable typo in ```with-bindings.js`` ([@rclai](https://github.com/rclai))
|
|
55
|
-
|
|
56
|
-
## Version 1.4.0
|
|
57
|
-
|
|
58
|
-
* hci-socket binding: include service data UUID's when filtering discover
|
|
59
|
-
* hci-socket binding: emit scan start/stop when external app changes scanning start ([@bradjc](https://github.com/bradjc))
|
|
60
|
-
* Support for pluggable bindings ([@hgwood](https://github.com/hgwood))
|
|
61
|
-
* hci-socket binding: don't kill all descriptors when looking for new Characteristics ([@Neutrosider](https://github.com/Neutrosider))
|
|
62
|
-
|
|
63
|
-
## Version 1.3.0
|
|
64
|
-
|
|
65
|
-
* Check and report LE Create Conn command status
|
|
66
|
-
* Correct parsing master clock accuracy value from LE Conn Complete event
|
|
67
|
-
* Added logic to reject rather than ignore unknown requests/commands. ([@george-hawkins](https://github.com/george-hawkins))
|
|
68
|
-
* Don't reset scan state on read local version response if state is powered on
|
|
69
|
-
* Expose local adapter address via ```noble.address```, available after ```poweredOn``` state change event
|
|
70
|
-
* Fix ```serviceUuids``` var check in ```peripheral-explorer.js``` ([@jrobeson](https://github.com/jrobeson))
|
|
71
|
-
|
|
72
|
-
## Version 1.2.1
|
|
73
|
-
|
|
74
|
-
* Use latest v0.4.1 bluetooth-hci-socket dependency (for kernel 4.1.x disconnect workaround)
|
|
75
|
-
* Add read + write LE host supported commands (for kernel 4.1.x disconnect workaround)
|
|
76
|
-
* Fix a potential exception when accessing a non existent element ([@Loghorn](https://github.com/Loghorn))
|
|
77
|
-
|
|
78
|
-
## Version 1.2.0
|
|
79
|
-
|
|
80
|
-
* Use v0.4.0 of bluetooth-hci-socket
|
|
81
|
-
* Ignore peripherals with only connectable flag on OS X 10.10
|
|
82
|
-
* Bindings no longer init themselves
|
|
83
|
-
* Fix this._discoveredPeripheralUUids = []; variable not initalized in constructor ([@jacobrosenthal](https://github.com/jacobrosenthal))
|
|
84
|
-
* New ```peripheral.connectable``` property
|
|
85
|
-
* Updates to Linux prerequisites in read me
|
|
86
|
-
* Throw error if scanning is started when state is not powered on
|
|
87
|
-
|
|
88
|
-
## Version 1.1.0
|
|
89
|
-
|
|
90
|
-
* Introduce ```peripheral.id```, ```periheral.uuid``` is deprecated now
|
|
91
|
-
* Initial Windows support via WinUSB and bluetooth-hci-socket
|
|
92
|
-
* Rework Linux stack to use [bluetooth-hci-socket](https://github.com/sandeepmistry/node-bluetooth-hci-socket)
|
|
93
|
-
* Clarify notify related API's in read me ([@OJFord](https://github.com/OJFord))
|
|
94
|
-
|
|
95
|
-
## Version 1.0.2
|
|
96
|
-
|
|
97
|
-
* Add mac dummy in binding.pyq ([@DomiR](https://github.com/DomiR))
|
|
98
|
-
* Fixes for distributed and websocket bindings ([@Loghorn](https://github.com/Loghorn))
|
|
99
|
-
* OS X Mavericks and legacy: manually emit write event for write without response requests
|
|
100
|
-
* Update README for packages needed for rpm-based systems ([@ppannuto](https://github.com/ppannuto))
|
|
101
|
-
* Linux: refresh serviceUuids for incoming advertisement ([@BBarash](https://github.com/BBarash))
|
|
102
|
-
|
|
103
|
-
## Version 1.0.1
|
|
104
|
-
|
|
105
|
-
* correct peripherals not being created correctly
|
|
106
|
-
|
|
107
|
-
## Version 1.0
|
|
108
|
-
|
|
109
|
-
* remove unneeded setTimeout's in OS X bindings
|
|
110
|
-
* added persistent peripherals between calls to .startScanning() on mavericks ([@andySigler](https://github.com/andySigler))
|
|
111
|
-
* report error or print warning if startScanning is called with state is not poweredOn
|
|
112
|
-
* emit events for warnings ([@voodootikigod ](https://github.com/voodootikigod))
|
|
113
|
-
* disable scanning flag on start on Linux to prevent unsupport adapter state in some cases
|
|
114
|
-
* update debug dependency version
|
|
115
|
-
* add address type to peripheral if known
|
|
116
|
-
|
|
117
|
-
## Older
|
|
118
|
-
|
|
119
|
-
* Changes not recorded
|
package/MAINTAINERS.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
* Philippe Coval <mailto:p.coval@samsung.com> (https://www.npmjs.com/~rzr)
|
package/test.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
const noble = require('./index');
|
|
2
|
-
|
|
3
|
-
console.log('noble');
|
|
4
|
-
|
|
5
|
-
noble.on('stateChange', function (state) {
|
|
6
|
-
console.log('on -> stateChange: ' + state);
|
|
7
|
-
|
|
8
|
-
if (state === 'poweredOn') {
|
|
9
|
-
noble.startScanning([], true);
|
|
10
|
-
} else {
|
|
11
|
-
noble.stopScanning();
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
noble.on('scanStart', function () {
|
|
16
|
-
console.log('on -> scanStart');
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
noble.on('scanStop', function () {
|
|
20
|
-
console.log('on -> scanStop');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
noble.on('discover', function (peripheral) {
|
|
24
|
-
console.log('on -> discover: ' + peripheral);
|
|
25
|
-
|
|
26
|
-
noble.stopScanning();
|
|
27
|
-
|
|
28
|
-
peripheral.on('connect', function () {
|
|
29
|
-
console.log('on -> connect');
|
|
30
|
-
this.updateRssi();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
peripheral.on('disconnect', function () {
|
|
34
|
-
console.log('on -> disconnect');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
peripheral.on('rssiUpdate', function (rssi) {
|
|
38
|
-
console.log('on -> RSSI update ' + rssi);
|
|
39
|
-
this.discoverServices();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
peripheral.on('servicesDiscover', function (services) {
|
|
43
|
-
console.log('on -> peripheral services discovered ' + services);
|
|
44
|
-
|
|
45
|
-
const serviceIndex = 0;
|
|
46
|
-
|
|
47
|
-
services[serviceIndex].on(
|
|
48
|
-
'includedServicesDiscover',
|
|
49
|
-
function (includedServiceUuids) {
|
|
50
|
-
console.log(
|
|
51
|
-
'on -> service included services discovered ' + includedServiceUuids
|
|
52
|
-
);
|
|
53
|
-
this.discoverCharacteristics();
|
|
54
|
-
}
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
services[serviceIndex].on(
|
|
58
|
-
'characteristicsDiscover',
|
|
59
|
-
function (characteristics) {
|
|
60
|
-
console.log(
|
|
61
|
-
'on -> service characteristics discovered ' + characteristics
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const characteristicIndex = 0;
|
|
65
|
-
|
|
66
|
-
characteristics[characteristicIndex].on(
|
|
67
|
-
'read',
|
|
68
|
-
function (data, isNotification) {
|
|
69
|
-
console.log(
|
|
70
|
-
'on -> characteristic read ' + data + ' ' + isNotification
|
|
71
|
-
);
|
|
72
|
-
console.log(data);
|
|
73
|
-
|
|
74
|
-
peripheral.disconnect();
|
|
75
|
-
}
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
characteristics[characteristicIndex].on('write', function () {
|
|
79
|
-
console.log('on -> characteristic write ');
|
|
80
|
-
|
|
81
|
-
peripheral.disconnect();
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
characteristics[characteristicIndex].on('broadcast', function (state) {
|
|
85
|
-
console.log('on -> characteristic broadcast ' + state);
|
|
86
|
-
|
|
87
|
-
peripheral.disconnect();
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
characteristics[characteristicIndex].on('notify', function (state) {
|
|
91
|
-
console.log('on -> characteristic notify ' + state);
|
|
92
|
-
|
|
93
|
-
peripheral.disconnect();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
characteristics[characteristicIndex].on(
|
|
97
|
-
'descriptorsDiscover',
|
|
98
|
-
function (descriptors) {
|
|
99
|
-
console.log('on -> descriptors discover ' + descriptors);
|
|
100
|
-
|
|
101
|
-
const descriptorIndex = 0;
|
|
102
|
-
|
|
103
|
-
descriptors[descriptorIndex].on('valueRead', function (data) {
|
|
104
|
-
console.log('on -> descriptor value read ' + data);
|
|
105
|
-
console.log(data);
|
|
106
|
-
peripheral.disconnect();
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
descriptors[descriptorIndex].on('valueWrite', function () {
|
|
110
|
-
console.log('on -> descriptor value write ');
|
|
111
|
-
peripheral.disconnect();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
descriptors[descriptorIndex].readValue();
|
|
115
|
-
// descriptors[descriptorIndex].writeValue(new Buffer([0]));
|
|
116
|
-
}
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
characteristics[characteristicIndex].read();
|
|
120
|
-
// characteristics[characteristicIndex].write(new Buffer('hello'));
|
|
121
|
-
// characteristics[characteristicIndex].broadcast(true);
|
|
122
|
-
// characteristics[characteristicIndex].notify(true);
|
|
123
|
-
// characteristics[characteristicIndex].discoverDescriptors();
|
|
124
|
-
}
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
services[serviceIndex].discoverIncludedServices();
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
peripheral.connect();
|
|
131
|
-
});
|