@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.
Files changed (88) hide show
  1. package/README.md +4 -2
  2. package/dist/api/api.d.ts +711 -71
  3. package/dist/api/api.js +5532 -4083
  4. package/dist/api/api.js.map +1 -1
  5. package/dist/api/proto.json +122 -32
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +4 -2
  8. package/dist/config.js.map +1 -1
  9. package/dist/demo.js +125 -32
  10. package/dist/demo.js.map +1 -1
  11. package/dist/device.d.ts +6 -0
  12. package/dist/device.d.ts.map +1 -1
  13. package/dist/device.js +25 -0
  14. package/dist/device.js.map +1 -1
  15. package/dist/nodes/index.d.ts +2 -1
  16. package/dist/nodes/index.d.ts.map +1 -1
  17. package/dist/nodes/index.js +5 -3
  18. package/dist/nodes/index.js.map +1 -1
  19. package/dist/nodes/spike_binner.d.ts +11 -0
  20. package/dist/nodes/{spike_detect.d.ts.map → spike_binner.d.ts.map} +1 -1
  21. package/dist/nodes/spike_binner.js +28 -0
  22. package/dist/nodes/{spike_detect.js.map → spike_binner.js.map} +1 -1
  23. package/dist/nodes/spike_detector.d.ts +11 -0
  24. package/dist/nodes/spike_detector.d.ts.map +1 -0
  25. package/dist/nodes/{spike_detect.js → spike_detector.js} +9 -9
  26. package/dist/nodes/spike_detector.js.map +1 -0
  27. package/dist/nodes/stream_out.d.ts +12 -5
  28. package/dist/nodes/stream_out.d.ts.map +1 -1
  29. package/dist/nodes/stream_out.js +58 -40
  30. package/dist/nodes/stream_out.js.map +1 -1
  31. package/dist/utils/ip.d.ts +2 -0
  32. package/dist/utils/ip.d.ts.map +1 -0
  33. package/dist/utils/ip.js +52 -0
  34. package/dist/utils/ip.js.map +1 -0
  35. package/package.json +6 -5
  36. package/scripts/postinstall.sh +50 -10
  37. package/src/api/api.d.ts +711 -71
  38. package/src/api/api.js +5671 -4121
  39. package/src/api/proto.json +122 -32
  40. package/src/config.ts +4 -2
  41. package/src/demo.ts +20 -8
  42. package/src/device.ts +34 -1
  43. package/src/nodes/index.ts +2 -1
  44. package/src/nodes/spike_binner.ts +30 -0
  45. package/src/nodes/spike_detector.ts +30 -0
  46. package/src/nodes/stream_out.ts +67 -50
  47. package/src/utils/ip.ts +35 -0
  48. package/synapse-api/.github/pull_request_template.md +10 -0
  49. package/synapse-api/README.md +1 -1
  50. package/synapse-api/api/datatype.proto +1 -0
  51. package/synapse-api/api/node.proto +6 -3
  52. package/synapse-api/api/nodes/spike_binner.proto +7 -0
  53. package/synapse-api/api/nodes/spike_detector.proto +19 -0
  54. package/synapse-api/api/nodes/stream_out.proto +31 -1
  55. package/synapse-api/api/query.proto +19 -1
  56. package/synapse-api/api/synapse.proto +1 -0
  57. package/dist/api-science-device/api.d.ts +0 -3
  58. package/dist/api-science-device/api.d.ts.map +0 -1
  59. package/dist/api-science-device/api.js +0 -3822
  60. package/dist/api-science-device/api.js.map +0 -1
  61. package/dist/api-science-device/proto.json +0 -258
  62. package/dist/nodejs.d.ts +0 -8
  63. package/dist/nodejs.d.ts.map +0 -1
  64. package/dist/nodejs.js +0 -32
  65. package/dist/nodejs.js.map +0 -1
  66. package/dist/nodes/spike_detect.d.ts +0 -11
  67. package/dist/science-device-api/api.d.ts +0 -3
  68. package/dist/science-device-api/api.d.ts.map +0 -1
  69. package/dist/science-device-api/api.js +0 -3822
  70. package/dist/science-device-api/api.js.map +0 -1
  71. package/dist/types/index.d.ts +0 -3
  72. package/dist/types/index.d.ts.map +0 -1
  73. package/dist/types/index.js +0 -19
  74. package/dist/types/index.js.map +0 -1
  75. package/dist/types.d.ts +0 -5
  76. package/dist/types.d.ts.map +0 -1
  77. package/dist/types.js +0 -19
  78. package/dist/types.js.map +0 -1
  79. package/dist/utils/device-management.d.ts +0 -37
  80. package/dist/utils/device-management.d.ts.map +0 -1
  81. package/dist/utils/device-management.js +0 -126
  82. package/dist/utils/device-management.js.map +0 -1
  83. package/dist/utils/ndtp.d.ts +0 -40
  84. package/dist/utils/ndtp.d.ts.map +0 -1
  85. package/dist/utils/ndtp.js +0 -140
  86. package/dist/utils/ndtp.js.map +0 -1
  87. package/src/nodes/spike_detect.ts +0 -30
  88. package/synapse-api/api/nodes/spike_detect.proto +0 -16
