SILF Protocol

Version note

This document describes protocol version 0.5 which will be implemented in silf laboratory up to version 1.0.0.

Version 1.0 of this protocol will be significantly simpler.

Namespaces

silf:mode:get

This namespace is used query modes from the experiment.

First client sends:

>>> write(LabdataModeGet(id="query1", type="query"))
<ns0:labdata xmlns:ns0="silf:mode:get" id="query1" type="query" />

Then server responds:

>>> write(LabdataModeGet(id="query1", type="result", suite=ModeSuite(default=Mode("Default mode", "This is the default mode description"))))
<ns0:labdata xmlns:ns0="silf:mode:get" id="query1" type="result">{"default": {"label": "Default mode", "description": "This is the default mode description"}}</ns0:labdata>

Stanza content

Contents of silf:mode:get in type result are formatted as follows:

{
    "mode-keyname": {
        "label": "Mode label", "description": "Mode description",
        "order" : "1"
    },
    "mode-keyname-2": {
        "label": "Mode label", "description": "Mode description",
        "order": "1"
    }
}

Each property in this object contains description of one mode, and name of this property is name of the mode.

Modes should be sorded ascending with order attribute, if order is equal sort them alphabetically.

Warning

Before we upgrade experiment software, client should not expect order attribute to be defined. If it is undefined sort it so all input fields with undefined should be below those with defined order.

Backend behaviour

In current implementation experiment does not change state when reclieving this message

Client behaviour

Client allows user to choose mode.

silf:mode:set

This namespace is used to set mode of the experiment, and to return experiment metadata to the users.

This namespace is used query modes from the experiment.

Client sends

>>> write(LabdataModeSet(id="query1", type="query", suite=ModeSelection(mode="default")))
<ns0:labdata xmlns:ns0="silf:mode:set" id="query1" type="query">{"mode": "default"}</ns0:labdata>

Code sent by client contains Json object contains single property “mode” and it’s value must be “mode-keyname” (that is name of property under which particular mode is found in silf:mode:get).

Server responds

Server responds with metadata containing description of selected mode.

Object will have following properties:

mode
name of selected mode — usefull for visitor users
experimentId
Globally unique identifier of experiment session
settings
Description of user controllable input fields, described in Input fields
resultDescription
Description of fields that will present results to the user Output fields

Example response:

