PyCollect - Live protocol¶
After Install and Run UBT Launcher in any of the available Modes, the system are ready to handle clients connections (take note about the selected port).
Data structure¶
Requests¶
- Each request sent to the WebSocket must be done in
JSON
format through astringify
command.- Each request must include at least one common argument:
command
.
Response¶
Each system response must include an debug
object with the argumments: command
, type
and origin
:
command
: With the same request command that trigger the response.type
: One ofDISP
,WAVE
,CHANNELS
,LOG
,ERROR
,RESP
.origin
: One ofPYCOLLECT
,PYMASIMO
.buffersize
: The size of internal buffer.recording
: Boolean that indicate if system are recording data.transmitting
: Boolean that indicate if system are transmitting data, inthis case, will send extra information about the data transmitted.
Types¶
DISP
: Indicate the presense os subrecords.WAVE
: Indicate the presense os waveforms.CHANNELS
: Indicate the presense of subrecords and waveforms.LOG
: When a command not need a response, this type is include amessage
argument.RESP
: Contain the response of a request.ERROR
: Contain an error message, this type is include amessage
argument.
Datetimes¶
All datetimes data are in Unix Timestamp format, for example:
Sun Aug 25 20:57:08 1991
is equivalent to683171828
Fri Jul 6 11:23:20 2018
is equivalent to1530894200
Special values¶
DATA_INVALID_LIMIT
: -32001DATA_INVALID
: -32767DATA_NOT_UPDATED
: -32766DATA_DISCONT
: -32765DATA_UNDER_RANGE
: -32764DATA_OVER_RANGE
: -32763DATA_NOT_CALIBRATED
: -32762
Commands¶
This list a commands are available, some of them need extra arguments.
available_channels
: Request the list of available subrecords based on the monitor modules activity merged with the list of waveforms supported by the monitor.available_subrecords
: Request the list of available subrecords based on the monitor modules activity.clear_data
: Clear buffer and stop data transfer.close_stream
: Stop stream and close serial port, save data if a recording enabled.debug
: Request debug information about device, conection, data transfering.get_csv
: Generate and save data un CSV format.get_edf
: Generate and save data in EDF+ format.get_raw
: Generate and save data in RAW format.list_all_measures
: Request a list of all measures supported by the monitor.list_all_waveforms
: Request a list of all waveform supported by the monitor.possible_waveforms
: Request the list of waveforms supported by the monitor.reconnect_device
: Send an instruction for reconnect with the serial port.request_channels
: Request to monitor a set of waveforms and subrecords.request_subrecords
: Request to monitor a set of subrecords.request_waveforms
: Request to monitor a set of waveforms.start_recording
: Clear data, continues the data transfer.stop_recording
:stop_transfer
: Stop the monitor data transfer.
Connection with WebSocket¶
A standard connection is enough, the default port is 8890
, the complete ip
could looks like: ws://localhost:8890/ws
, note the /ws
that complete the
address.
Quick test¶
This request will ask for available_channels
, start a default request_channels
,
wait for 5 seconds, start_recording
, wait for 10 seconds stop_transfer
and get_edf
, get_csv
, and get_raw
.
The result can be checked with the browser developer tools.
Available subrecords¶
Request¶
This command will stop a possible Subrecord transfer.
{
"command": "available_subrecords"
}
Response¶
{
"command": "available_subrecords",
"origin": "PYCOLLECT",
"type": "RESP",
"subrecords": [], //A list of available subrecords labels.
}
Request subrecords¶
Request¶
The value of subrecords must be a sublist from the list with available subrecords. If the list of `subrecords is empty the response will contain all available measures.
{
"command": "request_subrecords",
"subrecords": [], //List of subrecords labels.
}
Response¶
{
"type": "DISP",
"origin": "PYCOLLECT",
"command": "request_subrecords"
"datetime": 1530894200,
"data": {}, //A dictionary with the subrecords label and their respective measure.
}
Live example¶
Request possible waveforms¶
There is no way to list the waveforms that the device can send, this request return all possible waveforms
Response¶
The response is always the same.
{
"type": "RESP",
"origin": "PYCOLLECT",
"command": "possible_waveforms",
"waveforms": [], //A list of all waveforms.
}
Request waveforms¶
Request¶
The value of waveforms must be a sublist from the list with all waveforms. If the list of wafeforms is empty the request will be ignored.
{
"command": "request_waveforms",
"waveforms": [], //A list with the desired waveforms labels.
}
Response¶
The monitor only will send the available waveforms and not necessarily all that was requested.
{
"type": "WAVE",
"origin": "PYCOLLECT",
"command": "request_waveforms"
"channels": [ //list of channels, each channel is a dictionary
{ //channel dictionary
"label": "FLOW",
"datetime": 1530894182,
"physicalDimension": "l/min",
"samplefrequency": 25,
"samples": 100,
"physicalMaximum": null,
"physicalMinimum": null,
"digitalMaximum": 32768,
"digitalMinimum": -32768,
"prefilter": "",
"transducer": "",
"data": [...], //list of integers or floats
},
...
]
}
Live example¶
Available channels¶
Request¶
This command will stop a possible Subrecord and Waveforms transfer.
{
"command": "available_channels"
}
Response¶
{
"command": "available_channels",
"origin": "PYCOLLECT",
"type": "RESP",
"labels": [], //A list of available subrecords and waveforms labels.
}
Request channels¶
Request¶
The value of channels must be a sublist from the list with all waveforms and subrecords. If the list of labels is empty, then will reques the default dataset.
{
"command": "request_channels",
"channels": [], //A list with the desired waveforms and subrecords labels.
}
Response¶
The monitor only will send the available waveforms and not necessarily all that was requested.
{
"channels": [ //list of channels, each channel is a dictionary
{ //channel dictionary
"label": "FLOW",
"datetime": 1530894182,
"physicalDimension": "l/min",
"samplefrequency": 25,
"samples": 100,
"physicalMaximum": null,
"physicalMinimum": null,
"digitalMaximum": 32768,
"digitalMinimum": -32768,
"prefilter": "",
"transducer": "",
"data": [...], //list of integers, floats, strings or Nones
},
...
]
}
Live example¶
Stop transfer¶
This command will send a request to the monitor for stop the data transmitting.
request = {
"command": "stop_transfer"
}
Close stream¶
This command will send a request to the monitor for stop the data transmitting and will save possible data recording, the serial port will be closed too.
request = {
"command": "close_stream"
}
Reconnect with device¶
This command will send a request for connect with the monitor, this method is
called internally with the first connect, will return a debug
response.
request = {
"command": "reconnect_device"
}
Start recording¶
This command will clear the data buffer.
request = {
"command": "start_recording"
}
Clear data¶
This command will clear the data buffer and stop the data transmitting from monitor too.
request = {
"command": "clear_data"
}
Get debug information¶
Request¶
This request will return useful information about connection and transmission.
{
"command": "debug",
}
Response¶
A complete response, with transmission in process contains the next data.
{
"device": "gehealthcare", //Name of device connected
"port": null, //Serial port name
"ip_port": "8890", //IP port
"debug_mode": true, //Debug mode is enable
"user_dir": "/home/user/ubtdriver",
"download": "http://localhost:8890/download/",
"debug": {
"buffersize": 14976,
"recording": true,
"transmitting": true,
"origin": "PYCOLLECT",
"command": "debug",
"type": "RESP",
"subrecords": {
"startdatetime": 1532624765, //Timestamp for the first data
"enddatetime": 1532624805, //Timestamp for the last data
"totalseconds": 40, //Total of seconds processed
"labels": [] //List of subrecords labels
},
"waveforms": {
"startdatetime": 1532624798, //Timestamp for the first data
"enddatetime": 1532624804, //Timestamp for the last data
"totalseconds": 6, //Total of seconds processed
"labels": [] //List of waveforms labels
},
}
}
List all measures¶
Request¶
This request return information about all measures for all modules (availables or not).
{
"command": "list_all_measures",
}
Response¶
Each measure contain: label, description, unit and other information for internal usage.
{
"ECG HR": { //Label as dictionary key
"label": "ECG HR", //Label
"desc": "Heart rate", //Description
"key": "ecg:hr", //For internal usage
"unit": "1/min", //The physical unit
"subclass": "basic" //For unternal usage
},
...
}
List all waveforms¶
Request¶
This request return information about all waveforms.
{
"command": "list_all_waveforms",
}
Response¶
Each waveform contain: label, unit, samples per second and other information for internal usage.
{
"ECG1": { //Label as dictionary key
"label": "ECG1", //Label
"unit": "uV", //The physical unit
"shift": 0.000001, //For internal usage
"samps": 300, //Samples per second
"transducer": "", //Transductor used, used for generate the EDF+ file
"prefilter": "", //Prefilter, used for generate the EDF+ file
"physical_min": null, //Physical minimum, used for generate the EDF+ file
"physical_max": null, //Physical maximum, used for generate the EDF+ file
},
...
}
Save as RAW¶
In this implementation download event will kill the websocket.
request = {
"command": "get_raw"
}
Save as CSV¶
In this implementation download event will kill the websocket.
request = {
"command": "get_csv"
}
Save as EDF+¶
In this implementation download event will kill the websocket.
Bad request¶
When a request is not understood.
request = {
"command": "this_request_not_exist"
}