@neurodevs/node-lsl 20.0.0 → 22.1.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.
Files changed (117) hide show
  1. package/README.md +6 -6
  2. package/build/__tests__/AbstractPackageTest.d.ts +2 -1
  3. package/build/__tests__/AbstractPackageTest.js +9 -7
  4. package/build/__tests__/AbstractPackageTest.js.map +1 -1
  5. package/build/__tests__/impl/{BleDeviceController.test.d.ts → BleGattController.test.d.ts} +3 -3
  6. package/build/__tests__/impl/{BleDeviceController.test.js → BleGattController.test.js} +65 -65
  7. package/build/__tests__/impl/BleGattController.test.js.map +1 -0
  8. package/build/__tests__/impl/BleObserverController.test.d.ts +22 -0
  9. package/build/__tests__/impl/BleObserverController.test.js +112 -0
  10. package/build/__tests__/impl/BleObserverController.test.js.map +1 -0
  11. package/build/__tests__/impl/{LslEventMarkerEmitter.test.d.ts → LslEventMarkerOutlet.test.d.ts} +3 -3
  12. package/build/__tests__/impl/{LslEventMarkerEmitter.test.js → LslEventMarkerOutlet.test.js} +35 -36
  13. package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +1 -0
  14. package/build/__tests__/impl/LslJsonOutlet.test.d.ts +14 -0
  15. package/build/__tests__/impl/LslJsonOutlet.test.js +118 -0
  16. package/build/__tests__/impl/LslJsonOutlet.test.js.map +1 -0
  17. package/build/__tests__/impl/LslStreamInfo.test.js +0 -1
  18. package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
  19. package/build/__tests__/impl/LslStreamInlet.test.js +0 -1
  20. package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
  21. package/build/__tests__/impl/LslStreamOutlet.test.js +0 -1
  22. package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
  23. package/build/__tests__/impl/LslWebSocketBridge.test.js +0 -1
  24. package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
  25. package/build/__tests__/impl/UsbDeviceController.test.js.map +1 -1
  26. package/build/impl/{LslEventMarkerEmitter.d.ts → LslEventMarkerOutlet.d.ts} +6 -6
  27. package/build/impl/{LslEventMarkerEmitter.js → LslEventMarkerOutlet.js} +2 -2
  28. package/build/impl/LslEventMarkerOutlet.js.map +1 -0
  29. package/build/impl/LslJsonOutlet.d.ts +33 -0
  30. package/build/impl/LslJsonOutlet.js +44 -0
  31. package/build/impl/LslJsonOutlet.js.map +1 -0
  32. package/build/impl/LslStreamOutlet.d.ts +3 -4
  33. package/build/impl/controllers/{BleDeviceController.d.ts → BleGattController.d.ts} +10 -10
  34. package/build/impl/controllers/{BleDeviceController.js → BleGattController.js} +18 -18
  35. package/build/impl/controllers/BleGattController.js.map +1 -0
  36. package/build/impl/controllers/BleObserverController.d.ts +24 -0
  37. package/build/impl/controllers/BleObserverController.js +49 -0
  38. package/build/impl/controllers/BleObserverController.js.map +1 -0
  39. package/build/impl/controllers/UsbDeviceController.d.ts +9 -9
  40. package/build/impl/controllers/UsbDeviceController.js +7 -7
  41. package/build/impl/controllers/UsbDeviceController.js.map +1 -1
  42. package/build/index.d.ts +24 -16
  43. package/build/index.js +29 -19
  44. package/build/index.js.map +1 -1
  45. package/build/scripts/runEventMarkerOutlet.js +12 -0
  46. package/build/scripts/runEventMarkerOutlet.js.map +1 -0
  47. package/build/scripts/runMuse.js +2 -2
  48. package/build/scripts/runMuse.js.map +1 -1
  49. package/build/testDoubles/{BleController/FakeBleController.d.ts → BleGatt/FakeBleGatt.d.ts} +6 -6
  50. package/build/testDoubles/{BleController/FakeBleController.js → BleGatt/FakeBleGatt.js} +8 -8
  51. package/build/testDoubles/BleGatt/FakeBleGatt.js.map +1 -0
  52. package/build/testDoubles/{BleController/SpyBleController.d.ts → BleGatt/SpyBleGatt.d.ts} +4 -4
  53. package/build/testDoubles/{BleController/SpyBleController.js → BleGatt/SpyBleGatt.js} +3 -3
  54. package/build/testDoubles/BleGatt/SpyBleGatt.js.map +1 -0
  55. package/build/testDoubles/BleObserver/FakeBleObserver.d.ts +10 -0
  56. package/build/testDoubles/BleObserver/FakeBleObserver.js +20 -0
  57. package/build/testDoubles/BleObserver/FakeBleObserver.js.map +1 -0
  58. package/build/testDoubles/{LslEmitter/FakeLslEmitter.d.ts → EventMarkerOutlet/FakeEventMarkerOutlet.d.ts} +2 -2
  59. package/build/testDoubles/{LslEmitter/FakeLslEmitter.js → EventMarkerOutlet/FakeEventMarkerOutlet.js} +7 -7
  60. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +1 -0
  61. package/build/testDoubles/{LslEmitter/SpyLslEmitter.d.ts → EventMarkerOutlet/SpyEventMarkerOutlet.d.ts} +3 -3
  62. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js +23 -0
  63. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +1 -0
  64. package/build/testDoubles/{LslEmitter/ThrowingLslEmitter.d.ts → EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts} +2 -2
  65. package/build/testDoubles/{LslEmitter/ThrowingLslEmitter.js → EventMarkerOutlet/ThrowingEventMarkerOutlet.js} +2 -2
  66. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +1 -0
  67. package/build/testDoubles/JsonOutlet/FakeJsonOutlet.d.ts +10 -0
  68. package/build/testDoubles/JsonOutlet/FakeJsonOutlet.js +20 -0
  69. package/build/testDoubles/JsonOutlet/FakeJsonOutlet.js.map +1 -0
  70. package/build/testDoubles/UsbDevice/FakeUsbDevice.d.ts +12 -0
  71. package/build/testDoubles/UsbDevice/FakeUsbDevice.js +25 -0
  72. package/build/testDoubles/UsbDevice/FakeUsbDevice.js.map +1 -0
  73. package/package.json +3 -3
  74. package/src/__tests__/AbstractPackageTest.ts +9 -7
  75. package/src/__tests__/impl/{BleDeviceController.test.ts → BleGattController.test.ts} +43 -43
  76. package/src/__tests__/impl/BleObserverController.test.ts +158 -0
  77. package/src/__tests__/impl/{LslEventMarkerEmitter.test.ts → LslEventMarkerOutlet.test.ts} +20 -19
  78. package/src/__tests__/impl/LslJsonOutlet.test.ts +135 -0
  79. package/src/__tests__/impl/LslStreamInfo.test.ts +0 -1
  80. package/src/__tests__/impl/LslStreamInlet.test.ts +0 -1
  81. package/src/__tests__/impl/LslStreamOutlet.test.ts +0 -1
  82. package/src/__tests__/impl/LslWebSocketBridge.test.ts +0 -1
  83. package/src/__tests__/impl/UsbDeviceController.test.ts +2 -2
  84. package/src/impl/{LslEventMarkerEmitter.ts → LslEventMarkerOutlet.ts} +8 -6
  85. package/src/impl/LslJsonOutlet.ts +87 -0
  86. package/src/impl/LslStreamOutlet.ts +7 -5
  87. package/src/impl/controllers/{BleDeviceController.ts → BleGattController.ts} +23 -28
  88. package/src/impl/controllers/BleObserverController.ts +85 -0
  89. package/src/impl/controllers/UsbDeviceController.ts +14 -16
  90. package/src/index.ts +40 -24
  91. package/src/scripts/{runLslEmitter.ts → runEventMarkerOutlet.ts} +5 -5
  92. package/src/scripts/runMuse.ts +2 -2
  93. package/src/testDoubles/{BleController/FakeBleController.ts → BleGatt/FakeBleGatt.ts} +14 -14
  94. package/src/testDoubles/{BleController/SpyBleController.ts → BleGatt/SpyBleGatt.ts} +5 -5
  95. package/src/testDoubles/BleObserver/FakeBleObserver.ts +28 -0
  96. package/src/testDoubles/{LslEmitter/FakeLslEmitter.ts → EventMarkerOutlet/FakeEventMarkerOutlet.ts} +8 -8
  97. package/src/testDoubles/{LslEmitter/SpyLslEmitter.ts → EventMarkerOutlet/SpyEventMarkerOutlet.ts} +7 -7
  98. package/src/testDoubles/{LslEmitter/ThrowingLslEmitter.ts → EventMarkerOutlet/ThrowingEventMarkerOutlet.ts} +3 -3
  99. package/src/testDoubles/JsonOutlet/FakeJsonOutlet.ts +25 -0
  100. package/src/testDoubles/UsbDevice/FakeUsbDevice.ts +34 -0
  101. package/build/__tests__/impl/BleDeviceController.test.js.map +0 -1
  102. package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +0 -1
  103. package/build/impl/LslEventMarkerEmitter.js.map +0 -1
  104. package/build/impl/controllers/BleDeviceController.js.map +0 -1
  105. package/build/scripts/runLslEmitter.js +0 -12
  106. package/build/scripts/runLslEmitter.js.map +0 -1
  107. package/build/testDoubles/BleController/FakeBleController.js.map +0 -1
  108. package/build/testDoubles/BleController/SpyBleController.js.map +0 -1
  109. package/build/testDoubles/LslEmitter/FakeLslEmitter.js.map +0 -1
  110. package/build/testDoubles/LslEmitter/SpyLslEmitter.js +0 -23
  111. package/build/testDoubles/LslEmitter/SpyLslEmitter.js.map +0 -1
  112. package/build/testDoubles/LslEmitter/ThrowingLslEmitter.js.map +0 -1
  113. package/build/testDoubles/UsbController/FakeUsbController.d.ts +0 -12
  114. package/build/testDoubles/UsbController/FakeUsbController.js +0 -25
  115. package/build/testDoubles/UsbController/FakeUsbController.js.map +0 -1
  116. package/src/testDoubles/UsbController/FakeUsbController.ts +0 -34
  117. /package/build/scripts/{runLslEmitter.d.ts → runEventMarkerOutlet.d.ts} +0 -0
