@neurodevs/node-lsl 18.1.0 → 19.0.0
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/build/__tests__/AbstractPackageTest.d.ts +12 -10
- package/build/__tests__/AbstractPackageTest.js +33 -14
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/BleDeviceController.test.d.ts +5 -0
- package/build/__tests__/impl/BleDeviceController.test.js +36 -5
- package/build/__tests__/impl/BleDeviceController.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamOutlet.test.js +2 -4
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
- package/build/__tests__/impl/UsbDeviceController.test.d.ts +17 -0
- package/build/__tests__/impl/UsbDeviceController.test.js +81 -0
- package/build/__tests__/impl/UsbDeviceController.test.js.map +1 -0
- package/build/__tests__/impl/WindowedClockRegressor.test.d.ts +19 -0
- package/build/__tests__/impl/WindowedClockRegressor.test.js +172 -0
- package/build/__tests__/impl/WindowedClockRegressor.test.js.map +1 -0
- package/build/impl/LslStreamInlet.d.ts +1 -0
- package/build/impl/LslStreamInlet.js +2 -1
- package/build/impl/LslStreamInlet.js.map +1 -1
- package/build/impl/LslStreamOutlet.d.ts +1 -0
- package/build/impl/LslStreamOutlet.js +2 -1
- package/build/impl/LslStreamOutlet.js.map +1 -1
- package/build/impl/WindowedClockRegressor.d.ts +24 -0
- package/build/impl/WindowedClockRegressor.js +73 -0
- package/build/impl/WindowedClockRegressor.js.map +1 -0
- package/build/impl/controllers/BleDeviceController.d.ts +2 -0
- package/build/impl/controllers/BleDeviceController.js +8 -0
- package/build/impl/controllers/BleDeviceController.js.map +1 -1
- package/build/impl/controllers/UsbDeviceController.d.ts +23 -0
- package/build/impl/controllers/UsbDeviceController.js +40 -0
- package/build/impl/controllers/UsbDeviceController.js.map +1 -0
- package/build/index.d.ts +8 -0
- package/build/index.js +10 -0
- package/build/index.js.map +1 -1
- package/build/scripts/runUsb.d.ts +1 -0
- package/build/scripts/runUsb.js +14 -0
- package/build/scripts/runUsb.js.map +1 -0
- package/build/testDoubles/BleController/FakeBleController.d.ts +3 -1
- package/build/testDoubles/BleController/FakeBleController.js +5 -0
- package/build/testDoubles/BleController/FakeBleController.js.map +1 -1
- package/build/testDoubles/ClockRegressor/FakeClockRegressor.d.ts +17 -0
- package/build/testDoubles/ClockRegressor/FakeClockRegressor.js +23 -0
- package/build/testDoubles/ClockRegressor/FakeClockRegressor.js.map +1 -0
- package/build/testDoubles/UsbController/FakeUsbController.d.ts +12 -0
- package/build/testDoubles/UsbController/FakeUsbController.js +25 -0
- package/build/testDoubles/UsbController/FakeUsbController.js.map +1 -0
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/AbstractPackageTest.ts +59 -21
- package/src/__tests__/impl/BleDeviceController.test.ts +51 -8
- package/src/__tests__/impl/LslStreamOutlet.test.ts +5 -4
- package/src/__tests__/impl/UsbDeviceController.test.ts +109 -0
- package/src/__tests__/impl/WindowedClockRegressor.test.ts +262 -0
- package/src/impl/LslStreamInlet.ts +4 -1
- package/src/impl/LslStreamOutlet.ts +2 -1
- package/src/impl/WindowedClockRegressor.ts +136 -0
- package/src/impl/controllers/BleDeviceController.ts +17 -0
- package/src/impl/controllers/UsbDeviceController.ts +65 -0
- package/src/index.ts +16 -0
- package/src/scripts/runUsb.ts +20 -0
- package/src/testDoubles/BleController/FakeBleController.ts +11 -0
- package/src/testDoubles/ClockRegressor/FakeClockRegressor.ts +46 -0
- package/src/testDoubles/UsbController/FakeUsbController.ts +34 -0
- package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -2
|
@@ -3,6 +3,7 @@ export default class FakeBleController {
|
|
|
3
3
|
static callsToConstructor = [];
|
|
4
4
|
static numCallsToConnect = 0;
|
|
5
5
|
static callsToWriteCharacteristic = [];
|
|
6
|
+
static callsToSubscribeCharacteristics = [];
|
|
6
7
|
static numCallsToDisconnect = 0;
|
|
7
8
|
static fakeCharacteristics = {};
|
|
8
9
|
static fakeName = `fake-${generateId()}`;
|
|
@@ -23,6 +24,9 @@ export default class FakeBleController {
|
|
|
23
24
|
value,
|
|
24
25
|
});
|
|
25
26
|
}
|
|
27
|
+
async subscribeCharacteristics(charCallbacks) {
|
|
28
|
+
FakeBleController.callsToSubscribeCharacteristics.push(charCallbacks);
|
|
29
|
+
}
|
|
26
30
|
async disconnect() {
|
|
27
31
|
FakeBleController.numCallsToDisconnect++;
|
|
28
32
|
}
|
|
@@ -36,6 +40,7 @@ export default class FakeBleController {
|
|
|
36
40
|
this.callsToConstructor = [];
|
|
37
41
|
this.numCallsToConnect = 0;
|
|
38
42
|
this.callsToWriteCharacteristic = [];
|
|
43
|
+
this.callsToSubscribeCharacteristics = [];
|
|
39
44
|
this.numCallsToDisconnect = 0;
|
|
40
45
|
}
|
|
41
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FakeBleController.js","sourceRoot":"","sources":["../../../src/testDoubles/BleController/FakeBleController.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"FakeBleController.js","sourceRoot":"","sources":["../../../src/testDoubles/BleController/FakeBleController.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAA;AAO/C,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAC3B,MAAM,CAAC,kBAAkB,GAAyC,EAAE,CAAA;IAEpE,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAE5B,MAAM,CAAC,0BAA0B,GAGlC,EAAE,CAAA;IAED,MAAM,CAAC,+BAA+B,GACzC,EAAE,CAAA;IAEC,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAE/B,MAAM,CAAC,mBAAmB,GAA4B,EAAE,CAAA;IACxD,MAAM,CAAC,QAAQ,GAAG,QAAQ,UAAU,EAAE,EAAE,CAAA;IAEvC,KAAK,CAAQ;IACb,KAAK,CAAQ;IAErB,YAAmB,OAA8B;QAC7C,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;QAEpC,IAAI,CAAC,KAAK,GAAG,UAAU,IAAI,UAAU,EAAE,CAAA;QACvC,IAAI,CAAC,KAAK,GAAG,iBAAiB,CAAC,QAAQ,CAAA;QAEvC,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;IAEM,KAAK,CAAC,OAAO;QAChB,iBAAiB,CAAC,iBAAiB,EAAE,CAAA;IACzC,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAC5B,kBAA0B,EAC1B,KAAa;QAEb,iBAAiB,CAAC,0BAA0B,CAAC,IAAI,CAAC;YAC9C,kBAAkB;YAClB,KAAK;SACR,CAAC,CAAA;IACN,CAAC;IAEM,KAAK,CAAC,wBAAwB,CACjC,aAAsC;QAEtC,iBAAiB,CAAC,+BAA+B,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACzE,CAAC;IAEM,KAAK,CAAC,UAAU;QACnB,iBAAiB,CAAC,oBAAoB,EAAE,CAAA;IAC5C,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;QAC1B,IAAI,CAAC,0BAA0B,GAAG,EAAE,CAAA;QACpC,IAAI,CAAC,+BAA+B,GAAG,EAAE,CAAA;QACzC,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAA;IACjC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ClockRegressor, WindowedClockRegressorOptions } from '../../impl/WindowedClockRegressor.js';
|
|
2
|
+
export default class FakeClockRegressor implements ClockRegressor {
|
|
3
|
+
static callsToConstructor: {
|
|
4
|
+
nominalHz: number;
|
|
5
|
+
options?: WindowedClockRegressorOptions;
|
|
6
|
+
}[];
|
|
7
|
+
static callsToDeriveTimestamps: {
|
|
8
|
+
deviceTime: number;
|
|
9
|
+
earliestLslTime: number;
|
|
10
|
+
chunkSize: number;
|
|
11
|
+
}[];
|
|
12
|
+
static fakeResultValue: number;
|
|
13
|
+
readonly nominalHz: number;
|
|
14
|
+
constructor(nominalHz: number, options?: WindowedClockRegressorOptions);
|
|
15
|
+
deriveTimestamps(deviceTime: number, earliestLslTime: number, chunkSize: number): any[];
|
|
16
|
+
static resetTestDouble(): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export default class FakeClockRegressor {
|
|
2
|
+
static callsToConstructor = [];
|
|
3
|
+
static callsToDeriveTimestamps = [];
|
|
4
|
+
static fakeResultValue = 0;
|
|
5
|
+
nominalHz;
|
|
6
|
+
constructor(nominalHz, options) {
|
|
7
|
+
FakeClockRegressor.callsToConstructor.push({ nominalHz, options });
|
|
8
|
+
this.nominalHz = nominalHz;
|
|
9
|
+
}
|
|
10
|
+
deriveTimestamps(deviceTime, earliestLslTime, chunkSize) {
|
|
11
|
+
FakeClockRegressor.callsToDeriveTimestamps.push({
|
|
12
|
+
deviceTime,
|
|
13
|
+
earliestLslTime,
|
|
14
|
+
chunkSize,
|
|
15
|
+
});
|
|
16
|
+
return Array(chunkSize).fill(FakeClockRegressor.fakeResultValue);
|
|
17
|
+
}
|
|
18
|
+
static resetTestDouble() {
|
|
19
|
+
FakeClockRegressor.callsToConstructor = [];
|
|
20
|
+
FakeClockRegressor.callsToDeriveTimestamps = [];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=FakeClockRegressor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FakeClockRegressor.js","sourceRoot":"","sources":["../../../src/testDoubles/ClockRegressor/FakeClockRegressor.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,kBAAkB;IAC5B,MAAM,CAAC,kBAAkB,GAG1B,EAAE,CAAA;IACD,MAAM,CAAC,uBAAuB,GAI/B,EAAE,CAAA;IAED,MAAM,CAAC,eAAe,GAAG,CAAC,CAAA;IAEjB,SAAS,CAAQ;IAEjC,YACI,SAAiB,EACjB,OAAuC;QAEvC,kBAAkB,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;QAClE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC9B,CAAC;IAEM,gBAAgB,CACnB,UAAkB,EAClB,eAAuB,EACvB,SAAiB;QAEjB,kBAAkB,CAAC,uBAAuB,CAAC,IAAI,CAAC;YAC5C,UAAU;YACV,eAAe;YACf,SAAS;SACZ,CAAC,CAAA;QACF,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAA;IACpE,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,kBAAkB,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC1C,kBAAkB,CAAC,uBAAuB,GAAG,EAAE,CAAA;IACnD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { UsbController, UsbControllerOptions } from '../../impl/controllers/UsbDeviceController.js';
|
|
2
|
+
export default class FakeUsbController implements UsbController {
|
|
3
|
+
static callsToConstructor: (UsbControllerOptions | undefined)[];
|
|
4
|
+
static numCallsToConnect: number;
|
|
5
|
+
static callsToWriteUsb: string[];
|
|
6
|
+
static numCallsToDisconnect: number;
|
|
7
|
+
constructor(options?: UsbControllerOptions);
|
|
8
|
+
connect(): Promise<void>;
|
|
9
|
+
writeUsb(value: string): Promise<void>;
|
|
10
|
+
disconnect(): Promise<void>;
|
|
11
|
+
static resetTestDouble(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default class FakeUsbController {
|
|
2
|
+
static callsToConstructor = [];
|
|
3
|
+
static numCallsToConnect = 0;
|
|
4
|
+
static callsToWriteUsb = [];
|
|
5
|
+
static numCallsToDisconnect = 0;
|
|
6
|
+
constructor(options) {
|
|
7
|
+
FakeUsbController.callsToConstructor.push(options);
|
|
8
|
+
}
|
|
9
|
+
async connect() {
|
|
10
|
+
FakeUsbController.numCallsToConnect++;
|
|
11
|
+
}
|
|
12
|
+
async writeUsb(value) {
|
|
13
|
+
FakeUsbController.callsToWriteUsb.push(value);
|
|
14
|
+
}
|
|
15
|
+
async disconnect() {
|
|
16
|
+
FakeUsbController.numCallsToDisconnect++;
|
|
17
|
+
}
|
|
18
|
+
static resetTestDouble() {
|
|
19
|
+
FakeUsbController.callsToConstructor.length = 0;
|
|
20
|
+
FakeUsbController.numCallsToConnect = 0;
|
|
21
|
+
FakeUsbController.callsToWriteUsb.length = 0;
|
|
22
|
+
FakeUsbController.numCallsToDisconnect = 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=FakeUsbController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FakeUsbController.js","sourceRoot":"","sources":["../../../src/testDoubles/UsbController/FakeUsbController.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAC3B,MAAM,CAAC,kBAAkB,GAAyC,EAAE,CAAA;IACpE,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,eAAe,GAAa,EAAE,CAAA;IACrC,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAEtC,YAAmB,OAA8B;QAC7C,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;IAEM,KAAK,CAAC,OAAO;QAChB,iBAAiB,CAAC,iBAAiB,EAAE,CAAA;IACzC,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,KAAa;QAC/B,iBAAiB,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjD,CAAC;IAEM,KAAK,CAAC,UAAU;QACnB,iBAAiB,CAAC,oBAAoB,EAAE,CAAA;IAC5C,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,iBAAiB,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAA;QAC/C,iBAAiB,CAAC,iBAAiB,GAAG,CAAC,CAAA;QACvC,iBAAiB,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAA;QAC5C,iBAAiB,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAC9C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FakeWebSocketBridge.js","sourceRoot":"","sources":["../../../src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts"],"names":[],"mappings":"AACA,OAAO,kBAGN,MAAM,kCAAkC,CAAA;AACzC,OAAO,aAAa,MAAM,gCAAgC,CAAA;AAC1D,OAAO,mBAAmB,MAAM,sCAAsC,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAC7B,MAAM,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"FakeWebSocketBridge.js","sourceRoot":"","sources":["../../../src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts"],"names":[],"mappings":"AACA,OAAO,kBAGN,MAAM,kCAAkC,CAAA;AACzC,OAAO,aAAa,MAAM,gCAAgC,CAAA;AAC1D,OAAO,mBAAmB,MAAM,sCAAsC,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAC7B,MAAM,CAAC,kBAAkB,GAE1B,EAAE,CAAA;IAED,MAAM,CAAC,kBAAkB,GAAG,CAAC,CAAA;IAC7B,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAC/B,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAEnC,YAAmB,OAA2C;QAC1D,mBAAmB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxD,CAAC;IAEM,KAAK,CAAC,QAAQ;QACjB,mBAAmB,CAAC,kBAAkB,EAAE,CAAA;IAC5C,CAAC;IAEM,UAAU;QACb,mBAAmB,CAAC,oBAAoB,EAAE,CAAA;IAC9C,CAAC;IAEM,OAAO;QACV,mBAAmB,CAAC,iBAAiB,EAAE,CAAA;IAC3C,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAA;QAC7B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;QAE1B,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,IAAI,CAAC,sBAAsB,EAAE,CAAA;IACjC,CAAC;IAEO,MAAM,CAAC,gBAAgB;QAC3B,kBAAkB,CAAC,EAAE,GAAG,aAA4C,CAAA;QACpE,aAAa,CAAC,eAAe,EAAE,CAAA;IACnC,CAAC;IAEO,MAAM,CAAC,sBAAsB;QACjC,kBAAkB,CAAC,GAAG;YAClB,mBAAwD,CAAA;QAC5D,mBAAmB,CAAC,eAAe,EAAE,CAAA;IACzC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neurodevs/node-lsl",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "19.0.0",
|
|
4
4
|
"description": "Lab Streaming Layer (LSL) bindings for Node",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"watch.build.dev": "tsc-watch --sourceMap --onCompilationComplete 'yarn run build.copy-files'"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@neurodevs/generate-id": "^1.1.
|
|
45
|
-
"@neurodevs/ndx-native": "^7.
|
|
44
|
+
"@neurodevs/generate-id": "^1.1.3",
|
|
45
|
+
"@neurodevs/ndx-native": "^7.1.4",
|
|
46
46
|
"ffi-rs": "^1.3.1",
|
|
47
47
|
"ws": "^8.18.3"
|
|
48
48
|
},
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@neurodevs/node-tdd": "^3.0.1",
|
|
52
52
|
"@neurodevs/prettier-config-ndx": "^1.0.2",
|
|
53
53
|
"@types/ws": "^8.18.1",
|
|
54
|
-
"prettier": "^3.
|
|
54
|
+
"prettier": "^3.9.4",
|
|
55
55
|
"typescript": "^5.9.3"
|
|
56
56
|
},
|
|
57
57
|
"resolutions": {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { randomInt } from 'node:crypto'
|
|
2
|
+
|
|
3
|
+
import WebSocket, { Server } from 'ws'
|
|
1
4
|
import {
|
|
2
5
|
FakeLiblsl,
|
|
3
6
|
FakeLibndx,
|
|
@@ -6,7 +9,6 @@ import {
|
|
|
6
9
|
LibndxAdapter,
|
|
7
10
|
} from '@neurodevs/ndx-native'
|
|
8
11
|
import AbstractModuleTest from '@neurodevs/node-tdd'
|
|
9
|
-
import WebSocket, { Server } from 'ws'
|
|
10
12
|
|
|
11
13
|
import SpyEventMarkerEmitter from '../testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js'
|
|
12
14
|
import FakeStreamInfo from '../testDoubles/StreamInfo/FakeStreamInfo.js'
|
|
@@ -17,7 +19,6 @@ import FakeStreamOutlet from '../testDoubles/StreamOutlet/FakeStreamOutlet.js'
|
|
|
17
19
|
import SpyLslWebSocketBridge from '../testDoubles/WebSocketBridge/SpyLslWebSocketBridge.js'
|
|
18
20
|
import FakeWebSocket from '../testDoubles/WebSockets/FakeWebSocket.js'
|
|
19
21
|
import FakeWebSocketServer from '../testDoubles/WebSockets/FakeWebSocketServer.js'
|
|
20
|
-
|
|
21
22
|
import LslWebSocketBridge from '../impl/LslWebSocketBridge.js'
|
|
22
23
|
import BleDeviceController from '../impl/controllers/BleDeviceController.js'
|
|
23
24
|
import LslEventMarkerEmitter from '../impl/LslEventMarkerEmitter.js'
|
|
@@ -32,8 +33,31 @@ export default class AbstractPackageTest extends AbstractModuleTest {
|
|
|
32
33
|
protected static fakeLiblsl: FakeLiblsl
|
|
33
34
|
protected static fakeLibndx: FakeLibndx
|
|
34
35
|
|
|
36
|
+
protected static readonly fakeStreamInfo = new FakeStreamInfo()
|
|
37
|
+
|
|
38
|
+
protected static readonly name_ = this.generateId()
|
|
39
|
+
protected static readonly type = this.generateId()
|
|
40
|
+
protected static readonly sourceId = this.generateId()
|
|
41
|
+
protected static readonly units = this.generateId()
|
|
42
|
+
|
|
43
|
+
protected static readonly channelNames = [
|
|
44
|
+
this.generateId(),
|
|
45
|
+
this.generateId(),
|
|
46
|
+
this.generateId(),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
protected static readonly channelCount = this.channelNames.length
|
|
50
|
+
|
|
51
|
+
protected static readonly chunkSize = randomInt(2, 100)
|
|
52
|
+
protected static readonly sampleRateHz = Math.floor(Math.random() * 100)
|
|
53
|
+
protected static readonly maxBufferedMs = Math.floor(Math.random() * 1000)
|
|
54
|
+
|
|
35
55
|
protected static async beforeEach() {
|
|
36
56
|
await super.beforeEach()
|
|
57
|
+
|
|
58
|
+
this.setImmediateTimeouts()
|
|
59
|
+
|
|
60
|
+
this.setFakeLibndx()
|
|
37
61
|
}
|
|
38
62
|
|
|
39
63
|
protected static setFakeLiblsl() {
|
|
@@ -44,6 +68,39 @@ export default class AbstractPackageTest extends AbstractModuleTest {
|
|
|
44
68
|
FakeLiblsl.fakeInfoHandles = [{} as InfoHandle]
|
|
45
69
|
}
|
|
46
70
|
|
|
71
|
+
protected static callsToSetTimeout: number[] = []
|
|
72
|
+
|
|
73
|
+
protected static setImmediateTimeouts() {
|
|
74
|
+
this.callsToSetTimeout = []
|
|
75
|
+
|
|
76
|
+
BleDeviceController.setTimeout = ((
|
|
77
|
+
callback: (...args: unknown[]) => void,
|
|
78
|
+
delayMs?: number,
|
|
79
|
+
...args: unknown[]
|
|
80
|
+
) => {
|
|
81
|
+
this.callsToSetTimeout.push(delayMs ?? 0)
|
|
82
|
+
return setTimeout(callback, 0, ...args)
|
|
83
|
+
}) as unknown as typeof setTimeout
|
|
84
|
+
|
|
85
|
+
LslStreamOutlet.setTimeout = ((
|
|
86
|
+
callback: (...args: unknown[]) => void,
|
|
87
|
+
delayMs?: number,
|
|
88
|
+
...args: unknown[]
|
|
89
|
+
) => {
|
|
90
|
+
this.callsToSetTimeout.push(delayMs ?? 0)
|
|
91
|
+
return setTimeout(callback, 0, ...args)
|
|
92
|
+
}) as unknown as typeof setTimeout
|
|
93
|
+
|
|
94
|
+
LslStreamInlet.setTimeout = ((
|
|
95
|
+
callback: (...args: unknown[]) => void,
|
|
96
|
+
delayMs?: number,
|
|
97
|
+
...args: unknown[]
|
|
98
|
+
) => {
|
|
99
|
+
this.callsToSetTimeout.push(delayMs ?? 0)
|
|
100
|
+
return setTimeout(callback, 0, ...args)
|
|
101
|
+
}) as unknown as typeof setTimeout
|
|
102
|
+
}
|
|
103
|
+
|
|
47
104
|
protected static setFakeLibndx() {
|
|
48
105
|
this.fakeLibndx = new FakeLibndx()
|
|
49
106
|
LibndxAdapter.setInstance(this.fakeLibndx)
|
|
@@ -96,25 +153,6 @@ export default class AbstractPackageTest extends AbstractModuleTest {
|
|
|
96
153
|
FakeWebSocketServer.resetTestDouble()
|
|
97
154
|
}
|
|
98
155
|
|
|
99
|
-
protected static readonly fakeStreamInfo = new FakeStreamInfo()
|
|
100
|
-
|
|
101
|
-
protected static readonly name_ = this.generateId()
|
|
102
|
-
protected static readonly type = this.generateId()
|
|
103
|
-
protected static readonly sourceId = this.generateId()
|
|
104
|
-
protected static readonly units = this.generateId()
|
|
105
|
-
|
|
106
|
-
protected static readonly channelNames = [
|
|
107
|
-
this.generateId(),
|
|
108
|
-
this.generateId(),
|
|
109
|
-
this.generateId(),
|
|
110
|
-
]
|
|
111
|
-
|
|
112
|
-
protected static readonly channelCount = this.channelNames.length
|
|
113
|
-
|
|
114
|
-
protected static readonly chunkSize = 2
|
|
115
|
-
protected static readonly sampleRateHz = Math.floor(Math.random() * 100)
|
|
116
|
-
protected static readonly maxBufferedMs = Math.floor(Math.random() * 1000)
|
|
117
|
-
|
|
118
156
|
protected static async LslStreamInlet(
|
|
119
157
|
options: Partial<StreamInletOptions>,
|
|
120
158
|
onData: OnDataCallback
|
|
@@ -35,6 +35,14 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
|
|
|
35
35
|
},
|
|
36
36
|
]
|
|
37
37
|
|
|
38
|
+
private static readonly extraCharCallbacks = [
|
|
39
|
+
{
|
|
40
|
+
charUuid: this.generateId(),
|
|
41
|
+
charName: this.generateId(),
|
|
42
|
+
onData: async () => {},
|
|
43
|
+
},
|
|
44
|
+
]
|
|
45
|
+
|
|
38
46
|
private static onConnected = (_peripheral: NativePeripheral) => {
|
|
39
47
|
this.wasConnected = true
|
|
40
48
|
}
|
|
@@ -58,8 +66,6 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
|
|
|
58
66
|
await super.beforeEach()
|
|
59
67
|
|
|
60
68
|
BleDeviceController.waitAfterMs = 0
|
|
61
|
-
|
|
62
|
-
this.setFakeLibndx()
|
|
63
69
|
BleDeviceController.Class = SpyBleController
|
|
64
70
|
|
|
65
71
|
this.wasConnected = false
|
|
@@ -262,13 +268,10 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
|
|
|
262
268
|
const waitAfterMs = 20
|
|
263
269
|
BleDeviceController.waitAfterMs = waitAfterMs
|
|
264
270
|
|
|
265
|
-
const t0 = Date.now()
|
|
266
271
|
await this.connect()
|
|
267
|
-
const t1 = Date.now()
|
|
268
272
|
|
|
269
|
-
assert.
|
|
270
|
-
|
|
271
|
-
100 + waitAfterMs * 0.8,
|
|
273
|
+
assert.isTruthy(
|
|
274
|
+
this.callsToSetTimeout.includes(waitAfterMs),
|
|
272
275
|
'Did not wait after on connected!'
|
|
273
276
|
)
|
|
274
277
|
}
|
|
@@ -310,6 +313,42 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
|
|
|
310
313
|
)
|
|
311
314
|
}
|
|
312
315
|
|
|
316
|
+
@test()
|
|
317
|
+
protected static async subscribeCharacteristicsCallsLibndxBinding() {
|
|
318
|
+
await this.subscribeCharacteristics()
|
|
319
|
+
|
|
320
|
+
assert.isEqualDeep(
|
|
321
|
+
FakeLibndx.callsToAddBleCharCallbacks[0],
|
|
322
|
+
{
|
|
323
|
+
deviceUuid: this.uuid,
|
|
324
|
+
charCallbacks: this.extraCharCallbacks,
|
|
325
|
+
},
|
|
326
|
+
'Did not call addBleCharCallbacks as expected!'
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
@test()
|
|
331
|
+
protected static async subscribeCharacteristicsMergesIntoCharCallbacks() {
|
|
332
|
+
await this.subscribeCharacteristics()
|
|
333
|
+
|
|
334
|
+
assert.isEqualDeep(
|
|
335
|
+
this.instance.getCharacteristicCallbacks(),
|
|
336
|
+
[...this.charCallbacks, ...this.extraCharCallbacks],
|
|
337
|
+
'Did not merge the newly subscribed callbacks into charCallbacks!'
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
@test()
|
|
342
|
+
protected static async subscribeCharacteristicsThrowsOn400() {
|
|
343
|
+
this.setFake400Error()
|
|
344
|
+
|
|
345
|
+
await assert.doesThrowAsync(
|
|
346
|
+
async () => await this.subscribeCharacteristics(),
|
|
347
|
+
this.fake400Error,
|
|
348
|
+
'Did not throw error!'
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
|
|
313
352
|
@test()
|
|
314
353
|
protected static async callsSetBleRssiInterval() {
|
|
315
354
|
await this.connect()
|
|
@@ -431,7 +470,7 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
|
|
|
431
470
|
if (getCall()) {
|
|
432
471
|
resolve()
|
|
433
472
|
} else {
|
|
434
|
-
setTimeout(check,
|
|
473
|
+
setTimeout(check, 0)
|
|
435
474
|
}
|
|
436
475
|
}
|
|
437
476
|
check()
|
|
@@ -445,6 +484,10 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
|
|
|
445
484
|
)
|
|
446
485
|
}
|
|
447
486
|
|
|
487
|
+
private static async subscribeCharacteristics() {
|
|
488
|
+
await this.instance.subscribeCharacteristics(this.extraCharCallbacks)
|
|
489
|
+
}
|
|
490
|
+
|
|
448
491
|
private static async disconnect() {
|
|
449
492
|
await this.instance.disconnect()
|
|
450
493
|
}
|
|
@@ -265,11 +265,12 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
|
265
265
|
|
|
266
266
|
@test()
|
|
267
267
|
protected static async waitsForTenMsAfterConstructionBeforeReturning() {
|
|
268
|
-
|
|
269
|
-
await this.LslStreamOutlet({ waitAfterConstructionMs: 10 })
|
|
270
|
-
const endMs = Date.now()
|
|
268
|
+
await this.LslStreamOutlet()
|
|
271
269
|
|
|
272
|
-
assert.
|
|
270
|
+
assert.isTruthy(
|
|
271
|
+
this.callsToSetTimeout.includes(10),
|
|
272
|
+
'Did not wait for 10ms after construction!'
|
|
273
|
+
)
|
|
273
274
|
}
|
|
274
275
|
|
|
275
276
|
@test()
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { test, assert } from '@neurodevs/node-tdd'
|
|
2
|
+
|
|
3
|
+
import UsbDeviceController, {
|
|
4
|
+
UsbController,
|
|
5
|
+
} from '../../impl/controllers/UsbDeviceController.js'
|
|
6
|
+
import AbstractPackageTest from '../AbstractPackageTest.js'
|
|
7
|
+
import { FakeLibndx } from '@neurodevs/ndx-native'
|
|
8
|
+
|
|
9
|
+
export default class UsbDeviceControllerTest extends AbstractPackageTest {
|
|
10
|
+
private static instance: UsbController
|
|
11
|
+
|
|
12
|
+
private static readonly serialNumber = this.generateId()
|
|
13
|
+
private static readonly valueToWrite = this.generateId()
|
|
14
|
+
|
|
15
|
+
private static readonly callsToOnData: {
|
|
16
|
+
data: Buffer
|
|
17
|
+
length: number
|
|
18
|
+
timestampSec: number
|
|
19
|
+
}[] = []
|
|
20
|
+
|
|
21
|
+
private static readonly onData = (
|
|
22
|
+
data: Buffer,
|
|
23
|
+
length: number,
|
|
24
|
+
timestampSec: number
|
|
25
|
+
) => {
|
|
26
|
+
this.callsToOnData.push({ data, length, timestampSec })
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
protected static async beforeEach() {
|
|
30
|
+
await super.beforeEach()
|
|
31
|
+
|
|
32
|
+
this.instance = this.UsbDeviceController()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@test()
|
|
36
|
+
protected static async createsInstance() {
|
|
37
|
+
assert.isTruthy(this.instance, 'Failed to create instance!')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@test()
|
|
41
|
+
protected static async connectCallsLibndxCreateUsbBackend() {
|
|
42
|
+
await this.connect()
|
|
43
|
+
|
|
44
|
+
assert.isEqualDeep(
|
|
45
|
+
FakeLibndx.callsToCreateUsbBackend[0],
|
|
46
|
+
{
|
|
47
|
+
serialNumber: this.serialNumber,
|
|
48
|
+
},
|
|
49
|
+
'Did not call create_usb_backend!'
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@test()
|
|
54
|
+
protected static async connectCallsLibndxStartUsbBackend() {
|
|
55
|
+
await this.connect()
|
|
56
|
+
|
|
57
|
+
assert.isEqualDeep(
|
|
58
|
+
FakeLibndx.callsToStartUsbBackend[0],
|
|
59
|
+
{
|
|
60
|
+
serialNumber: this.serialNumber,
|
|
61
|
+
onData: this.onData,
|
|
62
|
+
},
|
|
63
|
+
'Did not call start_usb_backend!'
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@test()
|
|
68
|
+
protected static async disconnectCallsLibndxStopUsbBackend() {
|
|
69
|
+
await this.connect()
|
|
70
|
+
await this.disconnect()
|
|
71
|
+
|
|
72
|
+
assert.isEqualDeep(
|
|
73
|
+
FakeLibndx.callsToStopUsbBackend[0],
|
|
74
|
+
{
|
|
75
|
+
serialNumber: this.serialNumber,
|
|
76
|
+
},
|
|
77
|
+
'Did not call stop_usb_backend!'
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@test()
|
|
82
|
+
protected static async writeUsbCallsLibndxWriteUsbBackend() {
|
|
83
|
+
await this.instance.writeUsb(this.valueToWrite)
|
|
84
|
+
|
|
85
|
+
assert.isEqualDeep(
|
|
86
|
+
FakeLibndx.callsToWriteUsbBackend[0],
|
|
87
|
+
{
|
|
88
|
+
serialNumber: this.serialNumber,
|
|
89
|
+
value: this.valueToWrite,
|
|
90
|
+
},
|
|
91
|
+
'Did not call write_usb_backend!'
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private static async connect() {
|
|
96
|
+
await this.instance.connect()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private static async disconnect() {
|
|
100
|
+
await this.instance.disconnect()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private static UsbDeviceController() {
|
|
104
|
+
return UsbDeviceController.Create({
|
|
105
|
+
onData: this.onData,
|
|
106
|
+
serialNumber: this.serialNumber,
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
}
|