@@ -150,37 +150,52 @@
150
150
  }
151
151
  }
152
152
  },
153
- "SpikeDetectConfig": {
153
+ "SpikeBinnerConfig": {
154
154
  "fields": {
155
- "mode": {
156
- "type": "SpikeDetectMode",
157
- "id": 1
158
- },
159
- "thresholdUV": {
155
+ "binSizeMs": {
160
156
  "type": "uint32",
161
- "id": 2
162
- },
157
+ "id": 1
158
+ }
159
+ }
160
+ },
161
+ "TemplateMatcher": {
162
+ "fields": {
163
163
  "templateUV": {
164
164
  "rule": "repeated",
165
165
  "type": "uint32",
166
- "id": 3
167
- },
168
- "sort": {
169
- "type": "bool",
170
- "id": 4
171
- },
172
- "binSizeMs": {
166
+ "id": 1
167
+ }
168
+ }
169
+ },
170
+ "Thresholder": {
171
+ "fields": {
172
+ "thresholdUV": {
173
173
  "type": "uint32",
174
- "id": 5
174
+ "id": 1
175
+ }
176
+ }
177
+ },
178
+ "SpikeDetectorConfig": {
179
+ "oneofs": {
180
+ "config": {
181
+ "oneof": [
182
+ "thresholder",
183
+ "templateMatcher"
184
+ ]
175
185
  }
176
186
  },
177
- "nested": {
178
- "SpikeDetectMode": {
179
- "values": {
180
- "kThreshold": 0,
181
- "kTemplate": 1,
182
- "kWavelet": 2
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
- "multicastGroup": {
233
- "type": "string",
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
- "kSpikeDetect": 6,
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
- "spikeDetect",
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
- "spikeDetect": {
526
- "type": "SpikeDetectConfig",
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 SpikeDetect from "./nodes/spike_detect";
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.kSpikeDetect]: SpikeDetect,
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
- "multicast-group": {
20
- alias: "m",
20
+ "udp-port": {
21
+ alias: "p",
21
22
  type: "string",
22
- description: "Multicast group",
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 { multicastGroup, output } = argv;
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
- multicastGroup,
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
- console.log(`${device.host}:${device.port} ${device.capability} ${device.name} (${device.serial})`);
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(
@@ -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 SpikeDetect } from "./spike_detect";
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;
@@ -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 kMulticastTTL = 3;
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
- config: synapse.IStreamOutConfig;
11
- _socket: dgram.Socket;
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(config: synapse.IStreamOutConfig, onMessage?: (msg: Buffer) => void) {
20
+ constructor(
21
+ config: synapse.IStreamOutConfig,
22
+ callbacks?: { onMessage?: (msg: Buffer) => void; onError?: (error: Error) => void }
23
+ ) {
15
24
  super();
16
25
 
17
- this.config = config;
18
- this._onMessage = onMessage;
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<boolean> {
22
- if (this.device === null) {
23
- return false;
24
- }
25
-
26
- const socket = this.device.sockets.find((s) => s.nodeId === this.id);
27
- if (!socket) {
28
- return false;
29
- }
30
-
31
- const split = socket.bind.split(":");
32
- if (split.length !== 2) {
33
- return false;
34
- }
35
-
36
- const port = parseInt(split[1]);
37
- if (isNaN(port)) {
38
- return false;
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
- this._socket = dgram.createSocket("udp4");
54
+ this._socket.on("message", (msg: Buffer) => {
55
+ this._onMessage?.(msg);
56
+ });
47
57
 
48
- this._socket.on("error", () => {});
58
+ this._socket.on("error", (error: Error) => {
59
+ this._onError?.(error);
60
+ });
49
61
 
50
- this._socket.on("message", (msg: Buffer) => {
51
- this._onMessage?.(msg);
52
- });
62
+ await new Promise<void>((resolve, reject) => {
63
+ if (!this._socket) return reject(new Error("Socket is null"));
53
64
 
54
- this._socket.bind(port, host, () => {
55
- if (!this._socket) {
56
- return;
57
- }
65
+ this._socket.bind(this._destinationPort, this._destinationAddress, () => {
66
+ this._socket.setRecvBufferSize(kSocketBufferSize);
67
+ resolve();
68
+ });
69
+ });
58
70
 
59
- if (this.config.multicastGroup) {
60
- this._socket.setMulticastTTL(kMulticastTTL);
61
- this._socket.addMembership(this.config.multicastGroup);
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<boolean> {
77
+ async stop(): Promise<Status> {
69
78
  if (this._socket) {
70
79
  this._socket.close();
71
80
  }
72
81
 
73
- return true;
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: this.config,
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
 
@@ -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.
@@ -1,4 +1,4 @@
1
- # Synapse API 1.1
1
+ # Synapse API 2.0.0
2
2
 
3
3
  The Synapse Protocol defines a standard interface for interacting with a wide range of possible neural interface devices.
4
4
 
@@ -9,4 +9,5 @@ enum DataType {
9
9
  kSpiketrain = 3;
10
10
  kTimestamps = 4;
11
11
  kImage = 5;
12
+ kWaveforms = 6;
12
13
  }