@@ -28,7 +28,6 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
28
28
 
29
29
  this.randomOutletOptions = generateRandomOutletOptions()
30
30
 
31
- this.setFakeLiblsl()
32
31
  this.setFakeLslInfo()
33
32
 
34
33
  LslStreamOutlet.lsl = this.fakeLiblsl
@@ -18,7 +18,6 @@ export default class LslWebSocketBridgeTest extends AbstractPackageTest {
18
18
  protected static async beforeEach() {
19
19
  await super.beforeEach()
20
20
 
21
- this.setFakeLiblsl()
22
21
  this.setFakeLslInlet()
23
22
  this.setFakeWebSocket()
24
23
  this.setFakeWebSocketServer()
@@ -1,13 +1,13 @@
1
1
  import { test, assert } from '@neurodevs/node-tdd'
2
2
 
3
3
  import UsbDeviceController, {
4
- UsbController,
4
+ UsbDevice,
5
5
  } from '../../impl/controllers/UsbDeviceController.js'
6
6
  import AbstractPackageTest from '../AbstractPackageTest.js'
7
7
  import { FakeLibndx } from '@neurodevs/ndx-native'
8
8
 
9
9
  export default class UsbDeviceControllerTest extends AbstractPackageTest {
10
- private static instance: UsbController
10
+ private static instance: UsbDevice
11
11
 
12
12
  private static readonly serialNumber = this.generateId()
13
13
  private static readonly valueToWrite = this.generateId()
@@ -5,8 +5,8 @@ import LslStreamOutlet, {
5
5
  LslOutlet,
6
6
  } from './LslStreamOutlet.js'
7
7
 
8
- export default class LslEventMarkerEmitter implements LslEmitter {
9
- public static Class?: LslEmitterConstructor
8
+ export default class LslEventMarkerOutlet implements EventMarkerOutlet {
9
+ public static Class?: EventMarkerOutletConstructor
10
10
 
11
11
  protected outlet: LslOutlet
12
12
  private isRunning = false
@@ -17,7 +17,7 @@ export default class LslEventMarkerEmitter implements LslEmitter {
17
17
  this.outlet = outlet
18
18
  }
19
19
 
20
- public static async Create(options?: LslEmitterOptions) {
20
+ public static async Create(options?: EventMarkerOutletOptions) {
21
21
  const outlet = await this.LslStreamOutlet(options)
22
22
  return new (this.Class ?? this)(outlet)
23
23
  }
@@ -110,16 +110,18 @@ export default class LslEventMarkerEmitter implements LslEmitter {
110
110
  }
111
111
  }
112
112
 
113
- export interface LslEmitter {
113
+ export interface EventMarkerOutlet {
114
114
  emit(markerName: string, options?: EmitOptions): Promise<void>
115
115
  emitMany(markers: TimedEventMarker[]): Promise<void>
116
116
  interrupt(): void
117
117
  destroy(): void
118
118
  }
119
119
 
120
- export type LslEmitterOptions = Partial<LslOutletOptions>
120
+ export type EventMarkerOutletOptions = Partial<LslOutletOptions>
121
121
 
122
- export type LslEmitterConstructor = new (outlet: LslOutlet) => LslEmitter
122
+ export type EventMarkerOutletConstructor = new (
123
+ outlet: LslOutlet
124
+ ) => EventMarkerOutlet
123
125
 
124
126
  export interface EmitOptions {
125
127
  waitAfterMs?: number
@@ -0,0 +1,87 @@
1
+ import LslStreamOutlet, { LslOutlet } from './LslStreamOutlet.js'
2
+
3
+ export default class LslJsonOutlet implements JsonOutlet {
4
+ public static Class?: JsonOutletConstructor
5
+ public static backupIdCounter = 0
6
+
7
+ private outlet: LslOutlet
8
+ private maxBytesPerSample?: number
9
+
10
+ protected constructor(outlet: LslOutlet, maxBytesPerSample?: number) {
11
+ this.outlet = outlet
12
+ this.maxBytesPerSample = maxBytesPerSample
13
+ }
14
+
15
+ public static async Create(options?: JsonOutletOptions) {
16
+ const outlet = await this.LslStreamOutlet(options)
17
+ return new (this.Class ?? this)(outlet, options?.maxBytesPerSample)
18
+ }
19
+
20
+ public pushJson(data: Json) {
21
+ const json = JSON.stringify(data)
22
+ this.throwIfPayloadTooLarge(json)
23
+ this.outlet.pushSample([json])
24
+ }
25
+
26
+ private throwIfPayloadTooLarge(json: string) {
27
+ const totalBytes = Buffer.byteLength(json)
28
+
29
+ if (this.maxBytesPerSample && totalBytes > this.maxBytesPerSample) {
30
+ throw new Error(
31
+ `Payload of ${totalBytes} bytes exceeds maxBytesPerSample of ${this.maxBytesPerSample}!`
32
+ )
33
+ }
34
+ }
35
+
36
+ public destroy() {
37
+ this.outlet.destroy()
38
+ }
39
+
40
+ private static LslStreamOutlet(options?: JsonOutletOptions) {
41
+ this.backupIdCounter++
42
+
43
+ const { channelName, maxBytesPerSample: _, ...rest } = options ?? {}
44
+
45
+ return LslStreamOutlet.Create({
46
+ name: `JSON (json-${this.backupIdCounter})`,
47
+ type: 'JSON',
48
+ sourceId: `json-${this.backupIdCounter}`,
49
+ channelNames: [channelName ?? 'JSON'],
50
+ channelFormat: 'string',
51
+ sampleRateHz: 0,
52
+ chunkSize: 1,
53
+ ...rest,
54
+ })
55
+ }
56
+ }
57
+
58
+ export interface JsonOutlet {
59
+ pushJson(data: Json): void
60
+ destroy(): void
61
+ }
62
+
63
+ export type Json = Record<string, unknown>
64
+
65
+ export type JsonOutletConstructor = new (
66
+ outlet: LslOutlet,
67
+ maxBytesPerSample?: number
68
+ ) => JsonOutlet
69
+
70
+ export interface JsonOutletOptions {
71
+ name?: string
72
+ type?: string
73
+ sourceId?: string
74
+ channelName?: string
75
+ sampleRateHz?: number
76
+ chunkSize?: number
77
+ maxBufferedMs?: number
78
+ maxBytesPerSample?: number
79
+ manufacturer?: string
80
+ units?: string
81
+ waitAfterConstructionMs?: number
82
+ }
83
+
84
+ export type JsonOutletConstructorOptions = Omit<
85
+ JsonOutletOptions,
86
+ 'waitAfterConstructionMs'
87
+ >
@@ -180,11 +180,7 @@ export interface LslOutlet {
180
180
 
181
181
  export type LslOutletConstructor = new (options: LslOutletOptions) => LslOutlet
182
182
 
183
- export interface LslOutletOptions extends LslOutletConstructorOptions {
184
- waitAfterConstructionMs?: number
185
- }
186
-
187
- export interface LslOutletConstructorOptions {
183
+ export interface LslOutletOptions {
188
184
  name: string
189
185
  type: string
190
186
  sourceId: string
@@ -195,4 +191,10 @@ export interface LslOutletConstructorOptions {
195
191
  maxBufferedMs?: number
196
192
  manufacturer?: string
197
193
  units?: string
194
+ waitAfterConstructionMs?: number
198
195
  }
196
+
197
+ export type LslOutletConstructorOptions = Omit<
198
+ LslOutletOptions,
199
+ 'waitAfterConstructionMs'
200
+ >
@@ -1,7 +1,7 @@
1
1
  import { LibndxAdapter, Libndx, NativePeripheral } from '@neurodevs/ndx-native'
2
2
 
3
- export default class BleDeviceController implements BleController {
4
- public static Class?: BleControllerConstructor
3
+ export default class BleGattController implements BleGatt {
4
+ public static Class?: BleGattConstructor
5
5
  public static setTimeout = setTimeout
6
6
  public static waitAfterMs = 1000
7
7
 
@@ -28,7 +28,7 @@ export default class BleDeviceController implements BleController {
28
28
  private deviceName?: string
29
29
  private onConnected?: (peripheral: NativePeripheral) => void
30
30
 
31
- protected constructor(options: BleControllerOptions) {
31
+ protected constructor(options: BleGattOptions) {
32
32
  const {
33
33
  deviceUuid,
34
34
  deviceNamePrefix,
@@ -44,7 +44,7 @@ export default class BleDeviceController implements BleController {
44
44
  this.rssiIntervalMs = rssiIntervalMs
45
45
  }
46
46
 
47
- public static Create(options: BleControllerOptions) {
47
+ public static Create(options: BleGattOptions) {
48
48
  return new (this.Class ?? this)(options)
49
49
  }
50
50
 
@@ -53,13 +53,13 @@ export default class BleDeviceController implements BleController {
53
53
  await this.discoverUuid()
54
54
  }
55
55
 
56
- this.createBleBackend()
57
- this.startBleBackend()
56
+ this.createBleGattBackend()
57
+ this.startBleGattBackend()
58
58
 
59
59
  await this.waitForOnConnected()
60
60
  await this.waitToDiscoverServices()
61
61
 
62
- this.setBleRssiInterval()
62
+ this.startBleGattRssiPolling()
63
63
  }
64
64
 
65
65
  private async discoverUuid() {
@@ -81,15 +81,15 @@ export default class BleDeviceController implements BleController {
81
81
  if (this.deviceUuid) {
82
82
  resolve()
83
83
  } else {
84
- BleDeviceController.setTimeout(checkDiscovered, 100)
84
+ BleGattController.setTimeout(checkDiscovered, 100)
85
85
  }
86
86
  }
87
87
  checkDiscovered()
88
88
  })
89
89
  }
90
90
 
91
- private createBleBackend() {
92
- const { status, error } = this.ndx.createBleBackend({
91
+ private createBleGattBackend() {
92
+ const { status, error } = this.ndx.createBleGattBackend({
93
93
  deviceUuid: this.uuid,
94
94
  })
95
95
 
@@ -102,9 +102,9 @@ export default class BleDeviceController implements BleController {
102
102
  }
103
103
  }
104
104
 
105
- private setBleRssiInterval() {
105
+ private startBleGattRssiPolling() {
106
106
  if (this.rssiIntervalMs) {
107
- this.ndx.setBleRssiInterval({
107
+ this.ndx.startBleGattRssiPolling({
108
108
  deviceUuid: this.uuid,
109
109
  intervalMs: this.rssiIntervalMs,
110
110
  onRssi: (rssi: number) => {
@@ -114,8 +114,8 @@ export default class BleDeviceController implements BleController {
114
114
  }
115
115
  }
116
116
 
117
- private startBleBackend() {
118
- const { status, error } = this.ndx.startBleBackend({
117
+ private startBleGattBackend() {
118
+ const { status, error } = this.ndx.startBleGattBackend({
119
119
  deviceUuid: this.uuid,
120
120
  onConnected: (peripheral: NativePeripheral) => {
121
121
  const { name } = peripheral
@@ -136,7 +136,7 @@ export default class BleDeviceController implements BleController {
136
136
  if (this.connected) {
137
137
  resolve()
138
138
  } else {
139
- BleDeviceController.setTimeout(checkConnected, 100)
139
+ BleGattController.setTimeout(checkConnected, 100)
140
140
  }
141
141
  }
142
142
  checkConnected()
@@ -145,10 +145,7 @@ export default class BleDeviceController implements BleController {
145
145
 
146
146
  private async waitToDiscoverServices() {
147
147
  await new Promise<void>((resolve) =>
148
- BleDeviceController.setTimeout(
149
- resolve,
150
- BleDeviceController.waitAfterMs
151
- )
148
+ BleGattController.setTimeout(resolve, BleGattController.waitAfterMs)
152
149
  )
153
150
  }
154
151
 
@@ -156,7 +153,7 @@ export default class BleDeviceController implements BleController {
156
153
  charUuid: CharacteristicUuid,
157
154
  value: string
158
155
  ) {
159
- const { status, error } = this.ndx.writeBleCharacteristic({
156
+ const { status, error } = this.ndx.writeBleGattChar({
160
157
  deviceUuid: this.uuid,
161
158
  charUuid,
162
159
  value,
@@ -168,7 +165,7 @@ export default class BleDeviceController implements BleController {
168
165
  public async subscribeCharacteristics(
169
166
  charCallbacks: CharacteristicCallbacks
170
167
  ) {
171
- const { status, error } = this.ndx.addBleCharCallbacks({
168
+ const { status, error } = this.ndx.registerBleGattCharCallbacks({
172
169
  deviceUuid: this.uuid,
173
170
  charCallbacks,
174
171
  })
@@ -179,7 +176,7 @@ export default class BleDeviceController implements BleController {
179
176
  }
180
177
 
181
178
  public async disconnect() {
182
- const { status, error } = this.ndx.stopBleBackend({
179
+ const { status, error } = this.ndx.stopBleGattBackend({
183
180
  deviceUuid: this.uuid,
184
181
  })
185
182
 
@@ -196,11 +193,11 @@ export default class BleDeviceController implements BleController {
196
193
  }
197
194
 
198
195
  private get ndx() {
199
- return BleDeviceController.ndx
196
+ return BleGattController.ndx
200
197
  }
201
198
  }
202
199
 
203
- export interface BleController {
200
+ export interface BleGatt {
204
201
  uuid: string
205
202
  name: string
206
203
 
@@ -218,7 +215,7 @@ export interface BleController {
218
215
  disconnect(): Promise<void>
219
216
  }
220
217
 
221
- export type BleControllerOptions = {
218
+ export type BleGattOptions = {
222
219
  charCallbacks: CharacteristicCallbacks
223
220
  onConnected?: (peripheral: NativePeripheral) => void
224
221
  rssiIntervalMs?: number
@@ -227,9 +224,7 @@ export type BleControllerOptions = {
227
224
  | { deviceUuid?: string; deviceNamePrefix: string }
228
225
  )
229
226
 
230
- export type BleControllerConstructor = new (
231
- options: BleControllerOptions
232
- ) => BleController
227
+ export type BleGattConstructor = new (options: BleGattOptions) => BleGatt
233
228
 
234
229
  export type CharacteristicCallbacks = {
235
230
  charUuid: string
@@ -0,0 +1,85 @@
1
+ import { LibndxAdapter } from '@neurodevs/ndx-native'
2
+
3
+ export default class BleObserverController implements BleObserver {
4
+ public static Class?: BleObserverConstructor
5
+
6
+ private readonly deviceUuid: string
7
+ private readonly onAdvertisement?: OnAdvertisement
8
+ private readonly ndx = LibndxAdapter.getInstance()
9
+
10
+ protected constructor(options: BleObserverOptions) {
11
+ const { deviceUuid, onAdvertisement } = options
12
+
13
+ this.deviceUuid = deviceUuid ?? ''
14
+ this.onAdvertisement = onAdvertisement
15
+ }
16
+
17
+ public static Create(options: BleObserverOptions) {
18
+ return new (this.Class ?? this)(options)
19
+ }
20
+
21
+ public async startObserving() {
22
+ this.createBleObserverBackend()
23
+ this.startBleObserverBackend()
24
+ }
25
+
26
+ private createBleObserverBackend() {
27
+ const { status, error } = this.ndx.createBleObserverBackend({
28
+ deviceUuid: this.deviceUuid,
29
+ })
30
+
31
+ this.throwIfError(status, error)
32
+ }
33
+
34
+ private startBleObserverBackend() {
35
+ const { status, error } = this.ndx.startBleObserverBackend({
36
+ deviceUuid: this.deviceUuid,
37
+ onAdvertisement: (
38
+ data: Buffer,
39
+ length: number,
40
+ timestampSec: number
41
+ ) => {
42
+ this.onAdvertisement?.(data, length, timestampSec)
43
+ },
44
+ })
45
+
46
+ this.throwIfError(status, error)
47
+ }
48
+
49
+ public async stopObserving() {
50
+ this.stopBleObserverBackend()
51
+ }
52
+
53
+ private stopBleObserverBackend() {
54
+ const { status, error } = this.ndx.stopBleObserverBackend({
55
+ deviceUuid: this.deviceUuid,
56
+ })
57
+
58
+ this.throwIfError(status, error)
59
+ }
60
+
61
+ private throwIfError(status: number, error: string | undefined) {
62
+ if (status !== 200) {
63
+ throw new Error(`${status} error: ${error ?? 'Unknown error'}`)
64
+ }
65
+ }
66
+ }
67
+ export interface BleObserver {
68
+ startObserving(): Promise<void>
69
+ stopObserving(): Promise<void>
70
+ }
71
+
72
+ export type BleObserverConstructor = new (
73
+ options: BleObserverOptions
74
+ ) => BleObserver
75
+
76
+ export type BleObserverOptions = {
77
+ deviceUuid: string
78
+ onAdvertisement?: OnAdvertisement
79
+ }
80
+
81
+ export type OnAdvertisement = (
82
+ data: Buffer,
83
+ length: number,
84
+ timestampSec: number
85
+ ) => void
@@ -1,65 +1,63 @@
1
1
  import { LibndxAdapter } from '@neurodevs/ndx-native'
2
2
 
3
- export default class UsbDeviceController implements UsbController {
4
- public static Class?: UsbControllerConstructor
3
+ export default class UsbDeviceController implements UsbDevice {
4
+ public static Class?: UsbDeviceConstructor
5
5
 
6
6
  private onData: (data: Buffer, length: number, timestampSec: number) => void
7
7
  private serialNumber: string
8
8
 
9
9
  private ndx = LibndxAdapter.getInstance()
10
10
 
11
- protected constructor(options: UsbControllerOptions) {
11
+ protected constructor(options: UsbDeviceOptions) {
12
12
  const { onData, serialNumber } = options ?? {}
13
13
 
14
14
  this.onData = onData
15
15
  this.serialNumber = serialNumber ?? ''
16
16
  }
17
17
 
18
- public static Create(options: UsbControllerOptions) {
18
+ public static Create(options: UsbDeviceOptions) {
19
19
  return new (this.Class ?? this)(options)
20
20
  }
21
21
 
22
22
  public async connect() {
23
- this.ndx.createUsbBackend(this.usbControllerOptions)
24
- this.ndx.startUsbBackend(this.startUsbControllerOptions)
23
+ this.ndx.createUsbBackend(this.usbDeviceOptions)
24
+ this.ndx.startUsbBackend(this.startUsbDeviceOptions)
25
25
  }
26
26
 
27
- private get usbControllerOptions() {
27
+ private get usbDeviceOptions() {
28
28
  return {
29
29
  serialNumber: this.serialNumber,
30
30
  }
31
31
  }
32
32
 
33
- private get startUsbControllerOptions() {
33
+ private get startUsbDeviceOptions() {
34
34
  return {
35
- ...this.usbControllerOptions,
35
+ ...this.usbDeviceOptions,
36
36
  onData: this.onData,
37
37
  }
38
38
  }
39
39
 
40
40
  public async writeUsb(value: string) {
41
41
  this.ndx.writeUsbBackend({
42
- ...this.usbControllerOptions,
42
+ ...this.usbDeviceOptions,
43
43
  value,
44
44
  })
45
45
  }
46
46
 
47
47
  public async disconnect() {
48
- this.ndx.stopUsbBackend(this.usbControllerOptions)
48
+ this.ndx.stopUsbBackend(this.usbDeviceOptions)
49
49
  }
50
50
  }
51
51
 
52
- export interface UsbController {
52
+ export interface UsbDevice {
53
53
  connect(): Promise<void>
54
54
  writeUsb(value: string): Promise<void>
55
55
  disconnect(): Promise<void>
56
56
  }
57
57
 
58
- export interface UsbControllerOptions {
58
+ export interface UsbDeviceOptions {
59
59
  onData: (data: Buffer, length: number, timestampSec: number) => void
60
60
  serialNumber?: string
61
61
  }
62
62
 
63
- export type UsbControllerConstructor = new (
64
- options?: UsbControllerOptions
65
- ) => UsbController
63
+ export type UsbDeviceConstructor = new (options?: UsbDeviceOptions) => UsbDevice
package/src/index.ts CHANGED
@@ -1,3 +1,11 @@
1
+ // BleObserver
2
+
3
+ export { default as BleObserverController } from './impl/controllers/BleObserverController.js'
4
+ export * from './impl/controllers/BleObserverController.js'
5
+
6
+ export { default as FakeBleObserver } from './testDoubles/BleObserver/FakeBleObserver.js'
7
+ export * from './testDoubles/BleObserver/FakeBleObserver.js'
8
+
1
9
  // ClockRegressor
2
10
 
3
11
  export { default as WindowedClockRegressor } from './impl/clocks/WindowedClockRegressor.js'
@@ -6,16 +14,38 @@ export * from './impl/clocks/WindowedClockRegressor.js'
6
14
  export { default as FakeClockRegressor } from './testDoubles/ClockRegressor/FakeClockRegressor.js'
7
15
  export * from './testDoubles/ClockRegressor/FakeClockRegressor.js'
8
16
 
9
- // DeviceController
17
+ // BleGatt
18
+
19
+ export { default as BleGattController } from './impl/controllers/BleGattController.js'
20
+ export * from './impl/controllers/BleGattController.js'
21
+
22
+ export { default as SpyBleGatt } from './testDoubles/BleGatt/SpyBleGatt.js'
23
+ export * from './testDoubles/BleGatt/SpyBleGatt.js'
24
+
25
+ export { default as FakeBleGatt } from './testDoubles/BleGatt/FakeBleGatt.js'
26
+ export * from './testDoubles/BleGatt/FakeBleGatt.js'
27
+
28
+ // EventMarkerOutlet
29
+
30
+ export { default as LslEventMarkerOutlet } from './impl/LslEventMarkerOutlet.js'
31
+ export * from './impl/LslEventMarkerOutlet.js'
10
32
 
11
- export { default as BleDeviceController } from './impl/controllers/BleDeviceController.js'
12
- export * from './impl/controllers/BleDeviceController.js'
33
+ export { default as SpyEventMarkerOutlet } from './testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js'
34
+ export * from './testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js'
13
35
 
14
- export { default as SpyBleController } from './testDoubles/BleController/SpyBleController.js'
15
- export * from './testDoubles/BleController/SpyBleController.js'
36
+ export { default as FakeEventMarkerOutlet } from './testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js'
37
+ export * from './testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js'
16
38
 
17
- export { default as FakeBleController } from './testDoubles/BleController/FakeBleController.js'
18
- export * from './testDoubles/BleController/FakeBleController.js'
39
+ export { default as ThrowingEventMarkerOutlet } from './testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js'
40
+ export * from './testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js'
41
+
42
+ // JsonOutlet
43
+
44
+ export { default as LslJsonOutlet } from './impl/LslJsonOutlet.js'
45
+ export * from './impl/LslJsonOutlet.js'
46
+
47
+ export { default as FakeJsonOutlet } from './testDoubles/JsonOutlet/FakeJsonOutlet.js'
48
+ export * from './testDoubles/JsonOutlet/FakeJsonOutlet.js'
19
49
 
20
50
  // LslWsBridge
21
51
 
@@ -28,20 +58,6 @@ export * from './testDoubles/LslWsBridge/SpyLslWsBridge.js'
28
58
  export { default as FakeLslWsBridge } from './testDoubles/LslWsBridge/FakeLslWsBridge.js'
29
59
  export * from './testDoubles/LslWsBridge/FakeLslWsBridge.js'
30
60
 
31
- // LslEmitter
32
-
33
- export { default as LslEventMarkerEmitter } from './impl/LslEventMarkerEmitter.js'
34
- export * from './impl/LslEventMarkerEmitter.js'
35
-
36
- export { default as SpyLslEmitter } from './testDoubles/LslEmitter/SpyLslEmitter.js'
37
- export * from './testDoubles/LslEmitter/SpyLslEmitter.js'
38
-
39
- export { default as FakeLslEmitter } from './testDoubles/LslEmitter/FakeLslEmitter.js'
40
- export * from './testDoubles/LslEmitter/FakeLslEmitter.js'
41
-
42
- export { default as ThrowingLslEmitter } from './testDoubles/LslEmitter/ThrowingLslEmitter.js'
43
- export * from './testDoubles/LslEmitter/ThrowingLslEmitter.js'
44
-
45
61
  // LslInfo
46
62
 
47
63
  export { default as LslStreamInfo } from './impl/LslStreamInfo.js'
@@ -74,13 +90,13 @@ export * from './testDoubles/LslOutlet/FakeLslOutlet.js'
74
90
 
75
91
  export { default as generateRandomOutletOptions } from './testDoubles/generateRandomOutletOptions.js'
76
92
 
77
- // UsbController
93
+ // UsbDevice
78
94
 
79
95
  export { default as UsbDeviceController } from './impl/controllers/UsbDeviceController.js'
80
96
  export * from './impl/controllers/UsbDeviceController.js'
81
97
 
82
- export { default as FakeUsbController } from './testDoubles/UsbController/FakeUsbController.js'
83
- export * from './testDoubles/UsbController/FakeUsbController.js'
98
+ export { default as FakeUsbDevice } from './testDoubles/UsbDevice/FakeUsbDevice.js'
99
+ export * from './testDoubles/UsbDevice/FakeUsbDevice.js'
84
100
 
85
101
  // WebSockets
86
102
 
@@ -1,6 +1,6 @@
1
- import LslEventMarkerEmitter from '../impl/LslEventMarkerEmitter.js'
1
+ import LslEventMarkerOutlet from '../impl/LslEventMarkerOutlet.js'
2
2
 
3
- const emitter = await LslEventMarkerEmitter.Create()
3
+ const outlet = await LslEventMarkerOutlet.Create()
4
4
 
5
5
  const markers = [
6
6
  { name: 'phase-1-begin', waitAfterMs: 100 },
@@ -8,9 +8,9 @@ const markers = [
8
8
  { name: 'never-reached-marker', waitAfterMs: 100 },
9
9
  ]
10
10
 
11
- void emitter.emitMany(markers)
11
+ void outlet.emitMany(markers)
12
12
 
13
13
  await new Promise((resolve) => setTimeout(resolve, 250))
14
14
 
15
- emitter.interrupt()
16
- emitter.destroy()
15
+ outlet.interrupt()
16
+ outlet.destroy()
@@ -1,6 +1,6 @@
1
1
  import koffi from 'koffi'
2
2
 
3
- import BleDeviceController from '../impl/controllers/BleDeviceController.js'
3
+ import BleGattController from '../impl/controllers/BleGattController.js'
4
4
 
5
5
  const MUSE_CHARACTERISTIC_UUIDS: Record<string, string> = {
6
6
  CONTROL: '273E0001-4C4D-454D-96BE-F03BAC821358',
@@ -32,7 +32,7 @@ const charCallbacks = Object.entries(MUSE_CHARACTERISTIC_UUIDS).map(
32
32
  }
33
33
  )
34
34
 
35
- const muse = BleDeviceController.Create({
35
+ const muse = BleGattController.Create({
36
36
  deviceUuid: 'CA6A61B7-B7A8-AF24-3C9E-04A6A5012554',
37
37
  charCallbacks,
38
38
  rssiIntervalMs: 1000,