@stoprocent/noble 1.9.2-16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/.editorconfig +11 -0
  2. package/.eslintrc.js +25 -0
  3. package/.github/FUNDING.yml +2 -0
  4. package/.github/workflows/fediverse-action.yml +16 -0
  5. package/.github/workflows/nodepackage.yml +77 -0
  6. package/.github/workflows/npm-publish.yml +26 -0
  7. package/.github/workflows/prebuild.yml +65 -0
  8. package/.nycrc.json +4 -0
  9. package/CHANGELOG.md +119 -0
  10. package/LICENSE +20 -0
  11. package/MAINTAINERS.md +1 -0
  12. package/README.md +833 -0
  13. package/assets/noble-logo.png +0 -0
  14. package/assets/noble-logo.svg +13 -0
  15. package/binding.gyp +19 -0
  16. package/codecov.yml +5 -0
  17. package/examples/advertisement-discovery.js +65 -0
  18. package/examples/cache-gatt-discovery.js +198 -0
  19. package/examples/cache-gatt-reconnect.js +164 -0
  20. package/examples/echo.js +104 -0
  21. package/examples/enter-exit.js +78 -0
  22. package/examples/peripheral-explorer-async.js +133 -0
  23. package/examples/peripheral-explorer.js +225 -0
  24. package/examples/pizza/README.md +15 -0
  25. package/examples/pizza/central.js +194 -0
  26. package/examples/pizza/pizza.js +60 -0
  27. package/index.d.ts +203 -0
  28. package/index.js +6 -0
  29. package/lib/characteristic.js +161 -0
  30. package/lib/characteristics.json +449 -0
  31. package/lib/descriptor.js +72 -0
  32. package/lib/descriptors.json +47 -0
  33. package/lib/distributed/bindings.js +326 -0
  34. package/lib/hci-socket/acl-stream.js +60 -0
  35. package/lib/hci-socket/bindings.js +788 -0
  36. package/lib/hci-socket/crypto.js +74 -0
  37. package/lib/hci-socket/gap.js +432 -0
  38. package/lib/hci-socket/gatt.js +809 -0
  39. package/lib/hci-socket/hci-status.json +71 -0
  40. package/lib/hci-socket/hci.js +1264 -0
  41. package/lib/hci-socket/signaling.js +76 -0
  42. package/lib/hci-socket/smp.js +140 -0
  43. package/lib/hci-uart/bindings.js +569 -0
  44. package/lib/hci-uart/hci-serial-parser.js +70 -0
  45. package/lib/hci-uart/hci.js +1336 -0
  46. package/lib/mac/binding.gyp +26 -0
  47. package/lib/mac/bindings.js +11 -0
  48. package/lib/mac/src/ble_manager.h +41 -0
  49. package/lib/mac/src/ble_manager.mm +435 -0
  50. package/lib/mac/src/callbacks.cc +222 -0
  51. package/lib/mac/src/callbacks.h +84 -0
  52. package/lib/mac/src/napi_objc.h +12 -0
  53. package/lib/mac/src/napi_objc.mm +50 -0
  54. package/lib/mac/src/noble_mac.h +34 -0
  55. package/lib/mac/src/noble_mac.mm +264 -0
  56. package/lib/mac/src/objc_cpp.h +26 -0
  57. package/lib/mac/src/objc_cpp.mm +126 -0
  58. package/lib/mac/src/peripheral.h +23 -0
  59. package/lib/manufacture.js +48 -0
  60. package/lib/noble.js +593 -0
  61. package/lib/peripheral.js +219 -0
  62. package/lib/resolve-bindings-web.js +9 -0
  63. package/lib/resolve-bindings.js +44 -0
  64. package/lib/service.js +72 -0
  65. package/lib/services.json +92 -0
  66. package/lib/webbluetooth/bindings.js +368 -0
  67. package/lib/websocket/bindings.js +321 -0
  68. package/lib/win/binding.gyp +23 -0
  69. package/lib/win/bindings.js +11 -0
  70. package/lib/win/src/ble_manager.cc +802 -0
  71. package/lib/win/src/ble_manager.h +77 -0
  72. package/lib/win/src/callbacks.cc +274 -0
  73. package/lib/win/src/callbacks.h +33 -0
  74. package/lib/win/src/napi_winrt.cc +76 -0
  75. package/lib/win/src/napi_winrt.h +12 -0
  76. package/lib/win/src/noble_winrt.cc +308 -0
  77. package/lib/win/src/noble_winrt.h +34 -0
  78. package/lib/win/src/notify_map.cc +62 -0
  79. package/lib/win/src/notify_map.h +50 -0
  80. package/lib/win/src/peripheral.h +23 -0
  81. package/lib/win/src/peripheral_winrt.cc +296 -0
  82. package/lib/win/src/peripheral_winrt.h +82 -0
  83. package/lib/win/src/radio_watcher.cc +125 -0
  84. package/lib/win/src/radio_watcher.h +61 -0
  85. package/lib/win/src/winrt_cpp.cc +82 -0
  86. package/lib/win/src/winrt_cpp.h +11 -0
  87. package/lib/win/src/winrt_guid.cc +12 -0
  88. package/lib/win/src/winrt_guid.h +13 -0
  89. package/misc/nrf52840dk.hex +6921 -0
  90. package/misc/prj.conf +43 -0
  91. package/package.json +96 -0
  92. package/test/lib/characteristic.test.js +791 -0
  93. package/test/lib/descriptor.test.js +249 -0
  94. package/test/lib/distributed/bindings.test.js +918 -0
  95. package/test/lib/hci-socket/acl-stream.test.js +188 -0
  96. package/test/lib/hci-socket/bindings.test.js +1756 -0
  97. package/test/lib/hci-socket/crypto.test.js +55 -0
  98. package/test/lib/hci-socket/gap.test.js +1089 -0
  99. package/test/lib/hci-socket/gatt.test.js +2392 -0
  100. package/test/lib/hci-socket/hci.test.js +1891 -0
  101. package/test/lib/hci-socket/signaling.test.js +94 -0
  102. package/test/lib/hci-socket/smp.test.js +268 -0
  103. package/test/lib/manufacture.test.js +77 -0
  104. package/test/lib/peripheral.test.js +623 -0
  105. package/test/lib/resolve-bindings.test.js +102 -0
  106. package/test/lib/service.test.js +195 -0
  107. package/test/lib/webbluetooth/bindings.test.js +190 -0
  108. package/test/lib/websocket/bindings.test.js +456 -0
  109. package/test/noble.test.js +1565 -0
  110. package/test.js +131 -0
  111. package/with-bindings.js +5 -0
  112. package/ws-slave.js +404 -0
