@science-corporation/synapse 0.13.0 → 2.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/README.md +4 -2
- package/dist/api/api.d.ts +711 -71
- package/dist/api/api.js +5532 -4083
- package/dist/api/api.js.map +1 -1
- package/dist/api/proto.json +122 -32
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/demo.js +125 -32
- package/dist/demo.js.map +1 -1
- package/dist/device.d.ts +6 -0
- package/dist/device.d.ts.map +1 -1
- package/dist/device.js +25 -0
- package/dist/device.js.map +1 -1
- package/dist/nodes/index.d.ts +2 -1
- package/dist/nodes/index.d.ts.map +1 -1
- package/dist/nodes/index.js +5 -3
- package/dist/nodes/index.js.map +1 -1
- package/dist/nodes/spike_binner.d.ts +11 -0
- package/dist/nodes/{spike_detect.d.ts.map → spike_binner.d.ts.map} +1 -1
- package/dist/nodes/spike_binner.js +28 -0
- package/dist/nodes/{spike_detect.js.map → spike_binner.js.map} +1 -1
- package/dist/nodes/spike_detector.d.ts +11 -0
- package/dist/nodes/spike_detector.d.ts.map +1 -0
- package/dist/nodes/{spike_detect.js → spike_detector.js} +9 -9
- package/dist/nodes/spike_detector.js.map +1 -0
- package/dist/nodes/stream_out.d.ts +12 -5
- package/dist/nodes/stream_out.d.ts.map +1 -1
- package/dist/nodes/stream_out.js +58 -40
- package/dist/nodes/stream_out.js.map +1 -1
- package/dist/utils/ip.d.ts +2 -0
- package/dist/utils/ip.d.ts.map +1 -0
- package/dist/utils/ip.js +52 -0
- package/dist/utils/ip.js.map +1 -0
- package/package.json +6 -5
- package/scripts/postinstall.sh +50 -10
- package/src/api/api.d.ts +711 -71
- package/src/api/api.js +5671 -4121
- package/src/api/proto.json +122 -32
- package/src/config.ts +4 -2
- package/src/demo.ts +20 -8
- package/src/device.ts +34 -1
- package/src/nodes/index.ts +2 -1
- package/src/nodes/spike_binner.ts +30 -0
- package/src/nodes/spike_detector.ts +30 -0
- package/src/nodes/stream_out.ts +67 -50
- package/src/utils/ip.ts +35 -0
- package/synapse-api/.github/pull_request_template.md +10 -0
- package/synapse-api/README.md +1 -1
- package/synapse-api/api/datatype.proto +1 -0
- package/synapse-api/api/node.proto +6 -3
- package/synapse-api/api/nodes/spike_binner.proto +7 -0
- package/synapse-api/api/nodes/spike_detector.proto +19 -0
- package/synapse-api/api/nodes/stream_out.proto +31 -1
- package/synapse-api/api/query.proto +19 -1
- package/synapse-api/api/synapse.proto +1 -0
- package/dist/api-science-device/api.d.ts +0 -3
- package/dist/api-science-device/api.d.ts.map +0 -1
- package/dist/api-science-device/api.js +0 -3822
- package/dist/api-science-device/api.js.map +0 -1
- package/dist/api-science-device/proto.json +0 -258
- package/dist/nodejs.d.ts +0 -8
- package/dist/nodejs.d.ts.map +0 -1
- package/dist/nodejs.js +0 -32
- package/dist/nodejs.js.map +0 -1
- package/dist/nodes/spike_detect.d.ts +0 -11
- package/dist/science-device-api/api.d.ts +0 -3
- package/dist/science-device-api/api.d.ts.map +0 -1
- package/dist/science-device-api/api.js +0 -3822
- package/dist/science-device-api/api.js.map +0 -1
- package/dist/types/index.d.ts +0 -3
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -19
- package/dist/types/index.js.map +0 -1
- package/dist/types.d.ts +0 -5
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -19
- package/dist/types.js.map +0 -1
- package/dist/utils/device-management.d.ts +0 -37
- package/dist/utils/device-management.d.ts.map +0 -1
- package/dist/utils/device-management.js +0 -126
- package/dist/utils/device-management.js.map +0 -1
- package/dist/utils/ndtp.d.ts +0 -40
- package/dist/utils/ndtp.d.ts.map +0 -1
- package/dist/utils/ndtp.js +0 -140
- package/dist/utils/ndtp.js.map +0 -1
- package/src/nodes/spike_detect.ts +0 -30
- package/synapse-api/api/nodes/spike_detect.proto +0 -16
package/src/api/proto.json
CHANGED
|
@@ -150,37 +150,52 @@
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
},
|
|
153
|
-
"
|
|
153
|
+
"SpikeBinnerConfig": {
|
|
154
154
|
"fields": {
|
|
155
|
-
"
|
|
156
|
-
"type": "SpikeDetectMode",
|
|
157
|
-
"id": 1
|
|
158
|
-
},
|
|
159
|
-
"thresholdUV": {
|
|
155
|
+
"binSizeMs": {
|
|
160
156
|
"type": "uint32",
|
|
161
|
-
"id":
|
|
162
|
-
}
|
|
157
|
+
"id": 1
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"TemplateMatcher": {
|
|
162
|
+
"fields": {
|
|
163
163
|
"templateUV": {
|
|
164
164
|
"rule": "repeated",
|
|
165
165
|
"type": "uint32",
|
|
166
|
-
"id":
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
"
|
|
166
|
+
"id": 1
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"Thresholder": {
|
|
171
|
+
"fields": {
|
|
172
|
+
"thresholdUV": {
|
|
173
173
|
"type": "uint32",
|
|
174
|
-
"id":
|
|
174
|
+
"id": 1
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"SpikeDetectorConfig": {
|
|
179
|
+
"oneofs": {
|
|
180
|
+
"config": {
|
|
181
|
+
"oneof": [
|
|
182
|
+
"thresholder",
|
|
183
|
+
"templateMatcher"
|
|
184
|
+
]
|
|
175
185
|
}
|
|
176
186
|
},
|
|
177
|
-
"
|
|
178
|
-
"
|
|
179
|
-
"
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
187
|
+
"fields": {
|
|
188
|
+
"thresholder": {
|
|
189
|
+
"type": "Thresholder",
|
|
190
|
+
"id": 1
|
|
191
|
+
},
|
|
192
|
+
"templateMatcher": {
|
|
193
|
+
"type": "TemplateMatcher",
|
|
194
|
+
"id": 2
|
|
195
|
+
},
|
|
196
|
+
"samplesPerSpike": {
|
|
197
|
+
"type": "uint32",
|
|
198
|
+
"id": 3
|
|
184
199
|
}
|
|
185
200
|
}
|
|
186
201
|
},
|
|
@@ -212,7 +227,8 @@
|
|
|
212
227
|
"kBroadband": 2,
|
|
213
228
|
"kSpiketrain": 3,
|
|
214
229
|
"kTimestamps": 4,
|
|
215
|
-
"kImage": 5
|
|
230
|
+
"kImage": 5,
|
|
231
|
+
"kWaveforms": 6
|
|
216
232
|
}
|
|
217
233
|
},
|
|
218
234
|
"DiskWriterConfig": {
|
|
@@ -223,14 +239,33 @@
|
|
|
223
239
|
}
|
|
224
240
|
}
|
|
225
241
|
},
|
|
242
|
+
"UDPUnicastConfig": {
|
|
243
|
+
"fields": {
|
|
244
|
+
"destinationAddress": {
|
|
245
|
+
"type": "string",
|
|
246
|
+
"id": 1
|
|
247
|
+
},
|
|
248
|
+
"destinationPort": {
|
|
249
|
+
"type": "uint32",
|
|
250
|
+
"id": 2
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
},
|
|
226
254
|
"StreamOutConfig": {
|
|
255
|
+
"oneofs": {
|
|
256
|
+
"transport": {
|
|
257
|
+
"oneof": [
|
|
258
|
+
"udpUnicast"
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
},
|
|
227
262
|
"fields": {
|
|
228
263
|
"label": {
|
|
229
264
|
"type": "string",
|
|
230
265
|
"id": 1
|
|
231
266
|
},
|
|
232
|
-
"
|
|
233
|
-
"type": "
|
|
267
|
+
"udpUnicast": {
|
|
268
|
+
"type": "UDPUnicastConfig",
|
|
234
269
|
"id": 2
|
|
235
270
|
}
|
|
236
271
|
}
|
|
@@ -240,6 +275,10 @@
|
|
|
240
275
|
"throughputMbps": {
|
|
241
276
|
"type": "float",
|
|
242
277
|
"id": 1
|
|
278
|
+
},
|
|
279
|
+
"failedSendCount": {
|
|
280
|
+
"type": "uint64",
|
|
281
|
+
"id": 2
|
|
243
282
|
}
|
|
244
283
|
}
|
|
245
284
|
},
|
|
@@ -435,6 +474,11 @@
|
|
|
435
474
|
"requestType": "QueryRequest",
|
|
436
475
|
"responseType": "QueryResponse"
|
|
437
476
|
},
|
|
477
|
+
"StreamQuery": {
|
|
478
|
+
"requestType": "StreamQueryRequest",
|
|
479
|
+
"responseType": "StreamQueryResponse",
|
|
480
|
+
"responseStream": true
|
|
481
|
+
},
|
|
438
482
|
"ListFiles": {
|
|
439
483
|
"requestType": "google.protobuf.Empty",
|
|
440
484
|
"responseType": "ListFilesResponse"
|
|
@@ -471,10 +515,11 @@
|
|
|
471
515
|
"kBroadbandSource": 3,
|
|
472
516
|
"kElectricalStimulation": 4,
|
|
473
517
|
"kOpticalStimulation": 5,
|
|
474
|
-
"
|
|
518
|
+
"kSpikeDetector": 6,
|
|
475
519
|
"kSpikeSource": 7,
|
|
476
520
|
"kSpectralFilter": 8,
|
|
477
|
-
"kDiskWriter": 9
|
|
521
|
+
"kDiskWriter": 9,
|
|
522
|
+
"kSpikeBinner": 10
|
|
478
523
|
}
|
|
479
524
|
},
|
|
480
525
|
"NodeConfig": {
|
|
@@ -486,10 +531,11 @@
|
|
|
486
531
|
"broadbandSource",
|
|
487
532
|
"electricalStimulation",
|
|
488
533
|
"opticalStimulation",
|
|
489
|
-
"
|
|
534
|
+
"spikeDetector",
|
|
490
535
|
"spectralFilter",
|
|
491
536
|
"diskWriter",
|
|
492
|
-
"spikeSource"
|
|
537
|
+
"spikeSource",
|
|
538
|
+
"spikeBinner"
|
|
493
539
|
]
|
|
494
540
|
}
|
|
495
541
|
},
|
|
@@ -522,8 +568,8 @@
|
|
|
522
568
|
"type": "OpticalStimulationConfig",
|
|
523
569
|
"id": 8
|
|
524
570
|
},
|
|
525
|
-
"
|
|
526
|
-
"type": "
|
|
571
|
+
"spikeDetector": {
|
|
572
|
+
"type": "SpikeDetectorConfig",
|
|
527
573
|
"id": 9
|
|
528
574
|
},
|
|
529
575
|
"spectralFilter": {
|
|
@@ -537,6 +583,10 @@
|
|
|
537
583
|
"spikeSource": {
|
|
538
584
|
"type": "SpikeSourceConfig",
|
|
539
585
|
"id": 12
|
|
586
|
+
},
|
|
587
|
+
"spikeBinner": {
|
|
588
|
+
"type": "SpikeBinnerConfig",
|
|
589
|
+
"id": 13
|
|
540
590
|
}
|
|
541
591
|
}
|
|
542
592
|
},
|
|
@@ -747,6 +797,14 @@
|
|
|
747
797
|
}
|
|
748
798
|
}
|
|
749
799
|
},
|
|
800
|
+
"StreamQueryRequest": {
|
|
801
|
+
"fields": {
|
|
802
|
+
"request": {
|
|
803
|
+
"type": "QueryRequest",
|
|
804
|
+
"id": 1
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
},
|
|
750
808
|
"QueryResponse": {
|
|
751
809
|
"oneofs": {
|
|
752
810
|
"response": {
|
|
@@ -776,6 +834,38 @@
|
|
|
776
834
|
}
|
|
777
835
|
}
|
|
778
836
|
},
|
|
837
|
+
"StreamQueryResponse": {
|
|
838
|
+
"oneofs": {
|
|
839
|
+
"response": {
|
|
840
|
+
"oneof": [
|
|
841
|
+
"impedance",
|
|
842
|
+
"selfTest"
|
|
843
|
+
]
|
|
844
|
+
}
|
|
845
|
+
},
|
|
846
|
+
"fields": {
|
|
847
|
+
"code": {
|
|
848
|
+
"type": "StatusCode",
|
|
849
|
+
"id": 1
|
|
850
|
+
},
|
|
851
|
+
"message": {
|
|
852
|
+
"type": "string",
|
|
853
|
+
"id": 2
|
|
854
|
+
},
|
|
855
|
+
"timestampNs": {
|
|
856
|
+
"type": "uint64",
|
|
857
|
+
"id": 3
|
|
858
|
+
},
|
|
859
|
+
"impedance": {
|
|
860
|
+
"type": "ImpedanceResponse",
|
|
861
|
+
"id": 4
|
|
862
|
+
},
|
|
863
|
+
"selfTest": {
|
|
864
|
+
"type": "SelfTestResponse",
|
|
865
|
+
"id": 5
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
},
|
|
779
869
|
"StatusCode": {
|
|
780
870
|
"values": {
|
|
781
871
|
"kOk": 0,
|
package/src/config.ts
CHANGED
|
@@ -5,7 +5,8 @@ import DiskWriter from "./nodes/disk_writer";
|
|
|
5
5
|
import ElectricalStimulation from "./nodes/electrical_stimulation";
|
|
6
6
|
import OpticalStimulation from "./nodes/optical_stimulation";
|
|
7
7
|
import SpectralFilter from "./nodes/spectral_filter";
|
|
8
|
-
import
|
|
8
|
+
import SpikeBinner from "./nodes/spike_binner";
|
|
9
|
+
import SpikeDetector from "./nodes/spike_detector";
|
|
9
10
|
import SpikeSource from "./nodes/spike_source";
|
|
10
11
|
import StreamIn from "./nodes/stream_in";
|
|
11
12
|
import StreamOut from "./nodes/stream_out";
|
|
@@ -19,7 +20,8 @@ const kNodeTypeObjectMap = {
|
|
|
19
20
|
[synapse.NodeType.kSpikeSource]: SpikeSource,
|
|
20
21
|
[synapse.NodeType.kOpticalStimulation]: OpticalStimulation,
|
|
21
22
|
[synapse.NodeType.kSpectralFilter]: SpectralFilter,
|
|
22
|
-
[synapse.NodeType.
|
|
23
|
+
[synapse.NodeType.kSpikeBinner]: SpikeBinner,
|
|
24
|
+
[synapse.NodeType.kSpikeDetector]: SpikeDetector,
|
|
23
25
|
[synapse.NodeType.kStreamIn]: StreamIn,
|
|
24
26
|
[synapse.NodeType.kStreamOut]: StreamOut,
|
|
25
27
|
};
|
package/src/demo.ts
CHANGED
|
@@ -11,15 +11,17 @@ import StreamIn from "./nodes/stream_in";
|
|
|
11
11
|
import StreamOut from "./nodes/stream_out";
|
|
12
12
|
import { discover } from "./utils/discover";
|
|
13
13
|
import { getName } from "./utils/enum";
|
|
14
|
+
import { getClientIp } from "./utils/ip";
|
|
14
15
|
|
|
15
16
|
const cli = yargs(hideBin(process.argv))
|
|
16
17
|
.help()
|
|
17
18
|
.command("discover", "Discover synapse devices")
|
|
18
19
|
.command("read", "Read from StreamOut node", {
|
|
19
|
-
"
|
|
20
|
-
alias: "
|
|
20
|
+
"udp-port": {
|
|
21
|
+
alias: "p",
|
|
21
22
|
type: "string",
|
|
22
|
-
description: "
|
|
23
|
+
description: "UDP port",
|
|
24
|
+
default: "50038",
|
|
23
25
|
},
|
|
24
26
|
output: {
|
|
25
27
|
alias: "o",
|
|
@@ -93,7 +95,7 @@ const info = async (device: Device) => {
|
|
|
93
95
|
const read = async (device: Device, argv: any) => {
|
|
94
96
|
console.log("Reading from device's StreamOut node...");
|
|
95
97
|
|
|
96
|
-
const {
|
|
98
|
+
const { udpPort, output } = argv;
|
|
97
99
|
let status = null;
|
|
98
100
|
let stream = null;
|
|
99
101
|
if (output) {
|
|
@@ -122,9 +124,12 @@ const read = async (device: Device, argv: any) => {
|
|
|
122
124
|
});
|
|
123
125
|
const nodeStreamOut = new StreamOut(
|
|
124
126
|
{
|
|
125
|
-
|
|
127
|
+
udpUnicast: {
|
|
128
|
+
destinationPort: udpPort,
|
|
129
|
+
destinationAddress: await getClientIp(),
|
|
130
|
+
},
|
|
126
131
|
},
|
|
127
|
-
onMessage
|
|
132
|
+
{ onMessage }
|
|
128
133
|
);
|
|
129
134
|
|
|
130
135
|
status = config.add([nodeEphys, nodeStreamOut]);
|
|
@@ -148,7 +153,11 @@ const read = async (device: Device, argv: any) => {
|
|
|
148
153
|
return;
|
|
149
154
|
}
|
|
150
155
|
|
|
151
|
-
nodeStreamOut.start();
|
|
156
|
+
status = await nodeStreamOut.start();
|
|
157
|
+
if (!status.ok()) {
|
|
158
|
+
console.error("failed to start stream out node: ", status.message);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
152
161
|
|
|
153
162
|
let running = true;
|
|
154
163
|
process.on("SIGINT", function () {
|
|
@@ -159,6 +168,7 @@ const read = async (device: Device, argv: any) => {
|
|
|
159
168
|
running = false;
|
|
160
169
|
nodeStreamOut.stop();
|
|
161
170
|
device.stop();
|
|
171
|
+
process.exit();
|
|
162
172
|
});
|
|
163
173
|
};
|
|
164
174
|
|
|
@@ -280,7 +290,9 @@ const main = async () => {
|
|
|
280
290
|
if (argv._.includes("discover")) {
|
|
281
291
|
const devices = await discover();
|
|
282
292
|
for (const device of devices) {
|
|
283
|
-
|
|
293
|
+
const addr = `${device.host}:${device.port}`;
|
|
294
|
+
const serial = `[${device.serial}]`;
|
|
295
|
+
console.log(`${addr.padEnd(21)} ${device.capability.padStart(16)} ${serial.padStart(34)} "${device.name}"`);
|
|
284
296
|
}
|
|
285
297
|
return;
|
|
286
298
|
}
|
package/src/device.ts
CHANGED
|
@@ -18,7 +18,7 @@ class Device {
|
|
|
18
18
|
if (!status.ok() || !client) {
|
|
19
19
|
throw new Error(`Failed to create client for ${uri}: ${status.message}`);
|
|
20
20
|
}
|
|
21
|
-
this.rpc = client;
|
|
21
|
+
this.rpc = client as synapse.SynapseDevice;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
async configure(config: Config, options: CallOptions = {}): Promise<Status> {
|
|
@@ -90,6 +90,39 @@ class Device {
|
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
async streamQuery(
|
|
94
|
+
query: synapse.IStreamQueryRequest,
|
|
95
|
+
options: CallOptions = {},
|
|
96
|
+
callbacks: {
|
|
97
|
+
onData: (data: synapse.StreamQueryResponse) => void;
|
|
98
|
+
onEnd?: () => void;
|
|
99
|
+
onError?: (err: Error) => void;
|
|
100
|
+
onStatus?: (status: Status) => void;
|
|
101
|
+
}
|
|
102
|
+
) {
|
|
103
|
+
const { onData, onEnd, onError, onStatus } = callbacks;
|
|
104
|
+
const call = this.rpc.streamQuery(query, options);
|
|
105
|
+
call.on("data", (data: synapse.StreamQueryResponse) => {
|
|
106
|
+
onData(data);
|
|
107
|
+
});
|
|
108
|
+
if (onEnd) {
|
|
109
|
+
call.on("end", () => {
|
|
110
|
+
onEnd();
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (onError) {
|
|
114
|
+
call.on("error", (err: ServiceError) => {
|
|
115
|
+
onError(err);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
if (onStatus) {
|
|
119
|
+
call.on("status", (grpcStatus) => {
|
|
120
|
+
onStatus?.(new Status(grpcStatus.code, grpcStatus.details));
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return call;
|
|
124
|
+
}
|
|
125
|
+
|
|
93
126
|
// Logs
|
|
94
127
|
|
|
95
128
|
async getLogs(
|
package/src/nodes/index.ts
CHANGED
|
@@ -3,7 +3,8 @@ export { default as DiskWriter } from "./disk_writer";
|
|
|
3
3
|
export { default as ElectricalStimulation } from "./electrical_stimulation";
|
|
4
4
|
export { default as OpticalStimulation } from "./optical_stimulation";
|
|
5
5
|
export { default as SpectralFilter } from "./spectral_filter";
|
|
6
|
-
export { default as
|
|
6
|
+
export { default as SpikeBinner } from "./spike_binner";
|
|
7
|
+
export { default as SpikeDetector } from "./spike_detector";
|
|
7
8
|
export { default as SpikeSource } from "./spike_source";
|
|
8
9
|
export { default as StreamIn } from "./stream_in";
|
|
9
10
|
export { default as StreamOut } from "./stream_out";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { synapse } from "../api/api";
|
|
2
|
+
import Node from "../node";
|
|
3
|
+
|
|
4
|
+
class SpikeBinner extends Node {
|
|
5
|
+
type = synapse.NodeType.kSpikeBinner;
|
|
6
|
+
config: synapse.ISpikeBinnerConfig;
|
|
7
|
+
|
|
8
|
+
constructor(config: synapse.ISpikeBinnerConfig = {}) {
|
|
9
|
+
super();
|
|
10
|
+
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
toProto(): synapse.NodeConfig {
|
|
15
|
+
return super.toProto({
|
|
16
|
+
spikeBinner: this.config,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static fromProto(proto: synapse.INodeConfig): SpikeBinner {
|
|
21
|
+
const { spikeBinner } = proto;
|
|
22
|
+
if (!spikeBinner) {
|
|
23
|
+
throw new Error("Invalid config, missing spikeBinner");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return new SpikeBinner(proto.spikeBinner);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default SpikeBinner;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { synapse } from "../api/api";
|
|
2
|
+
import Node from "../node";
|
|
3
|
+
|
|
4
|
+
class SpikeDetector extends Node {
|
|
5
|
+
type = synapse.NodeType.kSpikeDetector;
|
|
6
|
+
config: synapse.ISpikeDetectorConfig;
|
|
7
|
+
|
|
8
|
+
constructor(config: synapse.ISpikeDetectorConfig = {}) {
|
|
9
|
+
super();
|
|
10
|
+
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
toProto(): synapse.NodeConfig {
|
|
15
|
+
return super.toProto({
|
|
16
|
+
spikeDetector: this.config,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static fromProto(proto: synapse.INodeConfig): SpikeDetector {
|
|
21
|
+
const { spikeDetector } = proto;
|
|
22
|
+
if (!spikeDetector) {
|
|
23
|
+
throw new Error("Invalid config, missing spikeDetector");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return new SpikeDetector(proto.spikeDetector);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default SpikeDetector;
|
package/src/nodes/stream_out.ts
CHANGED
|
@@ -2,80 +2,97 @@ import dgram from "dgram";
|
|
|
2
2
|
|
|
3
3
|
import { synapse } from "../api/api";
|
|
4
4
|
import Node from "../node";
|
|
5
|
+
import { Status, StatusCode } from "../utils/status";
|
|
6
|
+
import { getClientIp } from "../utils/ip";
|
|
5
7
|
|
|
6
|
-
const
|
|
8
|
+
const kDefaultStreamOutPort = 50038;
|
|
9
|
+
const kSocketBufferSize = 5 * 1024 * 1024; // 5MB
|
|
7
10
|
|
|
8
11
|
class StreamOut extends Node {
|
|
9
12
|
type = synapse.NodeType.kStreamOut;
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
_destinationAddress: string;
|
|
14
|
+
_destinationPort: number;
|
|
15
|
+
_label: string;
|
|
16
|
+
_socket: dgram.Socket | null;
|
|
12
17
|
_onMessage: ((msg: Buffer) => void) | null;
|
|
18
|
+
_onError: ((error: Error) => void) | null;
|
|
13
19
|
|
|
14
|
-
constructor(
|
|
20
|
+
constructor(
|
|
21
|
+
config: synapse.IStreamOutConfig,
|
|
22
|
+
callbacks?: { onMessage?: (msg: Buffer) => void; onError?: (error: Error) => void }
|
|
23
|
+
) {
|
|
15
24
|
super();
|
|
16
25
|
|
|
17
|
-
|
|
18
|
-
this.
|
|
26
|
+
const { udpUnicast } = config || {};
|
|
27
|
+
this._destinationAddress = udpUnicast?.destinationAddress;
|
|
28
|
+
this._destinationPort = udpUnicast?.destinationPort || kDefaultStreamOutPort;
|
|
29
|
+
this._label = config.label;
|
|
30
|
+
this._onMessage = callbacks?.onMessage;
|
|
31
|
+
this._onError = callbacks?.onError;
|
|
19
32
|
}
|
|
20
33
|
|
|
21
|
-
async start(): Promise<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const host = this.config.multicastGroup;
|
|
42
|
-
if (!host) {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
34
|
+
async start(): Promise<Status> {
|
|
35
|
+
try {
|
|
36
|
+
this._socket = dgram.createSocket("udp4");
|
|
37
|
+
|
|
38
|
+
if (!this._destinationAddress) {
|
|
39
|
+
try {
|
|
40
|
+
const ip = await getClientIp();
|
|
41
|
+
if (!ip) {
|
|
42
|
+
return new Status(StatusCode.INTERNAL, "failed to get client ip");
|
|
43
|
+
}
|
|
44
|
+
this._destinationAddress = ip;
|
|
45
|
+
} catch (e) {
|
|
46
|
+
console.error(e);
|
|
47
|
+
return new Status(StatusCode.INTERNAL, `failed to get client ip: ${e}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (!this._destinationPort) {
|
|
51
|
+
this._destinationPort = kDefaultStreamOutPort;
|
|
52
|
+
}
|
|
45
53
|
|
|
46
|
-
|
|
54
|
+
this._socket.on("message", (msg: Buffer) => {
|
|
55
|
+
this._onMessage?.(msg);
|
|
56
|
+
});
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
this._socket.on("error", (error: Error) => {
|
|
59
|
+
this._onError?.(error);
|
|
60
|
+
});
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
62
|
+
await new Promise<void>((resolve, reject) => {
|
|
63
|
+
if (!this._socket) return reject(new Error("Socket is null"));
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
this._socket.bind(this._destinationPort, this._destinationAddress, () => {
|
|
66
|
+
this._socket.setRecvBufferSize(kSocketBufferSize);
|
|
67
|
+
resolve();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
58
70
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
return true;
|
|
71
|
+
return new Status();
|
|
72
|
+
} catch (e) {
|
|
73
|
+
return new Status(StatusCode.INTERNAL, `failed to start stream out node: ${e}`);
|
|
74
|
+
}
|
|
66
75
|
}
|
|
67
76
|
|
|
68
|
-
async stop(): Promise<
|
|
77
|
+
async stop(): Promise<Status> {
|
|
69
78
|
if (this._socket) {
|
|
70
79
|
this._socket.close();
|
|
71
80
|
}
|
|
72
81
|
|
|
73
|
-
return
|
|
82
|
+
return new Status();
|
|
74
83
|
}
|
|
75
84
|
|
|
76
85
|
toProto(): synapse.NodeConfig {
|
|
86
|
+
const config: synapse.IStreamOutConfig = {
|
|
87
|
+
label: this._label,
|
|
88
|
+
udpUnicast: {
|
|
89
|
+
destinationAddress: this._destinationAddress,
|
|
90
|
+
destinationPort: this._destinationPort,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
77
94
|
return super.toProto({
|
|
78
|
-
streamOut:
|
|
95
|
+
streamOut: config,
|
|
79
96
|
});
|
|
80
97
|
}
|
|
81
98
|
|
|
@@ -85,7 +102,7 @@ class StreamOut extends Node {
|
|
|
85
102
|
throw new Error("Invalid config, missing streamOut");
|
|
86
103
|
}
|
|
87
104
|
|
|
88
|
-
return new StreamOut(streamOut);
|
|
105
|
+
return new StreamOut(streamOut, undefined);
|
|
89
106
|
}
|
|
90
107
|
}
|
|
91
108
|
|
package/src/utils/ip.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import dgram from "dgram";
|
|
2
|
+
|
|
3
|
+
export const getClientIp = async (): Promise<string | null> => {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
try {
|
|
6
|
+
const socket = dgram.createSocket("udp4");
|
|
7
|
+
|
|
8
|
+
socket.on("error", (err) => {
|
|
9
|
+
console.error(err);
|
|
10
|
+
socket.close();
|
|
11
|
+
reject(err);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
socket.bind(0, () => {
|
|
15
|
+
try {
|
|
16
|
+
socket.connect(53, "8.8.8.8", () => {
|
|
17
|
+
try {
|
|
18
|
+
const address = socket.address();
|
|
19
|
+
socket.close();
|
|
20
|
+
resolve(address.address);
|
|
21
|
+
} catch (e) {
|
|
22
|
+
socket.close();
|
|
23
|
+
reject(e);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
} catch (e) {
|
|
27
|
+
socket.close();
|
|
28
|
+
reject(e);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
} catch (e) {
|
|
32
|
+
reject(e);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Summary
|
|
2
|
+
Brief overview of the changes
|
|
3
|
+
|
|
4
|
+
# Changes
|
|
5
|
+
* Detailed breakdown of what changed and why. If there are new/changed API concepts, explain how they are meant to be used.
|
|
6
|
+
|
|
7
|
+
# Testing
|
|
8
|
+
How can this change be tested?
|
|
9
|
+
|
|
10
|
+
Please provide a link to a reference server and client implementation in synapse-python.
|
package/synapse-api/README.md
CHANGED