@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.
- package/.editorconfig +11 -0
- package/.eslintrc.js +25 -0
- package/.github/FUNDING.yml +2 -0
- package/.github/workflows/fediverse-action.yml +16 -0
- package/.github/workflows/nodepackage.yml +77 -0
- package/.github/workflows/npm-publish.yml +26 -0
- package/.github/workflows/prebuild.yml +65 -0
- package/.nycrc.json +4 -0
- package/CHANGELOG.md +119 -0
- package/LICENSE +20 -0
- package/MAINTAINERS.md +1 -0
- package/README.md +833 -0
- package/assets/noble-logo.png +0 -0
- package/assets/noble-logo.svg +13 -0
- package/binding.gyp +19 -0
- package/codecov.yml +5 -0
- package/examples/advertisement-discovery.js +65 -0
- package/examples/cache-gatt-discovery.js +198 -0
- package/examples/cache-gatt-reconnect.js +164 -0
- package/examples/echo.js +104 -0
- package/examples/enter-exit.js +78 -0
- package/examples/peripheral-explorer-async.js +133 -0
- package/examples/peripheral-explorer.js +225 -0
- package/examples/pizza/README.md +15 -0
- package/examples/pizza/central.js +194 -0
- package/examples/pizza/pizza.js +60 -0
- package/index.d.ts +203 -0
- package/index.js +6 -0
- package/lib/characteristic.js +161 -0
- package/lib/characteristics.json +449 -0
- package/lib/descriptor.js +72 -0
- package/lib/descriptors.json +47 -0
- package/lib/distributed/bindings.js +326 -0
- package/lib/hci-socket/acl-stream.js +60 -0
- package/lib/hci-socket/bindings.js +788 -0
- package/lib/hci-socket/crypto.js +74 -0
- package/lib/hci-socket/gap.js +432 -0
- package/lib/hci-socket/gatt.js +809 -0
- package/lib/hci-socket/hci-status.json +71 -0
- package/lib/hci-socket/hci.js +1264 -0
- package/lib/hci-socket/signaling.js +76 -0
- package/lib/hci-socket/smp.js +140 -0
- package/lib/hci-uart/bindings.js +569 -0
- package/lib/hci-uart/hci-serial-parser.js +70 -0
- package/lib/hci-uart/hci.js +1336 -0
- package/lib/mac/binding.gyp +26 -0
- package/lib/mac/bindings.js +11 -0
- package/lib/mac/src/ble_manager.h +41 -0
- package/lib/mac/src/ble_manager.mm +435 -0
- package/lib/mac/src/callbacks.cc +222 -0
- package/lib/mac/src/callbacks.h +84 -0
- package/lib/mac/src/napi_objc.h +12 -0
- package/lib/mac/src/napi_objc.mm +50 -0
- package/lib/mac/src/noble_mac.h +34 -0
- package/lib/mac/src/noble_mac.mm +264 -0
- package/lib/mac/src/objc_cpp.h +26 -0
- package/lib/mac/src/objc_cpp.mm +126 -0
- package/lib/mac/src/peripheral.h +23 -0
- package/lib/manufacture.js +48 -0
- package/lib/noble.js +593 -0
- package/lib/peripheral.js +219 -0
- package/lib/resolve-bindings-web.js +9 -0
- package/lib/resolve-bindings.js +44 -0
- package/lib/service.js +72 -0
- package/lib/services.json +92 -0
- package/lib/webbluetooth/bindings.js +368 -0
- package/lib/websocket/bindings.js +321 -0
- package/lib/win/binding.gyp +23 -0
- package/lib/win/bindings.js +11 -0
- package/lib/win/src/ble_manager.cc +802 -0
- package/lib/win/src/ble_manager.h +77 -0
- package/lib/win/src/callbacks.cc +274 -0
- package/lib/win/src/callbacks.h +33 -0
- package/lib/win/src/napi_winrt.cc +76 -0
- package/lib/win/src/napi_winrt.h +12 -0
- package/lib/win/src/noble_winrt.cc +308 -0
- package/lib/win/src/noble_winrt.h +34 -0
- package/lib/win/src/notify_map.cc +62 -0
- package/lib/win/src/notify_map.h +50 -0
- package/lib/win/src/peripheral.h +23 -0
- package/lib/win/src/peripheral_winrt.cc +296 -0
- package/lib/win/src/peripheral_winrt.h +82 -0
- package/lib/win/src/radio_watcher.cc +125 -0
- package/lib/win/src/radio_watcher.h +61 -0
- package/lib/win/src/winrt_cpp.cc +82 -0
- package/lib/win/src/winrt_cpp.h +11 -0
- package/lib/win/src/winrt_guid.cc +12 -0
- package/lib/win/src/winrt_guid.h +13 -0
- package/misc/nrf52840dk.hex +6921 -0
- package/misc/prj.conf +43 -0
- package/package.json +96 -0
- package/test/lib/characteristic.test.js +791 -0
- package/test/lib/descriptor.test.js +249 -0
- package/test/lib/distributed/bindings.test.js +918 -0
- package/test/lib/hci-socket/acl-stream.test.js +188 -0
- package/test/lib/hci-socket/bindings.test.js +1756 -0
- package/test/lib/hci-socket/crypto.test.js +55 -0
- package/test/lib/hci-socket/gap.test.js +1089 -0
- package/test/lib/hci-socket/gatt.test.js +2392 -0
- package/test/lib/hci-socket/hci.test.js +1891 -0
- package/test/lib/hci-socket/signaling.test.js +94 -0
- package/test/lib/hci-socket/smp.test.js +268 -0
- package/test/lib/manufacture.test.js +77 -0
- package/test/lib/peripheral.test.js +623 -0
- package/test/lib/resolve-bindings.test.js +102 -0
- package/test/lib/service.test.js +195 -0
- package/test/lib/webbluetooth/bindings.test.js +190 -0
- package/test/lib/websocket/bindings.test.js +456 -0
- package/test/noble.test.js +1565 -0
- package/test.js +131 -0
- package/with-bindings.js +5 -0
- package/ws-slave.js +404 -0
|
@@ -0,0 +1,1565 @@
|
|
|
1
|
+
const should = require('should');
|
|
2
|
+
const sinon = require('sinon');
|
|
3
|
+
|
|
4
|
+
const { assert } = sinon;
|
|
5
|
+
|
|
6
|
+
const Noble = require('../lib/noble');
|
|
7
|
+
const Peripheral = require('../lib/peripheral');
|
|
8
|
+
const Service = require('../lib/service');
|
|
9
|
+
const Characteristic = require('../lib/characteristic');
|
|
10
|
+
const Descriptor = require('../lib/descriptor');
|
|
11
|
+
|
|
12
|
+
describe('noble', () => {
|
|
13
|
+
/**
|
|
14
|
+
* @type {Noble & import('events').EventEmitter}
|
|
15
|
+
*/
|
|
16
|
+
let noble;
|
|
17
|
+
let mockBindings;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
mockBindings = {
|
|
21
|
+
init: () => {},
|
|
22
|
+
on: () => {}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
noble = new Noble(mockBindings);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('startScanning', () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
mockBindings.startScanning = sinon.spy();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
sinon.reset();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should emit warning due to serviceUuids', () => {
|
|
38
|
+
const callback = sinon.spy();
|
|
39
|
+
const eventCallback = sinon.spy();
|
|
40
|
+
const expectedAllowDuplicates = true;
|
|
41
|
+
noble.on('warning', eventCallback);
|
|
42
|
+
|
|
43
|
+
noble.startScanning(callback, expectedAllowDuplicates);
|
|
44
|
+
noble.emit('stateChange', 'poweredOn');
|
|
45
|
+
// Check for single callback
|
|
46
|
+
noble.emit('stateChange', 'poweredOn');
|
|
47
|
+
noble.emit('scanStart');
|
|
48
|
+
// Check for single callback
|
|
49
|
+
noble.emit('scanStart');
|
|
50
|
+
|
|
51
|
+
assert.calledOnceWithExactly(
|
|
52
|
+
mockBindings.startScanning,
|
|
53
|
+
callback,
|
|
54
|
+
expectedAllowDuplicates
|
|
55
|
+
);
|
|
56
|
+
assert.calledOnceWithExactly(
|
|
57
|
+
eventCallback,
|
|
58
|
+
'calling startScanning(callback) is deprecated'
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should emit warning due to allowDuplicates', () => {
|
|
63
|
+
const callback = sinon.spy();
|
|
64
|
+
const eventCallback = sinon.spy();
|
|
65
|
+
const expectedServiceUuids = [1, 2, 3];
|
|
66
|
+
noble.on('warning', eventCallback);
|
|
67
|
+
|
|
68
|
+
noble.startScanning(expectedServiceUuids, callback);
|
|
69
|
+
noble.emit('stateChange', 'poweredOn');
|
|
70
|
+
// Check for single callback
|
|
71
|
+
noble.emit('stateChange', 'poweredOn');
|
|
72
|
+
noble.emit('scanStart');
|
|
73
|
+
// Check for single callback
|
|
74
|
+
noble.emit('scanStart');
|
|
75
|
+
|
|
76
|
+
assert.calledOnceWithExactly(
|
|
77
|
+
mockBindings.startScanning,
|
|
78
|
+
expectedServiceUuids,
|
|
79
|
+
callback
|
|
80
|
+
);
|
|
81
|
+
assert.calledOnceWithExactly(
|
|
82
|
+
eventCallback,
|
|
83
|
+
'calling startScanning(serviceUuids, callback) is deprecated'
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should delegate to binding', () => {
|
|
88
|
+
const expectedServiceUuids = [1, 2, 3];
|
|
89
|
+
const expectedAllowDuplicates = true;
|
|
90
|
+
|
|
91
|
+
noble.startScanning(expectedServiceUuids, expectedAllowDuplicates);
|
|
92
|
+
noble.emit('stateChange', 'poweredOn');
|
|
93
|
+
// Check for single callback
|
|
94
|
+
noble.emit('stateChange', 'poweredOn');
|
|
95
|
+
noble.emit('scanStart');
|
|
96
|
+
// Check for single callback
|
|
97
|
+
noble.emit('scanStart');
|
|
98
|
+
|
|
99
|
+
assert.calledOnceWithExactly(
|
|
100
|
+
mockBindings.startScanning,
|
|
101
|
+
expectedServiceUuids,
|
|
102
|
+
expectedAllowDuplicates
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should delegate to callback', async () => {
|
|
107
|
+
const expectedServiceUuids = [1, 2, 3];
|
|
108
|
+
const expectedAllowDuplicates = true;
|
|
109
|
+
const callback = sinon.spy();
|
|
110
|
+
|
|
111
|
+
noble.startScanning(
|
|
112
|
+
expectedServiceUuids,
|
|
113
|
+
expectedAllowDuplicates,
|
|
114
|
+
callback
|
|
115
|
+
);
|
|
116
|
+
noble.emit('stateChange', 'poweredOn');
|
|
117
|
+
// Check for single callback
|
|
118
|
+
noble.emit('stateChange', 'poweredOn');
|
|
119
|
+
noble.emit('scanStart');
|
|
120
|
+
// Check for single callback
|
|
121
|
+
noble.emit('scanStart');
|
|
122
|
+
|
|
123
|
+
assert.calledOnceWithExactly(callback, null, undefined);
|
|
124
|
+
assert.calledOnceWithExactly(
|
|
125
|
+
mockBindings.startScanning,
|
|
126
|
+
expectedServiceUuids,
|
|
127
|
+
expectedAllowDuplicates
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should delegate to callback, already initialized', async () => {
|
|
132
|
+
noble.initialized = true;
|
|
133
|
+
noble._state = 'poweredOn';
|
|
134
|
+
|
|
135
|
+
noble.startScanning();
|
|
136
|
+
|
|
137
|
+
assert.calledOnceWithExactly(
|
|
138
|
+
mockBindings.startScanning,
|
|
139
|
+
undefined,
|
|
140
|
+
undefined
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should delegate to callback with filter', async () => {
|
|
145
|
+
const expectedServiceUuids = [1, 2, 3];
|
|
146
|
+
const expectedAllowDuplicates = true;
|
|
147
|
+
const callback = sinon.spy();
|
|
148
|
+
|
|
149
|
+
noble.startScanning(
|
|
150
|
+
expectedServiceUuids,
|
|
151
|
+
expectedAllowDuplicates,
|
|
152
|
+
callback
|
|
153
|
+
);
|
|
154
|
+
noble.emit('stateChange', 'poweredOn');
|
|
155
|
+
// Check for single callback
|
|
156
|
+
noble.emit('stateChange', 'poweredOn');
|
|
157
|
+
noble.emit('scanStart', 'filter');
|
|
158
|
+
|
|
159
|
+
assert.calledOnceWithExactly(callback, null, 'filter');
|
|
160
|
+
assert.calledOnceWithExactly(
|
|
161
|
+
mockBindings.startScanning,
|
|
162
|
+
expectedServiceUuids,
|
|
163
|
+
expectedAllowDuplicates
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should throw an error if not powered on', async () => {
|
|
168
|
+
try {
|
|
169
|
+
noble.startScanning();
|
|
170
|
+
noble.emit('stateChange', 'poweredOff');
|
|
171
|
+
// Check for single callback
|
|
172
|
+
noble.emit('stateChange', 'poweredOff');
|
|
173
|
+
noble.emit('scanStart');
|
|
174
|
+
// Check for single callback
|
|
175
|
+
noble.emit('scanStart');
|
|
176
|
+
|
|
177
|
+
assert.fail();
|
|
178
|
+
} catch (e) {
|
|
179
|
+
should(e.message).equal(
|
|
180
|
+
'Could not start scanning, state is poweredOff (not poweredOn)'
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
assert.notCalled(mockBindings.startScanning);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe('startScanningAsync', () => {
|
|
188
|
+
beforeEach(() => {
|
|
189
|
+
mockBindings.startScanning = sinon.spy();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
afterEach(() => {
|
|
193
|
+
sinon.reset();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('should delegate to binding', async () => {
|
|
197
|
+
const expectedServiceUuids = [1, 2, 3];
|
|
198
|
+
const expectedAllowDuplicates = true;
|
|
199
|
+
|
|
200
|
+
const promise = noble.startScanningAsync(
|
|
201
|
+
expectedServiceUuids,
|
|
202
|
+
expectedAllowDuplicates
|
|
203
|
+
);
|
|
204
|
+
noble.emit('stateChange', 'poweredOn');
|
|
205
|
+
// Check for single callback
|
|
206
|
+
noble.emit('stateChange', 'poweredOn');
|
|
207
|
+
noble.emit('scanStart');
|
|
208
|
+
// Check for single callback
|
|
209
|
+
noble.emit('scanStart');
|
|
210
|
+
|
|
211
|
+
should(promise).resolvedWith(undefined);
|
|
212
|
+
assert.calledOnceWithExactly(
|
|
213
|
+
mockBindings.startScanning,
|
|
214
|
+
expectedServiceUuids,
|
|
215
|
+
expectedAllowDuplicates
|
|
216
|
+
);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('should throw an error if not powered on', async () => {
|
|
220
|
+
const promise = noble.startScanningAsync();
|
|
221
|
+
noble.emit('stateChange', 'poweredOff');
|
|
222
|
+
// Check for single callback
|
|
223
|
+
noble.emit('stateChange', 'poweredOff');
|
|
224
|
+
noble.emit('scanStart');
|
|
225
|
+
// Check for single callback
|
|
226
|
+
noble.emit('scanStart');
|
|
227
|
+
|
|
228
|
+
should(promise).rejectedWith(
|
|
229
|
+
'Could not start scanning, state is poweredOff (not poweredOn)'
|
|
230
|
+
);
|
|
231
|
+
assert.notCalled(mockBindings.startScanning);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe('stopScanning', () => {
|
|
236
|
+
beforeEach(() => {
|
|
237
|
+
mockBindings.stopScanning = sinon.spy();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
afterEach(() => {
|
|
241
|
+
sinon.reset();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('should no callback', async () => {
|
|
245
|
+
noble.initialized = true;
|
|
246
|
+
noble.stopScanning();
|
|
247
|
+
assert.calledOnceWithExactly(mockBindings.stopScanning);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
describe('stopScanningAsync', () => {
|
|
252
|
+
beforeEach(() => {
|
|
253
|
+
mockBindings.stopScanning = sinon.spy();
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
afterEach(() => {
|
|
257
|
+
sinon.reset();
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it('should not delegate to binding (not initialized)', async () => {
|
|
261
|
+
const promise = noble.stopScanningAsync();
|
|
262
|
+
noble.emit('scanStop');
|
|
263
|
+
|
|
264
|
+
should(promise).resolvedWith(undefined);
|
|
265
|
+
assert.notCalled(mockBindings.stopScanning);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('should delegate to binding (initilazed)', async () => {
|
|
269
|
+
noble.initialized = true;
|
|
270
|
+
const promise = noble.stopScanningAsync();
|
|
271
|
+
noble.emit('scanStop');
|
|
272
|
+
|
|
273
|
+
should(promise).resolvedWith(undefined);
|
|
274
|
+
assert.calledOnceWithExactly(mockBindings.stopScanning);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
describe('connect', () => {
|
|
279
|
+
beforeEach(() => {
|
|
280
|
+
mockBindings.connect = sinon.spy();
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
afterEach(() => {
|
|
284
|
+
sinon.reset();
|
|
285
|
+
});
|
|
286
|
+
it('should delegate to binding', () => {
|
|
287
|
+
const peripheralUuid = 'peripheral-uuid';
|
|
288
|
+
const parameters = {};
|
|
289
|
+
|
|
290
|
+
noble.connect(peripheralUuid, parameters);
|
|
291
|
+
|
|
292
|
+
assert.calledOnceWithExactly(
|
|
293
|
+
mockBindings.connect,
|
|
294
|
+
peripheralUuid,
|
|
295
|
+
parameters
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
describe('onConnect', () => {
|
|
301
|
+
it('should emit connected on existing peripheral', () => {
|
|
302
|
+
const emit = sinon.spy();
|
|
303
|
+
noble._peripherals = {
|
|
304
|
+
uuid: { emit }
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const warningCallback = sinon.spy();
|
|
308
|
+
|
|
309
|
+
noble.on('warning', warningCallback);
|
|
310
|
+
noble.onConnect('uuid', false);
|
|
311
|
+
|
|
312
|
+
assert.calledOnceWithExactly(emit, 'connect', false);
|
|
313
|
+
assert.notCalled(warningCallback);
|
|
314
|
+
|
|
315
|
+
should(noble._peripherals).deepEqual({
|
|
316
|
+
uuid: { state: 'connected', emit }
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('should emit error on existing peripheral', () => {
|
|
321
|
+
const emit = sinon.spy();
|
|
322
|
+
noble._peripherals = {
|
|
323
|
+
uuid: { emit }
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const warningCallback = sinon.spy();
|
|
327
|
+
|
|
328
|
+
noble.on('warning', warningCallback);
|
|
329
|
+
noble.onConnect('uuid', true);
|
|
330
|
+
|
|
331
|
+
assert.calledOnceWithExactly(emit, 'connect', true);
|
|
332
|
+
assert.notCalled(warningCallback);
|
|
333
|
+
|
|
334
|
+
should(noble._peripherals).deepEqual({
|
|
335
|
+
uuid: { state: 'error', emit }
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('should emit warning on missing peripheral', () => {
|
|
340
|
+
const warningCallback = sinon.spy();
|
|
341
|
+
|
|
342
|
+
noble.on('warning', warningCallback);
|
|
343
|
+
noble.onConnect('uuid', true);
|
|
344
|
+
|
|
345
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid connected!');
|
|
346
|
+
|
|
347
|
+
should(noble._peripherals).deepEqual({});
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
describe('setScanParameters', () => {
|
|
352
|
+
beforeEach(() => {
|
|
353
|
+
mockBindings.setScanParameters = sinon.spy();
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
afterEach(() => {
|
|
357
|
+
sinon.reset();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it('should delegate to binding', async () => {
|
|
361
|
+
const interval = 'interval';
|
|
362
|
+
const window = 'window';
|
|
363
|
+
|
|
364
|
+
noble.setScanParameters(interval, window);
|
|
365
|
+
noble.emit('scanParametersSet');
|
|
366
|
+
|
|
367
|
+
assert.calledOnceWithExactly(
|
|
368
|
+
mockBindings.setScanParameters,
|
|
369
|
+
interval,
|
|
370
|
+
window
|
|
371
|
+
);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('should delegate to callback too', async () => {
|
|
375
|
+
const interval = 'interval';
|
|
376
|
+
const window = 'window';
|
|
377
|
+
const callback = sinon.spy();
|
|
378
|
+
|
|
379
|
+
noble.setScanParameters(interval, window, callback);
|
|
380
|
+
noble.emit('scanParametersSet');
|
|
381
|
+
// Check for single callback
|
|
382
|
+
noble.emit('scanParametersSet');
|
|
383
|
+
|
|
384
|
+
assert.calledOnceWithExactly(
|
|
385
|
+
mockBindings.setScanParameters,
|
|
386
|
+
interval,
|
|
387
|
+
window
|
|
388
|
+
);
|
|
389
|
+
assert.calledOnceWithExactly(callback);
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
describe('cancelConnect', () => {
|
|
394
|
+
beforeEach(() => {
|
|
395
|
+
mockBindings.cancelConnect = sinon.spy();
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
afterEach(() => {
|
|
399
|
+
sinon.reset();
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('should delegate to binding', () => {
|
|
403
|
+
const peripheralUuid = 'peripheral-uuid';
|
|
404
|
+
const parameters = {};
|
|
405
|
+
|
|
406
|
+
noble.cancelConnect(peripheralUuid, parameters);
|
|
407
|
+
|
|
408
|
+
assert.calledOnceWithExactly(
|
|
409
|
+
mockBindings.cancelConnect,
|
|
410
|
+
peripheralUuid,
|
|
411
|
+
parameters
|
|
412
|
+
);
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('should emit state', () => {
|
|
417
|
+
const callback = sinon.spy();
|
|
418
|
+
noble.on('stateChange', callback);
|
|
419
|
+
|
|
420
|
+
const state = 'newState';
|
|
421
|
+
noble.onStateChange(state);
|
|
422
|
+
|
|
423
|
+
should(noble._state).equal(state);
|
|
424
|
+
assert.calledOnceWithExactly(callback, state);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('should change address', () => {
|
|
428
|
+
const address = 'newAddress';
|
|
429
|
+
noble.onAddressChange(address);
|
|
430
|
+
|
|
431
|
+
should(noble.address).equal(address);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
it('should emit scanParametersSet event', () => {
|
|
435
|
+
const callback = sinon.spy();
|
|
436
|
+
noble.on('scanParametersSet', callback);
|
|
437
|
+
|
|
438
|
+
noble.onScanParametersSet();
|
|
439
|
+
|
|
440
|
+
assert.calledOnceWithExactly(callback);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it('should emit scanStart event', () => {
|
|
444
|
+
const callback = sinon.spy();
|
|
445
|
+
noble.on('scanStart', callback);
|
|
446
|
+
|
|
447
|
+
noble.onScanStart('filterDuplicates');
|
|
448
|
+
|
|
449
|
+
assert.calledOnceWithExactly(callback, 'filterDuplicates');
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it('should emit scanStop event', () => {
|
|
453
|
+
const callback = sinon.spy();
|
|
454
|
+
noble.on('scanStop', callback);
|
|
455
|
+
|
|
456
|
+
noble.onScanStop();
|
|
457
|
+
|
|
458
|
+
assert.calledOnceWithExactly(callback);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
describe('reset', () => {
|
|
462
|
+
beforeEach(() => {
|
|
463
|
+
mockBindings.reset = sinon.spy();
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
afterEach(() => {
|
|
467
|
+
sinon.reset();
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('should reset', () => {
|
|
471
|
+
noble.reset();
|
|
472
|
+
assert.calledOnceWithExactly(mockBindings.reset);
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
describe('disconnect', () => {
|
|
477
|
+
beforeEach(() => {
|
|
478
|
+
mockBindings.disconnect = sinon.spy();
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
afterEach(() => {
|
|
482
|
+
sinon.reset();
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
it('should disconnect', () => {
|
|
486
|
+
noble.disconnect('peripheralUuid');
|
|
487
|
+
assert.calledOnceWithExactly(mockBindings.disconnect, 'peripheralUuid');
|
|
488
|
+
});
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
describe('onDisconnect', () => {
|
|
492
|
+
it('should emit disconnect on existing peripheral', () => {
|
|
493
|
+
const emit = sinon.spy();
|
|
494
|
+
noble._peripherals = {
|
|
495
|
+
uuid: { emit }
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
const warningCallback = sinon.spy();
|
|
499
|
+
|
|
500
|
+
noble.on('warning', warningCallback);
|
|
501
|
+
noble.onDisconnect('uuid', false);
|
|
502
|
+
|
|
503
|
+
assert.calledOnceWithExactly(emit, 'disconnect', false);
|
|
504
|
+
assert.notCalled(warningCallback);
|
|
505
|
+
|
|
506
|
+
should(noble._peripherals).deepEqual({
|
|
507
|
+
uuid: { state: 'disconnected', emit }
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
it('should emit warning on missing peripheral', () => {
|
|
512
|
+
const warningCallback = sinon.spy();
|
|
513
|
+
|
|
514
|
+
noble.on('warning', warningCallback);
|
|
515
|
+
noble.onDisconnect('uuid', true);
|
|
516
|
+
|
|
517
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid disconnected!');
|
|
518
|
+
|
|
519
|
+
should(noble._peripherals).deepEqual({});
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
describe('onDiscover', () => {
|
|
524
|
+
beforeEach(() => {
|
|
525
|
+
mockBindings.disconnect = sinon.spy();
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
afterEach(() => {
|
|
529
|
+
sinon.reset();
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
it('should add new peripheral', () => {
|
|
533
|
+
const uuid = 'uuid';
|
|
534
|
+
const address = 'address';
|
|
535
|
+
const addressType = 'addressType';
|
|
536
|
+
const connectable = 'connectable';
|
|
537
|
+
const advertisement = [];
|
|
538
|
+
const rssi = 'rssi';
|
|
539
|
+
|
|
540
|
+
const eventCallback = sinon.spy();
|
|
541
|
+
noble.on('discover', eventCallback);
|
|
542
|
+
|
|
543
|
+
noble.onDiscover(
|
|
544
|
+
uuid,
|
|
545
|
+
address,
|
|
546
|
+
addressType,
|
|
547
|
+
connectable,
|
|
548
|
+
advertisement,
|
|
549
|
+
rssi
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
// Check new peripheral
|
|
553
|
+
should(noble._peripherals).have.keys(uuid);
|
|
554
|
+
const peripheral = noble._peripherals[uuid];
|
|
555
|
+
should(peripheral._noble).equal(noble);
|
|
556
|
+
should(peripheral.id).equal(uuid);
|
|
557
|
+
should(peripheral.address).equal(address);
|
|
558
|
+
should(peripheral.addressType).equal(addressType);
|
|
559
|
+
should(peripheral.connectable).equal(connectable);
|
|
560
|
+
should(peripheral.advertisement).equal(advertisement);
|
|
561
|
+
should(peripheral.rssi).equal(rssi);
|
|
562
|
+
|
|
563
|
+
should(noble._services).have.keys(uuid);
|
|
564
|
+
should(noble._characteristics).have.keys(uuid);
|
|
565
|
+
should(noble._descriptors).have.keys(uuid);
|
|
566
|
+
should(noble._discoveredPeripheralUUids).deepEqual([uuid]);
|
|
567
|
+
|
|
568
|
+
assert.calledOnceWithExactly(eventCallback, peripheral);
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
it('should update existing peripheral', () => {
|
|
572
|
+
const uuid = 'uuid';
|
|
573
|
+
const address = 'address';
|
|
574
|
+
const addressType = 'addressType';
|
|
575
|
+
const connectable = 'connectable';
|
|
576
|
+
const advertisement = [undefined, 'adv2', 'adv3'];
|
|
577
|
+
const rssi = 'rssi';
|
|
578
|
+
|
|
579
|
+
// init peripheral
|
|
580
|
+
noble._peripherals[uuid] = new Peripheral(
|
|
581
|
+
noble,
|
|
582
|
+
uuid,
|
|
583
|
+
'originalAddress',
|
|
584
|
+
'originalAddressType',
|
|
585
|
+
'originalConnectable',
|
|
586
|
+
['adv1'],
|
|
587
|
+
'originalRssi'
|
|
588
|
+
);
|
|
589
|
+
|
|
590
|
+
const eventCallback = sinon.spy();
|
|
591
|
+
noble.on('discover', eventCallback);
|
|
592
|
+
|
|
593
|
+
noble.onDiscover(
|
|
594
|
+
uuid,
|
|
595
|
+
address,
|
|
596
|
+
addressType,
|
|
597
|
+
connectable,
|
|
598
|
+
advertisement,
|
|
599
|
+
rssi
|
|
600
|
+
);
|
|
601
|
+
|
|
602
|
+
// Check new peripheral
|
|
603
|
+
should(noble._peripherals).have.keys(uuid);
|
|
604
|
+
const peripheral = noble._peripherals[uuid];
|
|
605
|
+
should(peripheral._noble).equal(noble);
|
|
606
|
+
should(peripheral.id).equal(uuid);
|
|
607
|
+
should(peripheral.address).equal('originalAddress');
|
|
608
|
+
should(peripheral.addressType).equal('originalAddressType');
|
|
609
|
+
should(peripheral.connectable).equal(connectable);
|
|
610
|
+
should(peripheral.advertisement).deepEqual(['adv1', 'adv2', 'adv3']);
|
|
611
|
+
should(peripheral.rssi).equal(rssi);
|
|
612
|
+
|
|
613
|
+
should(noble._services).be.empty();
|
|
614
|
+
should(noble._characteristics).be.empty();
|
|
615
|
+
should(noble._descriptors).be.empty();
|
|
616
|
+
should(noble._discoveredPeripheralUUids).deepEqual([uuid]);
|
|
617
|
+
|
|
618
|
+
assert.calledOnceWithExactly(eventCallback, peripheral);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it('should emit on duplicate', () => {
|
|
622
|
+
const uuid = 'uuid';
|
|
623
|
+
const address = 'address';
|
|
624
|
+
const addressType = 'addressType';
|
|
625
|
+
const connectable = 'connectable';
|
|
626
|
+
const advertisement = ['adv1', 'adv2', 'adv3'];
|
|
627
|
+
const rssi = 'rssi';
|
|
628
|
+
|
|
629
|
+
// register peripheral
|
|
630
|
+
noble._discoveredPeripheralUUids = [uuid];
|
|
631
|
+
noble._allowDuplicates = true;
|
|
632
|
+
|
|
633
|
+
const eventCallback = sinon.spy();
|
|
634
|
+
noble.on('discover', eventCallback);
|
|
635
|
+
|
|
636
|
+
noble.onDiscover(
|
|
637
|
+
uuid,
|
|
638
|
+
address,
|
|
639
|
+
addressType,
|
|
640
|
+
connectable,
|
|
641
|
+
advertisement,
|
|
642
|
+
rssi
|
|
643
|
+
);
|
|
644
|
+
|
|
645
|
+
assert.calledOnceWithExactly(eventCallback, noble._peripherals[uuid]);
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
it('should not emit on duplicate', () => {
|
|
649
|
+
const uuid = 'uuid';
|
|
650
|
+
const address = 'address';
|
|
651
|
+
const addressType = 'addressType';
|
|
652
|
+
const connectable = 'connectable';
|
|
653
|
+
const advertisement = ['adv1', 'adv2', 'adv3'];
|
|
654
|
+
const rssi = 'rssi';
|
|
655
|
+
|
|
656
|
+
// register peripheral
|
|
657
|
+
noble._discoveredPeripheralUUids = [uuid];
|
|
658
|
+
|
|
659
|
+
const eventCallback = sinon.spy();
|
|
660
|
+
noble.on('discover', eventCallback);
|
|
661
|
+
|
|
662
|
+
noble.onDiscover(
|
|
663
|
+
uuid,
|
|
664
|
+
address,
|
|
665
|
+
addressType,
|
|
666
|
+
connectable,
|
|
667
|
+
advertisement,
|
|
668
|
+
rssi
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
assert.notCalled(eventCallback);
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
it('should emit on new peripheral (even if duplicates are disallowed)', () => {
|
|
675
|
+
const uuid = 'uuid';
|
|
676
|
+
const address = 'address';
|
|
677
|
+
const addressType = 'addressType';
|
|
678
|
+
const connectable = 'connectable';
|
|
679
|
+
const advertisement = ['adv1', 'adv2', 'adv3'];
|
|
680
|
+
const rssi = 'rssi';
|
|
681
|
+
|
|
682
|
+
const eventCallback = sinon.spy();
|
|
683
|
+
noble.on('discover', eventCallback);
|
|
684
|
+
|
|
685
|
+
noble.onDiscover(
|
|
686
|
+
uuid,
|
|
687
|
+
address,
|
|
688
|
+
addressType,
|
|
689
|
+
connectable,
|
|
690
|
+
advertisement,
|
|
691
|
+
rssi
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
assert.calledOnceWithExactly(eventCallback, noble._peripherals[uuid]);
|
|
695
|
+
});
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
describe('updateRssi', () => {
|
|
699
|
+
beforeEach(() => {
|
|
700
|
+
mockBindings.updateRssi = sinon.spy();
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
afterEach(() => {
|
|
704
|
+
sinon.reset();
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
it('should updateRssi', () => {
|
|
708
|
+
noble.updateRssi('peripheralUuid');
|
|
709
|
+
assert.calledOnceWithExactly(mockBindings.updateRssi, 'peripheralUuid');
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
describe('onRssiUpdate', () => {
|
|
714
|
+
it('should emit rssiUpdate on existing peripheral', () => {
|
|
715
|
+
const emit = sinon.spy();
|
|
716
|
+
noble._peripherals = {
|
|
717
|
+
uuid: { emit }
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
const warningCallback = sinon.spy();
|
|
721
|
+
|
|
722
|
+
noble.on('warning', warningCallback);
|
|
723
|
+
noble.onRssiUpdate('uuid', 3);
|
|
724
|
+
|
|
725
|
+
assert.calledOnceWithExactly(emit, 'rssiUpdate', 3);
|
|
726
|
+
assert.notCalled(warningCallback);
|
|
727
|
+
|
|
728
|
+
should(noble._peripherals).deepEqual({
|
|
729
|
+
uuid: { rssi: 3, emit }
|
|
730
|
+
});
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
it('should emit warning on missing peripheral', () => {
|
|
734
|
+
const warningCallback = sinon.spy();
|
|
735
|
+
|
|
736
|
+
noble.on('warning', warningCallback);
|
|
737
|
+
noble.onRssiUpdate('uuid', 4);
|
|
738
|
+
|
|
739
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid RSSI update!');
|
|
740
|
+
|
|
741
|
+
should(noble._peripherals).deepEqual({});
|
|
742
|
+
});
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
it('should add multiple services', () => {
|
|
746
|
+
noble.addService = sinon.stub().returnsArg(1);
|
|
747
|
+
|
|
748
|
+
const peripheralUuid = 'peripheralUuid';
|
|
749
|
+
const services = ['service1', 'service2'];
|
|
750
|
+
const result = noble.addServices(peripheralUuid, services);
|
|
751
|
+
|
|
752
|
+
assert.callCount(noble.addService, 2);
|
|
753
|
+
assert.calledWithExactly(noble.addService, peripheralUuid, 'service1');
|
|
754
|
+
assert.calledWithExactly(noble.addService, peripheralUuid, 'service2');
|
|
755
|
+
|
|
756
|
+
should(result).deepEqual(services);
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
describe('addService', () => {
|
|
760
|
+
const peripheralUuid = 'peripheralUuid';
|
|
761
|
+
const service = {
|
|
762
|
+
uuid: 'serviceUuid'
|
|
763
|
+
};
|
|
764
|
+
const peripheral = {};
|
|
765
|
+
|
|
766
|
+
beforeEach(() => {
|
|
767
|
+
noble._peripherals = { [peripheralUuid]: peripheral };
|
|
768
|
+
noble._services = { [peripheralUuid]: {} };
|
|
769
|
+
noble._characteristics = { [peripheralUuid]: {} };
|
|
770
|
+
noble._descriptors = { [peripheralUuid]: {} };
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
it('should add service to lower layer', () => {
|
|
774
|
+
noble._bindings.addService = sinon.spy();
|
|
775
|
+
|
|
776
|
+
const result = noble.addService(peripheralUuid, service);
|
|
777
|
+
|
|
778
|
+
assert.calledOnceWithExactly(noble._bindings.addService, peripheralUuid, service);
|
|
779
|
+
|
|
780
|
+
const expectedService = new Service(noble, peripheralUuid, service.uuid);
|
|
781
|
+
should(result).deepEqual(expectedService);
|
|
782
|
+
should(peripheral.services).deepEqual([expectedService]);
|
|
783
|
+
should(noble._services).deepEqual({
|
|
784
|
+
[peripheralUuid]: {
|
|
785
|
+
[service.uuid]: expectedService
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
should(noble._characteristics).deepEqual({
|
|
789
|
+
[peripheralUuid]: {
|
|
790
|
+
[service.uuid]: {}
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
should(noble._descriptors).deepEqual({
|
|
794
|
+
[peripheralUuid]: {
|
|
795
|
+
[service.uuid]: {}
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
it('should add service only to noble', () => {
|
|
801
|
+
peripheral.services = [];
|
|
802
|
+
|
|
803
|
+
const result = noble.addService(peripheralUuid, service);
|
|
804
|
+
|
|
805
|
+
const expectedService = new Service(noble, peripheralUuid, service.uuid);
|
|
806
|
+
should(result).deepEqual(expectedService);
|
|
807
|
+
should(peripheral.services).deepEqual([expectedService]);
|
|
808
|
+
should(noble._services).deepEqual({
|
|
809
|
+
[peripheralUuid]: {
|
|
810
|
+
[service.uuid]: expectedService
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
should(noble._characteristics).deepEqual({
|
|
814
|
+
[peripheralUuid]: {
|
|
815
|
+
[service.uuid]: {}
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
should(noble._descriptors).deepEqual({
|
|
819
|
+
[peripheralUuid]: {
|
|
820
|
+
[service.uuid]: {}
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
});
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
describe('onServicesDiscovered', () => {
|
|
827
|
+
const peripheralUuid = 'peripheralUuid';
|
|
828
|
+
const services = ['service1', 'service2'];
|
|
829
|
+
|
|
830
|
+
it('should not emit servicesDiscovered', () => {
|
|
831
|
+
const callback = sinon.spy();
|
|
832
|
+
noble.on('servicesDiscovered', callback);
|
|
833
|
+
|
|
834
|
+
noble.onServicesDiscovered(peripheralUuid, services);
|
|
835
|
+
|
|
836
|
+
assert.notCalled(callback);
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
it('should emit servicesDiscovered', () => {
|
|
840
|
+
const emit = sinon.spy();
|
|
841
|
+
noble._peripherals = { [peripheralUuid]: { uuid: 'peripheral', emit } };
|
|
842
|
+
|
|
843
|
+
noble.onServicesDiscovered(peripheralUuid, services);
|
|
844
|
+
|
|
845
|
+
assert.calledOnceWithExactly(emit, 'servicesDiscovered', { uuid: 'peripheral', emit }, services);
|
|
846
|
+
});
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
it('discoverServices - should delegate to bindings', () => {
|
|
850
|
+
noble._bindings.discoverServices = sinon.spy();
|
|
851
|
+
noble.discoverServices('peripheral', 'uuids');
|
|
852
|
+
assert.calledOnceWithExactly(noble._bindings.discoverServices, 'peripheral', 'uuids');
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
describe('onServicesDiscover', () => {
|
|
856
|
+
it('should emit warning', () => {
|
|
857
|
+
const warningCallback = sinon.spy();
|
|
858
|
+
|
|
859
|
+
noble.on('warning', warningCallback);
|
|
860
|
+
|
|
861
|
+
noble.onServicesDiscover('pUuid', ['service1', 'service2']);
|
|
862
|
+
|
|
863
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral pUuid services discover!');
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
it('should emit servicesDiscover and store services', () => {
|
|
867
|
+
const warningCallback = sinon.spy();
|
|
868
|
+
const discoverCallback = sinon.spy();
|
|
869
|
+
|
|
870
|
+
const peripheralUuid = 'peripheralUuid';
|
|
871
|
+
|
|
872
|
+
noble._peripherals = { [peripheralUuid]: { emit: discoverCallback } };
|
|
873
|
+
noble._services = { [peripheralUuid]: {} };
|
|
874
|
+
noble._characteristics = { [peripheralUuid]: {} };
|
|
875
|
+
noble._descriptors = { [peripheralUuid]: {} };
|
|
876
|
+
|
|
877
|
+
noble.on('warning', warningCallback);
|
|
878
|
+
|
|
879
|
+
noble.onServicesDiscover(peripheralUuid, ['service1', 'service2']);
|
|
880
|
+
|
|
881
|
+
const services = [new Service(noble, peripheralUuid, 'service1'), new Service(noble, peripheralUuid, 'service2')];
|
|
882
|
+
|
|
883
|
+
assert.calledOnceWithExactly(discoverCallback, 'servicesDiscover', services);
|
|
884
|
+
assert.notCalled(warningCallback);
|
|
885
|
+
|
|
886
|
+
should(noble._peripherals).deepEqual({
|
|
887
|
+
[peripheralUuid]: { services, emit: discoverCallback }
|
|
888
|
+
});
|
|
889
|
+
should(noble._services).deepEqual({
|
|
890
|
+
[peripheralUuid]: { service1: services[0], service2: services[1] }
|
|
891
|
+
});
|
|
892
|
+
should(noble._characteristics).deepEqual({
|
|
893
|
+
[peripheralUuid]: { service1: {}, service2: {} }
|
|
894
|
+
});
|
|
895
|
+
should(noble._descriptors).deepEqual({
|
|
896
|
+
[peripheralUuid]: { service1: {}, service2: {} }
|
|
897
|
+
});
|
|
898
|
+
});
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
describe('discoverIncludedServices', () => {
|
|
902
|
+
beforeEach(() => {
|
|
903
|
+
mockBindings.discoverIncludedServices = sinon.spy();
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
afterEach(() => {
|
|
907
|
+
sinon.reset();
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
it('should disconnect', () => {
|
|
911
|
+
noble.discoverIncludedServices('peripheralUuid', 'serviceUuid', 'serviceUuids');
|
|
912
|
+
assert.calledOnceWithExactly(mockBindings.discoverIncludedServices, 'peripheralUuid', 'serviceUuid', 'serviceUuids');
|
|
913
|
+
});
|
|
914
|
+
});
|
|
915
|
+
|
|
916
|
+
describe('addCharacteristics', () => {
|
|
917
|
+
const peripheralUuid = 'peripheralUuid';
|
|
918
|
+
const serviceUuid = 'serviceUuid';
|
|
919
|
+
const characteristic1 = {
|
|
920
|
+
uuid: 'characteristic1',
|
|
921
|
+
properties: 'properties1'
|
|
922
|
+
};
|
|
923
|
+
const characteristic2 = {
|
|
924
|
+
uuid: 'characteristic2',
|
|
925
|
+
properties: 'properties2'
|
|
926
|
+
};
|
|
927
|
+
const characteristics = [characteristic1, characteristic2];
|
|
928
|
+
|
|
929
|
+
beforeEach(() => {
|
|
930
|
+
noble._services = { [peripheralUuid]: { [serviceUuid]: {} } };
|
|
931
|
+
noble._characteristics = { [peripheralUuid]: { [serviceUuid]: {} } };
|
|
932
|
+
noble._descriptors = { [peripheralUuid]: { [serviceUuid]: {} } };
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
it('should delegate to bindings', () => {
|
|
936
|
+
const warningCallback = sinon.spy();
|
|
937
|
+
|
|
938
|
+
noble._bindings.addCharacteristics = sinon.spy();
|
|
939
|
+
noble.on('warning', warningCallback);
|
|
940
|
+
|
|
941
|
+
const result = noble.addCharacteristics(peripheralUuid, serviceUuid, characteristics);
|
|
942
|
+
|
|
943
|
+
assert.notCalled(warningCallback);
|
|
944
|
+
assert.calledOnceWithExactly(noble._bindings.addCharacteristics, peripheralUuid, serviceUuid, characteristics);
|
|
945
|
+
|
|
946
|
+
const expectedCharacteristics = [
|
|
947
|
+
new Characteristic(noble, peripheralUuid, serviceUuid, 'characteristic1', 'properties1'),
|
|
948
|
+
new Characteristic(noble, peripheralUuid, serviceUuid, 'characteristic2', 'properties2')
|
|
949
|
+
];
|
|
950
|
+
should(result).deepEqual(expectedCharacteristics);
|
|
951
|
+
should(noble._services).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristics: expectedCharacteristics } } });
|
|
952
|
+
should(noble._characteristics).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristic1: expectedCharacteristics[0], characteristic2: expectedCharacteristics[1] } } });
|
|
953
|
+
should(noble._descriptors).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristic1: {}, characteristic2: {} } } });
|
|
954
|
+
});
|
|
955
|
+
|
|
956
|
+
it('should not delegate to bindings', () => {
|
|
957
|
+
const warningCallback = sinon.spy();
|
|
958
|
+
|
|
959
|
+
noble.on('warning', warningCallback);
|
|
960
|
+
|
|
961
|
+
const result = noble.addCharacteristics(peripheralUuid, serviceUuid, characteristics);
|
|
962
|
+
|
|
963
|
+
assert.notCalled(warningCallback);
|
|
964
|
+
|
|
965
|
+
const expectedCharacteristics = [
|
|
966
|
+
new Characteristic(noble, peripheralUuid, serviceUuid, 'characteristic1', 'properties1'),
|
|
967
|
+
new Characteristic(noble, peripheralUuid, serviceUuid, 'characteristic2', 'properties2')
|
|
968
|
+
];
|
|
969
|
+
should(result).deepEqual(expectedCharacteristics);
|
|
970
|
+
should(noble._services).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristics: expectedCharacteristics } } });
|
|
971
|
+
should(noble._characteristics).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristic1: expectedCharacteristics[0], characteristic2: expectedCharacteristics[1] } } });
|
|
972
|
+
should(noble._descriptors).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristic1: {}, characteristic2: {} } } });
|
|
973
|
+
});
|
|
974
|
+
|
|
975
|
+
it('should emit warning', () => {
|
|
976
|
+
const warningCallback = sinon.spy();
|
|
977
|
+
|
|
978
|
+
noble.on('warning', warningCallback);
|
|
979
|
+
|
|
980
|
+
noble._services = { peripheralUuid: {} };
|
|
981
|
+
const result = noble.addCharacteristics(peripheralUuid, serviceUuid, characteristics);
|
|
982
|
+
|
|
983
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown service peripheralUuid, serviceUuid characteristics discover!');
|
|
984
|
+
|
|
985
|
+
should(result).equal(undefined);
|
|
986
|
+
should(noble._services).deepEqual({ [peripheralUuid]: { } });
|
|
987
|
+
should(noble._characteristics).deepEqual({ [peripheralUuid]: { [serviceUuid]: { } } });
|
|
988
|
+
should(noble._descriptors).deepEqual({ [peripheralUuid]: { [serviceUuid]: { } } });
|
|
989
|
+
});
|
|
990
|
+
});
|
|
991
|
+
|
|
992
|
+
it('onCharacteristicsDiscovered - should emit event', () => {
|
|
993
|
+
const emit = sinon.spy();
|
|
994
|
+
|
|
995
|
+
noble._services = {
|
|
996
|
+
peripheralUuid: {
|
|
997
|
+
serviceUuid: {
|
|
998
|
+
emit
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
noble.onCharacteristicsDiscovered('peripheralUuid', 'serviceUuid', 'characteristics');
|
|
1004
|
+
|
|
1005
|
+
assert.calledOnceWithExactly(emit, 'characteristicsDiscovered', 'characteristics');
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
it('discoverCharacteristics - should delegate', () => {
|
|
1009
|
+
noble._bindings.discoverCharacteristics = sinon.spy();
|
|
1010
|
+
|
|
1011
|
+
noble.discoverCharacteristics('peripheralUuid', 'serviceUuid', 'characteristicUuids');
|
|
1012
|
+
|
|
1013
|
+
assert.calledOnceWithExactly(noble._bindings.discoverCharacteristics, 'peripheralUuid', 'serviceUuid', 'characteristicUuids');
|
|
1014
|
+
});
|
|
1015
|
+
|
|
1016
|
+
describe('onCharacteristicsDiscover', () => {
|
|
1017
|
+
it('should emit warning', () => {
|
|
1018
|
+
const warningCallback = sinon.spy();
|
|
1019
|
+
|
|
1020
|
+
const peripheralUuid = 'peripheralUuid';
|
|
1021
|
+
const serviceUuid = 'serviceUuid';
|
|
1022
|
+
const characteristics = ['characteristic1', 'characteristic2'];
|
|
1023
|
+
|
|
1024
|
+
noble.on('warning', warningCallback);
|
|
1025
|
+
|
|
1026
|
+
noble._services[peripheralUuid] = {};
|
|
1027
|
+
noble.onCharacteristicsDiscover(peripheralUuid, serviceUuid, characteristics);
|
|
1028
|
+
|
|
1029
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid characteristics discover!');
|
|
1030
|
+
});
|
|
1031
|
+
|
|
1032
|
+
it('should emit characteristicsDiscover and store characteristics', () => {
|
|
1033
|
+
const warningCallback = sinon.spy();
|
|
1034
|
+
const emit = sinon.spy();
|
|
1035
|
+
|
|
1036
|
+
const peripheralUuid = 'peripheralUuid';
|
|
1037
|
+
const serviceUuid = 'serviceUuid';
|
|
1038
|
+
const characteristics = [
|
|
1039
|
+
{ uuid: 'characteristic1', properties: 'properties1' },
|
|
1040
|
+
{ uuid: 'characteristic2', properties: 'properties2' }
|
|
1041
|
+
];
|
|
1042
|
+
|
|
1043
|
+
noble._services = { [peripheralUuid]: { [serviceUuid]: { emit } } };
|
|
1044
|
+
noble._characteristics = { [peripheralUuid]: { [serviceUuid]: {} } };
|
|
1045
|
+
noble._descriptors = { [peripheralUuid]: { [serviceUuid]: {} } };
|
|
1046
|
+
|
|
1047
|
+
noble.on('warning', warningCallback);
|
|
1048
|
+
|
|
1049
|
+
noble.onCharacteristicsDiscover(peripheralUuid, serviceUuid, characteristics);
|
|
1050
|
+
|
|
1051
|
+
const expectedCharacteristics = [
|
|
1052
|
+
new Characteristic(noble, peripheralUuid, serviceUuid, characteristics[0].uuid, characteristics[0].properties),
|
|
1053
|
+
new Characteristic(noble, peripheralUuid, serviceUuid, characteristics[1].uuid, characteristics[1].properties)
|
|
1054
|
+
];
|
|
1055
|
+
|
|
1056
|
+
assert.calledOnceWithExactly(emit, 'characteristicsDiscover', expectedCharacteristics);
|
|
1057
|
+
assert.notCalled(warningCallback);
|
|
1058
|
+
|
|
1059
|
+
should(noble._services).deepEqual({
|
|
1060
|
+
[peripheralUuid]: {
|
|
1061
|
+
[serviceUuid]: {
|
|
1062
|
+
emit, characteristics: expectedCharacteristics
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
should(noble._characteristics).deepEqual({
|
|
1067
|
+
[peripheralUuid]: {
|
|
1068
|
+
[serviceUuid]: { characteristic1: expectedCharacteristics[0], characteristic2: expectedCharacteristics[1] }
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
should(noble._descriptors).deepEqual({
|
|
1072
|
+
[peripheralUuid]: { [serviceUuid]: { characteristic1: {}, characteristic2: {} } }
|
|
1073
|
+
});
|
|
1074
|
+
});
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
it('read - should delegate to bindings', () => {
|
|
1078
|
+
noble._bindings.read = sinon.spy();
|
|
1079
|
+
noble.read('peripheralUuid', 'serviceUuid', 'characteristicUuid');
|
|
1080
|
+
assert.calledOnceWithExactly(noble._bindings.read, 'peripheralUuid', 'serviceUuid', 'characteristicUuid');
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
describe('onRead', () => {
|
|
1084
|
+
it('should emit warning', () => {
|
|
1085
|
+
const warningCallback = sinon.spy();
|
|
1086
|
+
noble.on('warning', warningCallback);
|
|
1087
|
+
|
|
1088
|
+
noble._characteristics = {
|
|
1089
|
+
peripheralUuid: {
|
|
1090
|
+
serviceUuid: {
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
noble.onRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'data', 'isNotification');
|
|
1095
|
+
|
|
1096
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid read!');
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
it('should emit data and read', () => {
|
|
1100
|
+
const warningCallback = sinon.spy();
|
|
1101
|
+
const emit = sinon.spy();
|
|
1102
|
+
|
|
1103
|
+
noble.on('warning', warningCallback);
|
|
1104
|
+
|
|
1105
|
+
noble._characteristics = {
|
|
1106
|
+
peripheralUuid: {
|
|
1107
|
+
serviceUuid: {
|
|
1108
|
+
characteristicUuid: {
|
|
1109
|
+
emit
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
noble.onRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'dataArg', 'isNotification');
|
|
1115
|
+
|
|
1116
|
+
assert.notCalled(warningCallback);
|
|
1117
|
+
assert.callCount(emit, 2);
|
|
1118
|
+
assert.calledWithExactly(emit, 'data', 'dataArg', 'isNotification');
|
|
1119
|
+
assert.calledWithExactly(emit, 'read', 'dataArg', 'isNotification');
|
|
1120
|
+
});
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
it('write - should delegate to bindings', () => {
|
|
1124
|
+
noble._bindings.write = sinon.spy();
|
|
1125
|
+
noble.write('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'dataArg', 'isNotification');
|
|
1126
|
+
assert.calledOnceWithExactly(noble._bindings.write, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'dataArg', 'isNotification');
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
describe('onWrite', () => {
|
|
1130
|
+
it('should emit warning', () => {
|
|
1131
|
+
const warningCallback = sinon.spy();
|
|
1132
|
+
noble.on('warning', warningCallback);
|
|
1133
|
+
|
|
1134
|
+
noble._characteristics = {
|
|
1135
|
+
peripheralUuid: {
|
|
1136
|
+
serviceUuid: {
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
noble.onWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid');
|
|
1141
|
+
|
|
1142
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid write!');
|
|
1143
|
+
});
|
|
1144
|
+
|
|
1145
|
+
it('should emit write', () => {
|
|
1146
|
+
const warningCallback = sinon.spy();
|
|
1147
|
+
const emit = sinon.spy();
|
|
1148
|
+
|
|
1149
|
+
noble.on('warning', warningCallback);
|
|
1150
|
+
|
|
1151
|
+
noble._characteristics = {
|
|
1152
|
+
peripheralUuid: {
|
|
1153
|
+
serviceUuid: {
|
|
1154
|
+
characteristicUuid: {
|
|
1155
|
+
emit
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
noble.onWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid');
|
|
1161
|
+
|
|
1162
|
+
assert.notCalled(warningCallback);
|
|
1163
|
+
assert.calledOnceWithExactly(emit, 'write');
|
|
1164
|
+
});
|
|
1165
|
+
});
|
|
1166
|
+
|
|
1167
|
+
it('broadcast - should delegate to bindings', () => {
|
|
1168
|
+
noble._bindings.broadcast = sinon.spy();
|
|
1169
|
+
noble.broadcast('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'broadcast');
|
|
1170
|
+
assert.calledOnceWithExactly(noble._bindings.broadcast, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'broadcast');
|
|
1171
|
+
});
|
|
1172
|
+
|
|
1173
|
+
describe('onBroadcast', () => {
|
|
1174
|
+
it('should emit warning', () => {
|
|
1175
|
+
const warningCallback = sinon.spy();
|
|
1176
|
+
noble.on('warning', warningCallback);
|
|
1177
|
+
|
|
1178
|
+
noble._characteristics = {
|
|
1179
|
+
peripheralUuid: {
|
|
1180
|
+
serviceUuid: {
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
noble.onBroadcast('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'state');
|
|
1185
|
+
|
|
1186
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid broadcast!');
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1189
|
+
it('should emit broadcast', () => {
|
|
1190
|
+
const warningCallback = sinon.spy();
|
|
1191
|
+
const emit = sinon.spy();
|
|
1192
|
+
|
|
1193
|
+
noble.on('warning', warningCallback);
|
|
1194
|
+
|
|
1195
|
+
noble._characteristics = {
|
|
1196
|
+
peripheralUuid: {
|
|
1197
|
+
serviceUuid: {
|
|
1198
|
+
characteristicUuid: {
|
|
1199
|
+
emit
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
noble.onBroadcast('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'state');
|
|
1205
|
+
|
|
1206
|
+
assert.notCalled(warningCallback);
|
|
1207
|
+
assert.calledOnceWithExactly(emit, 'broadcast', 'state');
|
|
1208
|
+
});
|
|
1209
|
+
});
|
|
1210
|
+
|
|
1211
|
+
it('notify - should delegate to bindings', () => {
|
|
1212
|
+
noble._bindings.notify = sinon.spy();
|
|
1213
|
+
noble.notify('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'notify');
|
|
1214
|
+
assert.calledOnceWithExactly(noble._bindings.notify, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'notify');
|
|
1215
|
+
});
|
|
1216
|
+
|
|
1217
|
+
describe('onNotify', () => {
|
|
1218
|
+
it('should emit warning', () => {
|
|
1219
|
+
const warningCallback = sinon.spy();
|
|
1220
|
+
noble.on('warning', warningCallback);
|
|
1221
|
+
|
|
1222
|
+
noble._characteristics = {
|
|
1223
|
+
peripheralUuid: {
|
|
1224
|
+
serviceUuid: {
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
};
|
|
1228
|
+
noble.onNotify('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'state');
|
|
1229
|
+
|
|
1230
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid notify!');
|
|
1231
|
+
});
|
|
1232
|
+
|
|
1233
|
+
it('should emit notify', () => {
|
|
1234
|
+
const warningCallback = sinon.spy();
|
|
1235
|
+
const emit = sinon.spy();
|
|
1236
|
+
|
|
1237
|
+
noble.on('warning', warningCallback);
|
|
1238
|
+
|
|
1239
|
+
noble._characteristics = {
|
|
1240
|
+
peripheralUuid: {
|
|
1241
|
+
serviceUuid: {
|
|
1242
|
+
characteristicUuid: {
|
|
1243
|
+
emit
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
};
|
|
1248
|
+
noble.onNotify('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'state');
|
|
1249
|
+
|
|
1250
|
+
assert.notCalled(warningCallback);
|
|
1251
|
+
assert.calledOnceWithExactly(emit, 'notify', 'state');
|
|
1252
|
+
});
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1255
|
+
it('discoverDescriptors - should delegate', () => {
|
|
1256
|
+
noble._bindings.discoverDescriptors = sinon.spy();
|
|
1257
|
+
|
|
1258
|
+
noble.discoverDescriptors('peripheralUuid', 'serviceUuid', 'characteristicUuid');
|
|
1259
|
+
|
|
1260
|
+
assert.calledOnceWithExactly(noble._bindings.discoverDescriptors, 'peripheralUuid', 'serviceUuid', 'characteristicUuid');
|
|
1261
|
+
});
|
|
1262
|
+
|
|
1263
|
+
describe('onDescriptorsDiscover', () => {
|
|
1264
|
+
it('should emit warning', () => {
|
|
1265
|
+
const warningCallback = sinon.spy();
|
|
1266
|
+
|
|
1267
|
+
const peripheralUuid = 'peripheralUuid';
|
|
1268
|
+
const serviceUuid = 'serviceUuid';
|
|
1269
|
+
const characteristicUuid = 'characteristicUuid';
|
|
1270
|
+
const descriptors = ['descriptor1', 'descriptor2'];
|
|
1271
|
+
|
|
1272
|
+
noble.on('warning', warningCallback);
|
|
1273
|
+
|
|
1274
|
+
noble._characteristics[peripheralUuid] = {
|
|
1275
|
+
[serviceUuid]: {}
|
|
1276
|
+
};
|
|
1277
|
+
noble.onDescriptorsDiscover(peripheralUuid, serviceUuid, characteristicUuid, descriptors);
|
|
1278
|
+
|
|
1279
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid descriptors discover!');
|
|
1280
|
+
});
|
|
1281
|
+
|
|
1282
|
+
it('should emit characteristicsDiscover and store characteristics', () => {
|
|
1283
|
+
const warningCallback = sinon.spy();
|
|
1284
|
+
const emit = sinon.spy();
|
|
1285
|
+
|
|
1286
|
+
const peripheralUuid = 'peripheralUuid';
|
|
1287
|
+
const serviceUuid = 'serviceUuid';
|
|
1288
|
+
const characteristicUuid = 'characteristicUuid';
|
|
1289
|
+
const descriptors = ['descriptor1', 'descriptor2'];
|
|
1290
|
+
|
|
1291
|
+
noble._characteristics = { [peripheralUuid]: { [serviceUuid]: { [characteristicUuid]: { emit } } } };
|
|
1292
|
+
noble._descriptors = { [peripheralUuid]: { [serviceUuid]: { [characteristicUuid]: {} } } };
|
|
1293
|
+
|
|
1294
|
+
noble.on('warning', warningCallback);
|
|
1295
|
+
|
|
1296
|
+
noble.onDescriptorsDiscover(peripheralUuid, serviceUuid, characteristicUuid, descriptors);
|
|
1297
|
+
|
|
1298
|
+
const expectedDescriptors = [
|
|
1299
|
+
new Descriptor(noble, peripheralUuid, serviceUuid, characteristicUuid, descriptors[0]),
|
|
1300
|
+
new Descriptor(noble, peripheralUuid, serviceUuid, characteristicUuid, descriptors[1])
|
|
1301
|
+
];
|
|
1302
|
+
|
|
1303
|
+
assert.calledOnceWithExactly(emit, 'descriptorsDiscover', expectedDescriptors);
|
|
1304
|
+
assert.notCalled(warningCallback);
|
|
1305
|
+
|
|
1306
|
+
should(noble._characteristics).deepEqual({
|
|
1307
|
+
[peripheralUuid]: { [serviceUuid]: { [characteristicUuid]: { emit, descriptors: expectedDescriptors } } }
|
|
1308
|
+
});
|
|
1309
|
+
should(noble._descriptors).deepEqual({
|
|
1310
|
+
[peripheralUuid]: { [serviceUuid]: { [characteristicUuid]: { descriptor1: expectedDescriptors[0], descriptor2: expectedDescriptors[1] } } }
|
|
1311
|
+
});
|
|
1312
|
+
});
|
|
1313
|
+
});
|
|
1314
|
+
|
|
1315
|
+
it('readValue - should delegate to bindings', () => {
|
|
1316
|
+
noble._bindings.readValue = sinon.spy();
|
|
1317
|
+
noble.readValue('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid');
|
|
1318
|
+
assert.calledOnceWithExactly(noble._bindings.readValue, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid');
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1321
|
+
describe('onValueRead', () => {
|
|
1322
|
+
it('should emit warning', () => {
|
|
1323
|
+
const warningCallback = sinon.spy();
|
|
1324
|
+
noble.on('warning', warningCallback);
|
|
1325
|
+
|
|
1326
|
+
noble._descriptors = {
|
|
1327
|
+
peripheralUuid: {
|
|
1328
|
+
serviceUuid: {
|
|
1329
|
+
characteristicUuid: {}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
};
|
|
1333
|
+
noble.onValueRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid', 'data');
|
|
1334
|
+
|
|
1335
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid value read!');
|
|
1336
|
+
});
|
|
1337
|
+
|
|
1338
|
+
it('should emit valueRead', () => {
|
|
1339
|
+
const warningCallback = sinon.spy();
|
|
1340
|
+
const emit = sinon.spy();
|
|
1341
|
+
|
|
1342
|
+
noble.on('warning', warningCallback);
|
|
1343
|
+
|
|
1344
|
+
noble._descriptors = {
|
|
1345
|
+
peripheralUuid: {
|
|
1346
|
+
serviceUuid: {
|
|
1347
|
+
characteristicUuid: {
|
|
1348
|
+
descriptorUuid: {
|
|
1349
|
+
emit
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
noble.onValueRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid', 'data');
|
|
1356
|
+
|
|
1357
|
+
assert.notCalled(warningCallback);
|
|
1358
|
+
assert.calledOnceWithExactly(emit, 'valueRead', 'data');
|
|
1359
|
+
});
|
|
1360
|
+
});
|
|
1361
|
+
|
|
1362
|
+
it('writeValue - should delegate to bindings', () => {
|
|
1363
|
+
noble._bindings.writeValue = sinon.spy();
|
|
1364
|
+
noble.writeValue('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid', 'data');
|
|
1365
|
+
assert.calledOnceWithExactly(noble._bindings.writeValue, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid', 'data');
|
|
1366
|
+
});
|
|
1367
|
+
|
|
1368
|
+
describe('onValueWrite', () => {
|
|
1369
|
+
it('should emit warning', () => {
|
|
1370
|
+
const warningCallback = sinon.spy();
|
|
1371
|
+
noble.on('warning', warningCallback);
|
|
1372
|
+
|
|
1373
|
+
noble._descriptors = {
|
|
1374
|
+
peripheralUuid: {
|
|
1375
|
+
serviceUuid: {
|
|
1376
|
+
characteristicUuid: {}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
noble.onValueWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid');
|
|
1381
|
+
|
|
1382
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid value write!');
|
|
1383
|
+
});
|
|
1384
|
+
|
|
1385
|
+
it('should emit valueWrite', () => {
|
|
1386
|
+
const warningCallback = sinon.spy();
|
|
1387
|
+
const emit = sinon.spy();
|
|
1388
|
+
|
|
1389
|
+
noble.on('warning', warningCallback);
|
|
1390
|
+
|
|
1391
|
+
noble._descriptors = {
|
|
1392
|
+
peripheralUuid: {
|
|
1393
|
+
serviceUuid: {
|
|
1394
|
+
characteristicUuid: {
|
|
1395
|
+
descriptorUuid: {
|
|
1396
|
+
emit
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
};
|
|
1402
|
+
noble.onValueWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid');
|
|
1403
|
+
|
|
1404
|
+
assert.notCalled(warningCallback);
|
|
1405
|
+
assert.calledOnceWithExactly(emit, 'valueWrite');
|
|
1406
|
+
});
|
|
1407
|
+
});
|
|
1408
|
+
|
|
1409
|
+
it('readHandle - should delegate to bindings', () => {
|
|
1410
|
+
noble._bindings.readHandle = sinon.spy();
|
|
1411
|
+
noble.readHandle('peripheralUuid', 'handle');
|
|
1412
|
+
assert.calledOnceWithExactly(noble._bindings.readHandle, 'peripheralUuid', 'handle');
|
|
1413
|
+
});
|
|
1414
|
+
|
|
1415
|
+
describe('onHandleRead', () => {
|
|
1416
|
+
it('should emit warning', () => {
|
|
1417
|
+
const warningCallback = sinon.spy();
|
|
1418
|
+
noble.on('warning', warningCallback);
|
|
1419
|
+
|
|
1420
|
+
noble._peripherals = {
|
|
1421
|
+
};
|
|
1422
|
+
noble.onHandleRead('peripheralUuid', 'nameOfHandle', 'data');
|
|
1423
|
+
|
|
1424
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid handle read!');
|
|
1425
|
+
});
|
|
1426
|
+
|
|
1427
|
+
it('should emit handleWrite', () => {
|
|
1428
|
+
const warningCallback = sinon.spy();
|
|
1429
|
+
const emit = sinon.spy();
|
|
1430
|
+
|
|
1431
|
+
noble.on('warning', warningCallback);
|
|
1432
|
+
|
|
1433
|
+
noble._peripherals = {
|
|
1434
|
+
peripheralUuid: {
|
|
1435
|
+
emit
|
|
1436
|
+
}
|
|
1437
|
+
};
|
|
1438
|
+
noble.onHandleRead('peripheralUuid', 'nameOfHandle', 'data');
|
|
1439
|
+
|
|
1440
|
+
assert.notCalled(warningCallback);
|
|
1441
|
+
assert.calledOnceWithExactly(emit, 'handleReadnameOfHandle', 'data');
|
|
1442
|
+
});
|
|
1443
|
+
});
|
|
1444
|
+
|
|
1445
|
+
it('writeHandle - should delegate to bindings', () => {
|
|
1446
|
+
noble._bindings.writeHandle = sinon.spy();
|
|
1447
|
+
noble.writeHandle('peripheralUuid', 'handle', 'data', 'withoutResponse');
|
|
1448
|
+
assert.calledOnceWithExactly(noble._bindings.writeHandle, 'peripheralUuid', 'handle', 'data', 'withoutResponse');
|
|
1449
|
+
});
|
|
1450
|
+
|
|
1451
|
+
describe('onHandleWrite', () => {
|
|
1452
|
+
it('should emit warning', () => {
|
|
1453
|
+
const warningCallback = sinon.spy();
|
|
1454
|
+
noble.on('warning', warningCallback);
|
|
1455
|
+
|
|
1456
|
+
noble._peripherals = {
|
|
1457
|
+
};
|
|
1458
|
+
noble.onHandleWrite('peripheralUuid', 'nameOfHandle');
|
|
1459
|
+
|
|
1460
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid handle write!');
|
|
1461
|
+
});
|
|
1462
|
+
|
|
1463
|
+
it('should emit handleRead', () => {
|
|
1464
|
+
const warningCallback = sinon.spy();
|
|
1465
|
+
const emit = sinon.spy();
|
|
1466
|
+
|
|
1467
|
+
noble.on('warning', warningCallback);
|
|
1468
|
+
|
|
1469
|
+
noble._peripherals = {
|
|
1470
|
+
peripheralUuid: {
|
|
1471
|
+
emit
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
noble.onHandleWrite('peripheralUuid', 'nameOfHandle');
|
|
1475
|
+
|
|
1476
|
+
assert.notCalled(warningCallback);
|
|
1477
|
+
assert.calledOnceWithExactly(emit, 'handleWritenameOfHandle');
|
|
1478
|
+
});
|
|
1479
|
+
});
|
|
1480
|
+
|
|
1481
|
+
describe('onHandleNotify', () => {
|
|
1482
|
+
it('should emit warning', () => {
|
|
1483
|
+
const warningCallback = sinon.spy();
|
|
1484
|
+
noble.on('warning', warningCallback);
|
|
1485
|
+
|
|
1486
|
+
noble._peripherals = {
|
|
1487
|
+
};
|
|
1488
|
+
noble.onHandleNotify('peripheralUuid', 'nameOfHandle', 'data');
|
|
1489
|
+
|
|
1490
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid handle notify!');
|
|
1491
|
+
});
|
|
1492
|
+
|
|
1493
|
+
it('should emit handleNotify', () => {
|
|
1494
|
+
const warningCallback = sinon.spy();
|
|
1495
|
+
const emit = sinon.spy();
|
|
1496
|
+
|
|
1497
|
+
noble.on('warning', warningCallback);
|
|
1498
|
+
|
|
1499
|
+
noble._peripherals = {
|
|
1500
|
+
peripheralUuid: {
|
|
1501
|
+
emit
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
noble.onHandleNotify('peripheralUuid', 'nameOfHandle', 'data');
|
|
1505
|
+
|
|
1506
|
+
assert.notCalled(warningCallback);
|
|
1507
|
+
assert.calledOnceWithExactly(emit, 'handleNotify', 'nameOfHandle', 'data');
|
|
1508
|
+
});
|
|
1509
|
+
});
|
|
1510
|
+
|
|
1511
|
+
it('onMtu - should update peripheral mtu', () => {
|
|
1512
|
+
const peripheral = {
|
|
1513
|
+
mtu: 'nan'
|
|
1514
|
+
};
|
|
1515
|
+
|
|
1516
|
+
noble._peripherals = { uuid: peripheral };
|
|
1517
|
+
noble.onMtu('uuid', 'mtu');
|
|
1518
|
+
|
|
1519
|
+
should(peripheral).deepEqual({ mtu: 'mtu' });
|
|
1520
|
+
});
|
|
1521
|
+
|
|
1522
|
+
it('onMtu - should not update peripheral mtu', () => {
|
|
1523
|
+
const peripheral = {
|
|
1524
|
+
};
|
|
1525
|
+
|
|
1526
|
+
noble._peripherals = { uuid: peripheral };
|
|
1527
|
+
noble.onMtu('uuid', 'mtu');
|
|
1528
|
+
|
|
1529
|
+
should(peripheral).deepEqual({ });
|
|
1530
|
+
});
|
|
1531
|
+
|
|
1532
|
+
describe('onIncludedServicesDiscover', () => {
|
|
1533
|
+
it('should emit connected on existing peripheral', () => {
|
|
1534
|
+
const emit = sinon.spy();
|
|
1535
|
+
noble._services = {
|
|
1536
|
+
uuid: { serviceUuid: { emit } }
|
|
1537
|
+
};
|
|
1538
|
+
|
|
1539
|
+
const warningCallback = sinon.spy();
|
|
1540
|
+
|
|
1541
|
+
noble.on('warning', warningCallback);
|
|
1542
|
+
noble.onIncludedServicesDiscover('uuid', 'serviceUuid', 'serviceUuids');
|
|
1543
|
+
|
|
1544
|
+
assert.calledOnceWithExactly(emit, 'includedServicesDiscover', 'serviceUuids');
|
|
1545
|
+
assert.notCalled(warningCallback);
|
|
1546
|
+
|
|
1547
|
+
should(noble._services).deepEqual({
|
|
1548
|
+
uuid: { serviceUuid: { includedServiceUuids: 'serviceUuids', emit } }
|
|
1549
|
+
});
|
|
1550
|
+
});
|
|
1551
|
+
|
|
1552
|
+
it('should emit warning on missing peripheral', () => {
|
|
1553
|
+
noble._services = { uuid: {} };
|
|
1554
|
+
|
|
1555
|
+
const warningCallback = sinon.spy();
|
|
1556
|
+
|
|
1557
|
+
noble.on('warning', warningCallback);
|
|
1558
|
+
noble.onIncludedServicesDiscover('uuid', 'serviceUuid', 'serviceUuids');
|
|
1559
|
+
|
|
1560
|
+
assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid, serviceUuid included services discover!');
|
|
1561
|
+
|
|
1562
|
+
should(noble._services).deepEqual({ uuid: {} });
|
|
1563
|
+
});
|
|
1564
|
+
});
|
|
1565
|
+
});
|