@science-corporation/synapse 0.9.0 → 0.12.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 +40 -18
- package/dist/api/api.d.ts +3881 -1739
- package/dist/api/api.js +10023 -5111
- package/dist/api/api.js.map +1 -1
- package/dist/api/proto.json +370 -63
- package/dist/api-science-device/api.d.ts +3 -0
- package/dist/api-science-device/api.d.ts.map +1 -0
- package/dist/api-science-device/api.js +3822 -0
- package/dist/api-science-device/api.js.map +1 -0
- package/dist/api-science-device/proto.json +258 -0
- package/dist/browser.d.ts +4 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +22 -0
- package/dist/browser.js.map +1 -0
- package/dist/config.d.ts +5 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +25 -17
- package/dist/config.js.map +1 -1
- package/dist/demo.js +42 -38
- package/dist/demo.js.map +1 -1
- package/dist/device.d.ts +20 -5
- package/dist/device.d.ts.map +1 -1
- package/dist/device.js +75 -27
- package/dist/device.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/nodejs.d.ts +8 -0
- package/dist/nodejs.d.ts.map +1 -0
- package/dist/nodejs.js +32 -0
- package/dist/nodejs.js.map +1 -0
- package/dist/nodes/broadband_source.d.ts +11 -0
- package/dist/nodes/broadband_source.d.ts.map +1 -0
- package/dist/nodes/{optical_broadband.js → broadband_source.js} +9 -9
- package/dist/nodes/broadband_source.js.map +1 -0
- package/dist/nodes/index.d.ts +3 -2
- package/dist/nodes/index.d.ts.map +1 -1
- package/dist/nodes/index.js +5 -5
- package/dist/nodes/index.js.map +1 -1
- package/dist/nodes/spike_source.d.ts +11 -0
- package/dist/nodes/spike_source.d.ts.map +1 -0
- package/dist/nodes/{electrical_broadband.js → spike_source.js} +9 -9
- package/dist/nodes/spike_source.js.map +1 -0
- package/dist/nodes/stream_in.d.ts +0 -4
- package/dist/nodes/stream_in.d.ts.map +1 -1
- package/dist/nodes/stream_in.js +1 -1
- package/dist/nodes/stream_in.js.map +1 -1
- package/dist/nodes/stream_out.d.ts +2 -2
- package/dist/nodes/stream_out.d.ts.map +1 -1
- package/dist/nodes/stream_out.js +2 -2
- package/dist/nodes/stream_out.js.map +1 -1
- package/dist/science-device-api/api.d.ts +3 -0
- package/dist/science-device-api/api.d.ts.map +1 -0
- package/dist/science-device-api/api.js +3822 -0
- package/dist/science-device-api/api.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/client.d.ts +8 -1
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js +30 -16
- package/dist/utils/client.js.map +1 -1
- package/dist/utils/device-management.d.ts +37 -0
- package/dist/utils/device-management.d.ts.map +1 -0
- package/dist/utils/device-management.js +126 -0
- package/dist/utils/device-management.js.map +1 -0
- package/dist/utils/discover.d.ts +3 -8
- package/dist/utils/discover.d.ts.map +1 -1
- package/dist/utils/discover.js +17 -32
- package/dist/utils/discover.js.map +1 -1
- package/dist/utils/enum.d.ts +1 -1
- package/dist/utils/enum.d.ts.map +1 -1
- package/dist/utils/enum.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/status.d.ts +28 -0
- package/dist/utils/status.d.ts.map +1 -0
- package/dist/utils/status.js +54 -0
- package/dist/utils/status.js.map +1 -0
- package/package.json +35 -9
- package/scripts/postinstall.sh +95 -0
- package/src/api/api.d.ts +3881 -1739
- package/src/api/api.js +10524 -5282
- package/src/api/proto.json +370 -63
- package/src/browser.ts +4 -0
- package/src/config.ts +31 -20
- package/src/demo.ts +43 -33
- package/src/device.ts +84 -30
- package/src/index.ts +4 -1
- package/src/nodes/broadband_source.ts +30 -0
- package/src/nodes/index.ts +4 -2
- package/src/nodes/spike_source.ts +30 -0
- package/src/nodes/stream_in.ts +1 -6
- package/src/nodes/stream_out.ts +4 -4
- package/src/utils/client.ts +38 -13
- package/src/utils/discover.ts +25 -45
- package/src/utils/enum.ts +1 -1
- package/src/utils/index.ts +1 -1
- package/src/utils/status.ts +57 -0
- package/synapse-api/.github/workflows/proto-check.yaml +33 -0
- package/synapse-api/COPYRIGHT +1 -0
- package/synapse-api/README.md +1 -1
- package/synapse-api/api/logging.proto +44 -0
- package/synapse-api/api/node.proto +22 -8
- package/synapse-api/api/nodes/broadband_source.proto +20 -0
- package/synapse-api/api/nodes/disk_writer.proto +7 -0
- package/synapse-api/api/nodes/electrical_stimulation.proto +4 -0
- package/synapse-api/api/nodes/signal_config.proto +22 -0
- package/synapse-api/api/nodes/signal_status.proto +18 -0
- package/synapse-api/api/nodes/spike_source.proto +15 -0
- package/synapse-api/api/nodes/stream_in.proto +5 -0
- package/synapse-api/api/nodes/stream_out.proto +4 -0
- package/synapse-api/api/query.proto +19 -0
- package/synapse-api/api/status.proto +6 -0
- package/synapse-api/api/synapse.proto +6 -2
- package/synapse-api/build.sh +17 -0
- package/dist/channel_mask.d.ts +0 -7
- package/dist/channel_mask.d.ts.map +0 -1
- package/dist/channel_mask.js +0 -14
- package/dist/channel_mask.js.map +0 -1
- package/dist/nodes/electrical_broadband.d.ts +0 -11
- package/dist/nodes/electrical_broadband.d.ts.map +0 -1
- package/dist/nodes/electrical_broadband.js.map +0 -1
- package/dist/nodes/optical_broadband.d.ts +0 -11
- package/dist/nodes/optical_broadband.d.ts.map +0 -1
- package/dist/nodes/optical_broadband.js.map +0 -1
- package/src/nodes/electrical_broadband.ts +0 -30
- package/src/nodes/optical_broadband.ts +0 -30
- package/synapse-api/api/nodes/electrical_broadband.proto +0 -15
- package/synapse-api/api/nodes/optical_broadband.proto +0 -11
package/src/config.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import Node from "./node";
|
|
2
2
|
import { synapse } from "./api/api";
|
|
3
|
-
import
|
|
3
|
+
import BroadbandSource from "./nodes/broadband_source";
|
|
4
4
|
import ElectricalStimulation from "./nodes/electrical_stimulation";
|
|
5
|
-
import OpticalBroadband from "./nodes/optical_broadband";
|
|
6
5
|
import OpticalStimulation from "./nodes/optical_stimulation";
|
|
7
6
|
import SpectralFilter from "./nodes/spectral_filter";
|
|
8
7
|
import SpikeDetect from "./nodes/spike_detect";
|
|
8
|
+
import SpikeSource from "./nodes/spike_source";
|
|
9
9
|
import StreamIn from "./nodes/stream_in";
|
|
10
10
|
import StreamOut from "./nodes/stream_out";
|
|
11
|
+
import { Status, StatusCode } from "./utils/status";
|
|
11
12
|
|
|
12
13
|
type Connection = [number, number];
|
|
13
14
|
const kNodeTypeObjectMap = {
|
|
14
|
-
[synapse.NodeType.
|
|
15
|
+
[synapse.NodeType.kBroadbandSource]: BroadbandSource,
|
|
15
16
|
[synapse.NodeType.kElectricalStimulation]: ElectricalStimulation,
|
|
16
|
-
[synapse.NodeType.
|
|
17
|
+
[synapse.NodeType.kSpikeSource]: SpikeSource,
|
|
17
18
|
[synapse.NodeType.kOpticalStimulation]: OpticalStimulation,
|
|
18
19
|
[synapse.NodeType.kSpectralFilter]: SpectralFilter,
|
|
19
20
|
[synapse.NodeType.kSpikeDetect]: SpikeDetect,
|
|
@@ -29,37 +30,47 @@ class Config {
|
|
|
29
30
|
return this.nodes.length + 1;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
add(nodes: Node[]) {
|
|
33
|
+
add(nodes: Node[]): Status {
|
|
33
34
|
for (const node of nodes) {
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
const status = this.addNode(node);
|
|
36
|
+
if (!status.ok()) {
|
|
37
|
+
return status;
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
|
-
return
|
|
40
|
+
return new Status();
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
connect(fromNode: Node, toNode: Node):
|
|
42
|
-
if (fromNode.id
|
|
43
|
-
return
|
|
43
|
+
connect(fromNode: Node, toNode: Node): Status {
|
|
44
|
+
if (!fromNode.id || !toNode.id) {
|
|
45
|
+
return new Status(StatusCode.INVALID_ARGUMENT, "source and destination nodes must have ids");
|
|
44
46
|
}
|
|
45
47
|
this.connections.push([fromNode.id, toNode.id]);
|
|
46
|
-
return
|
|
48
|
+
return new Status();
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
addNode(node: Node):
|
|
50
|
-
if (
|
|
51
|
-
return
|
|
51
|
+
addNode(node: Node, id?: number): Status {
|
|
52
|
+
if (node.id) {
|
|
53
|
+
return new Status(StatusCode.INVALID_ARGUMENT, "node must not have an id");
|
|
52
54
|
}
|
|
53
|
-
|
|
55
|
+
|
|
56
|
+
if (id === undefined) {
|
|
57
|
+
id = this._genNodeId();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (this.nodes.find((n) => n.id === id)) {
|
|
61
|
+
return new Status(StatusCode.INVALID_ARGUMENT, "node id must be unique");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
node.id = id;
|
|
54
65
|
this.nodes.push(node);
|
|
55
|
-
return
|
|
66
|
+
return new Status();
|
|
56
67
|
}
|
|
57
68
|
|
|
58
|
-
setDevice(device):
|
|
69
|
+
setDevice(device): Status {
|
|
59
70
|
for (const node of this.nodes) {
|
|
60
71
|
node.device = device;
|
|
61
72
|
}
|
|
62
|
-
return
|
|
73
|
+
return new Status();
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
static fromProto(proto: synapse.IDeviceConfiguration): Config {
|
|
@@ -74,7 +85,7 @@ class Config {
|
|
|
74
85
|
}
|
|
75
86
|
|
|
76
87
|
const node = NodeType.fromProto(nodeProto);
|
|
77
|
-
if (
|
|
88
|
+
if (nodeProto.id) {
|
|
78
89
|
node.id = nodeProto.id;
|
|
79
90
|
config.nodes.push(node);
|
|
80
91
|
} else {
|
package/src/demo.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
5
5
|
import { synapse } from "./api/api";
|
|
6
6
|
import Config from "./config";
|
|
7
7
|
import Device from "./device";
|
|
8
|
-
import ElectricalBroadband from "./nodes/
|
|
8
|
+
import ElectricalBroadband from "./nodes/broadband_source";
|
|
9
9
|
import OpticalStimulation from "./nodes/optical_stimulation";
|
|
10
10
|
import StreamIn from "./nodes/stream_in";
|
|
11
11
|
import StreamOut from "./nodes/stream_out";
|
|
@@ -48,8 +48,13 @@ const cli = yargs(hideBin(process.argv))
|
|
|
48
48
|
const info = async (device: Device) => {
|
|
49
49
|
console.log("Info()");
|
|
50
50
|
|
|
51
|
-
const
|
|
52
|
-
|
|
51
|
+
const { status: s, response } = await device.info();
|
|
52
|
+
if (!s.ok()) {
|
|
53
|
+
console.error(s.message);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const { serial, name, status, synapseVersion, firmwareVersion, peripherals, configuration } = response;
|
|
53
58
|
|
|
54
59
|
console.log(` - serial: ${serial}`);
|
|
55
60
|
console.log(` - name: ${name}`);
|
|
@@ -89,7 +94,7 @@ const read = async (device: Device, argv: any) => {
|
|
|
89
94
|
console.log("Reading from device's StreamOut node...");
|
|
90
95
|
|
|
91
96
|
const { multicastGroup, output } = argv;
|
|
92
|
-
let
|
|
97
|
+
let status = null;
|
|
93
98
|
let stream = null;
|
|
94
99
|
if (output) {
|
|
95
100
|
console.log(`Writing to file: ${output}`);
|
|
@@ -107,9 +112,13 @@ const read = async (device: Device, argv: any) => {
|
|
|
107
112
|
const config = new Config();
|
|
108
113
|
const nodeEphys = new ElectricalBroadband({
|
|
109
114
|
peripheralId: 3,
|
|
110
|
-
|
|
115
|
+
signal: {
|
|
116
|
+
electrode: {
|
|
117
|
+
channels: [{ id: 0, referenceId: 0, electrodeId: 1 }],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
111
120
|
bitWidth: 12,
|
|
112
|
-
|
|
121
|
+
sampleRateHz: 16000,
|
|
113
122
|
});
|
|
114
123
|
const nodeStreamOut = new StreamOut(
|
|
115
124
|
{
|
|
@@ -118,26 +127,24 @@ const read = async (device: Device, argv: any) => {
|
|
|
118
127
|
onMessage
|
|
119
128
|
);
|
|
120
129
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (!ok) {
|
|
124
|
-
console.error("
|
|
130
|
+
status = config.add([nodeEphys, nodeStreamOut]);
|
|
131
|
+
status = config.connect(nodeEphys, nodeStreamOut);
|
|
132
|
+
if (!status.ok()) {
|
|
133
|
+
console.error("failed to connect nodes: ", status.message);
|
|
125
134
|
return;
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
console.log("Configuring device...");
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
console.error(e);
|
|
138
|
+
status = await device.configure(config);
|
|
139
|
+
if (!status.ok()) {
|
|
140
|
+
console.error("failed to configure device: ", status.message);
|
|
133
141
|
return;
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
console.log("Starting device...");
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
console.error(e);
|
|
145
|
+
status = await device.start();
|
|
146
|
+
if (!status.ok()) {
|
|
147
|
+
console.error("failed to start device: ", status.message);
|
|
141
148
|
return;
|
|
142
149
|
}
|
|
143
150
|
|
|
@@ -164,7 +171,7 @@ const write = async (device: Device, argv: any) => {
|
|
|
164
171
|
}
|
|
165
172
|
|
|
166
173
|
console.log("Writing to device's StreamOut node...");
|
|
167
|
-
let
|
|
174
|
+
let status = null;
|
|
168
175
|
|
|
169
176
|
const config = new Config();
|
|
170
177
|
const nodeStreamIn = new StreamIn({
|
|
@@ -172,26 +179,29 @@ const write = async (device: Device, argv: any) => {
|
|
|
172
179
|
});
|
|
173
180
|
const nodeOptical = new OpticalStimulation();
|
|
174
181
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
182
|
+
status = config.add([nodeStreamIn, nodeOptical]);
|
|
183
|
+
if (!status.ok()) {
|
|
184
|
+
console.error("Failed to add nodes: ", status.message);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
status = config.connect(nodeStreamIn, nodeOptical);
|
|
189
|
+
if (!status.ok()) {
|
|
190
|
+
console.error("Failed to connect nodes: ", status.message);
|
|
179
191
|
return;
|
|
180
192
|
}
|
|
181
193
|
|
|
182
194
|
console.log("Configuring device...");
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
console.error(e);
|
|
195
|
+
status = await device.configure(config);
|
|
196
|
+
if (!status.ok()) {
|
|
197
|
+
console.error("Failed to configure device: ", status.message);
|
|
187
198
|
return;
|
|
188
199
|
}
|
|
189
200
|
|
|
190
201
|
console.log("Starting device...");
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
console.error(e);
|
|
202
|
+
status = await device.start();
|
|
203
|
+
if (!status.ok()) {
|
|
204
|
+
console.error("Failed to start device: ", status.message);
|
|
195
205
|
return;
|
|
196
206
|
}
|
|
197
207
|
|
|
@@ -286,8 +296,8 @@ const main = async () => {
|
|
|
286
296
|
|
|
287
297
|
try {
|
|
288
298
|
await info(device);
|
|
289
|
-
} catch (
|
|
290
|
-
console.error(
|
|
299
|
+
} catch (err) {
|
|
300
|
+
console.error(`Failed to get device info (${err.code}): ${err.message}`);
|
|
291
301
|
return;
|
|
292
302
|
}
|
|
293
303
|
|
package/src/device.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { Channel, credentials } from "@grpc/grpc-js";
|
|
1
|
+
import { Channel, credentials, ServiceError } from "@grpc/grpc-js";
|
|
2
2
|
|
|
3
|
+
import protos from "./api/proto.json";
|
|
3
4
|
import { synapse } from "./api/api";
|
|
4
5
|
import Config from "./config";
|
|
5
|
-
import { create } from "./utils/client";
|
|
6
|
-
import {
|
|
6
|
+
import { CallOptions, create } from "./utils/client";
|
|
7
|
+
import { fromDeviceStatus, Status } from "./utils/status";
|
|
8
|
+
|
|
9
|
+
const kSynapseService = "synapse.SynapseDevice";
|
|
7
10
|
|
|
8
11
|
class Device {
|
|
9
12
|
rpc: any | null = null;
|
|
@@ -11,82 +14,133 @@ class Device {
|
|
|
11
14
|
sockets: synapse.INodeSocket[] = [];
|
|
12
15
|
|
|
13
16
|
constructor(public uri: string) {
|
|
14
|
-
|
|
15
|
-
if (!
|
|
16
|
-
throw new Error(`Failed to create client for ${uri}`);
|
|
17
|
+
const { status, client } = create(protos, kSynapseService)(uri, credentials.createInsecure());
|
|
18
|
+
if (!status.ok() || !client) {
|
|
19
|
+
throw new Error(`Failed to create client for ${uri}: ${status.message}`);
|
|
17
20
|
}
|
|
21
|
+
this.rpc = client;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
async configure(config: Config): Promise<
|
|
24
|
+
async configure(config: Config, options: CallOptions = {}): Promise<Status> {
|
|
21
25
|
return new Promise((resolve, reject) => {
|
|
22
26
|
config.setDevice(this);
|
|
23
|
-
|
|
24
27
|
const proto = config.toProto();
|
|
25
|
-
this.rpc.configure(proto, (err, res) => {
|
|
28
|
+
this.rpc.configure(proto, options, (err: ServiceError, res) => {
|
|
26
29
|
if (err) {
|
|
27
30
|
reject(err);
|
|
28
31
|
} else {
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
const status = this._handleStatusResponse(res!);
|
|
33
|
+
if (status.ok()) {
|
|
34
|
+
resolve(status);
|
|
31
35
|
} else {
|
|
32
|
-
reject(`
|
|
36
|
+
reject(new Status(status.code, `failed to configure device: ${status.message}`));
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
});
|
|
36
40
|
});
|
|
37
41
|
}
|
|
38
42
|
|
|
39
|
-
async info(): Promise<synapse.DeviceInfo> {
|
|
43
|
+
async info(options: CallOptions = {}): Promise<{ status: Status; response?: synapse.DeviceInfo }> {
|
|
40
44
|
return new Promise((resolve, reject) => {
|
|
41
|
-
this.rpc.info({}, (err, res) => {
|
|
45
|
+
this.rpc.info({}, options, (err: ServiceError, res: synapse.DeviceInfo) => {
|
|
42
46
|
if (err) {
|
|
43
47
|
reject(err);
|
|
48
|
+
} else if (!res) {
|
|
49
|
+
reject(new Status(err.code, "failed to get device info: " + err.message));
|
|
44
50
|
} else {
|
|
45
|
-
|
|
51
|
+
const { sockets } = res.status;
|
|
52
|
+
this.sockets = sockets || [];
|
|
53
|
+
resolve({ status: new Status(), response: res });
|
|
46
54
|
}
|
|
47
55
|
});
|
|
48
56
|
});
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
async start(): Promise<
|
|
59
|
+
async start(options: CallOptions = {}): Promise<Status> {
|
|
52
60
|
return new Promise((resolve, reject) => {
|
|
53
|
-
this.rpc.start({}, (err, res) => {
|
|
61
|
+
this.rpc.start({}, options, (err: ServiceError, res: synapse.IStatus) => {
|
|
54
62
|
if (err) {
|
|
55
63
|
reject(err);
|
|
56
64
|
} else {
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
const status = this._handleStatusResponse(res!);
|
|
66
|
+
if (status.ok()) {
|
|
67
|
+
resolve(status);
|
|
59
68
|
} else {
|
|
60
|
-
reject(`
|
|
69
|
+
reject(new Status(status.code, `failed to start device: ${status.message}`));
|
|
61
70
|
}
|
|
62
71
|
}
|
|
63
72
|
});
|
|
64
73
|
});
|
|
65
74
|
}
|
|
66
75
|
|
|
67
|
-
async stop(): Promise<
|
|
76
|
+
async stop(options: CallOptions = {}): Promise<Status> {
|
|
68
77
|
return new Promise((resolve, reject) => {
|
|
69
|
-
this.rpc.stop({}, (err, res) => {
|
|
78
|
+
this.rpc.stop({}, options, (err: ServiceError, res: synapse.IStatus) => {
|
|
70
79
|
if (err) {
|
|
71
80
|
reject(err);
|
|
72
81
|
} else {
|
|
73
|
-
|
|
74
|
-
|
|
82
|
+
const status = this._handleStatusResponse(res!);
|
|
83
|
+
if (status.ok()) {
|
|
84
|
+
resolve(status);
|
|
75
85
|
} else {
|
|
76
|
-
reject(`
|
|
86
|
+
reject(new Status(status.code, `failed to stop device: ${status.message}`));
|
|
77
87
|
}
|
|
78
88
|
}
|
|
79
89
|
});
|
|
80
90
|
});
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
// Logs
|
|
94
|
+
|
|
95
|
+
async getLogs(
|
|
96
|
+
query: synapse.ILogQueryRequest,
|
|
97
|
+
options: CallOptions = {}
|
|
98
|
+
): Promise<{ status: Status; response?: synapse.LogQueryResponse }> {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
this.rpc.getLogs(query, options, (err: ServiceError, res: synapse.LogQueryResponse) => {
|
|
101
|
+
if (err) {
|
|
102
|
+
reject(err);
|
|
103
|
+
} else {
|
|
104
|
+
resolve({ status: new Status(), response: res });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async tailLogs(
|
|
111
|
+
query: synapse.ITailLogsRequest,
|
|
112
|
+
options: CallOptions = {},
|
|
113
|
+
callbacks: {
|
|
114
|
+
onData: (data: synapse.LogEntry) => void;
|
|
115
|
+
onEnd?: () => void;
|
|
116
|
+
onError?: (err: Error) => void;
|
|
117
|
+
onStatus?: (status: Status) => void;
|
|
118
|
+
}
|
|
119
|
+
) {
|
|
120
|
+
const { onData, onEnd, onError, onStatus } = callbacks;
|
|
121
|
+
const call = this.rpc.tailLogs(query, options);
|
|
122
|
+
call.on("data", onData);
|
|
123
|
+
if (onEnd) {
|
|
124
|
+
call.on("end", onEnd);
|
|
125
|
+
}
|
|
126
|
+
if (onError) {
|
|
127
|
+
call.on("error", onError);
|
|
128
|
+
}
|
|
129
|
+
if (onStatus) {
|
|
130
|
+
call.on("status", (grpcStatus) => {
|
|
131
|
+
onStatus?.(new Status(grpcStatus.code, grpcStatus.details));
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return call;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
_handleStatusResponse(status: synapse.IStatus): Status {
|
|
138
|
+
const { code, message, sockets } = status;
|
|
139
|
+
if (code !== synapse.StatusCode.kOk) {
|
|
140
|
+
return fromDeviceStatus({ code, message });
|
|
87
141
|
} else {
|
|
88
142
|
this.sockets = sockets || [];
|
|
89
|
-
return
|
|
143
|
+
return new Status();
|
|
90
144
|
}
|
|
91
145
|
}
|
|
92
146
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export { default as Config } from "./config";
|
|
2
2
|
export { default as Device } from "./device";
|
|
3
3
|
export * from "./nodes";
|
|
4
|
-
export {
|
|
4
|
+
export { IStatus, Status, StatusCode } from "./utils/status";
|
|
5
|
+
|
|
6
|
+
export type { CallOptions } from "./utils/client";
|
|
7
|
+
export * from "./api/api";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { synapse } from "../api/api";
|
|
2
|
+
import Node from "../node";
|
|
3
|
+
|
|
4
|
+
class BroadbandSource extends Node {
|
|
5
|
+
type = synapse.NodeType.kBroadbandSource;
|
|
6
|
+
config: synapse.IBroadbandSourceConfig;
|
|
7
|
+
|
|
8
|
+
constructor(config: synapse.IBroadbandSourceConfig = {}) {
|
|
9
|
+
super();
|
|
10
|
+
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
toProto(): synapse.NodeConfig {
|
|
15
|
+
return super.toProto({
|
|
16
|
+
broadbandSource: this.config,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static fromProto(proto: synapse.NodeConfig): BroadbandSource {
|
|
21
|
+
const { broadbandSource } = proto;
|
|
22
|
+
if (!broadbandSource) {
|
|
23
|
+
throw new Error("Invalid config, missing broadbandSource");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return new BroadbandSource(proto.broadbandSource);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default BroadbandSource;
|
package/src/nodes/index.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export { default as
|
|
1
|
+
export { default as BroadbandSource } from "./broadband_source";
|
|
2
2
|
export { default as ElectricalStimulation } from "./electrical_stimulation";
|
|
3
|
-
export { default as OpticalBroadband } from "./optical_broadband";
|
|
4
3
|
export { default as OpticalStimulation } from "./optical_stimulation";
|
|
5
4
|
export { default as SpectralFilter } from "./spectral_filter";
|
|
6
5
|
export { default as SpikeDetect } from "./spike_detect";
|
|
6
|
+
export { default as SpikeSource } from "./spike_source";
|
|
7
7
|
export { default as StreamIn } from "./stream_in";
|
|
8
8
|
export { default as StreamOut } from "./stream_out";
|
|
9
|
+
|
|
10
|
+
export type * from "../api/api";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { synapse } from "../api/api";
|
|
2
|
+
import Node from "../node";
|
|
3
|
+
|
|
4
|
+
class SpikeSource extends Node {
|
|
5
|
+
type = synapse.NodeType.kSpikeSource;
|
|
6
|
+
config: synapse.ISpikeSourceConfig;
|
|
7
|
+
|
|
8
|
+
constructor(config: synapse.ISpikeSourceConfig = {}) {
|
|
9
|
+
super();
|
|
10
|
+
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
toProto(): synapse.NodeConfig {
|
|
15
|
+
return super.toProto({
|
|
16
|
+
spikeSource: this.config,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static fromProto(proto: synapse.NodeConfig): SpikeSource {
|
|
21
|
+
const { spikeSource } = proto;
|
|
22
|
+
if (!spikeSource) {
|
|
23
|
+
throw new Error("Invalid config, missing spikeSource");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return new SpikeSource(proto.spikeSource);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default SpikeSource;
|
package/src/nodes/stream_in.ts
CHANGED
|
@@ -3,11 +3,6 @@ import dgram from "dgram";
|
|
|
3
3
|
import { synapse } from "../api/api";
|
|
4
4
|
import Node from "../node";
|
|
5
5
|
|
|
6
|
-
export interface StreamInArgs {
|
|
7
|
-
dataType: synapse.DataType;
|
|
8
|
-
shape?: number[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
6
|
class StreamIn extends Node {
|
|
12
7
|
type = synapse.NodeType.kStreamIn;
|
|
13
8
|
config: synapse.IStreamInConfig;
|
|
@@ -49,7 +44,7 @@ class StreamIn extends Node {
|
|
|
49
44
|
|
|
50
45
|
try {
|
|
51
46
|
this._socket.send(data, port, host);
|
|
52
|
-
} catch
|
|
47
|
+
} catch {
|
|
53
48
|
return false;
|
|
54
49
|
}
|
|
55
50
|
|
package/src/nodes/stream_out.ts
CHANGED
|
@@ -18,7 +18,7 @@ class StreamOut extends Node {
|
|
|
18
18
|
this._onMessage = onMessage;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
async start(): Promise<
|
|
21
|
+
async start(): Promise<boolean> {
|
|
22
22
|
if (this.device === null) {
|
|
23
23
|
return false;
|
|
24
24
|
}
|
|
@@ -45,9 +45,9 @@ class StreamOut extends Node {
|
|
|
45
45
|
|
|
46
46
|
this._socket = dgram.createSocket("udp4");
|
|
47
47
|
|
|
48
|
-
this._socket.on("error", (
|
|
48
|
+
this._socket.on("error", () => {});
|
|
49
49
|
|
|
50
|
-
this._socket.on("message", (msg: Buffer
|
|
50
|
+
this._socket.on("message", (msg: Buffer) => {
|
|
51
51
|
this._onMessage?.(msg);
|
|
52
52
|
});
|
|
53
53
|
|
|
@@ -65,7 +65,7 @@ class StreamOut extends Node {
|
|
|
65
65
|
return true;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
async stop(): Promise<
|
|
68
|
+
async stop(): Promise<boolean> {
|
|
69
69
|
if (this._socket) {
|
|
70
70
|
this._socket.close();
|
|
71
71
|
}
|
package/src/utils/client.ts
CHANGED
|
@@ -1,20 +1,45 @@
|
|
|
1
1
|
import { ChannelCredentials, ChannelOptions, loadPackageDefinition } from "@grpc/grpc-js";
|
|
2
2
|
import { fromJSON } from "@grpc/proto-loader";
|
|
3
|
+
import { Status, StatusCode } from "./status";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
export interface CallOptions {
|
|
6
|
+
deadline?: Date;
|
|
7
|
+
}
|
|
5
8
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
keepCase: false,
|
|
9
|
-
arrays: true,
|
|
10
|
-
enums: Number,
|
|
11
|
-
defaults: true,
|
|
12
|
-
oneofs: true,
|
|
13
|
-
});
|
|
14
|
-
const descriptor = loadPackageDefinition(definition as any);
|
|
15
|
-
return (descriptor.synapse as any).SynapseDevice;
|
|
9
|
+
const pick = (obj: any, path: string) => {
|
|
10
|
+
return path.split(".").reduce((acc, part) => (acc && acc[part]) || null, obj);
|
|
16
11
|
};
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
const loadClient = (protoJson: object, serviceName: string): { status: Status; factory?: any } => {
|
|
14
|
+
try {
|
|
15
|
+
const definition = fromJSON(protoJson as any, {
|
|
16
|
+
keepCase: false,
|
|
17
|
+
arrays: true,
|
|
18
|
+
enums: Number,
|
|
19
|
+
defaults: true,
|
|
20
|
+
oneofs: true,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const descriptor = loadPackageDefinition(definition as any);
|
|
24
|
+
|
|
25
|
+
const service = pick(descriptor, serviceName);
|
|
26
|
+
if (!service) {
|
|
27
|
+
return { status: new Status(StatusCode.INTERNAL, `service ${serviceName} not found in proto definition`) };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return { status: new Status(StatusCode.OK), factory: service };
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return { status: new Status(StatusCode.INTERNAL, "failed to load proto definition: " + error) };
|
|
33
|
+
}
|
|
20
34
|
};
|
|
35
|
+
|
|
36
|
+
export const create =
|
|
37
|
+
(protoJson: object, serviceName: string) =>
|
|
38
|
+
(address: string, credentials: ChannelCredentials, options?: ChannelOptions): { status: Status; client?: any } => {
|
|
39
|
+
const { status, factory } = loadClient(protoJson, serviceName);
|
|
40
|
+
if (!status.ok()) {
|
|
41
|
+
return { status };
|
|
42
|
+
}
|
|
43
|
+
const client = new factory(address, credentials, options);
|
|
44
|
+
return { status, client };
|
|
45
|
+
};
|