Streaming Data to NeuroScale (API)
# insert the pipeline id extracted from Dashboard or with the NeuroScale API
pipeline_id = 'pl_RSWmAgPYysWdFJzF7A99GS'
<Image title="Screenshot from 2022-06-16 15-32-22.png" alt="1617" src="../images/fe682ee-Screenshot_from_2022-06-16_15-32-22.png">
Pipeline I.D. and Metadata
</Image>
The HTTP request to check the state is a GET with URL <API-URL>/v1/instances/<instance-id>, empty body, and `Authorization` header as before. The response will be again a [JSON](http://www.json.org/)-encoded object of the same form as what was returned after instance creation, and the instance state of interest is in the "state" field:
At this point, you have a running instance, but you do not yet know the concrete endpoints over which to send/receive data to communicate with the instance. These endpoints can be looked up from the response body that corresponded to the <API-URL>/v1/instances/<instance-id> resource (same for the POST, GET and PATCH request cases). The list of endpoint URLs is in the field "endpoints", under "data". Each endpoint has a "url" field, as well as a "mode" field (which is either "read" for pipeline instance outputs or "write" for pipeline instance inputs):
The actual work is implemented in callback handler functions, which we go over next. Once our reader has connected to the host, we need to subscribe to a "topic", which is the MQTT way of specifying what messages shall be received. The topic is part of the URL of the read endpoint (specifically, the *path* of the URL) and begins with a '/' character. However, the topic namespace is hierarchical (like directories), and the read endpoint gives only the super-topic under which the pipeline instance generates all its data. Specifically, for every output node of the pipeline instance there will be a subtopic of that name (typically this will be a single subtopic named "default"). So if the read endpoint was, for instance, `mqtt://myhost.com:1883/testing` then the default node would publish its data under the topic `/testing/default`. If at some point we chose to listen to other nodes of a pipeline instance, we would have to subscribe to those subtopics as well. However, to make things simpler we can just subscribe to all subtopics, using the '#' (multi-level wildcard) subtopic as done below. We can then filter the received messages upon receipt according to their topic:
For efficiency, you will usually want to transmit multiple samples at a time (unless the data source has a very low or irregular sampling rate), here 10. The generated chunk is a list of samples, each of which is a list of values (one per channel):
If precision better than \~50ms is needed, you need to consider that by the time you get the sample from the hardware, it will already be a few milliseconds old (having travelled through the device, USB, various buffers, the driver stack, and the OS). If you know the average delay of your device, you can subtract this number from your timestamps to achieve accurate synchronization.
When you attempt to achieve millisecond-level synchronization between devices, you may be worried about jitter in your timestamp measurements — it is important to note that NeuroScale will internally remove the jitter using a [Kalman filter](https://en.wikipedia.org/wiki/Kalman_filter), so you do not (and should not) have to worry about it. Attempting to filter the jitter by hand will usually make it (much) worse.