@neurodevs/node-lsl 18.1.0 → 20.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 +19 -17
- package/build/__tests__/AbstractPackageTest.js +54 -39
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/BleDeviceController.test.d.ts +6 -1
- package/build/__tests__/impl/BleDeviceController.test.js +44 -15
- package/build/__tests__/impl/BleDeviceController.test.js.map +1 -1
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js +13 -13
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInfo.test.js +2 -2
- package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInlet.test.d.ts +3 -5
- package/build/__tests__/impl/LslStreamInlet.test.js +13 -46
- package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamOutlet.test.js +9 -16
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
- package/build/__tests__/impl/LslWebSocketBridge.test.js +9 -10
- package/build/__tests__/impl/LslWebSocketBridge.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/assertions.js +1 -1
- package/build/assertions.js.map +1 -1
- package/build/impl/LslEventMarkerEmitter.d.ts +12 -12
- package/build/impl/LslEventMarkerEmitter.js.map +1 -1
- package/build/impl/LslStreamInfo.d.ts +7 -7
- package/build/impl/LslStreamInfo.js.map +1 -1
- package/build/impl/LslStreamInlet.d.ts +63 -20
- package/build/impl/LslStreamInlet.js +221 -64
- package/build/impl/LslStreamInlet.js.map +1 -1
- package/build/impl/LslStreamOutlet.d.ts +16 -14
- package/build/impl/LslStreamOutlet.js +34 -37
- package/build/impl/LslStreamOutlet.js.map +1 -1
- package/build/impl/LslWebSocketBridge.d.ts +10 -10
- package/build/impl/LslWebSocketBridge.js.map +1 -1
- package/build/impl/clocks/WindowedClockRegressor.d.ts +24 -0
- package/build/impl/clocks/WindowedClockRegressor.js +73 -0
- package/build/impl/clocks/WindowedClockRegressor.js.map +1 -0
- package/build/impl/controllers/BleDeviceController.d.ts +3 -1
- package/build/impl/controllers/BleDeviceController.js +9 -1
- 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 +32 -20
- package/build/index.js +39 -26
- package/build/index.js.map +1 -1
- package/build/scripts/{runLslEventMarkerEmitter.js → runLslEmitter.js} +5 -4
- package/build/scripts/runLslEmitter.js.map +1 -0
- package/build/scripts/{runLslStreamOutlet.js → runLslOutlet.js} +1 -1
- package/build/scripts/runLslOutlet.js.map +1 -0
- package/build/scripts/runMuse.js +1 -1
- package/build/scripts/runMuse.js.map +1 -1
- 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/{EventMarkerEmitter/FakeEventMarkerEmitter.d.ts → LslEmitter/FakeLslEmitter.d.ts} +4 -4
- package/build/testDoubles/{EventMarkerEmitter/FakeEventMarkerEmitter.js → LslEmitter/FakeLslEmitter.js} +7 -7
- package/build/testDoubles/LslEmitter/FakeLslEmitter.js.map +1 -0
- package/build/testDoubles/{EventMarkerEmitter/SpyEventMarkerEmitter.d.ts → LslEmitter/SpyLslEmitter.d.ts} +4 -4
- package/build/testDoubles/{EventMarkerEmitter/SpyEventMarkerEmitter.js → LslEmitter/SpyLslEmitter.js} +3 -3
- package/build/testDoubles/LslEmitter/SpyLslEmitter.js.map +1 -0
- package/build/testDoubles/LslEmitter/ThrowingLslEmitter.d.ts +9 -0
- package/build/testDoubles/{EventMarkerEmitter/ThrowingEventMarkerEmitter.js → LslEmitter/ThrowingLslEmitter.js} +2 -2
- package/build/testDoubles/LslEmitter/ThrowingLslEmitter.js.map +1 -0
- package/build/testDoubles/{StreamInfo/FakeStreamInfo.d.ts → LslInfo/FakeLslInfo.d.ts} +4 -4
- package/build/testDoubles/{StreamInfo/FakeStreamInfo.js → LslInfo/FakeLslInfo.js} +7 -7
- package/build/testDoubles/LslInfo/FakeLslInfo.js.map +1 -0
- package/build/testDoubles/LslInfo/SpyLslInfo.d.ts +10 -0
- package/build/testDoubles/{StreamInfo/SpyStreamInfo.js → LslInfo/SpyLslInfo.js} +4 -4
- package/build/testDoubles/LslInfo/SpyLslInfo.js.map +1 -0
- package/build/testDoubles/{StreamInlet/FakeStreamInlet.d.ts → LslInlet/FakeLslInlet.d.ts} +4 -4
- package/build/testDoubles/{StreamInlet/FakeStreamInlet.js → LslInlet/FakeLslInlet.js} +12 -11
- package/build/testDoubles/LslInlet/FakeLslInlet.js.map +1 -0
- package/build/testDoubles/LslInlet/SpyLslInlet.d.ts +4 -0
- package/build/testDoubles/{StreamInlet/SpyStreamInlet.js → LslInlet/SpyLslInlet.js} +2 -2
- package/build/testDoubles/LslInlet/SpyLslInlet.js.map +1 -0
- package/build/testDoubles/{StreamOutlet/FakeStreamOutlet.d.ts → LslOutlet/FakeLslOutlet.d.ts} +5 -5
- package/build/testDoubles/{StreamOutlet/FakeStreamOutlet.js → LslOutlet/FakeLslOutlet.js} +8 -8
- package/build/testDoubles/LslOutlet/FakeLslOutlet.js.map +1 -0
- package/build/testDoubles/LslWsBridge/FakeLslWsBridge.d.ts +14 -0
- package/build/testDoubles/{WebSocketBridge/FakeWebSocketBridge.js → LslWsBridge/FakeLslWsBridge.js} +14 -14
- package/build/testDoubles/LslWsBridge/FakeLslWsBridge.js.map +1 -0
- package/build/testDoubles/LslWsBridge/SpyLslWsBridge.d.ts +4 -0
- package/build/testDoubles/{WebSocketBridge/SpyLslWebSocketBridge.js → LslWsBridge/SpyLslWsBridge.js} +2 -2
- package/build/testDoubles/LslWsBridge/SpyLslWsBridge.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/consts.d.ts +2 -12
- package/build/testDoubles/consts.js +0 -20
- package/build/testDoubles/consts.js.map +1 -1
- package/build/testDoubles/generateRandomOutletOptions.d.ts +2 -2
- package/build/testDoubles/generateRandomOutletOptions.js.map +1 -1
- package/package.json +6 -5
- package/src/__tests__/AbstractPackageTest.ts +78 -49
- package/src/__tests__/impl/BleDeviceController.test.ts +59 -18
- package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +19 -24
- package/src/__tests__/impl/LslStreamInfo.test.ts +8 -8
- package/src/__tests__/impl/LslStreamInlet.test.ts +21 -78
- package/src/__tests__/impl/LslStreamOutlet.test.ts +22 -28
- package/src/__tests__/impl/LslWebSocketBridge.test.ts +15 -18
- package/src/__tests__/impl/UsbDeviceController.test.ts +109 -0
- package/src/__tests__/impl/WindowedClockRegressor.test.ts +262 -0
- package/src/assertions.ts +1 -2
- package/src/impl/LslEventMarkerEmitter.ts +15 -17
- package/src/impl/LslStreamInfo.ts +7 -9
- package/src/impl/LslStreamInlet.ts +304 -77
- package/src/impl/LslStreamOutlet.ts +59 -57
- package/src/impl/LslWebSocketBridge.ts +15 -18
- package/src/impl/clocks/WindowedClockRegressor.ts +136 -0
- package/src/impl/controllers/BleDeviceController.ts +18 -1
- package/src/impl/controllers/UsbDeviceController.ts +65 -0
- package/src/index.ts +48 -28
- package/src/scripts/{runLslEventMarkerEmitter.ts → runLslEmitter.ts} +4 -3
- package/src/scripts/runMuse.ts +1 -1
- 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/{EventMarkerEmitter/FakeEventMarkerEmitter.ts → LslEmitter/FakeLslEmitter.ts} +10 -10
- package/src/testDoubles/{EventMarkerEmitter/SpyEventMarkerEmitter.ts → LslEmitter/SpyLslEmitter.ts} +4 -4
- package/src/testDoubles/{EventMarkerEmitter/ThrowingEventMarkerEmitter.ts → LslEmitter/ThrowingLslEmitter.ts} +4 -4
- package/src/testDoubles/{StreamInfo/FakeStreamInfo.ts → LslInfo/FakeLslInfo.ts} +9 -9
- package/src/testDoubles/{StreamInfo/SpyStreamInfo.ts → LslInfo/SpyLslInfo.ts} +5 -5
- package/src/testDoubles/{StreamInlet/FakeStreamInlet.ts → LslInlet/FakeLslInlet.ts} +15 -14
- package/src/testDoubles/LslInlet/SpyLslInlet.ts +10 -0
- package/src/testDoubles/{StreamOutlet/FakeStreamOutlet.ts → LslOutlet/FakeLslOutlet.ts} +11 -14
- package/src/testDoubles/{WebSocketBridge/FakeWebSocketBridge.ts → LslWsBridge/FakeLslWsBridge.ts} +19 -20
- package/src/testDoubles/LslWsBridge/SpyLslWsBridge.ts +9 -0
- package/src/testDoubles/UsbController/FakeUsbController.ts +34 -0
- package/src/testDoubles/consts.ts +3 -23
- package/src/testDoubles/generateRandomOutletOptions.ts +2 -2
- package/build/consts.d.ts +0 -11
- package/build/consts.js +0 -21
- package/build/consts.js.map +0 -1
- package/build/impl/workers/inlet/LslStreamInlet.worker.d.ts +0 -22
- package/build/impl/workers/inlet/LslStreamInlet.worker.js +0 -42
- package/build/impl/workers/inlet/LslStreamInlet.worker.js.map +0 -1
- package/build/impl/workers/inlet/StreamInletWorker.d.ts +0 -73
- package/build/impl/workers/inlet/StreamInletWorker.js +0 -253
- package/build/impl/workers/inlet/StreamInletWorker.js.map +0 -1
- package/build/impl/workers/outlet/LslStreamOutlet.worker.d.ts +0 -32
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js +0 -82
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js.map +0 -1
- package/build/scripts/discoverMuse.js +0 -40
- package/build/scripts/discoverMuse.js.map +0 -1
- package/build/scripts/runLslEventMarkerEmitter.js.map +0 -1
- package/build/scripts/runLslStreamOutlet.js.map +0 -1
- package/build/scripts/testDestroyOutlet.d.ts +0 -1
- package/build/scripts/testDestroyOutlet.js +0 -4
- package/build/scripts/testDestroyOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js.map +0 -1
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js.map +0 -1
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.d.ts +0 -9
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js.map +0 -1
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +0 -1
- package/build/testDoubles/StreamInfo/SpyStreamInfo.d.ts +0 -10
- package/build/testDoubles/StreamInfo/SpyStreamInfo.js.map +0 -1
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +0 -1
- package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +0 -4
- package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +0 -1
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +0 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +0 -14
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +0 -1
- package/build/testDoubles/WebSocketBridge/SpyLslWebSocketBridge.d.ts +0 -4
- package/build/testDoubles/WebSocketBridge/SpyLslWebSocketBridge.js.map +0 -1
- package/build/testDoubles/WorkerThreads/FakeWorker.d.ts +0 -27
- package/build/testDoubles/WorkerThreads/FakeWorker.js +0 -67
- package/build/testDoubles/WorkerThreads/FakeWorker.js.map +0 -1
- package/src/consts.ts +0 -21
- package/src/impl/workers/inlet/LslStreamInlet.worker.ts +0 -74
- package/src/impl/workers/inlet/StreamInletWorker.ts +0 -348
- package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +0 -144
- package/src/scripts/discoverMuse.ts +0 -50
- package/src/scripts/testDestroyOutlet.ts +0 -5
- package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +0 -10
- package/src/testDoubles/WebSocketBridge/SpyLslWebSocketBridge.ts +0 -9
- package/src/testDoubles/WorkerThreads/FakeWorker.ts +0 -99
- /package/build/scripts/{discoverMuse.d.ts → runLslEmitter.d.ts} +0 -0
- /package/build/scripts/{runLslEventMarkerEmitter.d.ts → runLslOutlet.d.ts} +0 -0
- /package/build/scripts/{runLslStreamOutlet.d.ts → runUsb.d.ts} +0 -0
- /package/src/scripts/{runLslStreamOutlet.ts → runLslOutlet.ts} +0 -0
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import WebSocket, { WebSocketServer } from 'ws'
|
|
2
2
|
|
|
3
|
-
import LslStreamInlet, {
|
|
4
|
-
StreamInlet,
|
|
5
|
-
StreamInletOptions,
|
|
6
|
-
} from './LslStreamInlet.js'
|
|
3
|
+
import LslStreamInlet, { LslInlet, LslInletOptions } from './LslStreamInlet.js'
|
|
7
4
|
|
|
8
|
-
export default class LslWebSocketBridge implements
|
|
9
|
-
public static Class?:
|
|
5
|
+
export default class LslWebSocketBridge implements LslWsBridge {
|
|
6
|
+
public static Class?: LslWsBridgeConstructor
|
|
10
7
|
public static WS = WebSocket
|
|
11
8
|
public static WSS = WebSocketServer
|
|
12
9
|
|
|
13
|
-
private inlet:
|
|
10
|
+
private inlet: LslInlet
|
|
14
11
|
private localServer?: WebSocketServer
|
|
15
12
|
private remoteSockets?: WebSocket[]
|
|
16
13
|
|
|
17
14
|
private isDestroyed = false
|
|
18
15
|
|
|
19
|
-
protected constructor(options:
|
|
16
|
+
protected constructor(options: LslWsBridgeConstructorOptions) {
|
|
20
17
|
const { inlet, localServer, remoteSockets } = options
|
|
21
18
|
|
|
22
19
|
this.inlet = inlet
|
|
@@ -26,9 +23,9 @@ export default class LslWebSocketBridge implements WebSocketBridge {
|
|
|
26
23
|
this.throwIfNoLocalServerOrRemoteSockets()
|
|
27
24
|
}
|
|
28
25
|
|
|
29
|
-
public static async Create(options:
|
|
26
|
+
public static async Create(options: LslWsBridgeOptions) {
|
|
30
27
|
const { listenPort, connectUrls, ...rest } = options
|
|
31
|
-
const inletOptions:
|
|
28
|
+
const inletOptions: LslInletOptions = rest
|
|
32
29
|
|
|
33
30
|
const localServer = this.WebSocketServer(listenPort)
|
|
34
31
|
const remoteSockets = this.createSocketsFrom(connectUrls)
|
|
@@ -155,7 +152,7 @@ export default class LslWebSocketBridge implements WebSocketBridge {
|
|
|
155
152
|
}
|
|
156
153
|
|
|
157
154
|
private static async LslStreamInlet(
|
|
158
|
-
options:
|
|
155
|
+
options: LslInletOptions,
|
|
159
156
|
localServer?: WebSocketServer,
|
|
160
157
|
remoteSockets?: WebSocket[]
|
|
161
158
|
) {
|
|
@@ -164,25 +161,25 @@ export default class LslWebSocketBridge implements WebSocketBridge {
|
|
|
164
161
|
}
|
|
165
162
|
}
|
|
166
163
|
|
|
167
|
-
export interface
|
|
164
|
+
export interface LslWsBridge {
|
|
168
165
|
activate(): Promise<void>
|
|
169
166
|
deactivate(): void
|
|
170
167
|
destroy(): void
|
|
171
168
|
}
|
|
172
169
|
|
|
173
|
-
export type
|
|
174
|
-
options:
|
|
175
|
-
) =>
|
|
170
|
+
export type LslWsBridgeConstructor = new (
|
|
171
|
+
options: LslWsBridgeConstructorOptions
|
|
172
|
+
) => LslWsBridge
|
|
176
173
|
|
|
177
|
-
export interface
|
|
174
|
+
export interface LslWsBridgeOptions {
|
|
178
175
|
sourceId: string
|
|
179
176
|
chunkSize: number
|
|
180
177
|
listenPort?: number
|
|
181
178
|
connectUrls?: string | string[]
|
|
182
179
|
}
|
|
183
180
|
|
|
184
|
-
export interface
|
|
185
|
-
inlet:
|
|
181
|
+
export interface LslWsBridgeConstructorOptions extends LslWsBridgeOptions {
|
|
182
|
+
inlet: LslInlet
|
|
186
183
|
localServer?: WebSocketServer
|
|
187
184
|
remoteSockets?: WebSocket[]
|
|
188
185
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export default class WindowedClockRegressor implements ClockRegressor {
|
|
2
|
+
public static Class?: ClockRegressorConstructor
|
|
3
|
+
|
|
4
|
+
private readonly nominalHz: number
|
|
5
|
+
private readonly windowLenSec: number
|
|
6
|
+
private readonly defaultWindowLenSec = 30
|
|
7
|
+
private readonly history: {
|
|
8
|
+
deviceTime: number
|
|
9
|
+
earliestLslTime: number
|
|
10
|
+
}[] = []
|
|
11
|
+
|
|
12
|
+
private slope = 1 // lsl-host-seconds per device-second
|
|
13
|
+
|
|
14
|
+
protected constructor(
|
|
15
|
+
nominalHz: number,
|
|
16
|
+
options?: WindowedClockRegressorOptions
|
|
17
|
+
) {
|
|
18
|
+
const { windowLenSec = this.defaultWindowLenSec } = options ?? {}
|
|
19
|
+
|
|
20
|
+
this.nominalHz = nominalHz
|
|
21
|
+
this.windowLenSec = windowLenSec
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public static Create(
|
|
25
|
+
nominalHz: number,
|
|
26
|
+
options?: WindowedClockRegressorOptions
|
|
27
|
+
) {
|
|
28
|
+
return new (this.Class ?? this)(nominalHz, options)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public deriveTimestamps(
|
|
32
|
+
deviceTime: number,
|
|
33
|
+
earliestLslTime: number,
|
|
34
|
+
chunkSize: number
|
|
35
|
+
) {
|
|
36
|
+
this.throwIfDeviceTimeDoesNotIncrease(deviceTime)
|
|
37
|
+
|
|
38
|
+
this.history.push({ deviceTime, earliestLslTime })
|
|
39
|
+
this.pruneHistoryOutsideWindow()
|
|
40
|
+
this.refitSlope()
|
|
41
|
+
|
|
42
|
+
const anchor = this.anchorTimeFor(deviceTime)
|
|
43
|
+
|
|
44
|
+
const timestamps = Array(chunkSize).fill(0)
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i <= chunkSize - 1; i++) {
|
|
47
|
+
const stepsFromLast = chunkSize - 1 - i
|
|
48
|
+
const deviceTimeOffset = -stepsFromLast / this.nominalHz
|
|
49
|
+
const lslTimeOffset = deviceTimeOffset * this.slope
|
|
50
|
+
|
|
51
|
+
timestamps[i] = anchor + lslTimeOffset
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return timestamps
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private anchorTimeFor(deviceTime: number) {
|
|
58
|
+
const xMean = this.currentMeanDeviceTime
|
|
59
|
+
const yMean = this.currentMeanLslTime
|
|
60
|
+
|
|
61
|
+
return yMean + this.slope * (deviceTime - xMean)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private throwIfDeviceTimeDoesNotIncrease(deviceTime: number) {
|
|
65
|
+
const last = this.history[this.history.length - 1]
|
|
66
|
+
|
|
67
|
+
if (last && deviceTime <= last.deviceTime) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`\nDevice time (${deviceTime}) did not increase from the previous device time (${last.deviceTime})! Device time is expected to always increase between calls, so this likely indicates a bug in the calling code.\n`
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private pruneHistoryOutsideWindow() {
|
|
75
|
+
const { deviceTime: latest } = this.history[this.history.length - 1]
|
|
76
|
+
const cutoff = latest - this.windowLenSec
|
|
77
|
+
|
|
78
|
+
while (this.history.length > 0 && this.history[0].deviceTime < cutoff) {
|
|
79
|
+
this.history.shift()
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private refitSlope() {
|
|
84
|
+
if (this.history.length < 2) {
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const xMean = this.currentMeanDeviceTime
|
|
89
|
+
const yMean = this.currentMeanLslTime
|
|
90
|
+
|
|
91
|
+
let numerator = 0
|
|
92
|
+
let denominator = 0
|
|
93
|
+
|
|
94
|
+
for (const { deviceTime, earliestLslTime } of this.history) {
|
|
95
|
+
const xCentered = deviceTime - xMean
|
|
96
|
+
|
|
97
|
+
numerator += xCentered * (earliestLslTime - yMean)
|
|
98
|
+
denominator += xCentered * xCentered
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.slope = numerator / denominator
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private get currentMeanDeviceTime() {
|
|
105
|
+
const totalDeviceTime = this.history.reduce(
|
|
106
|
+
(sum, { deviceTime }) => sum + deviceTime,
|
|
107
|
+
0
|
|
108
|
+
)
|
|
109
|
+
return totalDeviceTime / this.history.length
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private get currentMeanLslTime() {
|
|
113
|
+
const totalLslTime = this.history.reduce(
|
|
114
|
+
(sum, { earliestLslTime }) => sum + earliestLslTime,
|
|
115
|
+
0
|
|
116
|
+
)
|
|
117
|
+
return totalLslTime / this.history.length
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface ClockRegressor {
|
|
122
|
+
deriveTimestamps(
|
|
123
|
+
deviceTime: number,
|
|
124
|
+
earliestLslTime: number,
|
|
125
|
+
chunkSize: number
|
|
126
|
+
): number[]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export type ClockRegressorConstructor = new (
|
|
130
|
+
nominalHz: number,
|
|
131
|
+
options?: WindowedClockRegressorOptions
|
|
132
|
+
) => ClockRegressor
|
|
133
|
+
|
|
134
|
+
export interface WindowedClockRegressorOptions {
|
|
135
|
+
windowLenSec?: number
|
|
136
|
+
}
|
|
@@ -44,7 +44,7 @@ export default class BleDeviceController implements BleController {
|
|
|
44
44
|
this.rssiIntervalMs = rssiIntervalMs
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
public static
|
|
47
|
+
public static Create(options: BleControllerOptions) {
|
|
48
48
|
return new (this.Class ?? this)(options)
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -165,6 +165,19 @@ export default class BleDeviceController implements BleController {
|
|
|
165
165
|
this.throwIfError(status, error)
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
public async subscribeCharacteristics(
|
|
169
|
+
charCallbacks: CharacteristicCallbacks
|
|
170
|
+
) {
|
|
171
|
+
const { status, error } = this.ndx.addBleCharCallbacks({
|
|
172
|
+
deviceUuid: this.uuid,
|
|
173
|
+
charCallbacks,
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
this.throwIfError(status, error)
|
|
177
|
+
|
|
178
|
+
this.charCallbacks = [...this.charCallbacks, ...charCallbacks]
|
|
179
|
+
}
|
|
180
|
+
|
|
168
181
|
public async disconnect() {
|
|
169
182
|
const { status, error } = this.ndx.stopBleBackend({
|
|
170
183
|
deviceUuid: this.uuid,
|
|
@@ -193,6 +206,10 @@ export interface BleController {
|
|
|
193
206
|
|
|
194
207
|
connect(): Promise<void>
|
|
195
208
|
|
|
209
|
+
subscribeCharacteristics(
|
|
210
|
+
charCallbacks: CharacteristicCallbacks
|
|
211
|
+
): Promise<void>
|
|
212
|
+
|
|
196
213
|
writeCharacteristic(
|
|
197
214
|
charUuid: CharacteristicUuid,
|
|
198
215
|
value: string
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { LibndxAdapter } from '@neurodevs/ndx-native'
|
|
2
|
+
|
|
3
|
+
export default class UsbDeviceController implements UsbController {
|
|
4
|
+
public static Class?: UsbControllerConstructor
|
|
5
|
+
|
|
6
|
+
private onData: (data: Buffer, length: number, timestampSec: number) => void
|
|
7
|
+
private serialNumber: string
|
|
8
|
+
|
|
9
|
+
private ndx = LibndxAdapter.getInstance()
|
|
10
|
+
|
|
11
|
+
protected constructor(options: UsbControllerOptions) {
|
|
12
|
+
const { onData, serialNumber } = options ?? {}
|
|
13
|
+
|
|
14
|
+
this.onData = onData
|
|
15
|
+
this.serialNumber = serialNumber ?? ''
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public static Create(options: UsbControllerOptions) {
|
|
19
|
+
return new (this.Class ?? this)(options)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public async connect() {
|
|
23
|
+
this.ndx.createUsbBackend(this.usbControllerOptions)
|
|
24
|
+
this.ndx.startUsbBackend(this.startUsbControllerOptions)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private get usbControllerOptions() {
|
|
28
|
+
return {
|
|
29
|
+
serialNumber: this.serialNumber,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private get startUsbControllerOptions() {
|
|
34
|
+
return {
|
|
35
|
+
...this.usbControllerOptions,
|
|
36
|
+
onData: this.onData,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async writeUsb(value: string) {
|
|
41
|
+
this.ndx.writeUsbBackend({
|
|
42
|
+
...this.usbControllerOptions,
|
|
43
|
+
value,
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public async disconnect() {
|
|
48
|
+
this.ndx.stopUsbBackend(this.usbControllerOptions)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface UsbController {
|
|
53
|
+
connect(): Promise<void>
|
|
54
|
+
writeUsb(value: string): Promise<void>
|
|
55
|
+
disconnect(): Promise<void>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface UsbControllerOptions {
|
|
59
|
+
onData: (data: Buffer, length: number, timestampSec: number) => void
|
|
60
|
+
serialNumber?: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type UsbControllerConstructor = new (
|
|
64
|
+
options?: UsbControllerOptions
|
|
65
|
+
) => UsbController
|
package/src/index.ts
CHANGED
|
@@ -1,66 +1,86 @@
|
|
|
1
|
+
// ClockRegressor
|
|
2
|
+
|
|
3
|
+
export { default as WindowedClockRegressor } from './impl/clocks/WindowedClockRegressor.js'
|
|
4
|
+
export * from './impl/clocks/WindowedClockRegressor.js'
|
|
5
|
+
|
|
6
|
+
export { default as FakeClockRegressor } from './testDoubles/ClockRegressor/FakeClockRegressor.js'
|
|
7
|
+
export * from './testDoubles/ClockRegressor/FakeClockRegressor.js'
|
|
8
|
+
|
|
1
9
|
// DeviceController
|
|
2
10
|
|
|
3
11
|
export { default as BleDeviceController } from './impl/controllers/BleDeviceController.js'
|
|
4
12
|
export * from './impl/controllers/BleDeviceController.js'
|
|
5
13
|
|
|
14
|
+
export { default as SpyBleController } from './testDoubles/BleController/SpyBleController.js'
|
|
15
|
+
export * from './testDoubles/BleController/SpyBleController.js'
|
|
16
|
+
|
|
6
17
|
export { default as FakeBleController } from './testDoubles/BleController/FakeBleController.js'
|
|
7
18
|
export * from './testDoubles/BleController/FakeBleController.js'
|
|
8
19
|
|
|
9
|
-
|
|
10
|
-
export * from './testDoubles/BleController/SpyBleController.js'
|
|
20
|
+
// LslWsBridge
|
|
11
21
|
|
|
12
|
-
|
|
22
|
+
export { default as LslWebSocketBridge } from './impl/LslWebSocketBridge.js'
|
|
23
|
+
export * from './impl/LslWebSocketBridge.js'
|
|
24
|
+
|
|
25
|
+
export { default as SpyLslWsBridge } from './testDoubles/LslWsBridge/SpyLslWsBridge.js'
|
|
26
|
+
export * from './testDoubles/LslWsBridge/SpyLslWsBridge.js'
|
|
27
|
+
|
|
28
|
+
export { default as FakeLslWsBridge } from './testDoubles/LslWsBridge/FakeLslWsBridge.js'
|
|
29
|
+
export * from './testDoubles/LslWsBridge/FakeLslWsBridge.js'
|
|
30
|
+
|
|
31
|
+
// LslEmitter
|
|
13
32
|
|
|
14
33
|
export { default as LslEventMarkerEmitter } from './impl/LslEventMarkerEmitter.js'
|
|
15
34
|
export * from './impl/LslEventMarkerEmitter.js'
|
|
16
35
|
|
|
17
|
-
export { default as
|
|
18
|
-
export * from './testDoubles/
|
|
36
|
+
export { default as SpyLslEmitter } from './testDoubles/LslEmitter/SpyLslEmitter.js'
|
|
37
|
+
export * from './testDoubles/LslEmitter/SpyLslEmitter.js'
|
|
19
38
|
|
|
20
|
-
export { default as
|
|
21
|
-
export * from './testDoubles/
|
|
39
|
+
export { default as FakeLslEmitter } from './testDoubles/LslEmitter/FakeLslEmitter.js'
|
|
40
|
+
export * from './testDoubles/LslEmitter/FakeLslEmitter.js'
|
|
22
41
|
|
|
23
|
-
export { default as
|
|
24
|
-
export * from './testDoubles/
|
|
42
|
+
export { default as ThrowingLslEmitter } from './testDoubles/LslEmitter/ThrowingLslEmitter.js'
|
|
43
|
+
export * from './testDoubles/LslEmitter/ThrowingLslEmitter.js'
|
|
25
44
|
|
|
26
|
-
//
|
|
45
|
+
// LslInfo
|
|
27
46
|
|
|
28
47
|
export { default as LslStreamInfo } from './impl/LslStreamInfo.js'
|
|
29
48
|
export * from './impl/LslStreamInfo.js'
|
|
30
49
|
|
|
31
|
-
export { default as
|
|
32
|
-
export * from './testDoubles/
|
|
50
|
+
export { default as SpyLslInfo } from './testDoubles/LslInfo/SpyLslInfo.js'
|
|
51
|
+
export * from './testDoubles/LslInfo/SpyLslInfo.js'
|
|
33
52
|
|
|
34
|
-
export { default as
|
|
35
|
-
export * from './testDoubles/
|
|
53
|
+
export { default as FakeLslInfo } from './testDoubles/LslInfo/FakeLslInfo.js'
|
|
54
|
+
export * from './testDoubles/LslInfo/FakeLslInfo.js'
|
|
36
55
|
|
|
37
|
-
//
|
|
56
|
+
// LslInlet
|
|
38
57
|
|
|
39
58
|
export { default as LslStreamInlet } from './impl/LslStreamInlet.js'
|
|
40
59
|
export * from './impl/LslStreamInlet.js'
|
|
41
60
|
|
|
42
|
-
export { default as
|
|
43
|
-
export * from './testDoubles/
|
|
61
|
+
export { default as SpyLslInlet } from './testDoubles/LslInlet/SpyLslInlet.js'
|
|
62
|
+
export * from './testDoubles/LslInlet/SpyLslInlet.js'
|
|
44
63
|
|
|
45
|
-
|
|
64
|
+
export { default as FakeLslInlet } from './testDoubles/LslInlet/FakeLslInlet.js'
|
|
65
|
+
export * from './testDoubles/LslInlet/FakeLslInlet.js'
|
|
66
|
+
|
|
67
|
+
// LslOutlet
|
|
46
68
|
|
|
47
69
|
export { default as LslStreamOutlet } from './impl/LslStreamOutlet.js'
|
|
48
70
|
export * from './impl/LslStreamOutlet.js'
|
|
49
71
|
|
|
50
|
-
export { default as
|
|
51
|
-
export * from './testDoubles/
|
|
52
|
-
|
|
53
|
-
// WebSocketBridge
|
|
72
|
+
export { default as FakeLslOutlet } from './testDoubles/LslOutlet/FakeLslOutlet.js'
|
|
73
|
+
export * from './testDoubles/LslOutlet/FakeLslOutlet.js'
|
|
54
74
|
|
|
55
|
-
export { default as
|
|
56
|
-
export * from './impl/LslWebSocketBridge.js'
|
|
75
|
+
export { default as generateRandomOutletOptions } from './testDoubles/generateRandomOutletOptions.js'
|
|
57
76
|
|
|
58
|
-
|
|
59
|
-
export * from './testDoubles/WebSocketBridge/FakeWebSocketBridge.js'
|
|
77
|
+
// UsbController
|
|
60
78
|
|
|
61
|
-
|
|
79
|
+
export { default as UsbDeviceController } from './impl/controllers/UsbDeviceController.js'
|
|
80
|
+
export * from './impl/controllers/UsbDeviceController.js'
|
|
62
81
|
|
|
63
|
-
export { default as
|
|
82
|
+
export { default as FakeUsbController } from './testDoubles/UsbController/FakeUsbController.js'
|
|
83
|
+
export * from './testDoubles/UsbController/FakeUsbController.js'
|
|
64
84
|
|
|
65
85
|
// WebSockets
|
|
66
86
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import LslEventMarkerEmitter from '../impl/LslEventMarkerEmitter.js'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const emitter = await LslEventMarkerEmitter.Create()
|
|
4
4
|
|
|
5
5
|
const markers = [
|
|
6
6
|
{ name: 'phase-1-begin', waitAfterMs: 100 },
|
|
@@ -8,8 +8,9 @@ const markers = [
|
|
|
8
8
|
{ name: 'never-reached-marker', waitAfterMs: 100 },
|
|
9
9
|
]
|
|
10
10
|
|
|
11
|
-
void
|
|
11
|
+
void emitter.emitMany(markers)
|
|
12
12
|
|
|
13
13
|
await new Promise((resolve) => setTimeout(resolve, 250))
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
emitter.interrupt()
|
|
16
|
+
emitter.destroy()
|
package/src/scripts/runMuse.ts
CHANGED
|
@@ -32,7 +32,7 @@ const charCallbacks = Object.entries(MUSE_CHARACTERISTIC_UUIDS).map(
|
|
|
32
32
|
}
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
-
const muse =
|
|
35
|
+
const muse = BleDeviceController.Create({
|
|
36
36
|
deviceUuid: 'CA6A61B7-B7A8-AF24-3C9E-04A6A5012554',
|
|
37
37
|
charCallbacks,
|
|
38
38
|
rssiIntervalMs: 1000,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import UsbDeviceController from '../impl/controllers/UsbDeviceController.js'
|
|
2
|
+
|
|
3
|
+
console.info('\nCreating UsbDeviceController...')
|
|
4
|
+
|
|
5
|
+
const controller = UsbDeviceController.Create({
|
|
6
|
+
serialNumber: 'DP04WG8J',
|
|
7
|
+
onData: (_data: Buffer, length: number, timestampSec: number) => {
|
|
8
|
+
console.info(`[${timestampSec}] Buffer length: ${length}`)
|
|
9
|
+
},
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
console.info('Connecting to UsbDeviceController...')
|
|
13
|
+
|
|
14
|
+
await controller.connect()
|
|
15
|
+
|
|
16
|
+
console.info('Waiting for 10 seconds...')
|
|
17
|
+
|
|
18
|
+
await new Promise((resolve) => setTimeout(resolve, 10000))
|
|
19
|
+
|
|
20
|
+
console.info('Done!')
|
|
@@ -2,6 +2,7 @@ import generateId from '@neurodevs/generate-id'
|
|
|
2
2
|
import {
|
|
3
3
|
BleController,
|
|
4
4
|
BleControllerOptions,
|
|
5
|
+
CharacteristicCallbacks,
|
|
5
6
|
} from '../../impl/controllers/BleDeviceController.js'
|
|
6
7
|
|
|
7
8
|
export default class FakeBleController implements BleController {
|
|
@@ -14,6 +15,9 @@ export default class FakeBleController implements BleController {
|
|
|
14
15
|
value: string
|
|
15
16
|
}[] = []
|
|
16
17
|
|
|
18
|
+
public static callsToSubscribeCharacteristics: CharacteristicCallbacks[] =
|
|
19
|
+
[]
|
|
20
|
+
|
|
17
21
|
public static numCallsToDisconnect = 0
|
|
18
22
|
|
|
19
23
|
public static fakeCharacteristics: Record<string, unknown> = {}
|
|
@@ -45,6 +49,12 @@ export default class FakeBleController implements BleController {
|
|
|
45
49
|
})
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
public async subscribeCharacteristics(
|
|
53
|
+
charCallbacks: CharacteristicCallbacks
|
|
54
|
+
) {
|
|
55
|
+
FakeBleController.callsToSubscribeCharacteristics.push(charCallbacks)
|
|
56
|
+
}
|
|
57
|
+
|
|
48
58
|
public async disconnect() {
|
|
49
59
|
FakeBleController.numCallsToDisconnect++
|
|
50
60
|
}
|
|
@@ -61,6 +71,7 @@ export default class FakeBleController implements BleController {
|
|
|
61
71
|
this.callsToConstructor = []
|
|
62
72
|
this.numCallsToConnect = 0
|
|
63
73
|
this.callsToWriteCharacteristic = []
|
|
74
|
+
this.callsToSubscribeCharacteristics = []
|
|
64
75
|
this.numCallsToDisconnect = 0
|
|
65
76
|
}
|
|
66
77
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClockRegressor,
|
|
3
|
+
WindowedClockRegressorOptions,
|
|
4
|
+
} from '../../impl/clocks/WindowedClockRegressor.js'
|
|
5
|
+
|
|
6
|
+
export default class FakeClockRegressor implements ClockRegressor {
|
|
7
|
+
public static callsToConstructor: {
|
|
8
|
+
nominalHz: number
|
|
9
|
+
options?: WindowedClockRegressorOptions
|
|
10
|
+
}[] = []
|
|
11
|
+
public static callsToDeriveTimestamps: {
|
|
12
|
+
deviceTime: number
|
|
13
|
+
earliestLslTime: number
|
|
14
|
+
chunkSize: number
|
|
15
|
+
}[] = []
|
|
16
|
+
|
|
17
|
+
public static fakeResultValue = 0
|
|
18
|
+
|
|
19
|
+
public readonly nominalHz: number
|
|
20
|
+
|
|
21
|
+
public constructor(
|
|
22
|
+
nominalHz: number,
|
|
23
|
+
options?: WindowedClockRegressorOptions
|
|
24
|
+
) {
|
|
25
|
+
FakeClockRegressor.callsToConstructor.push({ nominalHz, options })
|
|
26
|
+
this.nominalHz = nominalHz
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public deriveTimestamps(
|
|
30
|
+
deviceTime: number,
|
|
31
|
+
earliestLslTime: number,
|
|
32
|
+
chunkSize: number
|
|
33
|
+
) {
|
|
34
|
+
FakeClockRegressor.callsToDeriveTimestamps.push({
|
|
35
|
+
deviceTime,
|
|
36
|
+
earliestLslTime,
|
|
37
|
+
chunkSize,
|
|
38
|
+
})
|
|
39
|
+
return Array(chunkSize).fill(FakeClockRegressor.fakeResultValue)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public static resetTestDouble() {
|
|
43
|
+
FakeClockRegressor.callsToConstructor = []
|
|
44
|
+
FakeClockRegressor.callsToDeriveTimestamps = []
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
LslEmitter,
|
|
3
|
+
EmitOptions,
|
|
4
4
|
TimedEventMarker,
|
|
5
5
|
} from '../../impl/LslEventMarkerEmitter.js'
|
|
6
6
|
|
|
7
|
-
export default class
|
|
7
|
+
export default class FakeLslEmitter implements LslEmitter {
|
|
8
8
|
public static numCallsToConstructor = 0
|
|
9
9
|
|
|
10
10
|
public static callsToEmit: {
|
|
11
11
|
markerName: string
|
|
12
|
-
options?:
|
|
12
|
+
options?: EmitOptions
|
|
13
13
|
}[] = []
|
|
14
14
|
|
|
15
15
|
public static callsToEmitMany: TimedEventMarker[][] = []
|
|
@@ -17,23 +17,23 @@ export default class FakeEventMarkerEmitter implements EventMarkerEmitter {
|
|
|
17
17
|
public static numCallsToDestroy = 0
|
|
18
18
|
|
|
19
19
|
public constructor() {
|
|
20
|
-
|
|
20
|
+
FakeLslEmitter.numCallsToConstructor++
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
public async emit(markerName: string, options?:
|
|
24
|
-
|
|
23
|
+
public async emit(markerName: string, options?: EmitOptions) {
|
|
24
|
+
FakeLslEmitter.callsToEmit.push({ markerName, options })
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
public async emitMany(markers: TimedEventMarker[]) {
|
|
28
|
-
|
|
28
|
+
FakeLslEmitter.callsToEmitMany.push(markers)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
public interrupt() {
|
|
32
|
-
|
|
32
|
+
FakeLslEmitter.numCallsToInterrupt++
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
public destroy() {
|
|
36
|
-
|
|
36
|
+
FakeLslEmitter.numCallsToDestroy++
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
public static resetTestDouble() {
|
package/src/testDoubles/{EventMarkerEmitter/SpyEventMarkerEmitter.ts → LslEmitter/SpyLslEmitter.ts}
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import LslEventMarkerEmitter from '../../impl/LslEventMarkerEmitter.js'
|
|
2
|
-
import {
|
|
2
|
+
import { LslOutlet } from '../../impl/LslStreamOutlet.js'
|
|
3
3
|
|
|
4
|
-
export default class
|
|
4
|
+
export default class SpyLslEmitter extends LslEventMarkerEmitter {
|
|
5
5
|
public static shouldCallWaitOnSuper = false
|
|
6
6
|
|
|
7
7
|
public totalwaitAfterMs: number
|
|
8
8
|
|
|
9
|
-
public constructor(outlet:
|
|
9
|
+
public constructor(outlet: LslOutlet) {
|
|
10
10
|
super(outlet)
|
|
11
11
|
|
|
12
12
|
this.totalwaitAfterMs = 0
|
|
@@ -15,7 +15,7 @@ export default class SpyEventMarkerEmitter extends LslEventMarkerEmitter {
|
|
|
15
15
|
public async wait(waitAfterMs: number) {
|
|
16
16
|
this.totalwaitAfterMs += waitAfterMs
|
|
17
17
|
|
|
18
|
-
if (
|
|
18
|
+
if (SpyLslEmitter.shouldCallWaitOnSuper) {
|
|
19
19
|
return super.wait(waitAfterMs)
|
|
20
20
|
}
|
|
21
21
|
return Promise.resolve()
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
LslEmitter,
|
|
3
|
+
EmitOptions,
|
|
4
4
|
TimedEventMarker,
|
|
5
5
|
} from '../../impl/LslEventMarkerEmitter.js'
|
|
6
6
|
|
|
7
|
-
export default class
|
|
7
|
+
export default class ThrowingLslEmitter implements LslEmitter {
|
|
8
8
|
private errorMsg = 'Intentional throwing: '
|
|
9
9
|
|
|
10
10
|
public constructor() {
|
|
11
11
|
throw new Error(this.errorMsg + 'constructor')
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
public async emit(_markerName: string, _options?:
|
|
14
|
+
public async emit(_markerName: string, _options?: EmitOptions) {
|
|
15
15
|
throw new Error(this.errorMsg + 'emit')
|
|
16
16
|
}
|
|
17
17
|
|