@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
package/.editorconfig
DELETED
package/.nycrc.json
DELETED
package/codecov.yml
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
/* eslint-disable handle-callback-err */
|
|
2
|
-
/** discover a device (here, the first one where the name was resolved),
|
|
3
|
-
* for the first device discover all services and characteristics,
|
|
4
|
-
* store the collected GATT information into a meta-data object and write to disk.
|
|
5
|
-
* Finds a temperature characteristic and registers for data.
|
|
6
|
-
* Prints timing information from discovered to connected to reading states.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const noble = require('../index');
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
|
|
12
|
-
// the sensor value to scan for, number of bits and factor for displaying it
|
|
13
|
-
const CHANNEL = process.env.CHANNEL ? process.env.CHANNEL : 'Temperature';
|
|
14
|
-
const BITS = process.env.BITS ? 1 * process.env.BITS : 16;
|
|
15
|
-
const FACTOR = process.env.FACTOR ? 1.0 * process.env.FACTOR : 0.1;
|
|
16
|
-
|
|
17
|
-
const EXT = '.dump';
|
|
18
|
-
|
|
19
|
-
noble.on('stateChange', function (state) {
|
|
20
|
-
if (state === 'poweredOn') {
|
|
21
|
-
noble.startScanning([], false);
|
|
22
|
-
} else {
|
|
23
|
-
noble.stopScanning();
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
let tDisco = 0; // time when device was discovered
|
|
28
|
-
let tConn = 0; // time when connection to device was established
|
|
29
|
-
let tRead = 0; // time when reading data starts.
|
|
30
|
-
|
|
31
|
-
// collect device meta-data into this object:
|
|
32
|
-
const meta = {
|
|
33
|
-
services: [], // stores an array of GATT service data objects
|
|
34
|
-
characteristics: {} // a map with key service-UUID, stores the array of characteristics
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
noble.on('discover', function (peripheral) {
|
|
38
|
-
console.log(
|
|
39
|
-
`peripheral discovered (${peripheral.id} with address <${peripheral.address}, ${peripheral.addressType}>, connectable ${peripheral.connectable}, RSSI ${peripheral.rssi}:`
|
|
40
|
-
);
|
|
41
|
-
console.log('\thello my local name is:');
|
|
42
|
-
console.log(`\t\t${peripheral.advertisement.localName}`);
|
|
43
|
-
console.log();
|
|
44
|
-
|
|
45
|
-
// connect to the first device with a valid name
|
|
46
|
-
if (peripheral.advertisement.localName) {
|
|
47
|
-
console.log(
|
|
48
|
-
`Connecting to ${peripheral.address} ${peripheral.advertisement.localName}`
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
tDisco = Date.now();
|
|
52
|
-
|
|
53
|
-
connectToDevice(peripheral);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const connectToDevice = function (peripheral) {
|
|
58
|
-
// BLE cannot scan and connect in parallel, so we stop scanning here:
|
|
59
|
-
noble.stopScanning();
|
|
60
|
-
|
|
61
|
-
peripheral.connect((error) => {
|
|
62
|
-
// noble.startScanning([], true)
|
|
63
|
-
if (error) {
|
|
64
|
-
console.log(`Connect error: ${error}`);
|
|
65
|
-
noble.startScanning([], true);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
tConn = Date.now();
|
|
69
|
-
console.log('Connected!');
|
|
70
|
-
|
|
71
|
-
findServices(noble, peripheral);
|
|
72
|
-
});
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
let servicesToRead = 0;
|
|
76
|
-
|
|
77
|
-
const findServices = function (noble, peripheral) {
|
|
78
|
-
meta.uuid = peripheral.uuid;
|
|
79
|
-
meta.address = peripheral.address;
|
|
80
|
-
meta.name = peripheral.advertisement.localName; // not needed but nice to have
|
|
81
|
-
|
|
82
|
-
meta.characteristics = {};
|
|
83
|
-
|
|
84
|
-
// callback triggers with GATT-relevant data
|
|
85
|
-
peripheral.on('servicesDiscovered', (peripheral, services) => {
|
|
86
|
-
console.log(`servicesDiscovered: Found ${services.length} services! `);
|
|
87
|
-
meta.services = services;
|
|
88
|
-
for (const i in services) {
|
|
89
|
-
const service = services[i];
|
|
90
|
-
console.log(`\tservice ${i} : ${JSON.stringify(service)}`);
|
|
91
|
-
// meta.services[ service.uuid ] = service
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
peripheral.discoverServices([], (error, services) => {
|
|
96
|
-
if (error) {
|
|
97
|
-
console.error(error);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
let sensorCharacteristic;
|
|
102
|
-
|
|
103
|
-
servicesToRead = services.length;
|
|
104
|
-
// we found the list of services, now trigger characteristics lookup for each of them:
|
|
105
|
-
|
|
106
|
-
for (let i = 0; i < services.length; i++) {
|
|
107
|
-
const service = services[i];
|
|
108
|
-
|
|
109
|
-
service.on('characteristicsDiscovered', (characteristics) => {
|
|
110
|
-
// store the list of characteristics per service
|
|
111
|
-
meta.characteristics[service.uuid] = characteristics;
|
|
112
|
-
|
|
113
|
-
console.log(`SRV\t${service.uuid} characteristic GATT data: `);
|
|
114
|
-
for (let i = 0; i < characteristics.length; i++) {
|
|
115
|
-
console.log(
|
|
116
|
-
`\t${service.uuid} chara.\t ${i} ${JSON.stringify(
|
|
117
|
-
characteristics[i]
|
|
118
|
-
)}`
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
service.discoverCharacteristics([], function (error, characteristics) {
|
|
124
|
-
if (error) {
|
|
125
|
-
console.error(error);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
console.log(`SRV\t${service.uuid} characteristic decoded data: `);
|
|
130
|
-
for (let j = 0; j < characteristics.length; j++) {
|
|
131
|
-
const ch = characteristics[j];
|
|
132
|
-
console.log(`\t${service.uuid} chara.\t ${j} ${ch}`);
|
|
133
|
-
|
|
134
|
-
if (ch.name === CHANNEL) {
|
|
135
|
-
console.log(`found ${CHANNEL} characteristic!`);
|
|
136
|
-
sensorCharacteristic = ch;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
servicesToRead--;
|
|
141
|
-
if (!servicesToRead) {
|
|
142
|
-
console.log('----------------- FINISHED');
|
|
143
|
-
console.log(JSON.stringify(meta, null, 4));
|
|
144
|
-
// write to file
|
|
145
|
-
fs.writeFile(
|
|
146
|
-
meta.uuid + EXT,
|
|
147
|
-
JSON.stringify(meta, null, 2),
|
|
148
|
-
function (err) {
|
|
149
|
-
if (err) {
|
|
150
|
-
return console.log(err);
|
|
151
|
-
}
|
|
152
|
-
console.log('The data was saved to ', meta.uuid + EXT);
|
|
153
|
-
}
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
if (sensorCharacteristic) {
|
|
157
|
-
console.log('Listening for temperature data...');
|
|
158
|
-
|
|
159
|
-
tRead = Date.now();
|
|
160
|
-
|
|
161
|
-
sensorCharacteristic.on('data', (data) => {
|
|
162
|
-
if (BITS === 16) {
|
|
163
|
-
console.log(` new ${CHANNEL} ${data.readUInt16LE() * FACTOR}`);
|
|
164
|
-
} else if (BITS === 32) {
|
|
165
|
-
console.log(` new ${CHANNEL} ${data.readUInt32LE() * FACTOR}`);
|
|
166
|
-
} else {
|
|
167
|
-
console.log(` Cannot cope with BITS value ${BITS}`);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
sensorCharacteristic.read();
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
console.log(
|
|
174
|
-
`Timespan from discovery to connected: ${tConn - tDisco} ms`
|
|
175
|
-
);
|
|
176
|
-
console.log(
|
|
177
|
-
`Timespan from connected to reading : ${tRead - tConn} ms`
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
process.on('SIGINT', function () {
|
|
186
|
-
console.log('Caught interrupt signal');
|
|
187
|
-
noble.stopScanning(() => process.exit());
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
process.on('SIGQUIT', function () {
|
|
191
|
-
console.log('Caught interrupt signal');
|
|
192
|
-
noble.stopScanning(() => process.exit());
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
process.on('SIGTERM', function () {
|
|
196
|
-
console.log('Caught interrupt signal');
|
|
197
|
-
noble.stopScanning(() => process.exit());
|
|
198
|
-
});
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/* eslint-disable handle-callback-err */
|
|
2
|
-
/** reconnect to a device that has been discovered earlier on using cache-gatt-discovery:
|
|
3
|
-
* If a device is discovered and a dump file exists, load it and connect to it, re-initializing service
|
|
4
|
-
* and characteristic objects in the noble stack.
|
|
5
|
-
* Finds a temperature characteristic and registers for data.
|
|
6
|
-
* Prints timing information from discovered to connected to reading states.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const noble = require('../index');
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
|
|
12
|
-
// the sensor value to scan for, number of bits and factor for displaying it
|
|
13
|
-
const CHANNEL = process.env.CHANNEL ? process.env.CHANNEL : 'Temperature';
|
|
14
|
-
const BITS = process.env.BITS ? 1 * process.env.BITS : 16;
|
|
15
|
-
const FACTOR = process.env.FACTOR ? 1.0 * process.env.FACTOR : 0.1;
|
|
16
|
-
|
|
17
|
-
const EXT = '.dump';
|
|
18
|
-
|
|
19
|
-
noble.on('stateChange', function (state) {
|
|
20
|
-
if (state === 'poweredOn') {
|
|
21
|
-
noble.startScanning([], false);
|
|
22
|
-
} else {
|
|
23
|
-
noble.stopScanning();
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
let tDisco = 0; // time when device was discovered
|
|
28
|
-
let tConn = 0; // time when connection to device was established
|
|
29
|
-
let tRead = 0; // time when reading data starts.
|
|
30
|
-
|
|
31
|
-
// collect device meta-data into this object:
|
|
32
|
-
let meta = {
|
|
33
|
-
services: {}, // a map indexted by service-UUID -> contains service data
|
|
34
|
-
characteristics: {} // an map with key service-UUID, stores the array of characteristics
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
noble.on('discover', function (peripheral) {
|
|
38
|
-
console.log(
|
|
39
|
-
`peripheral discovered (${peripheral.id} with address <${peripheral.address}, ${peripheral.addressType}>, connectable ${peripheral.connectable}, RSSI ${peripheral.rssi}:`
|
|
40
|
-
);
|
|
41
|
-
console.log('\thello my local name is:');
|
|
42
|
-
console.log(`\t\t${peripheral.advertisement.localName}`);
|
|
43
|
-
console.log();
|
|
44
|
-
|
|
45
|
-
// Check if a dump exists in the current directory.
|
|
46
|
-
fs.access(peripheral.uuid + EXT, fs.constants.F_OK, (err) => {
|
|
47
|
-
if (!err) {
|
|
48
|
-
console.log(`found dump file for ${peripheral.uuid}`);
|
|
49
|
-
|
|
50
|
-
tDisco = Date.now();
|
|
51
|
-
|
|
52
|
-
quickConnect(peripheral);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const quickConnect = function (peripheral) {
|
|
58
|
-
// BLE cannot scan and connect in parallel, so we stop scanning here:
|
|
59
|
-
noble.stopScanning();
|
|
60
|
-
|
|
61
|
-
peripheral.connect((error) => {
|
|
62
|
-
if (error) {
|
|
63
|
-
console.log(`Connect error: ${error}`);
|
|
64
|
-
noble.startScanning([], true);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
tConn = Date.now();
|
|
68
|
-
console.log('Connected!');
|
|
69
|
-
|
|
70
|
-
// load stored data. This needs to be done when connected, as we need a handle at GATT level
|
|
71
|
-
meta = loadData(peripheral);
|
|
72
|
-
|
|
73
|
-
// initialize the service and charateristics objects in Noble; return a temperature characteristic, if found
|
|
74
|
-
const sensorCharacteristic = setData(peripheral, meta);
|
|
75
|
-
|
|
76
|
-
if (!sensorCharacteristic) {
|
|
77
|
-
console.log('Warning - no temperature characteristic found.');
|
|
78
|
-
} else {
|
|
79
|
-
console.log('Listening for temperature data...');
|
|
80
|
-
|
|
81
|
-
tRead = Date.now();
|
|
82
|
-
|
|
83
|
-
sensorCharacteristic.on('data', (data) => {
|
|
84
|
-
if (BITS === 16) {
|
|
85
|
-
console.log(` new ${CHANNEL} ${data.readUInt16LE() * FACTOR}`);
|
|
86
|
-
} else if (BITS === 32) {
|
|
87
|
-
console.log(` new ${CHANNEL} ${data.readUInt32LE() * FACTOR}`);
|
|
88
|
-
} else {
|
|
89
|
-
console.log(` Cannot cope with BITS value ${BITS}`);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
sensorCharacteristic.read();
|
|
93
|
-
|
|
94
|
-
console.log(`Timespan from discovery to connected: ${tConn - tDisco} ms`);
|
|
95
|
-
console.log(`Timespan from connected to reading : ${tRead - tConn} ms`);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const loadData = function (peripheral) {
|
|
101
|
-
const dump = fs.readFileSync(peripheral.uuid + EXT);
|
|
102
|
-
const data = JSON.parse(dump);
|
|
103
|
-
|
|
104
|
-
// verify data: console.log(JSON.stringify(data,null,2))
|
|
105
|
-
return data;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const setData = function (peripheral, meta) {
|
|
109
|
-
// first, create the service objects:
|
|
110
|
-
console.log('initializing services... ');
|
|
111
|
-
|
|
112
|
-
// addServices returns an array of initialized service objects
|
|
113
|
-
const services = noble.addServices(peripheral.uuid, meta.services);
|
|
114
|
-
|
|
115
|
-
console.log('initialized services: ');
|
|
116
|
-
for (const i in services) {
|
|
117
|
-
const service = services[i];
|
|
118
|
-
console.log(`\tservice ${i} ${service}`);
|
|
119
|
-
}
|
|
120
|
-
console.log();
|
|
121
|
-
|
|
122
|
-
let sensorCharacteristic;
|
|
123
|
-
|
|
124
|
-
console.log('initializing characteristics... ');
|
|
125
|
-
// now, for each service, set the characteristics:
|
|
126
|
-
for (const i in services) {
|
|
127
|
-
const service = services[i];
|
|
128
|
-
const charas = meta.characteristics[service.uuid];
|
|
129
|
-
console.log(`\tservice ${i} ${service} ${JSON.stringify(charas)}`);
|
|
130
|
-
|
|
131
|
-
const characteristics = noble.addCharacteristics(
|
|
132
|
-
peripheral.uuid,
|
|
133
|
-
service.uuid,
|
|
134
|
-
charas
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
for (const j in characteristics) {
|
|
138
|
-
const characteristic = characteristics[j];
|
|
139
|
-
console.log(
|
|
140
|
-
`\t\tcharac ${service.uuid} ${j} ${characteristic} ${characteristic.rawProps}`
|
|
141
|
-
);
|
|
142
|
-
if (characteristic.name === CHANNEL) {
|
|
143
|
-
console.log(`\t\t\t-->found ${CHANNEL} characteristic!`);
|
|
144
|
-
sensorCharacteristic = characteristic;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return sensorCharacteristic;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
process.on('SIGINT', function () {
|
|
152
|
-
console.log('Caught interrupt signal');
|
|
153
|
-
noble.stopScanning(() => process.exit());
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
process.on('SIGQUIT', function () {
|
|
157
|
-
console.log('Caught interrupt signal');
|
|
158
|
-
noble.stopScanning(() => process.exit());
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
process.on('SIGTERM', function () {
|
|
162
|
-
console.log('Caught interrupt signal');
|
|
163
|
-
noble.stopScanning(() => process.exit());
|
|
164
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
const noble = require('../with-custom-binding')({ extended: true });
|
|
2
|
-
|
|
3
|
-
noble.on('stateChange', function (state) {
|
|
4
|
-
if (state === 'poweredOn') {
|
|
5
|
-
noble.startScanning([], false);
|
|
6
|
-
} else {
|
|
7
|
-
noble.stopScanning();
|
|
8
|
-
}
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
noble.on('discover', function (peripheral) {
|
|
12
|
-
console.log(`${new Date()}`);
|
|
13
|
-
console.log(
|
|
14
|
-
`Peripheral discovered (${peripheral.id} with address <${peripheral.address}, ${peripheral.addressType}>, connectable: ${peripheral.connectable}, scannable: ${peripheral.scannable}, RSSI ${peripheral.rssi}:`
|
|
15
|
-
);
|
|
16
|
-
console.log('\thello my local name is:');
|
|
17
|
-
console.log(`\t\t${peripheral.advertisement.localName}`);
|
|
18
|
-
console.log(
|
|
19
|
-
'\tcan I interest you in any of the following advertised services:'
|
|
20
|
-
);
|
|
21
|
-
console.log(`\t\t${JSON.stringify(peripheral.advertisement.serviceUuids)}`);
|
|
22
|
-
const serviceData = peripheral.advertisement.serviceData;
|
|
23
|
-
|
|
24
|
-
if (serviceData && serviceData.length) {
|
|
25
|
-
console.log('\there is my service data:');
|
|
26
|
-
for (const i in serviceData) {
|
|
27
|
-
console.log(
|
|
28
|
-
`\t\t${JSON.stringify(serviceData[i].uuid)}: ${JSON.stringify(
|
|
29
|
-
serviceData[i].data.toString('hex')
|
|
30
|
-
)}`
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (peripheral.advertisement.manufacturerData) {
|
|
36
|
-
console.log('\there is my manufacturer data:');
|
|
37
|
-
console.log(
|
|
38
|
-
`\t\t${JSON.stringify(
|
|
39
|
-
peripheral.advertisement.manufacturerData.toString('hex')
|
|
40
|
-
)}`
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (peripheral.advertisement.txPowerLevel !== undefined) {
|
|
45
|
-
console.log('\tmy TX power level is:');
|
|
46
|
-
console.log(`\t\t${peripheral.advertisement.txPowerLevel}`);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
console.log();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
process.on('SIGINT', function () {
|
|
53
|
-
console.log('Caught interrupt signal');
|
|
54
|
-
noble.stopScanning(() => process.exit());
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
process.on('SIGQUIT', function () {
|
|
58
|
-
console.log('Caught interrupt signal');
|
|
59
|
-
noble.stopScanning(() => process.exit());
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
process.on('SIGTERM', function () {
|
|
63
|
-
console.log('Caught interrupt signal');
|
|
64
|
-
noble.stopScanning(() => process.exit());
|
|
65
|
-
});
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/* eslint-disable handle-callback-err */
|
|
2
|
-
const async = require('async');
|
|
3
|
-
const noble = require('../index');
|
|
4
|
-
|
|
5
|
-
const peripheralIdOrAddress = process.argv[2].toLowerCase();
|
|
6
|
-
|
|
7
|
-
noble.on('stateChange', function (state) {
|
|
8
|
-
if (state === 'poweredOn') {
|
|
9
|
-
noble.startScanning([], false);
|
|
10
|
-
} else {
|
|
11
|
-
noble.stopScanning();
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
noble.on('discover', function (peripheral) {
|
|
16
|
-
if (
|
|
17
|
-
peripheral.id === peripheralIdOrAddress ||
|
|
18
|
-
peripheral.address === peripheralIdOrAddress
|
|
19
|
-
) {
|
|
20
|
-
noble.stopScanning();
|
|
21
|
-
|
|
22
|
-
console.log(`peripheral with ID ${peripheral.id} found`);
|
|
23
|
-
const advertisement = peripheral.advertisement;
|
|
24
|
-
|
|
25
|
-
const localName = advertisement.localName;
|
|
26
|
-
const txPowerLevel = advertisement.txPowerLevel;
|
|
27
|
-
const manufacturerData = advertisement.manufacturerData;
|
|
28
|
-
const serviceData = advertisement.serviceData;
|
|
29
|
-
const serviceUuids = advertisement.serviceUuids;
|
|
30
|
-
|
|
31
|
-
if (localName) {
|
|
32
|
-
console.log(` Local Name = ${localName}`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (txPowerLevel) {
|
|
36
|
-
console.log(` TX Power Level = ${txPowerLevel}`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (manufacturerData) {
|
|
40
|
-
console.log(` Manufacturer Data = ${manufacturerData.toString('hex')}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (serviceData) {
|
|
44
|
-
console.log(
|
|
45
|
-
` Service Data = ${JSON.stringify(serviceData, null, 2)}`
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (serviceUuids) {
|
|
50
|
-
console.log(` Service UUIDs = ${serviceUuids}`);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
console.log();
|
|
54
|
-
|
|
55
|
-
explore(peripheral);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
function explore (peripheral) {
|
|
60
|
-
console.log('services and characteristics:');
|
|
61
|
-
|
|
62
|
-
peripheral.on('disconnect', function () {
|
|
63
|
-
process.exit(0);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
peripheral.connect(function (error) {
|
|
67
|
-
if (error) {
|
|
68
|
-
console.error(error);
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
peripheral.discoverServices([], function (error, services) {
|
|
73
|
-
if (error) {
|
|
74
|
-
console.error(error);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let serviceIndex = 0;
|
|
79
|
-
|
|
80
|
-
async.whilst(
|
|
81
|
-
function () {
|
|
82
|
-
return serviceIndex < services.length;
|
|
83
|
-
},
|
|
84
|
-
function (callback) {
|
|
85
|
-
const service = services[serviceIndex];
|
|
86
|
-
let serviceInfo = service.uuid;
|
|
87
|
-
|
|
88
|
-
if (service.name) {
|
|
89
|
-
serviceInfo += ` (${service.name})`;
|
|
90
|
-
}
|
|
91
|
-
console.log(serviceInfo);
|
|
92
|
-
|
|
93
|
-
service.discoverCharacteristics(
|
|
94
|
-
[],
|
|
95
|
-
function (error, characteristics) {
|
|
96
|
-
if (error) {
|
|
97
|
-
console.error(error);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
let characteristicIndex = 0;
|
|
102
|
-
|
|
103
|
-
async.whilst(
|
|
104
|
-
function () {
|
|
105
|
-
return characteristicIndex < characteristics.length;
|
|
106
|
-
},
|
|
107
|
-
function (callback) {
|
|
108
|
-
const characteristic = characteristics[characteristicIndex];
|
|
109
|
-
let characteristicInfo = ` ${characteristic.uuid}`;
|
|
110
|
-
|
|
111
|
-
if (characteristic.name) {
|
|
112
|
-
characteristicInfo += ` (${characteristic.name})`;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async.series([
|
|
116
|
-
function (callback) {
|
|
117
|
-
characteristic.discoverDescriptors(function (
|
|
118
|
-
error,
|
|
119
|
-
descriptors
|
|
120
|
-
) {
|
|
121
|
-
if (error) {
|
|
122
|
-
console.error(error);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async.detect(
|
|
127
|
-
descriptors,
|
|
128
|
-
function (descriptor, callback) {
|
|
129
|
-
if (descriptor.uuid === '2901') {
|
|
130
|
-
return callback(descriptor);
|
|
131
|
-
} else {
|
|
132
|
-
return callback();
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
function (userDescriptionDescriptor) {
|
|
136
|
-
if (userDescriptionDescriptor) {
|
|
137
|
-
userDescriptionDescriptor.readValue(function (
|
|
138
|
-
error,
|
|
139
|
-
data
|
|
140
|
-
) {
|
|
141
|
-
if (error) {
|
|
142
|
-
console.error(error);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (data) {
|
|
146
|
-
characteristicInfo += ` (${data.toString()})`;
|
|
147
|
-
}
|
|
148
|
-
callback();
|
|
149
|
-
});
|
|
150
|
-
} else {
|
|
151
|
-
callback();
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
);
|
|
155
|
-
});
|
|
156
|
-
},
|
|
157
|
-
function (callback) {
|
|
158
|
-
characteristicInfo += `\n properties ${characteristic.properties.join(
|
|
159
|
-
', '
|
|
160
|
-
)}`;
|
|
161
|
-
|
|
162
|
-
if (characteristic.properties.indexOf('read') !== -1) {
|
|
163
|
-
characteristic.read(function (error, data) {
|
|
164
|
-
if (error) {
|
|
165
|
-
console.error(error);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (data) {
|
|
169
|
-
const string = data.toString('ascii');
|
|
170
|
-
|
|
171
|
-
characteristicInfo += `\n value ${data.toString(
|
|
172
|
-
'hex'
|
|
173
|
-
)} | '${string}'`;
|
|
174
|
-
}
|
|
175
|
-
callback();
|
|
176
|
-
});
|
|
177
|
-
} else {
|
|
178
|
-
callback();
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
function () {
|
|
182
|
-
console.log(characteristicInfo);
|
|
183
|
-
characteristicIndex++;
|
|
184
|
-
callback();
|
|
185
|
-
}
|
|
186
|
-
]);
|
|
187
|
-
},
|
|
188
|
-
function (error) {
|
|
189
|
-
if (error) {
|
|
190
|
-
console.error(error);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
serviceIndex++;
|
|
194
|
-
callback();
|
|
195
|
-
}
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
);
|
|
199
|
-
},
|
|
200
|
-
function (error) {
|
|
201
|
-
if (error) {
|
|
202
|
-
console.error(error);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
peripheral.disconnect();
|
|
206
|
-
}
|
|
207
|
-
);
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
process.on('SIGINT', function () {
|
|
213
|
-
console.log('Caught interrupt signal');
|
|
214
|
-
noble.stopScanning(() => process.exit());
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
process.on('SIGQUIT', function () {
|
|
218
|
-
console.log('Caught interrupt signal');
|
|
219
|
-
noble.stopScanning(() => process.exit());
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
process.on('SIGTERM', function () {
|
|
223
|
-
console.log('Caught interrupt signal');
|
|
224
|
-
noble.stopScanning(() => process.exit());
|
|
225
|
-
});
|