@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
@@ -0,0 +1,326 @@
1
+ const events = require('events');
2
+ const util = require('util');
3
+
4
+ const WebSocketServer = require('ws').Server;
5
+
6
+ const NobleBindings = function () {
7
+ this._wss = new WebSocketServer({
8
+ port: 0xB1e
9
+ });
10
+
11
+ this._startScanCommand = null;
12
+ this._peripherals = {};
13
+
14
+ this._wss.on('connection', this._onConnection.bind(this));
15
+ this.on('close', this._onClose.bind(this));
16
+ this.on('message', this._onMessage.bind(this));
17
+
18
+ process.nextTick(() => {
19
+ this.emit('stateChange', 'poweredOff');
20
+ });
21
+ };
22
+
23
+ util.inherits(NobleBindings, events.EventEmitter);
24
+
25
+ NobleBindings.prototype.init = function () {
26
+ // no-op
27
+ };
28
+
29
+ NobleBindings.prototype._onConnection = function (ws) {
30
+ const _this = this;
31
+
32
+ if (this._wss.clients.length === 1) {
33
+ this.emit('stateChange', 'poweredOn');
34
+ } else if (this._startScanCommand) {
35
+ this._sendCommand(ws, this._startScanCommand);
36
+ }
37
+
38
+ ws.on('close', () => {
39
+ _this.emit('close', ws);
40
+ });
41
+
42
+ ws.on('message', data => {
43
+ _this.emit('message', ws, JSON.parse(data));
44
+ });
45
+ };
46
+
47
+ NobleBindings.prototype._onClose = function (ws) {
48
+ if (this._wss.clients.length === 0) {
49
+ this.emit('stateChange', 'poweredOff');
50
+ }
51
+ };
52
+
53
+ NobleBindings.prototype._onMessage = function (ws, event) {
54
+ let {
55
+ type,
56
+ peripheralUuid,
57
+ address,
58
+ addressType,
59
+ connectable,
60
+ advertisement,
61
+ rssi,
62
+ serviceUuids,
63
+ serviceUuid,
64
+ includedServiceUuids,
65
+ characteristics,
66
+ characteristicUuid,
67
+ isNotification,
68
+ state,
69
+ descriptors,
70
+ descriptorUuid,
71
+ handle
72
+ } = event;
73
+ const data = event.data ? Buffer.from(event.data, 'hex') : null;
74
+
75
+ if (type === 'discover') {
76
+ advertisement = {
77
+ localName: advertisement.localName,
78
+ txPowerLevel: advertisement.txPowerLevel,
79
+ serviceUuids: advertisement.serviceUuids,
80
+ manufacturerData: (advertisement.manufacturerData ? Buffer.from(advertisement.manufacturerData, 'hex') : null),
81
+ serviceData: (advertisement.serviceData ? Buffer.from(advertisement.serviceData, 'hex') : null)
82
+ };
83
+
84
+ // TODO: handle duplicate peripheralUuid's
85
+ this._peripherals[peripheralUuid] = {
86
+ uuid: peripheralUuid,
87
+ address: address,
88
+ advertisement: advertisement,
89
+ rssi: rssi,
90
+ ws: ws
91
+ };
92
+
93
+ this.emit('discover', peripheralUuid, address, addressType, connectable, advertisement, rssi);
94
+ } else if (type === 'connect') {
95
+ this.emit('connect', peripheralUuid);
96
+ } else if (type === 'disconnect') {
97
+ this.emit('disconnect', peripheralUuid);
98
+ } else if (type === 'rssiUpdate') {
99
+ this.emit('rssiUpdate', peripheralUuid, rssi);
100
+ } else if (type === 'servicesDiscover') {
101
+ this.emit('servicesDiscover', peripheralUuid, serviceUuids);
102
+ } else if (type === 'includedServicesDiscover') {
103
+ this.emit('includedServicesDiscover', peripheralUuid, serviceUuid, includedServiceUuids);
104
+ } else if (type === 'characteristicsDiscover') {
105
+ this.emit('characteristicsDiscover', peripheralUuid, serviceUuid, characteristics);
106
+ } else if (type === 'read') {
107
+ this.emit('read', peripheralUuid, serviceUuid, characteristicUuid, data, isNotification);
108
+ } else if (type === 'write') {
109
+ this.emit('write', peripheralUuid, serviceUuid, characteristicUuid);
110
+ } else if (type === 'broadcast') {
111
+ this.emit('broadcast', peripheralUuid, serviceUuid, characteristicUuid, state);
112
+ } else if (type === 'notify') {
113
+ this.emit('notify', peripheralUuid, serviceUuid, characteristicUuid, state);
114
+ } else if (type === 'descriptorsDiscover') {
115
+ this.emit('descriptorsDiscover', peripheralUuid, serviceUuid, characteristicUuid, descriptors);
116
+ } else if (type === 'valueRead') {
117
+ this.emit('valueRead', peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid, data);
118
+ } else if (type === 'valueWrite') {
119
+ this.emit('valueWrite', peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid);
120
+ } else if (type === 'handleRead') {
121
+ this.emit('handleRead', peripheralUuid, handle, data);
122
+ } else if (type === 'handleWrite') {
123
+ this.emit('handleWrite', peripheralUuid, handle);
124
+ } else if (type === 'handleNotify') {
125
+ this.emit('handleNotify', peripheralUuid, handle, data);
126
+ }
127
+ };
128
+
129
+ NobleBindings.prototype._sendCommand = function (ws, command) {
130
+ const clients = ws ? [ws] : this._wss.clients;
131
+
132
+ const message = JSON.stringify(command);
133
+
134
+ for (let i = 0; i < clients.length; i++) {
135
+ clients[i].send(message);
136
+ }
137
+ };
138
+
139
+ NobleBindings.prototype.startScanning = function (serviceUuids, allowDuplicates) {
140
+ this._startScanCommand = {
141
+ action: 'startScanning',
142
+ serviceUuids: serviceUuids,
143
+ allowDuplicates: allowDuplicates
144
+ };
145
+
146
+ this._sendCommand(null, this._startScanCommand);
147
+
148
+ this.emit('scanStart');
149
+ };
150
+
151
+ NobleBindings.prototype.stopScanning = function () {
152
+ this._startScanCommand = null;
153
+
154
+ this._sendCommand(null, {
155
+ action: 'stopScanning'
156
+ });
157
+
158
+ this.emit('scanStop');
159
+ };
160
+
161
+ NobleBindings.prototype.connect = function (deviceUuid) {
162
+ const peripheral = this._peripherals[deviceUuid];
163
+
164
+ this._sendCommand(peripheral.ws, {
165
+ action: 'connect',
166
+ peripheralUuid: peripheral.uuid
167
+ });
168
+ };
169
+
170
+ NobleBindings.prototype.disconnect = function (deviceUuid) {
171
+ const peripheral = this._peripherals[deviceUuid];
172
+
173
+ this._sendCommand(peripheral.ws, {
174
+ action: 'disconnect',
175
+ peripheralUuid: peripheral.uuid
176
+ });
177
+ };
178
+
179
+ NobleBindings.prototype.updateRssi = function (deviceUuid) {
180
+ const peripheral = this._peripherals[deviceUuid];
181
+
182
+ this._sendCommand(peripheral.ws, {
183
+ action: 'updateRssi',
184
+ peripheralUuid: peripheral.uuid
185
+ });
186
+ };
187
+
188
+ NobleBindings.prototype.discoverServices = function (deviceUuid, uuids) {
189
+ const peripheral = this._peripherals[deviceUuid];
190
+
191
+ this._sendCommand(peripheral.ws, {
192
+ action: 'discoverServices',
193
+ peripheralUuid: peripheral.uuid,
194
+ uuids: uuids
195
+ });
196
+ };
197
+
198
+ NobleBindings.prototype.discoverIncludedServices = function (deviceUuid, serviceUuid, serviceUuids) {
199
+ const peripheral = this._peripherals[deviceUuid];
200
+
201
+ this._sendCommand(peripheral.ws, {
202
+ action: 'discoverIncludedServices',
203
+ peripheralUuid: peripheral.uuid,
204
+ serviceUuid: serviceUuid,
205
+ serviceUuids: serviceUuids
206
+ });
207
+ };
208
+
209
+ NobleBindings.prototype.discoverCharacteristics = function (deviceUuid, serviceUuid, characteristicUuids) {
210
+ const peripheral = this._peripherals[deviceUuid];
211
+
212
+ this._sendCommand(peripheral.ws, {
213
+ action: 'discoverCharacteristics',
214
+ peripheralUuid: peripheral.uuid,
215
+ serviceUuid: serviceUuid,
216
+ characteristicUuids: characteristicUuids
217
+ });
218
+ };
219
+
220
+ NobleBindings.prototype.read = function (deviceUuid, serviceUuid, characteristicUuid) {
221
+ const peripheral = this._peripherals[deviceUuid];
222
+
223
+ this._sendCommand(peripheral.ws, {
224
+ action: 'read',
225
+ peripheralUuid: peripheral.uuid,
226
+ serviceUuid: serviceUuid,
227
+ characteristicUuid: characteristicUuid
228
+ });
229
+ };
230
+
231
+ NobleBindings.prototype.write = function (deviceUuid, serviceUuid, characteristicUuid, data, withoutResponse) {
232
+ const peripheral = this._peripherals[deviceUuid];
233
+
234
+ this._sendCommand(peripheral.ws, {
235
+ action: 'write',
236
+ peripheralUuid: peripheral.uuid,
237
+ serviceUuid: serviceUuid,
238
+ characteristicUuid: characteristicUuid,
239
+ data: data.toString('hex'),
240
+ withoutResponse: withoutResponse
241
+ });
242
+ };
243
+
244
+ NobleBindings.prototype.broadcast = function (deviceUuid, serviceUuid, characteristicUuid, broadcast) {
245
+ const peripheral = this._peripherals[deviceUuid];
246
+
247
+ this._sendCommand(peripheral.ws, {
248
+ action: 'broadcast',
249
+ peripheralUuid: peripheral.uuid,
250
+ serviceUuid: serviceUuid,
251
+ characteristicUuid: characteristicUuid,
252
+ broadcast: broadcast
253
+ });
254
+ };
255
+
256
+ NobleBindings.prototype.notify = function (deviceUuid, serviceUuid, characteristicUuid, notify) {
257
+ const peripheral = this._peripherals[deviceUuid];
258
+
259
+ this._sendCommand(peripheral.ws, {
260
+ action: 'notify',
261
+ peripheralUuid: peripheral.uuid,
262
+ serviceUuid: serviceUuid,
263
+ characteristicUuid: characteristicUuid,
264
+ notify: notify
265
+ });
266
+ };
267
+
268
+ NobleBindings.prototype.discoverDescriptors = function (deviceUuid, serviceUuid, characteristicUuid) {
269
+ const peripheral = this._peripherals[deviceUuid];
270
+
271
+ this._sendCommand(peripheral.ws, {
272
+ action: 'discoverDescriptors',
273
+ peripheralUuid: peripheral.uuid,
274
+ serviceUuid: serviceUuid,
275
+ characteristicUuid: characteristicUuid
276
+ });
277
+ };
278
+
279
+ NobleBindings.prototype.readValue = function (deviceUuid, serviceUuid, characteristicUuid, descriptorUuid) {
280
+ const peripheral = this._peripherals[deviceUuid];
281
+
282
+ this._sendCommand(peripheral.ws, {
283
+ action: 'readValue',
284
+ peripheralUuid: peripheral.uuid,
285
+ serviceUuid: serviceUuid,
286
+ characteristicUuid: characteristicUuid,
287
+ descriptorUuid: descriptorUuid
288
+ });
289
+ };
290
+
291
+ NobleBindings.prototype.writeValue = function (deviceUuid, serviceUuid, characteristicUuid, descriptorUuid, data) {
292
+ const peripheral = this._peripherals[deviceUuid];
293
+
294
+ this._sendCommand(peripheral.ws, {
295
+ action: 'writeValue',
296
+ peripheralUuid: peripheral.uuid,
297
+ serviceUuid: serviceUuid,
298
+ characteristicUuid: characteristicUuid,
299
+ descriptorUuid: descriptorUuid,
300
+ data: data.toString('hex')
301
+ });
302
+ };
303
+
304
+ NobleBindings.prototype.readHandle = function (deviceUuid, handle) {
305
+ const peripheral = this._peripherals[deviceUuid];
306
+
307
+ this._sendCommand(peripheral.ws, {
308
+ action: 'readHandle',
309
+ peripheralUuid: peripheral.uuid,
310
+ handle: handle
311
+ });
312
+ };
313
+
314
+ NobleBindings.prototype.writeHandle = function (deviceUuid, handle, data, withoutResponse) {
315
+ const peripheral = this._peripherals[deviceUuid];
316
+
317
+ this._sendCommand(peripheral.ws, {
318
+ action: 'readHandle',
319
+ peripheralUuid: peripheral.uuid,
320
+ handle: handle,
321
+ data: data.toString('hex'),
322
+ withoutResponse: withoutResponse
323
+ });
324
+ };
325
+
326
+ module.exports = NobleBindings;
@@ -0,0 +1,60 @@
1
+ const events = require('events');
2
+ const util = require('util');
3
+
4
+ const Smp = require('./smp');
5
+
6
+ const AclStream = function (hci, handle, localAddressType, localAddress, remoteAddressType, remoteAddress) {
7
+ this._hci = hci;
8
+ this._handle = handle;
9
+
10
+ this._smp = new Smp(this, localAddressType, localAddress, remoteAddressType, remoteAddress);
11
+
12
+ this.onSmpStkBinded = this.onSmpStk.bind(this);
13
+ this.onSmpFailBinded = this.onSmpFail.bind(this);
14
+ this.onSmpEndBinded = this.onSmpEnd.bind(this);
15
+
16
+ this._smp.on('stk', this.onSmpStkBinded);
17
+ this._smp.on('fail', this.onSmpFailBinded);
18
+ this._smp.on('end', this.onSmpEndBinded);
19
+ };
20
+
21
+ util.inherits(AclStream, events.EventEmitter);
22
+
23
+ AclStream.prototype.encrypt = function () {
24
+ this._smp.sendPairingRequest();
25
+ };
26
+
27
+ AclStream.prototype.write = function (cid, data) {
28
+ this._hci.writeAclDataPkt(this._handle, cid, data);
29
+ };
30
+
31
+ AclStream.prototype.push = function (cid, data) {
32
+ if (data) {
33
+ this.emit('data', cid, data);
34
+ } else {
35
+ this.emit('end');
36
+ }
37
+ };
38
+
39
+ AclStream.prototype.pushEncrypt = function (encrypt) {
40
+ this.emit('encrypt', encrypt);
41
+ };
42
+
43
+ AclStream.prototype.onSmpStk = function (stk) {
44
+ const random = Buffer.from('0000000000000000', 'hex');
45
+ const diversifier = Buffer.from('0000', 'hex');
46
+
47
+ this._hci.startLeEncryption(this._handle, random, diversifier, stk);
48
+ };
49
+
50
+ AclStream.prototype.onSmpFail = function () {
51
+ this.emit('encryptFail');
52
+ };
53
+
54
+ AclStream.prototype.onSmpEnd = function () {
55
+ this._smp.removeListener('stk', this.onSmpStkBinded);
56
+ this._smp.removeListener('fail', this.onSmpFailBinded);
57
+ this._smp.removeListener('end', this.onSmpEndBinded);
58
+ };
59
+
60
+ module.exports = AclStream;