package/test.js ADDED
@@ -0,0 +1,131 @@
1
+ const noble = require('./index')({ extended: false });
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
+ });
@@ -0,0 +1,5 @@
1
+ const Noble = require('./lib/noble');
2
+
3
+ module.exports = function (bindings) {
4
+ return new Noble(bindings);
5
+ };
package/ws-slave.js ADDED
@@ -0,0 +1,404 @@
1
+ /* jshint loopfunc: true */
2
+ const WebSocket = require('ws');
3
+
4
+ const noble = require('./index');
5
+
6
+ const serverMode = !process.argv[2];
7
+ const port = 0xB1e;
8
+ const host = process.argv[2];
9
+
10
+ let ws;
11
+ let wss;
12
+
13
+ if (serverMode) {
14
+ console.log('noble - ws slave - server mode');
15
+ wss = new WebSocket.Server({
16
+ port: 0xB1e
17
+ });
18
+
19
+ wss.on('connection', function (ws_) {
20
+ console.log('ws -> connection');
21
+
22
+ ws = ws_;
23
+
24
+ ws.on('message', onMessage);
25
+
26
+ ws.on('close', function () {
27
+ console.log('ws -> close');
28
+ noble.stopScanning();
29
+ });
30
+
31
+ noble.on('stateChange', function (state) {
32
+ sendEvent({
33
+ type: 'stateChange',
34
+ state: state
35
+ });
36
+ });
37
+
38
+ // Send poweredOn if already in this state.
39
+ if (noble.state === 'poweredOn') {
40
+ sendEvent({
41
+ type: 'stateChange',
42
+ state: 'poweredOn'
43
+ });
44
+ }
45
+ });
46
+ } else {
47
+ ws = new WebSocket('ws://' + host + ':' + port);
48
+
49
+ ws.on('open', function () {
50
+ console.log('ws -> open');
51
+ });
52
+
53
+ ws.on('message', function (message) {
54
+ onMessage(message);
55
+ });
56
+
57
+ ws.on('close', function () {
58
+ console.log('ws -> close');
59
+
60
+ noble.stopScanning();
61
+ });
62
+ }
63
+
64
+ const peripherals = {};
65
+
66
+ // TODO: open/close ws on state change
67
+
68
+ function sendEvent (event) {
69
+ const message = JSON.stringify(event);
70
+
71
+ console.log('ws -> send: ' + message);
72
+
73
+ const clients = serverMode ? wss.clients : [ws];
74
+
75
+ for (let i = 0; i < clients.length; i++) {
76
+ clients[i].send(message);
77
+ }
78
+ }
79
+
80
+ const onMessage = function (message) {
81
+ console.log('ws -> message: ' + message);
82
+
83
+ const command = JSON.parse(message);
84
+
85
+ const action = command.action;
86
+ const peripheralUuid = command.peripheralUuid;
87
+ const serviceUuids = command.serviceUuids;
88
+ const serviceUuid = command.serviceUuid;
89
+ const characteristicUuids = command.characteristicUuids;
90
+ const characteristicUuid = command.characteristicUuid;
91
+ const data = command.data ? Buffer.from(command.data, 'hex') : null;
92
+ const withoutResponse = command.withoutResponse;
93
+ const broadcast = command.broadcast;
94
+ const notify = command.notify;
95
+ const descriptorUuid = command.descriptorUuid;
96
+ let handle;
97
+
98
+ const peripheral = peripherals[peripheralUuid];
99
+ let service = null;
100
+ let characteristic = null;
101
+ let descriptor = null;
102
+
103
+ if (peripheral && serviceUuid) {
104
+ const services = peripheral.services;
105
+
106
+ for (const i in services) {
107
+ if (services[i].uuid === serviceUuid) {
108
+ service = services[i];
109
+
110
+ if (characteristicUuid) {
111
+ const characteristics = service.characteristics;
112
+
113
+ for (const j in characteristics) {
114
+ if (characteristics[j].uuid === characteristicUuid) {
115
+ characteristic = characteristics[j];
116
+
117
+ if (descriptorUuid) {
118
+ const descriptors = characteristic.descriptors;
119
+
120
+ for (const k in descriptors) {
121
+ if (descriptors[k].uuid === descriptorUuid) {
122
+ descriptor = descriptors[k];
123
+ break;
124
+ }
125
+ }
126
+ }
127
+ break;
128
+ }
129
+ }
130
+ }
131
+ break;
132
+ }
133
+ }
134
+ }
135
+
136
+ if (action === 'startScanning') {
137
+ noble.startScanning(serviceUuids, command.allowDuplicates);
138
+ } else if (action === 'stopScanning') {
139
+ noble.stopScanning();
140
+ } else if (action === 'connect') {
141
+ peripheral.connect();
142
+ } else if (action === 'disconnect') {
143
+ peripheral.disconnect();
144
+ } else if (action === 'updateRssi') {
145
+ peripheral.updateRssi();
146
+ } else if (action === 'discoverServices') {
147
+ peripheral.discoverServices(command.uuids);
148
+ } else if (action === 'discoverIncludedServices') {
149
+ service.discoverIncludedServices(serviceUuids);
150
+ } else if (action === 'discoverCharacteristics') {
151
+ service.discoverCharacteristics(characteristicUuids);
152
+ } else if (action === 'read') {
153
+ characteristic.read();
154
+ } else if (action === 'write') {
155
+ characteristic.write(data, withoutResponse);
156
+ } else if (action === 'broadcast') {
157
+ characteristic.broadcast(broadcast);
158
+ } else if (action === 'notify') {
159
+ characteristic.notify(notify);
160
+ } else if (action === 'discoverDescriptors') {
161
+ characteristic.discoverDescriptors();
162
+ } else if (action === 'readValue') {
163
+ descriptor.readValue();
164
+ } else if (action === 'writeValue') {
165
+ descriptor.writeValue(data);
166
+ } else if (action === 'readHandle') {
167
+ peripheral.readHandle(handle);
168
+ } else if (action === 'writeHandle') {
169
+ peripheral.writeHandle(handle, data, withoutResponse);
170
+ }
171
+ };
172
+
173
+ noble.on('discover', function (peripheral) {
174
+ peripherals[peripheral.uuid] = peripheral;
175
+
176
+ peripheral.on('connect', function () {
177
+ sendEvent({
178
+ type: 'connect',
179
+ peripheralUuid: this.uuid
180
+ });
181
+ });
182
+
183
+ peripheral.on('disconnect', function () {
184
+ sendEvent({
185
+ type: 'disconnect',
186
+ peripheralUuid: this.uuid
187
+ });
188
+
189
+ for (const i in this.services) {
190
+ for (const j in this.services[i].characteristics) {
191
+ for (const k in this.services[i].characteristics[j].descriptors) {
192
+ this.services[i].characteristics[j].descriptors[k].removeAllListeners();
193
+ }
194
+
195
+ this.services[i].characteristics[j].removeAllListeners();
196
+ }
197
+ this.services[i].removeAllListeners();
198
+ }
199
+
200
+ this.removeAllListeners();
201
+ });
202
+
203
+ peripheral.on('rssiUpdate', function (rssi) {
204
+ sendEvent({
205
+ type: 'rssiUpdate',
206
+ peripheralUuid: this.uuid,
207
+ rssi: rssi
208
+ });
209
+ });
210
+
211
+ peripheral.on('servicesDiscover', function (services) {
212
+ const peripheral = this;
213
+ const serviceUuids = [];
214
+
215
+ const includedServicesDiscover = function (includedServiceUuids) {
216
+ sendEvent({
217
+ type: 'includedServicesDiscover',
218
+ peripheralUuid: peripheral.uuid,
219
+ serviceUuid: this.uuid,
220
+ includedServiceUuids: includedServiceUuids
221
+ });
222
+ };
223
+
224
+ const characteristicsDiscover = function (characteristics) {
225
+ const service = this;
226
+ const discoveredCharacteristics = [];
227
+
228
+ const read = function (data, isNotification) {
229
+ const characteristic = this;
230
+
231
+ sendEvent({
232
+ type: 'read',
233
+ peripheralUuid: peripheral.uuid,
234
+ serviceUuid: service.uuid,
235
+ characteristicUuid: characteristic.uuid,
236
+ data: data.toString('hex'),
237
+ isNotification: isNotification
238
+ });
239
+ };
240
+
241
+ const write = function () {
242
+ const characteristic = this;
243
+
244
+ sendEvent({
245
+ type: 'write',
246
+ peripheralUuid: peripheral.uuid,
247
+ serviceUuid: service.uuid,
248
+ characteristicUuid: characteristic.uuid
249
+ });
250
+ };
251
+
252
+ const broadcast = function (state) {
253
+ const characteristic = this;
254
+
255
+ sendEvent({
256
+ type: 'broadcast',
257
+ peripheralUuid: peripheral.uuid,
258
+ serviceUuid: service.uuid,
259
+ characteristicUuid: characteristic.uuid,
260
+ state: state
261
+ });
262
+ };
263
+
264
+ const notify = function (state) {
265
+ const characteristic = this;
266
+
267
+ sendEvent({
268
+ type: 'notify',
269
+ peripheralUuid: peripheral.uuid,
270
+ serviceUuid: service.uuid,
271
+ characteristicUuid: characteristic.uuid,
272
+ state: state
273
+ });
274
+ };
275
+
276
+ const descriptorsDiscover = function (descriptors) {
277
+ const characteristic = this;
278
+
279
+ const discoveredDescriptors = [];
280
+
281
+ const valueRead = function (data) {
282
+ const descriptor = this;
283
+
284
+ sendEvent({
285
+ type: 'valueRead',
286
+ peripheralUuid: peripheral.uuid,
287
+ serviceUuid: service.uuid,
288
+ characteristicUuid: characteristic.uuid,
289
+ descriptorUuid: descriptor.uuid,
290
+ data: data.toString('hex')
291
+ });
292
+ };
293
+
294
+ const valueWrite = function (data) {
295
+ const descriptor = this;
296
+
297
+ sendEvent({
298
+ type: 'valueWrite',
299
+ peripheralUuid: peripheral.uuid,
300
+ serviceUuid: service.uuid,
301
+ characteristicUuid: characteristic.uuid,
302
+ descriptorUuid: descriptor.uuid
303
+ });
304
+ };
305
+
306
+ for (const k in descriptors) {
307
+ descriptors[k].on('valueRead', valueRead);
308
+
309
+ descriptors[k].on('valueWrite', valueWrite);
310
+
311
+ discoveredDescriptors.push(descriptors[k].uuid);
312
+ }
313
+
314
+ sendEvent({
315
+ type: 'descriptorsDiscover',
316
+ peripheralUuid: peripheral.uuid,
317
+ serviceUuid: service.uuid,
318
+ characteristicUuid: this.uuid,
319
+ descriptors: discoveredDescriptors
320
+ });
321
+ };
322
+
323
+ for (let j = 0; j < characteristics.length; j++) {
324
+ characteristics[j].on('read', read);
325
+
326
+ characteristics[j].on('write', write);
327
+
328
+ characteristics[j].on('broadcast', broadcast);
329
+
330
+ characteristics[j].on('notify', notify);
331
+
332
+ characteristics[j].on('descriptorsDiscover', descriptorsDiscover);
333
+
334
+ discoveredCharacteristics.push({
335
+ uuid: characteristics[j].uuid,
336
+ properties: characteristics[j].properties
337
+ });
338
+ }
339
+
340
+ sendEvent({
341
+ type: 'characteristicsDiscover',
342
+ peripheralUuid: peripheral.uuid,
343
+ serviceUuid: this.uuid,
344
+ characteristics: discoveredCharacteristics
345
+ });
346
+ };
347
+
348
+ for (const i in services) {
349
+ services[i].on('includedServicesDiscover', includedServicesDiscover);
350
+
351
+ services[i].on('characteristicsDiscover', characteristicsDiscover);
352
+
353
+ serviceUuids.push(services[i].uuid);
354
+ }
355
+
356
+ sendEvent({
357
+ type: 'servicesDiscover',
358
+ peripheralUuid: this.uuid,
359
+ serviceUuids: serviceUuids
360
+ });
361
+ });
362
+
363
+ peripheral.on('handleRead', function (handle, data) {
364
+ sendEvent({
365
+ type: 'handleRead',
366
+ peripheralUuid: this.uuid,
367
+ handle: handle,
368
+ data: data.toString('hex')
369
+ });
370
+ });
371
+
372
+ peripheral.on('handleWrite', function (handle) {
373
+ sendEvent({
374
+ type: 'handleWrite',
375
+ peripheralUuid: this.uuid,
376
+ handle: handle
377
+ });
378
+ });
379
+
380
+ peripheral.on('handleNotify', function (handle, data) {
381
+ sendEvent({
382
+ type: 'handleNotify',
383
+ peripheralUuid: this.uuid,
384
+ handle: handle,
385
+ data: data.toString('hex')
386
+ });
387
+ });
388
+
389
+ sendEvent({
390
+ type: 'discover',
391
+ peripheralUuid: peripheral.uuid,
392
+ address: peripheral.address,
393
+ addressType: peripheral.addressType,
394
+ connectable: peripheral.connectable,
395
+ advertisement: {
396
+ localName: peripheral.advertisement.localName,
397
+ txPowerLevel: peripheral.advertisement.txPowerLevel,
398
+ serviceUuids: peripheral.advertisement.serviceUuids,
399
+ manufacturerData: (peripheral.advertisement.manufacturerData ? peripheral.advertisement.manufacturerData.toString('hex') : null),
400
+ serviceData: (peripheral.advertisement.serviceData ? peripheral.advertisement.serviceData.toString('hex') : null)
401
+ },
402
+ rssi: peripheral.rssi
403
+ });
404
+ });