{
    "experimentId": "urn:uuid:a12e6562-5feb-4046-b98f-d8c40ca1609c",
    "mode": "aluminium",
    "settings": {
        "acquisition_time": {
            "live": false, "metadata": {
            "label": "Czas pomiaru dla jednej grubo\u015bci materia\u0142u"},
            "name": "acquisition_time", "validations": {"min_value": 5.0, "max_value": 600.0}, "type": "interval",
            "sort" : "1"},
        "light": {"live": false, "metadata": {"label": "O\u015bwietlenie", "style": "light_control"}, "name": "light", "type": "boolean", "sort" : "1"}
    },
    "resultDescription": {
        "time_left": {"name": ["tile_left"], "type": "array", "class": "interval-indicator", "settings": {}, "metadata": {"label": "Czas pozosta\u0142y do ko\u0144ca bierz\u0105cego punktu"}},
        "chart": {"name": ["chart"], "type": "array", "class": "chart", "settings": {}, "metadata": {"chart.axis.y.label": "Liczba zlicze\u0144 zarejestrowana przez licznik", "chart.axis.x.label": "Grubo\u015b\u0107 przes\u0142ony [mm]"}
   }
}

silf:settings:check

Namespace: silf:settings:check issed to check settings for validity, prior to submiting them.

Client sends:

{
    "acquisition_time": {"value": 150, "current": false},
    "light": {"value": false, "current": false}
}

Property names in this object correspond to appropriate property names from settings proprerty in silf:mode:set.

Server responds either with empty tag of type result or with an error message (see: Errors).

When user finishes edition of a control (for example when focus is lost) Client should send values of all controls that were touched by user in current experiment run, and set current to true for control that triggered rsult sending, and to false for all others.

Settings

Settings themselves have following properties

value

Value of the settings. Type of the setting varies and is based on type send in silf:mode:set

current

Whether this setting was most recently updated by user. This helps to customise displayed erros and validation, in case of controls that are dependend on each other.

silf:series:start

Sets all the parameters and starts the measurement series, contents sent by the client are the same as for silf:settings:check.

Note

Currently current property in this stanza is ignored by the server. But I think it is easier to have the same format (despite ignored information).

Server response

Server responds either with an error: Errors, or with following structure:

{
    "metadata": {"label": "Czas pomiaru 90s."},
    "initialSettings": {
        "acquisition_time": {"current": false, "value": 90},
        "light": {"current": false, "value": false}
    },
    "seriesId": "urn:uuid:6bd8a024-5a8b-4f04-be84-76dcad89d89f"
}

Where properties have following meaning:

seriesId
Unique id of current series
metadata
Dictionary containing additional metadata of the series. For now only key in this dictionary is series label (ie. non-unique human-readable name of the series)
initialSettings
Structure containing settings for the series (as it was set by the user)

silf:settings:update

Note

It’s a planned feaure and details might change.

During experiment session user my update input fields which are labeled as live (see: Input fields). In this case client should send silf:settings:update containing only the changed settings.

For example if only light was changed user should send:

{
    "light": {"value": false, "current": true}
}

If settings validate server should respond with silf:settings:update containting changed settings. If there are erros in settings, server should respod with proper error.

silf:results

Results are send as an object, where each result is sent as a distinct property, name of this property is also name of associated result.

So in following example:

{
    'foo' : {value: [1, 2, 3], pragma: "append"}.
    'bar' : {value: [1], pragma: "transient"}.
}

two results are sent, one named foo other named bar.

Single result

Result type has following properties:

pragma
Controls method in which result series is reconstructed.
value
Result value

Result series reconstruction

Experiment user wants to see whole result series, but in most cases we don’t want to send whole series each time (in some cases we need to!). We also don’t want to send new result stanza for each point if it is unnecessary.

Pragma property defines how series is reconstructed from series of result messages.

We support following pragmas:

append

Initially experiment series is empty, after each result contents of value property is appended to series.

For example if we sent following results:

{ "value": [1, 2, 3], "pragma": "append"}
{ "value": [4, 5], "pragma": "append"}

Series will be reconstructed as: {“value”: [1, 2, 3, 4, 5], “pragma”: “append”}

replace
Initially experiment series is empty, after reclieving of each result we replace series contents with this result.
transient
As append but will not be stored. Usefull when sending status variables.

silf:series:stop

Stops the series.

User sends following object:

{
    "seriesId" : "urn:uuid:6bd8a024-5a8b-4f04-be84-76dcad89d89f"
}

seriesId property signified series to stop.

Client can omit this seriesId property.

Experiment responds with the same object:

{
    "seriesId" : "urn:uuid:6bd8a024-5a8b-4f04-be84-76dcad89d89f"
}

silf:experiment:stop

Stops the experiment. User sends empty tag to the server.

Structures used in many stanzas

Input fields

Control fields contain at least following fields:

name
name of the control, it is not visible to user, but used to in both: silf:settings:check, and silf:series:stop.
type
Type of data this controls sends.
live
Boolean value. Currently unused.
metatadata
A dictionary that contains data visble to users: label Label of conntrol.
validations
Dictionary containing validations ot be done at client side.
default_value
Default value. It has the same type.
order

Used to sort input fields before they are rendered. Input fields with highter order should be presented on top of the input field list. In case of equal order fields should be sorted alphabetically on name attribute.

Warning

Before we upgrade experiment software, client should not expect order attribute to be defined. If it is undefined sort it so all input fields with undefined should be below those with defined order.

Currently we following types of input fields:

Number control

It allows user to submit an integer.

It has following possible validations:

min_value
minimal value present in the field
max_value
maximal value present in the field
step
increment in which to go from min_value to max_value
Value rendered to JSON Format

Client should create values that are json number objects, or dscimal strings.

{
    "number_control": {"value": 150, "current": false},
    "number_control_2": {"value": "36", "current": false}
}

Example of serialized control:

>>> control = NumberControl("foo", "Enter a number")
>>> control.to_json_dict() == {
... 'type': 'number', 'name': 'foo',
... 'metadata': {'label': 'Enter a number'},
... 'live': False}
True
>>> control.min_value = 1
>>> control.max_value = 10
>>> control.to_json_dict() ==  {
... 'type': 'number',
... 'validations': {'min_value': 1, 'max_value': 10},
... 'live': False,
... 'metadata': {'label': 'Enter a number'}, 'name': 'foo'}
True

Boolean control

It allows user to submit an boolean value.

Value rendered to JSON Format

Client should create values that are json boolean objects (any other objects will be passed to bool function.

{
    "number_control": {"value": 150, "current": false},
    "number_control_2": {"value": "36", "current": false}
}

Time interval control

Allows student to submit amount of time.

{
    "timedelta_control": {"value": 150, "current": false}
}

It has following validations:

min_value
minimal amout of time student could send. In the same format as it is send from client as settings.
max_value
maximal amount of time student can send.
Value rendered to JSON Format

Client should send to server amount of seconds (possibly as a float value).

ComboBox control

Renders a combo box.

It has no additional properties, but metadata property must contain choices property containing object defining the combo box.

Keys in the choices object define values that may will be sent from this controls, and values are user readable labels.

Example:

{
 'type': 'combo-box',
 'live': False,
 'metadata': {
     'label': 'Select material',
     'choices': {
         'lead': 'Use lead aperture',
         'cu': 'Use cooper aperture'
     }
 },
 'name': 'material',
 'default_value': 'cu'
}

This control would be rendered as a ComboBox with two choices: Use lead aperture and Use cooper aperture. And if user would choose Use cooper aperture, this control would send:

{
    ...
    'material: 'cu',
    ...
}

Output fields

Set of output fields is a plain object, each property denotes one output field, name of the property.

This block defines two output fields named foo and bar.

{
    'foo':   {'name': ['some_result'], ... },
    'bar':   {'name': ['other_result'], ... }
}

Format of object desceibing single output fields is defined in the next section.

Definitionamen of single output field

Output fields have following attributes:

name

names of result fields this output consumes. It is an array of strings.

Warning

Warning this is unimplemented in GUI, names is ignored, and follwing logic is used:

If experiment reclieves:

{
    'foo':   {'name': ['bar'], ... },
    'baz':   {'name': ['foobar'], ... }
}

Control that is under property foo will display results from property foo (and not bar as name would indicate).

This will be fixed sometime!

Until then Python API disallows sending name that is different than control name. So currently writen code is future proof.

type
Type of the resul field. This attribute defines how this field works. A string.
class
HTML class of result. This defines how does this field look. A string.
metadata
Dictionary od properties of this field that are visible
settings
Dictionary od properties of this field that are not visible to user
Applicable classes, and their behaviour

For now following classes are understood by the client.

Indicators, that display only the newest measurement in the series:

interval-indicator
Renders incoming data as a time interval, signifying (for example) time left end of current measurement point. It requires for
integer-indicator
Renders a number, for example number of registered counts on geiger counter.

Other classes:

chart
A chart.
Indicator example

Example of serialized indicator:

{
 'class': 'integer-indicator',
 'metadata': {'label': 'Current voltage [V]'},
 'name': ['current_voltage'],
 'settings': {},
 'type': 'array'
}
Chart example

Example of serialized chart:

{
 'class': 'chart',
 'metadata': {'chart.axis.x.label': 'Voltage between GM electrodes',
  'chart.axis.y.label': 'Counts in given time interval',
  'label': 'GM Counter characteristics'},
 'name': ['chart'],
 'settings': {},
 'type': 'array'}

How are results send and displayed

Each output field defines from which result field (or fields) it pulls the results, this defined in the name property.

Errors

Results are send as an object with single property errors that contains a list of error objects.

Each error object has following properties:

severity
A string describing how severe is this error. Following values are acceptable: error, warning, info.
error_type
A string. Following values are accetable: device, user. If value is user it means that user generated this error, and (so) can be fixed, device means that there is some error in the device.
metadata

Object with other error info:

message
Message for user
field
If it is present it is the name of an input field that is cause of this error (used when validating input fields).

Example:

{'errors':[
   {
       'severity':'error',
       'error_type': 'user',
       'metadata':{
           'message': 'Invalid value in field foo',
           'field': 'foo',
   },{
       'severity':'error',
       'error_type': 'user',
       'metadata':{
           'message': 'Invalid value in field bar',
           'field': 'bar',
    }
])