@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,456 @@
1
+ const sinon = require('sinon');
2
+ const should = require('should');
3
+ const proxyquire = require('proxyquire').noCallThru();
4
+
5
+ const { assert } = sinon;
6
+
7
+ describe('webbluetooth bindings', () => {
8
+ const FakeWebsocket = sinon.spy();
9
+
10
+ const Bindings = proxyquire('../../../lib/websocket/bindings', {
11
+ ws: FakeWebsocket
12
+ });
13
+
14
+ let bindings;
15
+
16
+ beforeEach(() => {
17
+ FakeWebsocket.prototype.on = sinon.spy();
18
+
19
+ bindings = new Bindings();
20
+ });
21
+
22
+ afterEach(() => {
23
+ sinon.reset();
24
+ });
25
+
26
+ it('constructor', () => {
27
+ assert.calledOnceWithExactly(FakeWebsocket, 'ws://localhost:2846');
28
+ assert.callCount(bindings._ws.on, 4);
29
+ assert.calledWithMatch(bindings._ws.on, 'open', sinon.match.func);
30
+ assert.calledWithMatch(bindings._ws.on, 'close', sinon.match.func);
31
+ assert.calledWithMatch(bindings._ws.on, 'error', sinon.match.func);
32
+ assert.calledWithMatch(bindings._ws.on, 'message', sinon.match.func);
33
+ });
34
+
35
+ it('onClose - should emit stateChange', () => {
36
+ const callback = sinon.spy();
37
+
38
+ bindings.on('stateChange', callback);
39
+ bindings._onClose();
40
+
41
+ assert.calledOnceWithExactly(callback, 'poweredOff');
42
+ });
43
+
44
+ describe('_onMessage', () => {
45
+ const mainEvent = {
46
+ peripheralUuid: 'peripheralUuid',
47
+ address: 'address',
48
+ addressType: 'addressType',
49
+ connectable: 'connectable',
50
+ advertisement: {
51
+ localName: 'localName',
52
+ txPowerLevel: 34,
53
+ serviceUuids: 'ad.serviceUuids',
54
+ manufacturerData: null,
55
+ serviceData: null
56
+ },
57
+ rssi: 'rssi',
58
+ serviceUuids: 'serviceUuids',
59
+ serviceUuid: 'serviceUuid',
60
+ includedServiceUuids: 'includedServiceUuids',
61
+ characteristics: 'characteristics',
62
+ characteristicUuid: 'characteristicUuid',
63
+ isNotification: 'isNotification',
64
+ state: 'state',
65
+ descriptors: 'descriptors',
66
+ descriptorUuid: 'descriptorUuid',
67
+ handle: 'handle'
68
+ };
69
+
70
+ [
71
+ { type: 'stateChange', event: ['stateChange', mainEvent.state] },
72
+ { type: 'discover', event: ['discover', mainEvent.peripheralUuid, mainEvent.address, mainEvent.addressType, mainEvent.connectable, mainEvent.advertisement, mainEvent.rssi] },
73
+ { type: 'connect', event: ['connect', mainEvent.peripheralUuid] },
74
+ { type: 'disconnect', event: ['disconnect', mainEvent.peripheralUuid] },
75
+ { type: 'rssiUpdate', event: ['rssiUpdate', mainEvent.peripheralUuid, mainEvent.rssi] },
76
+ { type: 'servicesDiscover', event: ['servicesDiscover', mainEvent.peripheralUuid, mainEvent.serviceUuids] },
77
+ { type: 'includedServicesDiscover', event: ['includedServicesDiscover', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.includedServiceUuids] },
78
+ { type: 'characteristicsDiscover', event: ['characteristicsDiscover', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.characteristics] },
79
+ { type: 'read', event: ['read', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.characteristicUuid, null, mainEvent.isNotification] },
80
+ { type: 'write', event: ['write', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.characteristicUuid] },
81
+ { type: 'broadcast', event: ['broadcast', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.characteristicUuid, mainEvent.state] },
82
+ { type: 'notify', event: ['notify', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.characteristicUuid, mainEvent.state] },
83
+ { type: 'descriptorsDiscover', event: ['descriptorsDiscover', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.characteristicUuid, mainEvent.descriptors] },
84
+ { type: 'valueRead', event: ['valueRead', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.characteristicUuid, mainEvent.descriptorUuid, null] },
85
+ { type: 'valueWrite', event: ['valueWrite', mainEvent.peripheralUuid, mainEvent.serviceUuid, mainEvent.characteristicUuid, mainEvent.descriptorUuid] },
86
+ { type: 'handleRead', event: ['handleRead', mainEvent.peripheralUuid, mainEvent.handle, null] },
87
+ { type: 'handleWrite', event: ['handleWrite', mainEvent.peripheralUuid, mainEvent.handle] },
88
+ { type: 'handleNotify', event: ['handleNotify', mainEvent.peripheralUuid, mainEvent.handle, null] }
89
+ ].forEach(args => {
90
+ const { type, event } = args;
91
+ it(`should emit ${type}`, () => {
92
+ bindings.emit = sinon.spy();
93
+
94
+ const eventMsg = Object.assign({ type }, mainEvent);
95
+ bindings._onMessage(eventMsg);
96
+
97
+ assert.calledOnceWithExactly(bindings.emit, ...event);
98
+ });
99
+ });
100
+ });
101
+
102
+ describe('sendCommand', () => {
103
+ it('should not callback without error', () => {
104
+ const errorCallback = sinon.spy();
105
+
106
+ bindings._ws.send = sinon.spy();
107
+ bindings._sendCommand({ command: 3 }, errorCallback);
108
+
109
+ bindings._ws.send.callArgWith(1, null);
110
+
111
+ assert.calledOnceWithMatch(bindings._ws.send, '{"command":3}', sinon.match.func);
112
+ assert.notCalled(errorCallback);
113
+ });
114
+
115
+ it('should callback error', () => {
116
+ const errorCallback = sinon.spy();
117
+
118
+ bindings._ws.send = sinon.spy();
119
+ bindings._sendCommand({ command: 3 }, errorCallback);
120
+
121
+ bindings._ws.send.callArgWith(1, 'error');
122
+
123
+ assert.calledOnceWithMatch(bindings._ws.send, '{"command":3}', sinon.match.func);
124
+ assert.calledOnceWithExactly(errorCallback, 'error');
125
+ });
126
+
127
+ it('should not callback error as it is missing', () => {
128
+ bindings._ws.send = sinon.spy();
129
+ bindings._sendCommand({ command: 3 });
130
+
131
+ bindings._ws.send.callArgWith(1, 'error');
132
+
133
+ assert.calledOnceWithMatch(bindings._ws.send, '{"command":3}', sinon.match.func);
134
+ });
135
+ });
136
+
137
+ it('startScanning - should emit scanStart', () => {
138
+ const callback = sinon.spy();
139
+ const serviceUuids = ['service'];
140
+ const allowDuplicates = true;
141
+
142
+ bindings._sendCommand = sinon.spy();
143
+ bindings.on('scanStart', callback);
144
+ bindings.startScanning(serviceUuids, allowDuplicates);
145
+
146
+ const startCommand = {
147
+ action: 'startScanning',
148
+ serviceUuids: serviceUuids,
149
+ allowDuplicates: allowDuplicates
150
+ };
151
+ assert.calledOnceWithExactly(callback);
152
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
153
+ should(bindings._startScanCommand).deepEqual(startCommand);
154
+ });
155
+
156
+ it('stopScanning - should emit scanStop', () => {
157
+ const callback = sinon.spy();
158
+
159
+ bindings._startScanCommand = 'command';
160
+ bindings._sendCommand = sinon.spy();
161
+ bindings.on('scanStop', callback);
162
+ bindings.stopScanning();
163
+
164
+ const startCommand = {
165
+ action: 'stopScanning'
166
+ };
167
+ assert.calledOnceWithExactly(callback);
168
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
169
+ should(bindings._startScanCommand).equal(null);
170
+ });
171
+
172
+ it('connect - should send connect command', () => {
173
+ const deviceUuid = 'deviceUuid';
174
+
175
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
176
+ bindings._startScanCommand = 'command';
177
+ bindings._sendCommand = sinon.spy();
178
+ bindings.connect(deviceUuid);
179
+
180
+ const startCommand = {
181
+ action: 'connect',
182
+ peripheralUuid: 'uuid'
183
+ };
184
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
185
+ });
186
+
187
+ it('disconnect - should send disconnect command', () => {
188
+ const deviceUuid = 'deviceUuid';
189
+
190
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
191
+ bindings._startScanCommand = 'command';
192
+ bindings._sendCommand = sinon.spy();
193
+ bindings.disconnect(deviceUuid);
194
+
195
+ const startCommand = {
196
+ action: 'disconnect',
197
+ peripheralUuid: 'uuid'
198
+ };
199
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
200
+ });
201
+
202
+ it('updateRssi - should send updateRssi command', () => {
203
+ const deviceUuid = 'deviceUuid';
204
+
205
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
206
+ bindings._startScanCommand = 'command';
207
+ bindings._sendCommand = sinon.spy();
208
+ bindings.updateRssi(deviceUuid);
209
+
210
+ const startCommand = {
211
+ action: 'updateRssi',
212
+ peripheralUuid: 'uuid'
213
+ };
214
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
215
+ });
216
+
217
+ it('discoverServices - should send discoverServices command', () => {
218
+ const deviceUuid = 'deviceUuid';
219
+ const uuids = 'uuids';
220
+
221
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
222
+ bindings._startScanCommand = 'command';
223
+ bindings._sendCommand = sinon.spy();
224
+ bindings.discoverServices(deviceUuid, uuids);
225
+
226
+ const startCommand = {
227
+ action: 'discoverServices',
228
+ peripheralUuid: 'uuid',
229
+ uuids
230
+ };
231
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
232
+ });
233
+
234
+ it('discoverIncludedServices - should send discoverIncludedServices command', () => {
235
+ const deviceUuid = 'deviceUuid';
236
+ const serviceUuid = 'serviceUuid';
237
+ const serviceUuids = 'serviceUuids';
238
+
239
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
240
+ bindings._startScanCommand = 'command';
241
+ bindings._sendCommand = sinon.spy();
242
+ bindings.discoverIncludedServices(deviceUuid, serviceUuid, serviceUuids);
243
+
244
+ const startCommand = {
245
+ action: 'discoverIncludedServices',
246
+ peripheralUuid: 'uuid',
247
+ serviceUuid,
248
+ serviceUuids
249
+ };
250
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
251
+ });
252
+
253
+ it('discoverCharacteristics - should send discoverIncludedServices command', () => {
254
+ const deviceUuid = 'deviceUuid';
255
+ const serviceUuid = 'serviceUuid';
256
+ const characteristicUuids = 'characteristicUuids';
257
+
258
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
259
+ bindings._startScanCommand = 'command';
260
+ bindings._sendCommand = sinon.spy();
261
+ bindings.discoverCharacteristics(deviceUuid, serviceUuid, characteristicUuids);
262
+
263
+ const startCommand = {
264
+ action: 'discoverCharacteristics',
265
+ peripheralUuid: 'uuid',
266
+ serviceUuid,
267
+ characteristicUuids
268
+ };
269
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
270
+ });
271
+
272
+ it('read - should send read command', () => {
273
+ const deviceUuid = 'deviceUuid';
274
+ const serviceUuid = 'serviceUuid';
275
+ const characteristicUuid = 'characteristicUuid';
276
+
277
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
278
+ bindings._startScanCommand = 'command';
279
+ bindings._sendCommand = sinon.spy();
280
+ bindings.read(deviceUuid, serviceUuid, characteristicUuid);
281
+
282
+ const startCommand = {
283
+ action: 'read',
284
+ peripheralUuid: 'uuid',
285
+ serviceUuid,
286
+ characteristicUuid
287
+ };
288
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
289
+ });
290
+
291
+ it('write - should send write command', () => {
292
+ const deviceUuid = 'deviceUuid';
293
+ const serviceUuid = 'serviceUuid';
294
+ const characteristicUuid = 'characteristicUuid';
295
+ const data = Buffer.from([0x34, 0x12]);
296
+ const withoutResponse = true;
297
+
298
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
299
+ bindings._startScanCommand = 'command';
300
+ bindings._sendCommand = sinon.spy();
301
+ bindings.write(deviceUuid, serviceUuid, characteristicUuid, data, withoutResponse);
302
+
303
+ const startCommand = {
304
+ action: 'write',
305
+ peripheralUuid: 'uuid',
306
+ serviceUuid,
307
+ characteristicUuid,
308
+ data: '3412',
309
+ withoutResponse
310
+ };
311
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
312
+ });
313
+
314
+ it('broadcast - should send broadcast command', () => {
315
+ const deviceUuid = 'deviceUuid';
316
+ const serviceUuid = 'serviceUuid';
317
+ const characteristicUuid = 'characteristicUuid';
318
+ const broadcast = true;
319
+
320
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
321
+ bindings._startScanCommand = 'command';
322
+ bindings._sendCommand = sinon.spy();
323
+ bindings.broadcast(deviceUuid, serviceUuid, characteristicUuid, broadcast);
324
+
325
+ const startCommand = {
326
+ action: 'broadcast',
327
+ peripheralUuid: 'uuid',
328
+ serviceUuid,
329
+ characteristicUuid,
330
+ broadcast
331
+ };
332
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
333
+ });
334
+
335
+ it('notify - should send notify command', () => {
336
+ const deviceUuid = 'deviceUuid';
337
+ const serviceUuid = 'serviceUuid';
338
+ const characteristicUuid = 'characteristicUuid';
339
+ const notify = true;
340
+
341
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
342
+ bindings._startScanCommand = 'command';
343
+ bindings._sendCommand = sinon.spy();
344
+ bindings.notify(deviceUuid, serviceUuid, characteristicUuid, notify);
345
+
346
+ const startCommand = {
347
+ action: 'notify',
348
+ peripheralUuid: 'uuid',
349
+ serviceUuid,
350
+ characteristicUuid,
351
+ notify
352
+ };
353
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
354
+ });
355
+
356
+ it('discoverDescriptors - should send discoverDescriptors command', () => {
357
+ const deviceUuid = 'deviceUuid';
358
+ const serviceUuid = 'serviceUuid';
359
+ const characteristicUuid = 'characteristicUuid';
360
+
361
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
362
+ bindings._startScanCommand = 'command';
363
+ bindings._sendCommand = sinon.spy();
364
+ bindings.discoverDescriptors(deviceUuid, serviceUuid, characteristicUuid);
365
+
366
+ const startCommand = {
367
+ action: 'discoverDescriptors',
368
+ peripheralUuid: 'uuid',
369
+ serviceUuid,
370
+ characteristicUuid
371
+ };
372
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
373
+ });
374
+
375
+ it('readValue - should send readValue command', () => {
376
+ const deviceUuid = 'deviceUuid';
377
+ const serviceUuid = 'serviceUuid';
378
+ const characteristicUuid = 'characteristicUuid';
379
+ const descriptorUuid = 'descriptorUuid';
380
+
381
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
382
+ bindings._startScanCommand = 'command';
383
+ bindings._sendCommand = sinon.spy();
384
+ bindings.readValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid);
385
+
386
+ const startCommand = {
387
+ action: 'readValue',
388
+ peripheralUuid: 'uuid',
389
+ serviceUuid,
390
+ characteristicUuid,
391
+ descriptorUuid
392
+ };
393
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
394
+ });
395
+
396
+ it('writeValue - should send writeValue command', () => {
397
+ const deviceUuid = 'deviceUuid';
398
+ const serviceUuid = 'serviceUuid';
399
+ const characteristicUuid = 'characteristicUuid';
400
+ const descriptorUuid = 'descriptorUuid';
401
+ const data = Buffer.from([0x34, 0x12]);
402
+
403
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
404
+ bindings._startScanCommand = 'command';
405
+ bindings._sendCommand = sinon.spy();
406
+ bindings.writeValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid, data);
407
+
408
+ const startCommand = {
409
+ action: 'writeValue',
410
+ peripheralUuid: 'uuid',
411
+ serviceUuid,
412
+ characteristicUuid,
413
+ descriptorUuid,
414
+ data: '3412'
415
+ };
416
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
417
+ });
418
+
419
+ it('readHandle - should send readHandle command', () => {
420
+ const deviceUuid = 'deviceUuid';
421
+ const handle = 'handle';
422
+
423
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
424
+ bindings._startScanCommand = 'command';
425
+ bindings._sendCommand = sinon.spy();
426
+ bindings.readHandle(deviceUuid, handle);
427
+
428
+ const startCommand = {
429
+ action: 'readHandle',
430
+ peripheralUuid: 'uuid',
431
+ handle
432
+ };
433
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
434
+ });
435
+
436
+ it('writeHandle - should send writeHandle command', () => {
437
+ const deviceUuid = 'deviceUuid';
438
+ const handle = 'handle';
439
+ const data = Buffer.from([0x34, 0x12]);
440
+ const withoutResponse = true;
441
+
442
+ bindings._peripherals[deviceUuid] = { uuid: 'uuid' };
443
+ bindings._startScanCommand = 'command';
444
+ bindings._sendCommand = sinon.spy();
445
+ bindings.writeHandle(deviceUuid, handle, data, withoutResponse);
446
+
447
+ const startCommand = {
448
+ action: 'writeHandle',
449
+ peripheralUuid: 'uuid',
450
+ handle,
451
+ data: '3412',
452
+ withoutResponse
453
+ };
454
+ assert.calledOnceWithExactly(bindings._sendCommand, startCommand);
455
+ });
456
+ });