@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,1891 @@
1
+ const should = require('should');
2
+ const sinon = require('sinon');
3
+ const proxyquire = require('proxyquire').noCallThru();
4
+
5
+ const { assert } = sinon;
6
+
7
+ describe('hci-socket hci', () => {
8
+ const deviceId = 'deviceId';
9
+ const Socket = sinon.stub();
10
+
11
+ const Hci = proxyquire('../../../lib/hci-socket/hci', {
12
+ '@abandonware/bluetooth-hci-socket': Socket
13
+ });
14
+
15
+ let hci;
16
+
17
+ beforeEach(() => {
18
+ Socket.prototype.on = sinon.stub();
19
+ Socket.prototype.bindUser = sinon.stub();
20
+ Socket.prototype.bindRaw = sinon.stub();
21
+ Socket.prototype.start = sinon.stub();
22
+ Socket.prototype.isDevUp = sinon.stub();
23
+ Socket.prototype.removeAllListeners = sinon.stub();
24
+ Socket.prototype.setFilter = sinon.stub();
25
+ Socket.prototype.write = sinon.stub();
26
+
27
+ hci = new Hci({});
28
+ hci._deviceId = deviceId;
29
+ });
30
+
31
+ afterEach(() => {
32
+ sinon.reset();
33
+ });
34
+
35
+ describe('init', () => {
36
+ it('should reset', () => {
37
+ hci.reset = sinon.spy();
38
+
39
+ hci._userChannel = 'userChannel';
40
+ hci.init();
41
+
42
+ assert.callCount(hci._socket.on, 2);
43
+ assert.calledWithMatch(hci._socket.on, 'data', sinon.match.func);
44
+ assert.calledWithMatch(hci._socket.on, 'error', sinon.match.func);
45
+
46
+ assert.calledOnceWithExactly(hci._socket.bindUser, deviceId);
47
+ assert.calledOnceWithExactly(hci._socket.start);
48
+
49
+ assert.calledOnceWithExactly(hci.reset);
50
+ });
51
+
52
+ it('should bindRaw', () => {
53
+ hci.pollIsDevUp = sinon.spy();
54
+
55
+ hci._userChannel = undefined;
56
+ hci._bound = false;
57
+ hci.init();
58
+
59
+ assert.callCount(hci._socket.on, 2);
60
+ assert.calledWithMatch(hci._socket.on, 'data', sinon.match.func);
61
+ assert.calledWithMatch(hci._socket.on, 'error', sinon.match.func);
62
+
63
+ assert.calledOnceWithExactly(hci._socket.bindRaw, deviceId);
64
+ assert.calledOnceWithExactly(hci._socket.start);
65
+
66
+ assert.calledOnceWithExactly(hci.pollIsDevUp);
67
+
68
+ should(hci._bound).be.true();
69
+ });
70
+
71
+ it('should not bindRaw', () => {
72
+ hci.pollIsDevUp = sinon.spy();
73
+
74
+ hci._userChannel = undefined;
75
+ hci._bound = true;
76
+ hci.init();
77
+
78
+ assert.callCount(hci._socket.on, 2);
79
+ assert.calledWithMatch(hci._socket.on, 'data', sinon.match.func);
80
+ assert.calledWithMatch(hci._socket.on, 'error', sinon.match.func);
81
+
82
+ assert.notCalled(hci._socket.bindRaw);
83
+ assert.calledOnceWithExactly(hci._socket.start);
84
+
85
+ assert.calledOnceWithExactly(hci.pollIsDevUp);
86
+
87
+ should(hci._bound).be.true();
88
+ });
89
+ });
90
+
91
+ describe('pollIsDevUp', () => {
92
+ let callback;
93
+
94
+ beforeEach(() => {
95
+ sinon.useFakeTimers();
96
+
97
+ callback = sinon.spy();
98
+
99
+ hci.setSocketFilter = sinon.spy();
100
+ hci.setEventMask = sinon.spy();
101
+ hci.setLeEventMask = sinon.spy();
102
+ hci.readLocalVersion = sinon.spy();
103
+ hci.writeLeHostSupported = sinon.spy();
104
+ hci.readLeHostSupported = sinon.spy();
105
+ hci.readLeBufferSize = sinon.spy();
106
+ hci.readBdAddr = sinon.spy();
107
+ hci.init = sinon.spy();
108
+ hci.setCodedPhySupport = sinon.spy();
109
+
110
+ hci.on('stateChange', callback);
111
+ });
112
+
113
+ afterEach(() => {
114
+ sinon.restore();
115
+ sinon.reset();
116
+ });
117
+
118
+ it('should only register timeout', () => {
119
+ hci._socket.isDevUp.returns(true);
120
+ hci._isDevUp = true;
121
+
122
+ hci.pollIsDevUp();
123
+
124
+ assert.notCalled(hci.setSocketFilter);
125
+ assert.notCalled(hci.setEventMask);
126
+ assert.notCalled(hci.setLeEventMask);
127
+ assert.notCalled(hci.readLocalVersion);
128
+ assert.notCalled(hci.writeLeHostSupported);
129
+ assert.notCalled(hci.readLeHostSupported);
130
+ assert.notCalled(hci.readLeBufferSize);
131
+ assert.notCalled(hci.readBdAddr);
132
+ assert.notCalled(hci.setCodedPhySupport);
133
+ assert.notCalled(hci.init);
134
+ assert.notCalled(callback);
135
+ });
136
+
137
+ it('should re-init', () => {
138
+ hci._socket.isDevUp.returns(true);
139
+ hci._isDevUp = false;
140
+ hci._state = 'poweredOff';
141
+
142
+ hci.pollIsDevUp();
143
+
144
+ should(hci._state).equal(null);
145
+
146
+ assert.calledOnceWithExactly(hci._socket.removeAllListeners);
147
+ assert.calledOnceWithExactly(hci.init);
148
+
149
+ assert.notCalled(hci.setSocketFilter);
150
+ assert.notCalled(hci.setEventMask);
151
+ assert.notCalled(hci.setLeEventMask);
152
+ assert.notCalled(hci.readLocalVersion);
153
+ assert.notCalled(hci.writeLeHostSupported);
154
+ assert.notCalled(hci.readLeHostSupported);
155
+ assert.notCalled(hci.readLeBufferSize);
156
+ assert.notCalled(hci.readBdAddr);
157
+ assert.notCalled(hci.setCodedPhySupport);
158
+ assert.notCalled(callback);
159
+ });
160
+
161
+ it('should init all', () => {
162
+ hci._socket.isDevUp.returns(true);
163
+ hci._isDevUp = false;
164
+ hci._state = undefined;
165
+
166
+ hci.pollIsDevUp();
167
+
168
+ assert.calledOnceWithExactly(hci.setSocketFilter);
169
+ assert.calledOnceWithExactly(hci.setEventMask);
170
+ assert.calledOnceWithExactly(hci.setLeEventMask);
171
+ assert.calledOnceWithExactly(hci.readLocalVersion);
172
+ assert.calledOnceWithExactly(hci.writeLeHostSupported);
173
+ assert.calledOnceWithExactly(hci.readLeHostSupported);
174
+ assert.calledOnceWithExactly(hci.readLeBufferSize);
175
+ assert.calledOnceWithExactly(hci.readBdAddr);
176
+
177
+ assert.notCalled(hci.setCodedPhySupport);
178
+ assert.notCalled(hci._socket.removeAllListeners);
179
+ assert.notCalled(hci.init);
180
+ assert.notCalled(callback);
181
+ });
182
+
183
+ it('should init all with extended option', () => {
184
+ hci._socket.isDevUp.returns(true);
185
+ hci._isDevUp = false;
186
+ hci._state = undefined;
187
+ hci._isExtended = true;
188
+
189
+ hci.pollIsDevUp();
190
+
191
+ assert.calledOnceWithExactly(hci.setSocketFilter);
192
+ assert.calledOnceWithExactly(hci.setEventMask);
193
+ assert.calledOnceWithExactly(hci.setLeEventMask);
194
+ assert.calledOnceWithExactly(hci.readLocalVersion);
195
+ assert.calledOnceWithExactly(hci.writeLeHostSupported);
196
+ assert.calledOnceWithExactly(hci.readLeHostSupported);
197
+ assert.calledOnceWithExactly(hci.readLeBufferSize);
198
+ assert.calledOnceWithExactly(hci.readBdAddr);
199
+ assert.calledOnceWithExactly(hci.setCodedPhySupport);
200
+
201
+ assert.notCalled(hci._socket.removeAllListeners);
202
+ assert.notCalled(hci.init);
203
+ assert.notCalled(callback);
204
+ });
205
+
206
+ it('should emit stateChange', () => {
207
+ hci._socket.isDevUp.returns(false);
208
+ hci._isDevUp = true;
209
+
210
+ hci.pollIsDevUp();
211
+
212
+ assert.calledOnceWithExactly(callback, 'poweredOff');
213
+
214
+ assert.notCalled(hci._socket.removeAllListeners);
215
+ assert.notCalled(hci.init);
216
+ assert.notCalled(hci.setSocketFilter);
217
+ assert.notCalled(hci.setEventMask);
218
+ assert.notCalled(hci.setLeEventMask);
219
+ assert.notCalled(hci.readLocalVersion);
220
+ assert.notCalled(hci.writeLeHostSupported);
221
+ assert.notCalled(hci.readLeHostSupported);
222
+ assert.notCalled(hci.readLeBufferSize);
223
+ assert.notCalled(hci.readBdAddr);
224
+ assert.notCalled(hci.setCodedPhySupport);
225
+ });
226
+ });
227
+
228
+ it('should write codedPhySupport command', () => {
229
+ hci.setCodedPhySupport();
230
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x31, 0x20, 0x03, 0x00, 0x05, 0x05]));
231
+ });
232
+
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
+ it('should setSocketFilter', () => {
239
+ hci.setSocketFilter();
240
+ assert.calledOnceWithExactly(hci._socket.setFilter, Buffer.from([0x16, 0, 0, 0, 0x20, 0xc1, 0x08, 0, 0, 0, 0, 0x40, 0, 0]));
241
+ });
242
+
243
+ it('should setEventMask', () => {
244
+ hci.setEventMask();
245
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 1, 0x0c, 0x08, 0xff, 0xff, 0xfb, 0xff, 0x07, 0xf8, 0xbf, 0x3d]));
246
+ });
247
+
248
+ it('should reset', () => {
249
+ hci.reset();
250
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 3, 0x0c, 0]));
251
+ });
252
+
253
+ it('should readSupportedCommands', () => {
254
+ hci.readSupportedCommands();
255
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x02, 0x10, 0x00]));
256
+ });
257
+
258
+ it('should readLocalVersion', () => {
259
+ hci.readLocalVersion();
260
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 1, 0x10, 0]));
261
+ });
262
+
263
+ it('should readBufferSize', () => {
264
+ hci.readBufferSize();
265
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 5, 0x10, 0]));
266
+ });
267
+
268
+ it('should readBdAddr', () => {
269
+ hci.readBdAddr();
270
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 9, 0x10, 0]));
271
+ });
272
+
273
+ describe('setLeEventMask', () => {
274
+ it('should setLeEventMask', () => {
275
+ hci.setLeEventMask();
276
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 1, 0x20, 8, 0x1f, 0, 0, 0, 0, 0, 0, 0]));
277
+ });
278
+
279
+ it('should setLeEventMask for BLE5 (extended)', () => {
280
+ hci._isExtended = true;
281
+ hci.setLeEventMask();
282
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 1, 0x20, 8, 0x1f, 0xff, 0, 0, 0, 0, 0, 0]));
283
+ });
284
+ });
285
+
286
+ it('should readLeBufferSize', () => {
287
+ hci.readLeBufferSize();
288
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 2, 0x20, 0]));
289
+ });
290
+
291
+ it('should readLeHostSupported', () => {
292
+ hci.readLeHostSupported();
293
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x6c, 0x0c, 0]));
294
+ });
295
+
296
+ it('should writeLeHostSupported', () => {
297
+ hci.writeLeHostSupported();
298
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x6d, 0x0c, 2, 1, 0]));
299
+ });
300
+
301
+ describe('setScanParameters', () => {
302
+ it('should keep default parameters', () => {
303
+ hci.setScanParameters();
304
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x0b, 0x20, 7, 1, 0x12, 0, 0x12, 0, 0, 0]));
305
+ });
306
+
307
+ it('should keep default parameters (extended)', () => {
308
+ hci._isExtended = true;
309
+ hci.setScanParameters();
310
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x41, 0x20, 0x0d, 0x00, 0x00, 0x05, 0x01, 0x12, 0x00, 0x12, 0x00, 0x01, 0x12, 0x00, 0x12, 0x00]));
311
+ });
312
+
313
+ it('should force parameters', () => {
314
+ hci.setScanParameters(0x2222, 0x3333);
315
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x0b, 0x20, 7, 1, 0x22, 0x022, 0x33, 0x33, 0, 0]));
316
+ });
317
+
318
+ it('should force parameters (extended)', () => {
319
+ hci._isExtended = true;
320
+ hci.setScanParameters(0x2222, 0x3333);
321
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x41, 0x20, 0x0d, 0x00, 0x00, 0x05, 0x01, 0x22, 0x22, 0x33, 0x33, 0x01, 0x22, 0x22, 0x33, 0x33]));
322
+ });
323
+ });
324
+
325
+ describe('setScanEnabled', () => {
326
+ it('should keep default parameters', () => {
327
+ hci.setScanEnabled();
328
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x0c, 0x20, 2, 0, 0]));
329
+ });
330
+
331
+ it('should keep default parameters (extended)', () => {
332
+ hci._isExtended = true;
333
+ hci.setScanEnabled();
334
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x42, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
335
+ });
336
+
337
+ it('should force parameters', () => {
338
+ hci.setScanEnabled(true, true);
339
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x0c, 0x20, 2, 1, 1]));
340
+ });
341
+
342
+ it('should force parameters (extended)', () => {
343
+ hci._isExtended = true;
344
+ hci.setScanEnabled(true, true);
345
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x42, 0x20, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00]));
346
+ });
347
+ });
348
+
349
+ describe('createLeConn', () => {
350
+ it('should keep default parameters', () => {
351
+ const address = 'aa:bb:cc:dd:ee';
352
+ const addressType = 'random';
353
+ hci.createLeConn(address, addressType);
354
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x0d, 0x20, 0x19, 0x60, 0x00, 0x30, 0x00, 0x00, 0x01, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x00, 0x00, 0x06, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x04, 0x00, 0x06, 0x00]));
355
+ });
356
+
357
+ it('should keep default parameters (extended)', () => {
358
+ const address = 'aa:bb:cc:dd:ee';
359
+ const addressType = 'random';
360
+ hci._isExtended = true;
361
+ hci.createLeConn(address, addressType);
362
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x43, 0x20, 0x2a, 0x00, 0x00, 0x01, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x00, 0x05, 0x60, 0x00, 0x60, 0x00, 0x06, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x06, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00]));
363
+ });
364
+
365
+ it('should override default parameters', () => {
366
+ const address = 'ee:dd:cc:bb:aa';
367
+ const addressType = 'not_random';
368
+ const parameters = { minInterval: 0x0060, maxInterval: 0x00c0, latency: 0x0010, timeout: 0x0c80 };
369
+ hci.createLeConn(address, addressType, parameters);
370
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x0d, 0x20, 0x19, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x10, 0x00, 0x80, 0x0c, 0x04, 0x00, 0x06, 0x00]));
371
+ });
372
+
373
+ it('should override default parameters (extended)', () => {
374
+ const address = 'ee:dd:cc:bb:aa';
375
+ const addressType = 'not_random';
376
+ const parameters = { minInterval: 0x0060, maxInterval: 0x00c0, latency: 0x0010, timeout: 0x0c80 };
377
+ hci._isExtended = true;
378
+ hci.createLeConn(address, addressType, parameters);
379
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x43, 0x20, 0x2a, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x05, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x10, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x10, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00]));
380
+ });
381
+ });
382
+
383
+ it('should write connUpdateLe', () => {
384
+ const handle = 0x1234;
385
+ const minInterval = 5;
386
+ const maxInterval = 15;
387
+ const latency = 12;
388
+ const supervisionTimeout = 25;
389
+ hci.connUpdateLe(handle, minInterval, maxInterval, latency, supervisionTimeout);
390
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x13, 0x20, 0x0e, 0x34, 0x12, 0x04, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00]));
391
+ });
392
+
393
+ it('should write cancelConnect', () => {
394
+ hci.cancelConnect();
395
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x0e, 0x20, 0x00]));
396
+ });
397
+
398
+ it('should write startLeEncryption', () => {
399
+ const handle = 0x1234;
400
+ const random = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
401
+ const diversifier = Buffer.from([11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 24, 25]);
402
+ const key = Buffer.from([31, 32, 33, 34, 35, 36, 37, 38, 39, 30, 31, 32, 33, 33, 34, 35]);
403
+ hci.startLeEncryption(handle, random, diversifier, key);
404
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x19, 0x20, 0x1c, 0x34, 0x12, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0b, 0x0c, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x1e, 0x1f, 0x20, 0x21, 0x21, 0x22, 0x23]));
405
+ });
406
+
407
+ describe('disconnect', () => {
408
+ it('should write disconnect with defaults', () => {
409
+ const handle = 0x1234;
410
+ const reason = undefined;
411
+ hci.disconnect(handle, reason);
412
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x06, 0x04, 0x03, 0x34, 0x12, 0x13]));
413
+ });
414
+
415
+ it('should write disconnect with reason', () => {
416
+ const handle = 0x1234;
417
+ const reason = 17;
418
+ hci.disconnect(handle, reason);
419
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x06, 0x04, 0x03, 0x34, 0x12, 0x11]));
420
+ });
421
+ });
422
+
423
+ it('should write readRssi', () => {
424
+ const handle = 0x1234;
425
+ hci.readRssi(handle);
426
+ assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x05, 0x14, 0x02, 0x34, 0x12]));
427
+ });
428
+
429
+ it('should writeAclDataPkt - push in aclQueue and flushAcl', async () => {
430
+ hci.flushAcl = sinon.spy();
431
+ hci._aclBuffers = [1, 2, 3, 4, 5, 6, 7, 8];
432
+
433
+ const handle = 0x1234;
434
+ const cid = 345;
435
+ const data = Buffer.from([5, 6, 7, 8, 9, 10, 11]);
436
+ await hci.writeAclDataPkt(handle, cid, data);
437
+
438
+ assert.calledOnceWithExactly(hci.flushAcl);
439
+
440
+ should(hci._aclQueue).deepEqual([
441
+ {
442
+ handle: 4660,
443
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
444
+ },
445
+ {
446
+ handle: 4660,
447
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
448
+ }
449
+ ]);
450
+ });
451
+
452
+ describe('flushAcl', () => {
453
+ it('should not write flush on no pending connections', () => {
454
+ const queue = [
455
+ {
456
+ handle: 4660,
457
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
458
+ },
459
+ {
460
+ handle: 4660,
461
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
462
+ }
463
+ ];
464
+ hci._aclQueue = [...queue];
465
+
466
+ hci.flushAcl();
467
+
468
+ assert.notCalled(hci._socket.write);
469
+ should(hci._aclQueue).deepEqual(queue);
470
+ });
471
+
472
+ it('should not write flush on empty queue', () => {
473
+ hci._aclQueue = [];
474
+ hci._aclConnections.set(4660, { pending: 3 });
475
+ hci._aclConnections.set(4661, { pending: 2 });
476
+ hci._aclBuffers = { num: 12 };
477
+
478
+ hci.flushAcl();
479
+
480
+ assert.notCalled(hci._socket.write);
481
+
482
+ should(hci._aclQueue).be.empty();
483
+ });
484
+
485
+ it('should not write flush on not enough pending connections', () => {
486
+ const queue = [
487
+ {
488
+ handle: 4660,
489
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
490
+ },
491
+ {
492
+ handle: 4660,
493
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
494
+ }
495
+ ];
496
+ hci._aclQueue = [...queue];
497
+ hci._aclConnections.set(4660, { pending: 3 });
498
+ hci._aclConnections.set(4661, { pending: 2 });
499
+ hci._aclBuffers = { num: 1 };
500
+
501
+ hci.flushAcl();
502
+
503
+ assert.notCalled(hci._socket.write);
504
+ should(hci._aclQueue).deepEqual(queue);
505
+ });
506
+
507
+ it('should write flush', async () => {
508
+ const queue = [
509
+ {
510
+ handle: 4660,
511
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
512
+ },
513
+ {
514
+ handle: 4660,
515
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
516
+ },
517
+ {
518
+ handle: 4661,
519
+ packet: Buffer.from([0x02])
520
+ }
521
+ ];
522
+ hci._aclQueue = [...queue];
523
+ hci._aclConnections.set(4660, { pending: 3 });
524
+ hci._aclConnections.set(4661, { pending: 2 });
525
+ hci._aclBuffers = { num: 12 };
526
+
527
+ await hci.flushAcl();
528
+
529
+ assert.callCount(hci._socket.write, 3);
530
+ assert.calledWithExactly(hci._socket.write, Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08]));
531
+ assert.calledWithExactly(hci._socket.write, Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b]));
532
+ assert.calledWithExactly(hci._socket.write, Buffer.from([0x02]));
533
+
534
+ should(hci._aclQueue).be.empty();
535
+ });
536
+ });
537
+
538
+ describe('onSocketData', () => {
539
+ const aclQueue = [
540
+ {
541
+ handle: 4660,
542
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
543
+ },
544
+ {
545
+ handle: 4660,
546
+ packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
547
+ },
548
+ {
549
+ handle: 4661,
550
+ packet: Buffer.from([0x02])
551
+ }
552
+ ];
553
+
554
+ let disconnCompleteCallback;
555
+ let encryptChangeCallback;
556
+ let aclDataPktCallback;
557
+ let leScanEnableSetCmdCallback;
558
+
559
+ beforeEach(() => {
560
+ hci.flushAcl = sinon.spy();
561
+ hci.processCmdCompleteEvent = sinon.spy();
562
+ hci.processCmdStatusEvent = sinon.spy();
563
+ hci.processLeMetaEvent = sinon.spy();
564
+
565
+ hci._aclQueue = [...aclQueue];
566
+ hci._aclConnections.set(4660, { pending: 3 });
567
+ hci._aclConnections.set(4661, { pending: 2 });
568
+
569
+ disconnCompleteCallback = sinon.spy();
570
+ encryptChangeCallback = sinon.spy();
571
+ aclDataPktCallback = sinon.spy();
572
+ leScanEnableSetCmdCallback = sinon.spy();
573
+ hci.on('disconnComplete', disconnCompleteCallback);
574
+ hci.on('encryptChange', encryptChangeCallback);
575
+ hci.on('aclDataPkt', aclDataPktCallback);
576
+ hci.on('leScanEnableSetCmd', leScanEnableSetCmdCallback);
577
+ });
578
+
579
+ afterEach(() => {
580
+ sinon.reset();
581
+ });
582
+
583
+ it('should flushAcl - HCI_EVENT_PKT / EVT_DISCONN_COMPLETE', () => {
584
+ const eventType = 4;
585
+ const subEventType = 5;
586
+ const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3]);
587
+
588
+ hci.onSocketData(data);
589
+
590
+ // called
591
+ assert.calledOnceWithExactly(hci.flushAcl);
592
+ assert.calledOnceWithExactly(disconnCompleteCallback, 4660, 3);
593
+
594
+ // not called
595
+ assert.notCalled(hci.processCmdCompleteEvent);
596
+ assert.notCalled(hci.processLeMetaEvent);
597
+ assert.notCalled(encryptChangeCallback);
598
+ assert.notCalled(aclDataPktCallback);
599
+ assert.notCalled(leScanEnableSetCmdCallback);
600
+
601
+ // hci checks
602
+ should(hci._aclQueue).deepEqual([
603
+ {
604
+ handle: 4661,
605
+ packet: Buffer.from([0x02])
606
+ }
607
+ ]);
608
+ should(hci._aclConnections).have.keys(4661);
609
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
610
+ });
611
+
612
+ it('should only emit encryptChange - HCI_EVENT_PKT / EVT_ENCRYPT_CHANGE', () => {
613
+ const eventType = 4;
614
+ const subEventType = 8;
615
+ const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3]);
616
+ hci.onSocketData(data);
617
+
618
+ // called
619
+ assert.calledOnceWithExactly(encryptChangeCallback, 4660, 3);
620
+
621
+ // not called
622
+ assert.notCalled(hci.flushAcl);
623
+ assert.notCalled(hci.processCmdCompleteEvent);
624
+ assert.notCalled(hci.processLeMetaEvent);
625
+ assert.notCalled(disconnCompleteCallback);
626
+ assert.notCalled(aclDataPktCallback);
627
+ assert.notCalled(leScanEnableSetCmdCallback);
628
+
629
+ // hci checks
630
+ should(hci._aclQueue).deepEqual(aclQueue);
631
+ should(hci._aclConnections).have.keys(4660, 4661);
632
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
633
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
634
+ });
635
+
636
+ it('should only processCmdCompleteEvent - HCI_EVENT_PKT / EVT_CMD_COMPLETE', () => {
637
+ const eventType = 4;
638
+ const subEventType = 14;
639
+ const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3, 9, 9]);
640
+ hci.onSocketData(data);
641
+
642
+ // called
643
+ assert.calledOnceWithExactly(hci.processCmdCompleteEvent, 4660, 3, Buffer.from([9, 9]));
644
+
645
+ // not called
646
+ assert.notCalled(hci.flushAcl);
647
+ assert.notCalled(encryptChangeCallback);
648
+ assert.notCalled(hci.processLeMetaEvent);
649
+ assert.notCalled(disconnCompleteCallback);
650
+ assert.notCalled(aclDataPktCallback);
651
+ assert.notCalled(leScanEnableSetCmdCallback);
652
+
653
+ // hci checks
654
+ should(hci._aclQueue).deepEqual(aclQueue);
655
+ should(hci._aclConnections).have.keys(4660, 4661);
656
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
657
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
658
+ });
659
+
660
+ it('should only processCmdStatusEvent - HCI_EVENT_PKT / EVT_CMD_STATUS', () => {
661
+ const eventType = 4;
662
+ const subEventType = 15;
663
+ const data = Buffer.from([eventType, subEventType, 4, 2, 0x34, 0x12, 3, 9, 9]);
664
+ hci.onSocketData(data);
665
+
666
+ // called
667
+ assert.calledOnceWithExactly(hci.processCmdStatusEvent, 786, 2);
668
+
669
+ // not called
670
+ assert.notCalled(hci.flushAcl);
671
+ assert.notCalled(encryptChangeCallback);
672
+ assert.notCalled(hci.processCmdCompleteEvent);
673
+ assert.notCalled(hci.processLeMetaEvent);
674
+ assert.notCalled(disconnCompleteCallback);
675
+ assert.notCalled(aclDataPktCallback);
676
+ assert.notCalled(leScanEnableSetCmdCallback);
677
+
678
+ // hci checks
679
+ should(hci._aclQueue).deepEqual(aclQueue);
680
+ should(hci._aclConnections).have.keys(4660, 4661);
681
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
682
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
683
+ });
684
+
685
+ it('should only processLeMetaEvent - HCI_EVENT_PKT / EVT_LE_META_EVENT', () => {
686
+ const eventType = 4;
687
+ const subEventType = 62;
688
+ const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
689
+ hci.onSocketData(data);
690
+
691
+ // called
692
+ assert.calledOnceWithExactly(hci.processLeMetaEvent, 1, 52, Buffer.from([0x12, 3, 9, 9]));
693
+
694
+ // not called
695
+ assert.notCalled(hci.flushAcl);
696
+ assert.notCalled(encryptChangeCallback);
697
+ assert.notCalled(hci.processCmdCompleteEvent);
698
+ assert.notCalled(disconnCompleteCallback);
699
+ assert.notCalled(aclDataPktCallback);
700
+ assert.notCalled(leScanEnableSetCmdCallback);
701
+
702
+ // hci checks
703
+ should(hci._aclQueue).deepEqual(aclQueue);
704
+ should(hci._aclConnections).have.keys(4660, 4661);
705
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
706
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
707
+ });
708
+
709
+ it('should only flushAcl - HCI_EVENT_PKT / EVT_NUMBER_OF_COMPLETED_PACKETS', () => {
710
+ const eventType = 4;
711
+ const subEventType = 19;
712
+ const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
713
+ hci.onSocketData(data);
714
+
715
+ // called
716
+ assert.calledOnceWithExactly(hci.flushAcl);
717
+
718
+ // not called
719
+ assert.notCalled(hci.processLeMetaEvent);
720
+ assert.notCalled(encryptChangeCallback);
721
+ assert.notCalled(hci.processCmdCompleteEvent);
722
+ assert.notCalled(disconnCompleteCallback);
723
+ assert.notCalled(aclDataPktCallback);
724
+ assert.notCalled(leScanEnableSetCmdCallback);
725
+
726
+ // hci checks
727
+ should(hci._aclQueue).deepEqual(aclQueue);
728
+ should(hci._aclConnections).have.keys(4660, 4661);
729
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 0 });
730
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
731
+ });
732
+
733
+ it('should do nothing - HCI_EVENT_PKT / ??', () => {
734
+ const eventType = 4;
735
+ const subEventType = 122;
736
+ const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
737
+ hci.onSocketData(data);
738
+
739
+ // called
740
+
741
+ // not called
742
+ assert.notCalled(hci.flushAcl);
743
+ assert.notCalled(hci.processLeMetaEvent);
744
+ assert.notCalled(encryptChangeCallback);
745
+ assert.notCalled(hci.processCmdCompleteEvent);
746
+ assert.notCalled(disconnCompleteCallback);
747
+ assert.notCalled(aclDataPktCallback);
748
+ assert.notCalled(leScanEnableSetCmdCallback);
749
+
750
+ // hci checks
751
+ should(hci._aclQueue).deepEqual(aclQueue);
752
+ should(hci._aclConnections).have.keys(4660, 4661);
753
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
754
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
755
+ });
756
+
757
+ it('should only emit aclDataPkt - HCI_ACLDATA_PKT / ACL_START', () => {
758
+ const eventType = 2;
759
+ const subEventTypeP1 = 0xf2;
760
+ const subEventTypeP2 = 0x24;
761
+ const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8, 7]);
762
+ hci.onSocketData(data);
763
+
764
+ // called
765
+ assert.calledOnceWithExactly(aclDataPktCallback, 1266, 2307, Buffer.from([9, 8, 7]));
766
+
767
+ // not called
768
+ assert.notCalled(hci.flushAcl);
769
+ assert.notCalled(hci.processLeMetaEvent);
770
+ assert.notCalled(encryptChangeCallback);
771
+ assert.notCalled(hci.processCmdCompleteEvent);
772
+ assert.notCalled(disconnCompleteCallback);
773
+ assert.notCalled(leScanEnableSetCmdCallback);
774
+
775
+ // hci checks
776
+ should(hci._aclQueue).deepEqual(aclQueue);
777
+ should(hci._aclConnections).have.keys(4660, 4661);
778
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
779
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
780
+
781
+ should(hci._handleBuffers).be.empty();
782
+ });
783
+
784
+ it('should register handle buffer - HCI_ACLDATA_PKT / ACL_START', () => {
785
+ const eventType = 2;
786
+ const subEventTypeP1 = 0xf2;
787
+ const subEventTypeP2 = 0x24;
788
+ const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
789
+ hci.onSocketData(data);
790
+
791
+ // called
792
+
793
+ // not called
794
+ assert.notCalled(aclDataPktCallback);
795
+ assert.notCalled(hci.flushAcl);
796
+ assert.notCalled(hci.processLeMetaEvent);
797
+ assert.notCalled(encryptChangeCallback);
798
+ assert.notCalled(hci.processCmdCompleteEvent);
799
+ assert.notCalled(disconnCompleteCallback);
800
+ assert.notCalled(leScanEnableSetCmdCallback);
801
+
802
+ // hci checks
803
+ should(hci._aclQueue).deepEqual(aclQueue);
804
+ should(hci._aclConnections).have.keys(4660, 4661);
805
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
806
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
807
+
808
+ should(hci._handleBuffers).deepEqual({
809
+ 1266: {
810
+ length: 3,
811
+ cid: 2307,
812
+ data: Buffer.from([9, 8])
813
+ }
814
+ });
815
+ });
816
+
817
+ it('should do nothing - HCI_ACLDATA_PKT / ACL_CONT', () => {
818
+ const eventType = 2;
819
+ const subEventTypeP1 = 0xf2;
820
+ const subEventTypeP2 = 0x14;
821
+ const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
822
+ hci.onSocketData(data);
823
+
824
+ // called
825
+
826
+ // not called
827
+ assert.notCalled(aclDataPktCallback);
828
+ assert.notCalled(hci.flushAcl);
829
+ assert.notCalled(hci.processLeMetaEvent);
830
+ assert.notCalled(encryptChangeCallback);
831
+ assert.notCalled(hci.processCmdCompleteEvent);
832
+ assert.notCalled(disconnCompleteCallback);
833
+ assert.notCalled(leScanEnableSetCmdCallback);
834
+
835
+ // hci checks
836
+ should(hci._aclQueue).deepEqual(aclQueue);
837
+ should(hci._aclConnections).have.keys(4660, 4661);
838
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
839
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
840
+
841
+ should(hci._handleBuffers).be.empty();
842
+ });
843
+
844
+ it('should concat data - HCI_ACLDATA_PKT / ACL_CONT', () => {
845
+ const eventType = 2;
846
+ const subEventTypeP1 = 0xf2;
847
+ const subEventTypeP2 = 0x14;
848
+ const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
849
+
850
+ const handleBuffers = {
851
+ 1266: {
852
+ length: 3,
853
+ cid: 2307,
854
+ data: Buffer.from([3, 4])
855
+ }
856
+ };
857
+ hci._handleBuffers = handleBuffers;
858
+
859
+ hci.onSocketData(data);
860
+
861
+ // called
862
+
863
+ // not called
864
+ assert.notCalled(aclDataPktCallback);
865
+ assert.notCalled(hci.flushAcl);
866
+ assert.notCalled(hci.processLeMetaEvent);
867
+ assert.notCalled(encryptChangeCallback);
868
+ assert.notCalled(hci.processCmdCompleteEvent);
869
+ assert.notCalled(disconnCompleteCallback);
870
+ assert.notCalled(leScanEnableSetCmdCallback);
871
+
872
+ // hci checks
873
+ should(hci._aclQueue).deepEqual(aclQueue);
874
+ should(hci._aclConnections).have.keys(4660, 4661);
875
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
876
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
877
+
878
+ should(hci._handleBuffers).deepEqual({
879
+ 1266: {
880
+ length: 3,
881
+ cid: 2307,
882
+ data: Buffer.from([3, 4, 3, 0, 3, 9, 9, 8])
883
+ }
884
+ });
885
+ });
886
+
887
+ it('should concat data and emit aclDataPkt - HCI_ACLDATA_PKT / ACL_CONT', () => {
888
+ const eventType = 2;
889
+ const subEventTypeP1 = 0xf2;
890
+ const subEventTypeP2 = 0x14;
891
+ const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
892
+
893
+ const handleBuffers = {
894
+ 1266: {
895
+ length: 8,
896
+ cid: 2307,
897
+ data: Buffer.from([3, 4])
898
+ }
899
+ };
900
+ hci._handleBuffers = handleBuffers;
901
+
902
+ hci.onSocketData(data);
903
+
904
+ // called
905
+ assert.calledOnceWithExactly(aclDataPktCallback, 1266, 2307, Buffer.from([3, 4, 3, 0, 3, 9, 9, 8]));
906
+
907
+ // not called
908
+ assert.notCalled(hci.flushAcl);
909
+ assert.notCalled(hci.processLeMetaEvent);
910
+ assert.notCalled(encryptChangeCallback);
911
+ assert.notCalled(hci.processCmdCompleteEvent);
912
+ assert.notCalled(disconnCompleteCallback);
913
+ assert.notCalled(leScanEnableSetCmdCallback);
914
+
915
+ // hci checks
916
+ should(hci._aclQueue).deepEqual(aclQueue);
917
+ should(hci._aclConnections).have.keys(4660, 4661);
918
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
919
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
920
+
921
+ should(hci._handleBuffers).be.empty();
922
+ });
923
+
924
+ it('should do nothing - HCI_ACLDATA_PKT / ??', () => {
925
+ const eventType = 2;
926
+ const subEventType = 122;
927
+ const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
928
+ hci.onSocketData(data);
929
+
930
+ // called
931
+
932
+ // not called
933
+ assert.notCalled(hci.flushAcl);
934
+ assert.notCalled(hci.processLeMetaEvent);
935
+ assert.notCalled(encryptChangeCallback);
936
+ assert.notCalled(hci.processCmdCompleteEvent);
937
+ assert.notCalled(disconnCompleteCallback);
938
+ assert.notCalled(aclDataPktCallback);
939
+ assert.notCalled(leScanEnableSetCmdCallback);
940
+
941
+ // hci checks
942
+ should(hci._aclQueue).deepEqual(aclQueue);
943
+ should(hci._aclConnections).have.keys(4660, 4661);
944
+ should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
945
+ should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
946
+ });
947
+
948
+ it('should emit leScanEnableSetCmd - HCI_COMMAND_PKT / LE_SET_SCAN_ENABLE_CMD', () => {
949
+ const eventType = 1;
950
+ const subEventTypeP1 = 0x0c;
951
+ const subEventTypeP2 = 0x20;
952
+ const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
953
+
954
+ const handleBuffers = {
955
+ 1266: {
956
+ length: 8,
957
+ cid: 2307,
958
+ data: Buffer.from([3, 4])
959
+ }
960
+ };
961
+ hci._handleBuffers = handleBuffers;
962
+
963
+ hci.onSocketData(data);
964
+
965
+ // called
966
+ assert.calledOnceWithExactly(leScanEnableSetCmdCallback, true, false);
967
+
968
+ // not called
969
+ assert.notCalled(hci.flushAcl);
970
+ assert.notCalled(hci.processLeMetaEvent);
971
+ assert.notCalled(encryptChangeCallback);
972
+ assert.notCalled(hci.processCmdCompleteEvent);
973
+ assert.notCalled(disconnCompleteCallback);
974
+ assert.notCalled(aclDataPktCallback);
975
+
976
+ // hci checks
977
+ should(hci._aclQueue).deepEqual(aclQueue);
978
+ should(hci._aclConnections).have.keys(4660, 4661);
979
+ });
980
+
981
+ it('should not emit leScanEnableSetCmd - HCI_COMMAND_PKT / ???', () => {
982
+ const eventType = 1;
983
+ const subEventTypeP1 = 0x0c;
984
+ const subEventTypeP2 = 0x21;
985
+ const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
986
+
987
+ const handleBuffers = {
988
+ 1266: {
989
+ length: 8,
990
+ cid: 2307,
991
+ data: Buffer.from([3, 4])
992
+ }
993
+ };
994
+ hci._handleBuffers = handleBuffers;
995
+
996
+ hci.onSocketData(data);
997
+
998
+ // called
999
+
1000
+ // not called
1001
+ assert.notCalled(leScanEnableSetCmdCallback);
1002
+ assert.notCalled(hci.flushAcl);
1003
+ assert.notCalled(hci.processLeMetaEvent);
1004
+ assert.notCalled(encryptChangeCallback);
1005
+ assert.notCalled(hci.processCmdCompleteEvent);
1006
+ assert.notCalled(disconnCompleteCallback);
1007
+ assert.notCalled(aclDataPktCallback);
1008
+
1009
+ // hci checks
1010
+ should(hci._aclQueue).deepEqual(aclQueue);
1011
+ should(hci._aclConnections).have.keys(4660, 4661);
1012
+ });
1013
+
1014
+ it('should do nothing - ?? / ???', () => {
1015
+ const eventType = 122;
1016
+ const subEventTypeP1 = 0x0c;
1017
+ const subEventTypeP2 = 0x21;
1018
+ const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
1019
+
1020
+ const handleBuffers = {
1021
+ 1266: {
1022
+ length: 8,
1023
+ cid: 2307,
1024
+ data: Buffer.from([3, 4])
1025
+ }
1026
+ };
1027
+ hci._handleBuffers = handleBuffers;
1028
+
1029
+ hci.onSocketData(data);
1030
+
1031
+ // called
1032
+
1033
+ // not called
1034
+ assert.notCalled(leScanEnableSetCmdCallback);
1035
+ assert.notCalled(hci.flushAcl);
1036
+ assert.notCalled(hci.processLeMetaEvent);
1037
+ assert.notCalled(encryptChangeCallback);
1038
+ assert.notCalled(hci.processCmdCompleteEvent);
1039
+ assert.notCalled(disconnCompleteCallback);
1040
+ assert.notCalled(aclDataPktCallback);
1041
+
1042
+ // hci checks
1043
+ should(hci._aclQueue).deepEqual(aclQueue);
1044
+ should(hci._aclConnections).have.keys(4660, 4661);
1045
+ });
1046
+ });
1047
+
1048
+ describe('onSocketError', () => {
1049
+ it('should emit stateChange', () => {
1050
+ const callback = sinon.spy();
1051
+
1052
+ hci.on('stateChange', callback);
1053
+ hci.onSocketError({ code: 'EPERM', message: 'Network is down' });
1054
+
1055
+ assert.calledOnceWithExactly(callback, 'unauthorized');
1056
+ });
1057
+
1058
+ it('should do nothing with message', () => {
1059
+ const callback = sinon.spy();
1060
+
1061
+ hci.on('stateChange', callback);
1062
+ hci.onSocketError({ message: 'Network is down' });
1063
+
1064
+ assert.notCalled(callback);
1065
+ });
1066
+
1067
+ it('should do nothing', () => {
1068
+ const callback = sinon.spy();
1069
+
1070
+ hci.on('stateChange', callback);
1071
+ hci.onSocketError({ });
1072
+
1073
+ assert.notCalled(callback);
1074
+ });
1075
+ });
1076
+
1077
+ describe('processCmdCompleteEvent', () => {
1078
+ const aclBuffers = {
1079
+ length: 99,
1080
+ num: 88
1081
+ };
1082
+
1083
+ let rssiReadCallback;
1084
+ let leScanEnableSetCallback;
1085
+ let leScanParametersSetCallback;
1086
+ let stateChangeCallback;
1087
+ let addressChangeCallback;
1088
+ let readLocalVersionCallback;
1089
+
1090
+ beforeEach(() => {
1091
+ hci.setEventMask = sinon.spy();
1092
+ hci.setLeEventMask = sinon.spy();
1093
+ hci.readLocalVersion = sinon.spy();
1094
+ hci.readBdAddr = sinon.spy();
1095
+ hci.setScanEnabled = sinon.spy();
1096
+ hci.setScanParameters = sinon.spy();
1097
+ hci.readBufferSize = sinon.spy();
1098
+ hci.setCodedPhySupport = sinon.spy();
1099
+
1100
+ hci._aclBuffers = aclBuffers;
1101
+
1102
+ rssiReadCallback = sinon.spy();
1103
+ leScanEnableSetCallback = sinon.spy();
1104
+ leScanParametersSetCallback = sinon.spy();
1105
+ stateChangeCallback = sinon.spy();
1106
+ addressChangeCallback = sinon.spy();
1107
+ readLocalVersionCallback = sinon.spy();
1108
+
1109
+ hci.on('rssiRead', rssiReadCallback);
1110
+ hci.on('leScanEnableSet', leScanEnableSetCallback);
1111
+ hci.on('leScanParametersSet', leScanParametersSetCallback);
1112
+ hci.on('stateChange', stateChangeCallback);
1113
+ hci.on('addressChange', addressChangeCallback);
1114
+ hci.on('readLocalVersion', readLocalVersionCallback);
1115
+ });
1116
+
1117
+ it('should do nothing', () => {
1118
+ const cmd = 0;
1119
+ const status = 0;
1120
+ const result = Buffer.from([]);
1121
+
1122
+ hci.processCmdCompleteEvent(cmd, status, result);
1123
+
1124
+ // called
1125
+
1126
+ // not called
1127
+ assert.notCalled(hci.setEventMask);
1128
+ assert.notCalled(hci.setLeEventMask);
1129
+ assert.notCalled(hci.readLocalVersion);
1130
+ assert.notCalled(hci.readBdAddr);
1131
+ assert.notCalled(hci.setScanEnabled);
1132
+ assert.notCalled(hci.setScanParameters);
1133
+ assert.notCalled(hci.readBufferSize);
1134
+ assert.notCalled(hci.setCodedPhySupport);
1135
+ assert.notCalled(rssiReadCallback);
1136
+ assert.notCalled(leScanEnableSetCallback);
1137
+ assert.notCalled(leScanParametersSetCallback);
1138
+ assert.notCalled(stateChangeCallback);
1139
+ assert.notCalled(addressChangeCallback);
1140
+ assert.notCalled(readLocalVersionCallback);
1141
+
1142
+ // hci checks
1143
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1144
+ should(hci._isExtended).equal(false);
1145
+ });
1146
+
1147
+ it('should reset', () => {
1148
+ const cmd = 3075;
1149
+ const status = 0;
1150
+ const result = Buffer.from([]);
1151
+
1152
+ hci.processCmdCompleteEvent(cmd, status, result);
1153
+
1154
+ // called
1155
+ assert.calledOnceWithExactly(hci.setEventMask);
1156
+ assert.calledOnceWithExactly(hci.setLeEventMask);
1157
+ assert.calledOnceWithExactly(hci.readLocalVersion);
1158
+ assert.calledOnceWithExactly(hci.readBdAddr);
1159
+
1160
+ // not called
1161
+ assert.notCalled(hci.setScanEnabled);
1162
+ assert.notCalled(hci.setScanParameters);
1163
+ assert.notCalled(hci.readBufferSize);
1164
+ assert.notCalled(hci.setCodedPhySupport);
1165
+ assert.notCalled(rssiReadCallback);
1166
+ assert.notCalled(leScanEnableSetCallback);
1167
+ assert.notCalled(leScanParametersSetCallback);
1168
+ assert.notCalled(stateChangeCallback);
1169
+ assert.notCalled(addressChangeCallback);
1170
+ assert.notCalled(readLocalVersionCallback);
1171
+
1172
+ // hci checks
1173
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1174
+ should(hci._isExtended).equal(false);
1175
+ });
1176
+
1177
+ it('should reset (extended)', () => {
1178
+ const cmd = 3075;
1179
+ const status = 0;
1180
+ const result = Buffer.from([]);
1181
+
1182
+ hci._isExtended = true;
1183
+ hci.processCmdCompleteEvent(cmd, status, result);
1184
+
1185
+ // called
1186
+ assert.calledOnceWithExactly(hci.setEventMask);
1187
+ assert.calledOnceWithExactly(hci.setLeEventMask);
1188
+ assert.calledOnceWithExactly(hci.readLocalVersion);
1189
+ assert.calledOnceWithExactly(hci.readBdAddr);
1190
+ assert.calledOnceWithExactly(hci.setCodedPhySupport);
1191
+
1192
+ // not called
1193
+ assert.notCalled(hci.setScanEnabled);
1194
+ assert.notCalled(hci.setScanParameters);
1195
+ assert.notCalled(hci.readBufferSize);
1196
+ assert.notCalled(rssiReadCallback);
1197
+ assert.notCalled(leScanEnableSetCallback);
1198
+ assert.notCalled(leScanParametersSetCallback);
1199
+ assert.notCalled(stateChangeCallback);
1200
+ assert.notCalled(addressChangeCallback);
1201
+ assert.notCalled(readLocalVersionCallback);
1202
+
1203
+ // hci checks
1204
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1205
+ should(hci._isExtended).equal(true);
1206
+ });
1207
+
1208
+ it('should only log debug - READ_LE_HOST_SUPPORTED_CMD', () => {
1209
+ const cmd = 3180;
1210
+ const status = 0;
1211
+ const result = Buffer.from([0, 1]);
1212
+
1213
+ hci.processCmdCompleteEvent(cmd, status, result);
1214
+
1215
+ // called
1216
+
1217
+ // not called
1218
+ assert.notCalled(hci.setEventMask);
1219
+ assert.notCalled(hci.setLeEventMask);
1220
+ assert.notCalled(hci.readLocalVersion);
1221
+ assert.notCalled(hci.readBdAddr);
1222
+ assert.notCalled(hci.setScanEnabled);
1223
+ assert.notCalled(hci.setScanParameters);
1224
+ assert.notCalled(hci.readBufferSize);
1225
+ assert.notCalled(hci.setCodedPhySupport);
1226
+ assert.notCalled(rssiReadCallback);
1227
+ assert.notCalled(leScanEnableSetCallback);
1228
+ assert.notCalled(leScanParametersSetCallback);
1229
+ assert.notCalled(stateChangeCallback);
1230
+ assert.notCalled(addressChangeCallback);
1231
+ assert.notCalled(readLocalVersionCallback);
1232
+
1233
+ // hci checks
1234
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1235
+ should(hci._isExtended).equal(false);
1236
+ });
1237
+
1238
+ it('should do nothing - READ_LE_HOST_SUPPORTED_CMD', () => {
1239
+ const cmd = 3180;
1240
+ const status = 1;
1241
+ const result = Buffer.from([]);
1242
+
1243
+ hci.processCmdCompleteEvent(cmd, status, result);
1244
+
1245
+ // called
1246
+
1247
+ // not called
1248
+ assert.notCalled(hci.setEventMask);
1249
+ assert.notCalled(hci.setLeEventMask);
1250
+ assert.notCalled(hci.readLocalVersion);
1251
+ assert.notCalled(hci.readBdAddr);
1252
+ assert.notCalled(hci.setScanEnabled);
1253
+ assert.notCalled(hci.setScanParameters);
1254
+ assert.notCalled(hci.readBufferSize);
1255
+ assert.notCalled(hci.setCodedPhySupport);
1256
+ assert.notCalled(rssiReadCallback);
1257
+ assert.notCalled(leScanEnableSetCallback);
1258
+ assert.notCalled(leScanParametersSetCallback);
1259
+ assert.notCalled(stateChangeCallback);
1260
+ assert.notCalled(addressChangeCallback);
1261
+ assert.notCalled(readLocalVersionCallback);
1262
+
1263
+ // hci checks
1264
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1265
+ should(hci._isExtended).equal(false);
1266
+ });
1267
+
1268
+ it('should emit stateChange - READ_LOCAL_VERSION_CMD', () => {
1269
+ const cmd = 4097;
1270
+ const status = 0;
1271
+ const result = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7]);
1272
+
1273
+ hci.processCmdCompleteEvent(cmd, status, result);
1274
+
1275
+ // called
1276
+ assert.calledOnceWithExactly(stateChangeCallback, 'unsupported');
1277
+ assert.calledOnceWithExactly(readLocalVersionCallback, 0, 513, 3, 1284, 1798);
1278
+
1279
+ // not called
1280
+ assert.notCalled(hci.setEventMask);
1281
+ assert.notCalled(hci.setLeEventMask);
1282
+ assert.notCalled(hci.readLocalVersion);
1283
+ assert.notCalled(hci.readBdAddr);
1284
+ assert.notCalled(hci.setScanEnabled);
1285
+ assert.notCalled(hci.setScanParameters);
1286
+ assert.notCalled(hci.readBufferSize);
1287
+ assert.notCalled(hci.setCodedPhySupport);
1288
+ assert.notCalled(rssiReadCallback);
1289
+ assert.notCalled(leScanEnableSetCallback);
1290
+ assert.notCalled(leScanParametersSetCallback);
1291
+ assert.notCalled(addressChangeCallback);
1292
+
1293
+ // hci checks
1294
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1295
+ should(hci._isExtended).equal(false);
1296
+ });
1297
+
1298
+ it('should not emit stateChange - READ_LOCAL_VERSION_CMD', () => {
1299
+ const cmd = 4097;
1300
+ const status = 0;
1301
+ const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
1302
+
1303
+ hci.processCmdCompleteEvent(cmd, status, result);
1304
+
1305
+ // called
1306
+ assert.calledOnceWithExactly(readLocalVersionCallback, 9, 513, 3, 1284, 1798);
1307
+ assert.calledOnceWithExactly(hci.setScanEnabled, false, true);
1308
+ assert.calledOnceWithExactly(hci.setScanParameters);
1309
+
1310
+ // not called
1311
+ assert.notCalled(hci.setEventMask);
1312
+ assert.notCalled(hci.setLeEventMask);
1313
+ assert.notCalled(hci.readLocalVersion);
1314
+ assert.notCalled(hci.readBdAddr);
1315
+ assert.notCalled(hci.readBufferSize);
1316
+ assert.notCalled(hci.setCodedPhySupport);
1317
+ assert.notCalled(rssiReadCallback);
1318
+ assert.notCalled(stateChangeCallback);
1319
+ assert.notCalled(leScanEnableSetCallback);
1320
+ assert.notCalled(leScanParametersSetCallback);
1321
+ assert.notCalled(addressChangeCallback);
1322
+
1323
+ // hci checks
1324
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1325
+ should(hci._isExtended).equal(false);
1326
+ });
1327
+
1328
+ it('should not scan - READ_LOCAL_VERSION_CMD', () => {
1329
+ const cmd = 4097;
1330
+ const status = 0;
1331
+ const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
1332
+
1333
+ hci._state = 'poweredOn';
1334
+ hci.processCmdCompleteEvent(cmd, status, result);
1335
+
1336
+ // called
1337
+ assert.calledOnceWithExactly(readLocalVersionCallback, 9, 513, 3, 1284, 1798);
1338
+
1339
+ // not called
1340
+ assert.notCalled(hci.setEventMask);
1341
+ assert.notCalled(hci.setLeEventMask);
1342
+ assert.notCalled(hci.readLocalVersion);
1343
+ assert.notCalled(hci.readBdAddr);
1344
+ assert.notCalled(hci.setScanEnabled);
1345
+ assert.notCalled(hci.setScanParameters);
1346
+ assert.notCalled(hci.readBufferSize);
1347
+ assert.notCalled(hci.setCodedPhySupport);
1348
+ assert.notCalled(rssiReadCallback);
1349
+ assert.notCalled(stateChangeCallback);
1350
+ assert.notCalled(leScanEnableSetCallback);
1351
+ assert.notCalled(leScanParametersSetCallback);
1352
+ assert.notCalled(addressChangeCallback);
1353
+
1354
+ // hci checks
1355
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1356
+ should(hci._isExtended).equal(false);
1357
+ });
1358
+
1359
+ it('should change extended - READ_SUPPORTED_COMMANDS_CMD', () => {
1360
+ const cmd = 4098;
1361
+ const status = 0;
1362
+ const result = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 30, 31, 32, 33, 34, 35, 35, 36, 0xff]);
1363
+
1364
+ hci._state = 'poweredOn';
1365
+ hci.processCmdCompleteEvent(cmd, status, result);
1366
+
1367
+ // called
1368
+
1369
+ // not called
1370
+ assert.notCalled(readLocalVersionCallback);
1371
+ assert.notCalled(hci.setEventMask);
1372
+ assert.notCalled(hci.setLeEventMask);
1373
+ assert.notCalled(hci.readLocalVersion);
1374
+ assert.notCalled(hci.readBdAddr);
1375
+ assert.notCalled(hci.setScanEnabled);
1376
+ assert.notCalled(hci.setScanParameters);
1377
+ assert.notCalled(hci.readBufferSize);
1378
+ assert.notCalled(hci.setCodedPhySupport);
1379
+ assert.notCalled(rssiReadCallback);
1380
+ assert.notCalled(stateChangeCallback);
1381
+ assert.notCalled(leScanEnableSetCallback);
1382
+ assert.notCalled(leScanParametersSetCallback);
1383
+ assert.notCalled(addressChangeCallback);
1384
+
1385
+ // hci checks
1386
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1387
+ should(hci._isExtended).equal(32);
1388
+ });
1389
+
1390
+ it('should emit addressChange - READ_BD_ADDR_CMD', () => {
1391
+ const cmd = 4105;
1392
+ const status = 0;
1393
+ const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
1394
+
1395
+ hci.addressType = 'addressType';
1396
+ hci.address = 'address';
1397
+ hci.processCmdCompleteEvent(cmd, status, result);
1398
+
1399
+ // called
1400
+ assert.calledOnceWithExactly(addressChangeCallback, '07:06:05:04:03:02:01:09');
1401
+
1402
+ // not called
1403
+ assert.notCalled(hci.setEventMask);
1404
+ assert.notCalled(hci.setLeEventMask);
1405
+ assert.notCalled(hci.readLocalVersion);
1406
+ assert.notCalled(hci.readBdAddr);
1407
+ assert.notCalled(hci.setScanEnabled);
1408
+ assert.notCalled(hci.setScanParameters);
1409
+ assert.notCalled(hci.readBufferSize);
1410
+ assert.notCalled(hci.setCodedPhySupport);
1411
+ assert.notCalled(rssiReadCallback);
1412
+ assert.notCalled(stateChangeCallback);
1413
+ assert.notCalled(leScanEnableSetCallback);
1414
+ assert.notCalled(leScanParametersSetCallback);
1415
+ assert.notCalled(readLocalVersionCallback);
1416
+
1417
+ // hci checks
1418
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1419
+ should(hci._isExtended).equal(false);
1420
+ should(hci.addressType).equal('public');
1421
+ should(hci.address).equal('07:06:05:04:03:02:01:09');
1422
+ });
1423
+
1424
+ [8203, 8257].forEach((cmd) => {
1425
+ it(`should emit stateChange - LE_SET_SCAN_PARAMETERS_CMD - ${cmd}`, () => {
1426
+ const status = 0;
1427
+ const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
1428
+
1429
+ hci.processCmdCompleteEvent(cmd, status, result);
1430
+
1431
+ // called
1432
+ assert.calledOnceWithExactly(stateChangeCallback, 'poweredOn');
1433
+ assert.calledOnceWithExactly(leScanParametersSetCallback);
1434
+
1435
+ // not called
1436
+ assert.notCalled(addressChangeCallback);
1437
+ assert.notCalled(hci.setEventMask);
1438
+ assert.notCalled(hci.setLeEventMask);
1439
+ assert.notCalled(hci.readLocalVersion);
1440
+ assert.notCalled(hci.readBdAddr);
1441
+ assert.notCalled(hci.setScanEnabled);
1442
+ assert.notCalled(hci.setScanParameters);
1443
+ assert.notCalled(hci.readBufferSize);
1444
+ assert.notCalled(hci.setCodedPhySupport);
1445
+ assert.notCalled(rssiReadCallback);
1446
+ assert.notCalled(leScanEnableSetCallback);
1447
+ assert.notCalled(readLocalVersionCallback);
1448
+
1449
+ // hci checks
1450
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1451
+ should(hci._isExtended).equal(false);
1452
+ });
1453
+ });
1454
+
1455
+ [8204, 8258].forEach((cmd) => {
1456
+ it(`should emit leScanEnableSet - LE_SET_SCAN_ENABLE_CMD - ${cmd}`, () => {
1457
+ const status = 4;
1458
+ const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
1459
+
1460
+ hci.processCmdCompleteEvent(cmd, status, result);
1461
+
1462
+ // called
1463
+ assert.calledOnceWithExactly(leScanEnableSetCallback, status);
1464
+
1465
+ // not called
1466
+ assert.notCalled(addressChangeCallback);
1467
+ assert.notCalled(hci.setEventMask);
1468
+ assert.notCalled(hci.setLeEventMask);
1469
+ assert.notCalled(hci.readLocalVersion);
1470
+ assert.notCalled(hci.readBdAddr);
1471
+ assert.notCalled(hci.setScanEnabled);
1472
+ assert.notCalled(hci.setScanParameters);
1473
+ assert.notCalled(hci.readBufferSize);
1474
+ assert.notCalled(hci.setCodedPhySupport);
1475
+ assert.notCalled(rssiReadCallback);
1476
+ assert.notCalled(stateChangeCallback);
1477
+ assert.notCalled(leScanParametersSetCallback);
1478
+ assert.notCalled(readLocalVersionCallback);
1479
+
1480
+ // hci checks
1481
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1482
+ should(hci._isExtended).equal(false);
1483
+ });
1484
+ });
1485
+
1486
+ it('should emit rssiRead - READ_RSSI_CMD', () => {
1487
+ const cmd = 5125;
1488
+ const status = 4;
1489
+ const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
1490
+
1491
+ hci.processCmdCompleteEvent(cmd, status, result);
1492
+
1493
+ // called
1494
+ assert.calledOnceWithExactly(rssiReadCallback, 265, 2);
1495
+
1496
+ // not called
1497
+ assert.notCalled(addressChangeCallback);
1498
+ assert.notCalled(hci.setEventMask);
1499
+ assert.notCalled(hci.setLeEventMask);
1500
+ assert.notCalled(hci.readLocalVersion);
1501
+ assert.notCalled(hci.readBdAddr);
1502
+ assert.notCalled(hci.setScanEnabled);
1503
+ assert.notCalled(hci.setScanParameters);
1504
+ assert.notCalled(hci.readBufferSize);
1505
+ assert.notCalled(hci.setCodedPhySupport);
1506
+ assert.notCalled(leScanEnableSetCallback);
1507
+ assert.notCalled(stateChangeCallback);
1508
+ assert.notCalled(leScanParametersSetCallback);
1509
+ assert.notCalled(readLocalVersionCallback);
1510
+
1511
+ // hci checks
1512
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1513
+ should(hci._isExtended).equal(false);
1514
+ });
1515
+
1516
+ it('should read buffer size - LE_READ_BUFFER_SIZE_CMD', () => {
1517
+ const cmd = 8194;
1518
+ const status = 0;
1519
+ const result = Buffer.from([0, 0, 0]);
1520
+
1521
+ hci.processCmdCompleteEvent(cmd, status, result);
1522
+
1523
+ // called
1524
+ assert.calledOnceWithExactly(hci.readBufferSize);
1525
+
1526
+ // not called
1527
+ assert.notCalled(rssiReadCallback);
1528
+ assert.notCalled(addressChangeCallback);
1529
+ assert.notCalled(hci.setEventMask);
1530
+ assert.notCalled(hci.setLeEventMask);
1531
+ assert.notCalled(hci.readLocalVersion);
1532
+ assert.notCalled(hci.readBdAddr);
1533
+ assert.notCalled(hci.setScanEnabled);
1534
+ assert.notCalled(hci.setScanParameters);
1535
+ assert.notCalled(hci.setCodedPhySupport);
1536
+ assert.notCalled(leScanEnableSetCallback);
1537
+ assert.notCalled(stateChangeCallback);
1538
+ assert.notCalled(leScanParametersSetCallback);
1539
+ assert.notCalled(readLocalVersionCallback);
1540
+
1541
+ // hci checks
1542
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1543
+ should(hci._isExtended).equal(false);
1544
+ });
1545
+
1546
+ it('should change buffers - LE_READ_BUFFER_SIZE_CMD', () => {
1547
+ const cmd = 8194;
1548
+ const status = 0;
1549
+ const result = Buffer.from([1, 0, 2]);
1550
+
1551
+ hci.processCmdCompleteEvent(cmd, status, result);
1552
+
1553
+ // called
1554
+
1555
+ // not called
1556
+ assert.notCalled(hci.readBufferSize);
1557
+ assert.notCalled(rssiReadCallback);
1558
+ assert.notCalled(addressChangeCallback);
1559
+ assert.notCalled(hci.setEventMask);
1560
+ assert.notCalled(hci.setLeEventMask);
1561
+ assert.notCalled(hci.readLocalVersion);
1562
+ assert.notCalled(hci.readBdAddr);
1563
+ assert.notCalled(hci.setScanEnabled);
1564
+ assert.notCalled(hci.setScanParameters);
1565
+ assert.notCalled(hci.setCodedPhySupport);
1566
+ assert.notCalled(leScanEnableSetCallback);
1567
+ assert.notCalled(stateChangeCallback);
1568
+ assert.notCalled(leScanParametersSetCallback);
1569
+ assert.notCalled(readLocalVersionCallback);
1570
+
1571
+ // hci checks
1572
+ should(hci._aclBuffers).deepEqual({
1573
+ length: 1,
1574
+ num: 2
1575
+ });
1576
+ should(hci._isExtended).equal(false);
1577
+ });
1578
+
1579
+ it('should do nothing - LE_READ_BUFFER_SIZE_CMD', () => {
1580
+ const cmd = 8194;
1581
+ const status = 0;
1582
+ const result = Buffer.from([1, 0, 2]);
1583
+
1584
+ hci.processCmdCompleteEvent(cmd, status, result);
1585
+
1586
+ // called
1587
+
1588
+ // not called
1589
+ assert.notCalled(hci.readBufferSize);
1590
+ assert.notCalled(rssiReadCallback);
1591
+ assert.notCalled(addressChangeCallback);
1592
+ assert.notCalled(hci.setEventMask);
1593
+ assert.notCalled(hci.setLeEventMask);
1594
+ assert.notCalled(hci.readLocalVersion);
1595
+ assert.notCalled(hci.readBdAddr);
1596
+ assert.notCalled(hci.setScanEnabled);
1597
+ assert.notCalled(hci.setScanParameters);
1598
+ assert.notCalled(hci.setCodedPhySupport);
1599
+ assert.notCalled(leScanEnableSetCallback);
1600
+ assert.notCalled(stateChangeCallback);
1601
+ assert.notCalled(leScanParametersSetCallback);
1602
+ assert.notCalled(readLocalVersionCallback);
1603
+
1604
+ // hci checks
1605
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1606
+ should(hci._isExtended).equal(false);
1607
+ });
1608
+
1609
+ it('should do nothing - READ_BUFFER_SIZE_CMD', () => {
1610
+ const cmd = 4101;
1611
+ const status = 0;
1612
+ const result = Buffer.from([1, 0, 3, 2, 0]);
1613
+
1614
+ hci.processCmdCompleteEvent(cmd, status, result);
1615
+
1616
+ // called
1617
+
1618
+ // not called
1619
+ assert.notCalled(hci.readBufferSize);
1620
+ assert.notCalled(rssiReadCallback);
1621
+ assert.notCalled(addressChangeCallback);
1622
+ assert.notCalled(hci.setEventMask);
1623
+ assert.notCalled(hci.setLeEventMask);
1624
+ assert.notCalled(hci.readLocalVersion);
1625
+ assert.notCalled(hci.readBdAddr);
1626
+ assert.notCalled(hci.setScanEnabled);
1627
+ assert.notCalled(hci.setScanParameters);
1628
+ assert.notCalled(hci.setCodedPhySupport);
1629
+ assert.notCalled(leScanEnableSetCallback);
1630
+ assert.notCalled(stateChangeCallback);
1631
+ assert.notCalled(leScanParametersSetCallback);
1632
+ assert.notCalled(readLocalVersionCallback);
1633
+
1634
+ // hci checks
1635
+ should(hci._aclBuffers).deepEqual({
1636
+ length: 1,
1637
+ num: 2
1638
+ });
1639
+ should(hci._isExtended).equal(false);
1640
+ });
1641
+
1642
+ it('should do nothing - ??', () => {
1643
+ const cmd = 1;
1644
+ const status = 0;
1645
+ const result = Buffer.from([1, 0, 3, 2, 0]);
1646
+
1647
+ hci.processCmdCompleteEvent(cmd, status, result);
1648
+
1649
+ // called
1650
+
1651
+ // not called
1652
+ assert.notCalled(hci.readBufferSize);
1653
+ assert.notCalled(rssiReadCallback);
1654
+ assert.notCalled(addressChangeCallback);
1655
+ assert.notCalled(hci.setEventMask);
1656
+ assert.notCalled(hci.setLeEventMask);
1657
+ assert.notCalled(hci.readLocalVersion);
1658
+ assert.notCalled(hci.readBdAddr);
1659
+ assert.notCalled(hci.setScanEnabled);
1660
+ assert.notCalled(hci.setScanParameters);
1661
+ assert.notCalled(hci.setCodedPhySupport);
1662
+ assert.notCalled(leScanEnableSetCallback);
1663
+ assert.notCalled(stateChangeCallback);
1664
+ assert.notCalled(leScanParametersSetCallback);
1665
+ assert.notCalled(readLocalVersionCallback);
1666
+
1667
+ // hci checks
1668
+ should(hci._aclBuffers).deepEqual(aclBuffers);
1669
+ should(hci._isExtended).equal(false);
1670
+ });
1671
+ });
1672
+
1673
+ describe('processLeMetaEvent', () => {
1674
+ beforeEach(() => {
1675
+ hci.processLeConnComplete = sinon.spy();
1676
+ hci.processLeAdvertisingReport = sinon.spy();
1677
+ hci.processLeConnUpdateComplete = sinon.spy();
1678
+ });
1679
+
1680
+ it('should do nothing', () => {
1681
+ const eventType = 0;
1682
+ const status = 'status';
1683
+ const data = 'data';
1684
+
1685
+ hci.processLeMetaEvent(eventType, status, data);
1686
+
1687
+ assert.notCalled(hci.processLeConnComplete);
1688
+ assert.notCalled(hci.processLeAdvertisingReport);
1689
+ assert.notCalled(hci.processLeConnUpdateComplete);
1690
+ });
1691
+
1692
+ it('should processLeConnComplete', () => {
1693
+ const eventType = 1;
1694
+ const status = 'status';
1695
+ const data = 'data';
1696
+
1697
+ hci.processLeMetaEvent(eventType, status, data);
1698
+
1699
+ assert.calledOnceWithExactly(hci.processLeConnComplete, status, data);
1700
+ assert.notCalled(hci.processLeAdvertisingReport);
1701
+ assert.notCalled(hci.processLeConnUpdateComplete);
1702
+ });
1703
+
1704
+ it('should processLeAdvertisingReport', () => {
1705
+ const eventType = 2;
1706
+ const status = 'status';
1707
+ const data = 'data';
1708
+
1709
+ hci.processLeMetaEvent(eventType, status, data);
1710
+
1711
+ assert.calledOnceWithExactly(hci.processLeAdvertisingReport, status, data);
1712
+ assert.notCalled(hci.processLeConnComplete);
1713
+ assert.notCalled(hci.processLeConnUpdateComplete);
1714
+ });
1715
+
1716
+ it('should processLeConnUpdateComplete', () => {
1717
+ const eventType = 3;
1718
+ const status = 'status';
1719
+ const data = 'data';
1720
+
1721
+ hci.processLeMetaEvent(eventType, status, data);
1722
+
1723
+ assert.calledOnceWithExactly(hci.processLeConnUpdateComplete, status, data);
1724
+ assert.notCalled(hci.processLeConnComplete);
1725
+ assert.notCalled(hci.processLeAdvertisingReport);
1726
+ });
1727
+ });
1728
+
1729
+ it('should emit leConnComplete', () => {
1730
+ const status = 'status';
1731
+ const data = Buffer.from([0x34, 0x11, 4, 1, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 2, 1, 4, 3, 7, 8, 9]);
1732
+ const callback = sinon.spy();
1733
+
1734
+ hci.on('leConnComplete', callback);
1735
+ hci.processLeConnComplete(status, data);
1736
+
1737
+ assert.calledOnceWithExactly(callback, status, 4404, 4, 'random', 'ff:ee:dd:cc:bb:aa', 322.5, 772, 20550, 9);
1738
+ should(hci._aclConnections).keys(4404);
1739
+ should(hci._aclConnections.get(4404)).deepEqual({ pending: 0 });
1740
+ });
1741
+
1742
+ it('should emit leConnComplete on processLeEnhancedConnComplete', () => {
1743
+ const status = 'status';
1744
+ const data = Buffer.from([0x34, 0x11, 4, 1, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 2, 1, 4, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]);
1745
+ const callback = sinon.spy();
1746
+
1747
+ hci.on('leConnComplete', callback);
1748
+ hci.processLeEnhancedConnComplete(status, data);
1749
+
1750
+ assert.calledOnceWithExactly(callback, status, 4404, 4, 'random', 'ff:ee:dd:cc:bb:aa', 5138.75, 4625, 51390, 21);
1751
+ should(hci._aclConnections).keys(4404);
1752
+ should(hci._aclConnections.get(4404)).deepEqual({ pending: 0 });
1753
+ });
1754
+
1755
+ describe('processLeAdvertisingReport', () => {
1756
+ it('should emit without error', () => {
1757
+ const count = 2;
1758
+ const data1 = Buffer.from([0, 1, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 2, 3, 4, 0]);
1759
+ const data2 = Buffer.from([1, 0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 4, 3, 4, 5, 6, 7]);
1760
+ const data = Buffer.concat([data1, data2]);
1761
+ const callback = sinon.spy();
1762
+
1763
+ hci.on('leAdvertisingReport', callback);
1764
+ hci.processLeAdvertisingReport(count, data);
1765
+
1766
+ assert.callCount(callback, 2);
1767
+ });
1768
+
1769
+ it('should emit only once with random address', () => {
1770
+ const count = 1;
1771
+ const data = Buffer.from([0, 1, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 2, 3, 4, 0]);
1772
+ const callback = sinon.spy();
1773
+
1774
+ hci.on('leAdvertisingReport', callback);
1775
+ hci.processLeAdvertisingReport(count, data);
1776
+
1777
+ assert.calledOnceWithExactly(callback, 0, 0, 'ff:ee:dd:cc:bb:aa', 'random', Buffer.from([0x03, 0x04]), 0);
1778
+ });
1779
+
1780
+ it('should emit only once with public address', () => {
1781
+ const count = 1;
1782
+ const data = Buffer.from([1, 0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 4, 3, 4, 5, 6, 7]);
1783
+ const callback = sinon.spy();
1784
+
1785
+ hci.on('leAdvertisingReport', callback);
1786
+ hci.processLeAdvertisingReport(count, data);
1787
+
1788
+ assert.calledOnceWithExactly(callback, 0, 1, 'aa:bb:cc:dd:ee:ff', 'public', Buffer.from([0x03, 0x04, 0x05, 0x06]), 7);
1789
+ });
1790
+
1791
+ it('should catch error', () => {
1792
+ const count = 1;
1793
+ const data = Buffer.from([1, 0, 0xff, 0xee]);
1794
+ const callback = sinon.spy();
1795
+
1796
+ hci.on('leAdvertisingReport', callback);
1797
+ hci.processLeAdvertisingReport(count, data);
1798
+
1799
+ assert.notCalled(callback);
1800
+ });
1801
+ });
1802
+
1803
+ describe('processLeExtendedAdvertisingReport', () => {
1804
+ it('should emit without error', () => {
1805
+ const count = 2;
1806
+ const data1 = Buffer.from([0, 1, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0]);
1807
+ const data2 = Buffer.from([1, 0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 4, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]);
1808
+ const data = Buffer.concat([data1, data2]);
1809
+ const callback = sinon.spy();
1810
+
1811
+ hci.on('leExtendedAdvertisingReport', callback);
1812
+ hci.processLeExtendedAdvertisingReport(count, data);
1813
+
1814
+ assert.callCount(callback, 2);
1815
+ });
1816
+
1817
+ it('should emit only once with random address', () => {
1818
+ const count = 1;
1819
+ const data = Buffer.from([0, 1, 1, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]);
1820
+ const callback = sinon.spy();
1821
+
1822
+ hci.on('leExtendedAdvertisingReport', callback);
1823
+ hci.processLeExtendedAdvertisingReport(count, data);
1824
+
1825
+ assert.calledOnceWithExactly(callback, 0, 256, 'ff:ee:dd:cc:bb:aa', 'random', 5, 6, Buffer.from([0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17]));
1826
+ });
1827
+
1828
+ it('should emit only once with public address', () => {
1829
+ const count = 1;
1830
+ const data = Buffer.from([0, 1, 2, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]);
1831
+ const callback = sinon.spy();
1832
+
1833
+ hci.on('leExtendedAdvertisingReport', callback);
1834
+ hci.processLeExtendedAdvertisingReport(count, data);
1835
+
1836
+ assert.calledOnceWithExactly(callback, 0, 256, 'aa:bb:cc:dd:ee:ff', 'public', 5, 6, Buffer.from([0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17]));
1837
+ });
1838
+
1839
+ it('should catch error', () => {
1840
+ const count = 1;
1841
+ const data = Buffer.from([1, 0, 0xff, 0xee]);
1842
+ const callback = sinon.spy();
1843
+
1844
+ hci.on('leExtendedAdvertisingReport', callback);
1845
+ hci.processLeExtendedAdvertisingReport(count, data);
1846
+
1847
+ assert.notCalled(callback);
1848
+ });
1849
+ });
1850
+
1851
+ it('processLeConnUpdateComplete', () => {
1852
+ const callback = sinon.spy();
1853
+ hci.on('leConnUpdateComplete', callback);
1854
+ hci.processLeConnUpdateComplete('status', Buffer.from(([1, 0, 2, 0, 3, 0, 4, 0])));
1855
+
1856
+ assert.calledOnceWithExactly(callback, 'status', 1, 2.5, 3, 40);
1857
+ });
1858
+
1859
+ describe('processCmdStatusEvent', () => {
1860
+ it('should do nothing on bad cmd', () => {
1861
+ const callback = sinon.spy();
1862
+ hci.on('leConnComplete', callback);
1863
+ hci.processCmdStatusEvent(8206, 'status');
1864
+
1865
+ assert.notCalled(callback);
1866
+ });
1867
+
1868
+ [8205, 8259].forEach((cmd) => {
1869
+ it(`should do nothing on bad status - cmd = ${cmd}`, () => {
1870
+ const callback = sinon.spy();
1871
+ hci.on('leConnComplete', callback);
1872
+ hci.processCmdStatusEvent(cmd, 0);
1873
+
1874
+ assert.notCalled(callback);
1875
+ });
1876
+
1877
+ it(`should emit event - cmd = ${cmd}`, () => {
1878
+ const callback = sinon.spy();
1879
+ hci.on('leConnComplete', callback);
1880
+ hci.processCmdStatusEvent(cmd, 'status');
1881
+
1882
+ assert.calledOnceWithExactly(callback, 'status');
1883
+ });
1884
+ });
1885
+ });
1886
+
1887
+ it('should change state', () => {
1888
+ hci.onStateChange('newState');
1889
+ should(hci._state).equal('newState');
1890
+ });
1891
+ });