Improve doc.
Change-Id: I0b25fd1c645a47084fb7fda1bbb7d41a2d10dcbb
This commit is contained in:
parent
cf3fabfa0f
commit
77b01404d9
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,4 +10,4 @@ RELEASE-VERSION
|
|||||||
build
|
build
|
||||||
|
|
||||||
# Sphinx
|
# Sphinx
|
||||||
doc/srcdoc/_build
|
doc/_build
|
||||||
|
6
Makefile
6
Makefile
@ -9,10 +9,8 @@ clean:
|
|||||||
@rm -rf html
|
@rm -rf html
|
||||||
@mkdir html
|
@mkdir html
|
||||||
|
|
||||||
doc: doc/*.md
|
doc:
|
||||||
@echo "Generating html tree"
|
$(MAKE) -C doc html
|
||||||
@bin/make_doc.py
|
|
||||||
$(MAKE) -C doc/srcdoc html
|
|
||||||
|
|
||||||
demo:
|
demo:
|
||||||
@bin/secop-server -q demo &
|
@bin/secop-server -q demo &
|
||||||
|
@ -1,315 +0,0 @@
|
|||||||
## A SECoP Syntax for Demonstration
|
|
||||||
|
|
||||||
I feel it is very hard to explain in a talk what we are talking
|
|
||||||
about when discussing the concepts of SECoP. Would it not be easier
|
|
||||||
with an example syntax and an example SEC node? That is why I
|
|
||||||
created a simple syntax, which is on one hand easily understandable
|
|
||||||
by humans and on the other hand fulfills the requirements for a real syntax.
|
|
||||||
|
|
||||||
### An Example of an SEC Node with the Demo Syntax
|
|
||||||
|
|
||||||
We have 2 main devices: sample temperature and magnetic field.
|
|
||||||
|
|
||||||
> ts
|
|
||||||
ts=9.887
|
|
||||||
|
|
||||||
> mf
|
|
||||||
mf=5.1
|
|
||||||
|
|
||||||
|
|
||||||
We have some additional devices, coil temperature of upper and lower coil.
|
|
||||||
|
|
||||||
> tc1
|
|
||||||
tc1=2.23
|
|
||||||
|
|
||||||
> tc2
|
|
||||||
tc2=2.311
|
|
||||||
|
|
||||||
When we use the term "device" here, we do not mean a device in the sense of a
|
|
||||||
cryomagnet or a furnace. For SECoP, roughly any physical quantity which may
|
|
||||||
be of interest to the experimentalist, is its own device.
|
|
||||||
|
|
||||||
|
|
||||||
We can use wildcards to see the values of all devices at once.
|
|
||||||
|
|
||||||
> *
|
|
||||||
ts=9.887
|
|
||||||
mf=5.1
|
|
||||||
tc1=2.23
|
|
||||||
tc2=2.311
|
|
||||||
label='Cryomagnet MX15; at 9.887 K; Persistent at 5.1 Tesla'
|
|
||||||
|
|
||||||
|
|
||||||
The "> " is not part of the syntax, it is just indicating the request.
|
|
||||||
A request is always one line.
|
|
||||||
A reply might contain several lines and always ends with an empty line.
|
|
||||||
|
|
||||||
The last device here is a text displayed on the SE computer. It may not be
|
|
||||||
very useful, but it demonstrates that a device value may also be a text.
|
|
||||||
|
|
||||||
A device has parameters. The main parameter is its value. The value parameter
|
|
||||||
is just omitted in the path. We can list the the parameters and its values
|
|
||||||
with the following command:
|
|
||||||
|
|
||||||
> mf:*
|
|
||||||
mf=5.13
|
|
||||||
mf:status=0
|
|
||||||
mf:target=14.9
|
|
||||||
mf:ramp=0.4
|
|
||||||
mf:set_point=5.13
|
|
||||||
mf:persistent_mode=0
|
|
||||||
mf:switch_heater=1
|
|
||||||
|
|
||||||
If we want to change the field we have to set its target value:
|
|
||||||
|
|
||||||
> mf:target=12
|
|
||||||
mf:target=12.0
|
|
||||||
|
|
||||||
> mf:*
|
|
||||||
mf=5.13
|
|
||||||
mf:status=1
|
|
||||||
mf:target=12.0
|
|
||||||
mf:ramp=0.4
|
|
||||||
mf:set_point=5.13
|
|
||||||
mf:persistent_mode=0
|
|
||||||
mf:switch_heater=1
|
|
||||||
|
|
||||||
The status is indicating the state of the device. 0 means idle, 1 means busy
|
|
||||||
(running to the target).
|
|
||||||
|
|
||||||
A parameter has properties. The 'value' property is implicit, its just
|
|
||||||
omitted in the path:
|
|
||||||
|
|
||||||
> mf:status:*
|
|
||||||
mf:status=0
|
|
||||||
mf:status:value_names=0:idle,1:busy,2:error
|
|
||||||
mf:status:type=int
|
|
||||||
mf:status:t=2016-08-23 14:55:45.254348
|
|
||||||
|
|
||||||
Please notice the property "value_names" indicating the meaning of the status
|
|
||||||
values.
|
|
||||||
|
|
||||||
> mf:target:*
|
|
||||||
mf:target=12.0
|
|
||||||
mf:target:writable=1
|
|
||||||
mf:target:unit=T
|
|
||||||
mf:target:type=float
|
|
||||||
mf:target:t=2016-08-23 14:55:44.658749
|
|
||||||
|
|
||||||
The last property 't' is the timestamp. If the client want to record timestamps,
|
|
||||||
it can enable it for all device or parameter readings:
|
|
||||||
|
|
||||||
> :reply_items=t
|
|
||||||
:reply_items=t
|
|
||||||
|
|
||||||
> *
|
|
||||||
ts=9.867;t=2016-08-23 14:55:44.655862
|
|
||||||
mf=5.13;t=2016-08-23 14:55:44.656032
|
|
||||||
tc1=2.23;t=2016-08-23 14:55:44.656112
|
|
||||||
tc2=2.311;t=2016-08-23 14:55:44.656147
|
|
||||||
label='Cryomagnet MX15; at 9.867 K; Ramping at 5.13 Tesla';t=2016-08-23 14:55:44.656183
|
|
||||||
|
|
||||||
There is also a list command showing the devices (and parameters) without
|
|
||||||
values. I am not sure if we really need that, as we can just use a wildcard
|
|
||||||
read command and throw away the values.
|
|
||||||
|
|
||||||
> !*
|
|
||||||
ts
|
|
||||||
mf
|
|
||||||
tc1
|
|
||||||
tc2
|
|
||||||
label
|
|
||||||
|
|
||||||
> !ts:*
|
|
||||||
ts
|
|
||||||
ts:status
|
|
||||||
ts:target
|
|
||||||
ts:ramp
|
|
||||||
ts:use_ramp
|
|
||||||
ts:set_point
|
|
||||||
ts:heater_power
|
|
||||||
ts:raw_sensor
|
|
||||||
|
|
||||||
The property "meaning" indicates the meaning of the most important devices.
|
|
||||||
We can list all the devices which have a "meaning" property
|
|
||||||
|
|
||||||
> *::meaning
|
|
||||||
ts::meaning=temperature
|
|
||||||
mf::meaning=magnetic_field
|
|
||||||
|
|
||||||
> Markus: We have more things to tell here.
|
|
||||||
|
|
||||||
|
|
||||||
As a last example: the ultimate command to get everything:
|
|
||||||
|
|
||||||
> *:*:*
|
|
||||||
ts=9.887
|
|
||||||
ts::meaning=temperature
|
|
||||||
ts::unit=K
|
|
||||||
ts::description='VTI sensor (15 Tesla magnet)\ncalibration: X28611'
|
|
||||||
ts::type=float
|
|
||||||
ts::t=2016-08-23 14:55:44.655862
|
|
||||||
ts:status=0
|
|
||||||
ts:status:type=int
|
|
||||||
ts:status:t=2016-08-23 14:55:44.655946
|
|
||||||
ts:target=10.0
|
|
||||||
ts:target:writable=1
|
|
||||||
ts:target:unit=K
|
|
||||||
ts:target:type=float
|
|
||||||
ts:target:t=2016-08-23 14:55:44.655959
|
|
||||||
ts:ramp=0.0
|
|
||||||
ts:ramp:writable=1
|
|
||||||
ts:ramp:unit=K/min
|
|
||||||
ts:ramp:type=float
|
|
||||||
ts:ramp:t=2016-08-23 14:55:44.655972
|
|
||||||
ts:use_ramp=0
|
|
||||||
ts:use_ramp:type=int
|
|
||||||
ts:use_ramp:t=2016-08-23 14:55:44.655984
|
|
||||||
ts:set_point=10.0
|
|
||||||
ts:set_point:unit=K
|
|
||||||
ts:set_point:type=float
|
|
||||||
ts:set_point:t=2016-08-23 14:55:44.655995
|
|
||||||
ts:heater_power=0.154
|
|
||||||
ts:heater_power:unit=W
|
|
||||||
ts:heater_power:type=float
|
|
||||||
ts:heater_power:t=2016-08-23 14:55:44.656006
|
|
||||||
ts:raw_sensor=1876.3
|
|
||||||
ts:raw_sensor:unit=Ohm
|
|
||||||
ts:raw_sensor:type=float
|
|
||||||
ts:raw_sensor:t=2016-08-23 14:55:44.656018
|
|
||||||
mf=5.13
|
|
||||||
mf::meaning=magnetic_field
|
|
||||||
mf::unit=T
|
|
||||||
mf::description=magnetic field (15 Tesla magnet)
|
|
||||||
mf::type=float
|
|
||||||
mf::t=2016-08-23 14:55:44.656032
|
|
||||||
mf:status=0
|
|
||||||
mf:status:type=int
|
|
||||||
mf:status:t=2016-08-23 14:55:44.656044
|
|
||||||
mf:target=12.0
|
|
||||||
mf:target:writable=1
|
|
||||||
mf:target:unit=T
|
|
||||||
mf:target:type=float
|
|
||||||
mf:target:t=2016-08-23 14:55:44.658749
|
|
||||||
mf:ramp=0.4
|
|
||||||
mf:ramp:writable=1
|
|
||||||
mf:ramp:unit=T/min
|
|
||||||
mf:ramp:type=float
|
|
||||||
mf:ramp:t=2016-08-23 14:55:44.656066
|
|
||||||
mf:set_point=5.13
|
|
||||||
mf:set_point:unit=T
|
|
||||||
mf:set_point:type=float
|
|
||||||
mf:set_point:t=2016-08-23 14:55:44.656077
|
|
||||||
mf:persistent_mode=0
|
|
||||||
mf:persistent_mode:type=int
|
|
||||||
mf:persistent_mode:t=2016-08-23 14:55:44.656088
|
|
||||||
mf:switch_heater=1
|
|
||||||
mf:switch_heater:type=int
|
|
||||||
mf:switch_heater:t=2016-08-23 14:55:44.656099
|
|
||||||
tc1=2.23
|
|
||||||
tc1::unit=K
|
|
||||||
tc1::description='top coil (15 Tesla magnet)\ncalibration: X30906'
|
|
||||||
tc1::type=float
|
|
||||||
tc1::t=2016-08-23 14:55:44.656112
|
|
||||||
tc1:status=0
|
|
||||||
tc1:status:type=int
|
|
||||||
tc1:status:t=2016-08-23 14:55:44.656123
|
|
||||||
tc1:raw_sensor=5434.0
|
|
||||||
tc1:raw_sensor:unit=Ohm
|
|
||||||
tc1:raw_sensor:type=float
|
|
||||||
tc1:raw_sensor:t=2016-08-23 14:55:44.656134
|
|
||||||
tc2=2.311
|
|
||||||
tc2::unit=K
|
|
||||||
tc2::description='bottom coil (15 Tesla magnet)\ncalibration: C103'
|
|
||||||
tc2::type=float
|
|
||||||
tc2::t=2016-08-23 14:55:44.656147
|
|
||||||
tc2:status=0
|
|
||||||
tc2:status:type=int
|
|
||||||
tc2:status:t=2016-08-23 14:55:44.656159
|
|
||||||
tc2:raw_sensor=4834.5
|
|
||||||
tc2:raw_sensor:unit=Ohm
|
|
||||||
tc2:raw_sensor:type=float
|
|
||||||
tc2:raw_sensor:t=2016-08-23 14:55:44.656169
|
|
||||||
label='Cryomagnet MX15; Ramping'
|
|
||||||
label::writable=1
|
|
||||||
label::type=string
|
|
||||||
label::t=2016-08-23 14:55:44.656183
|
|
||||||
.:reply_items=t
|
|
||||||
.:reply_items:writable=1
|
|
||||||
.:reply_items:type=string
|
|
||||||
.:reply_items:t=2016-08-23 14:55:44.659617
|
|
||||||
.:compact_output=0
|
|
||||||
.:compact_output:writable=1
|
|
||||||
.:compact_output:type=int
|
|
||||||
.:compact_output:t=2016-08-23 14:55:44.656219
|
|
||||||
|
|
||||||
|
|
||||||
The last device '.' is a dummy device to hold the parameters of a client
|
|
||||||
connection. Changing these parameters must not affect other client connections.
|
|
||||||
The experimental parameter compact_output is for compressing the result of
|
|
||||||
wildcard requests: unchanged device and parameter names are omitted.
|
|
||||||
|
|
||||||
|
|
||||||
> :compact_output=1
|
|
||||||
.:compact_output=1
|
|
||||||
|
|
||||||
> *:*:*
|
|
||||||
ts=9.887
|
|
||||||
::meaning=temperature
|
|
||||||
::unit=K
|
|
||||||
::description='VTI sensor (15 Tesla magnet)\ncalibration: X28611'
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180514
|
|
||||||
:status=0
|
|
||||||
::type=int
|
|
||||||
::t=2016-08-23 15:04:55.180587
|
|
||||||
:target=10.0
|
|
||||||
::writable=1
|
|
||||||
::unit=K
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180594
|
|
||||||
:ramp=0.0
|
|
||||||
::writable=1
|
|
||||||
::unit=K/min
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180599
|
|
||||||
:use_ramp=0
|
|
||||||
::type=int
|
|
||||||
::t=2016-08-23 15:04:55.180604
|
|
||||||
:set_point=10.0
|
|
||||||
::unit=K
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180609
|
|
||||||
:heater_power=0.154
|
|
||||||
::unit=W
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180615
|
|
||||||
:raw_sensor=1876.3
|
|
||||||
::unit=Ohm
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180620
|
|
||||||
mf=5.13
|
|
||||||
::meaning=magnetic_field
|
|
||||||
::unit=T
|
|
||||||
::description=magnetic field (15 Tesla magnet)
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180626
|
|
||||||
:status=0
|
|
||||||
::type=int
|
|
||||||
::t=2016-08-23 15:04:55.180632
|
|
||||||
:target=14.9
|
|
||||||
::writable=1
|
|
||||||
::unit=T
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180637
|
|
||||||
:ramp=0.4
|
|
||||||
::writable=1
|
|
||||||
::unit=T/min
|
|
||||||
::type=float
|
|
||||||
::t=2016-08-23 15:04:55.180642
|
|
||||||
:set_point=5.13
|
|
||||||
::unit=T
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
@ -1,285 +0,0 @@
|
|||||||
## A SECoP Syntax for Demonstration
|
|
||||||
|
|
||||||
### Mapping of Messages
|
|
||||||
|
|
||||||
Please remind: replies always end with en empty line, which means that there are
|
|
||||||
2 newline characters at the end of each reply. To emphasize that, in this document
|
|
||||||
a bare '_' is shown as a replacement for the closing empty line.
|
|
||||||
|
|
||||||
#### ListDevices
|
|
||||||
|
|
||||||
> !*
|
|
||||||
<device-name1>
|
|
||||||
<device-name2>
|
|
||||||
...
|
|
||||||
<device-nameN>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### ListDeviceParams
|
|
||||||
|
|
||||||
> !<device>:*
|
|
||||||
<device>:<param1>
|
|
||||||
<device>:<param2>
|
|
||||||
...
|
|
||||||
<device>:<paramN>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### ReadRequest
|
|
||||||
|
|
||||||
> <device>:<param>
|
|
||||||
<device>:<param1>=<value>
|
|
||||||
_
|
|
||||||
|
|
||||||
Or, in case it is combined with timestamp (may be also sigma, unit ...). See also
|
|
||||||
below under "client parameters" / "reply_items".
|
|
||||||
|
|
||||||
> <device>:<param>
|
|
||||||
<device>:<param1>=<value>;t=<timestamp>
|
|
||||||
_
|
|
||||||
> <device>:<param>
|
|
||||||
<device>:<param1>=<value>;t=<timestamp>;s=<sigma>
|
|
||||||
_
|
|
||||||
> <device>:<param>
|
|
||||||
<device>:<param1>=<value>;t=<timestamp>;s=<sigma>;unit=<unit>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### ReadPropertiesOfAllDevices
|
|
||||||
remark: for shortness the name of the value property and the preceding ':' is omitted
|
|
||||||
|
|
||||||
> *:*:*
|
|
||||||
<device1>:<param1>=<value1>
|
|
||||||
<device1>:<param1>:<prop2>=<value2>
|
|
||||||
...
|
|
||||||
<deviceN>:<paramM>:<propL>=<valueK>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### ReadPropertiesOfADevice
|
|
||||||
means read properties of all parameters of a device)
|
|
||||||
|
|
||||||
> <device>:*:*
|
|
||||||
<device>:<param1>=<value1>
|
|
||||||
<device>:<param1>:<prop2>=<value2>
|
|
||||||
...
|
|
||||||
<device>:<paramN>:<propM>=<valueL>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### ReadPropertiesOfAParameter
|
|
||||||
|
|
||||||
> <device>:<param>:*
|
|
||||||
<device>:<param>=<value1>
|
|
||||||
<device>:<param>:<prop2>=<value2>
|
|
||||||
...
|
|
||||||
<device>:<param>:<propN>=<valueN>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### ReadSpecificProperty
|
|
||||||
|
|
||||||
> <device>:<param>:<prop>
|
|
||||||
<device>:<param>:<prop>=<value>
|
|
||||||
_
|
|
||||||
|
|
||||||
In case you want the value only, and not the timestamp etc, '.' is a placeholder for the
|
|
||||||
value property
|
|
||||||
|
|
||||||
> <device>:<param>:.
|
|
||||||
<device>:<param>:.=<value>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### ReadValueNotOlderThan
|
|
||||||
|
|
||||||
Instead of this special Request, I propose to make a client parameter "max_age",
|
|
||||||
which specifies in general how old values may be to be returned from cache.
|
|
||||||
|
|
||||||
#### Write
|
|
||||||
|
|
||||||
remark: writes to other than the 'value' property are not allowed. If anyone sees a
|
|
||||||
reasonable need to make writeable properties, a WriteProperty Request/Reply should
|
|
||||||
be discussed
|
|
||||||
|
|
||||||
> <device>:<param>=<value>
|
|
||||||
<device>:<param>=<readback-value>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### Command
|
|
||||||
|
|
||||||
If we want to distinguish between a write request and a command, we need also a
|
|
||||||
different syntax. It is to decide, how arguments may be structured / typed.
|
|
||||||
Should a command also send back a "return value"?
|
|
||||||
|
|
||||||
> <device>:<param> <arguments>
|
|
||||||
<device>:<param> <arguments>
|
|
||||||
_
|
|
||||||
|
|
||||||
#### Error replies
|
|
||||||
|
|
||||||
Error reply format:
|
|
||||||
|
|
||||||
~<error-specifier>~ <path or other info>
|
|
||||||
_
|
|
||||||
|
|
||||||
The error-specifier should be predefined identifer.
|
|
||||||
|
|
||||||
> tempature:target
|
|
||||||
~NoSuchCommand~ tempature
|
|
||||||
_
|
|
||||||
|
|
||||||
> temperature:taget
|
|
||||||
~NoSuchParameter~ temperature:taget
|
|
||||||
_
|
|
||||||
|
|
||||||
#### FeatureListRequest
|
|
||||||
|
|
||||||
Instead of an extra FeatureListRequest message, I propose to do have a device,
|
|
||||||
which contains some SEC node properties, with information about the SEC node,
|
|
||||||
and client parameters, which can be set by the ECS for optional
|
|
||||||
features. Remind that internally the SEC Node has to store the client parameters
|
|
||||||
separately for every client.
|
|
||||||
|
|
||||||
#### SEC Node properties
|
|
||||||
|
|
||||||
You are welcome to propose better names:
|
|
||||||
|
|
||||||
> ::implements_timestamps
|
|
||||||
::implements_timestamps=1
|
|
||||||
_
|
|
||||||
> ::implements_async_communication
|
|
||||||
::implements_async_communication=1
|
|
||||||
_
|
|
||||||
|
|
||||||
The maximum time delay for a response from the SEC Node:
|
|
||||||
|
|
||||||
> ::reply_timeout=10
|
|
||||||
::reply_timeout=10
|
|
||||||
_
|
|
||||||
|
|
||||||
SEC Node properties might be omitted for the default behaviour.
|
|
||||||
|
|
||||||
#### Client parameters
|
|
||||||
|
|
||||||
Enable transmission of timestamp and sigma with every value
|
|
||||||
|
|
||||||
> :reply_items=t,s
|
|
||||||
:reply_items=t,s
|
|
||||||
_
|
|
||||||
|
|
||||||
If a requested property is not present on a parameter, it is just omitted in the reply.
|
|
||||||
|
|
||||||
The reply_items parameter might be not be present, when the SEC node does not implement
|
|
||||||
timestamps and similar.
|
|
||||||
|
|
||||||
Update timeout (see Update message)
|
|
||||||
|
|
||||||
> :update_timeout=10
|
|
||||||
:update_timeout=10
|
|
||||||
|
|
||||||
#### SubscribeToAsyncData
|
|
||||||
|
|
||||||
In different flavors: all parameters and all devices:
|
|
||||||
|
|
||||||
> +*:*
|
|
||||||
<device1>.<param1>
|
|
||||||
...
|
|
||||||
<deviceN>.<paramM>
|
|
||||||
_
|
|
||||||
|
|
||||||
Only the values of all devices:
|
|
||||||
|
|
||||||
> +*
|
|
||||||
+<device1>
|
|
||||||
...
|
|
||||||
+<deviceN>
|
|
||||||
_
|
|
||||||
|
|
||||||
All parameters of one device:
|
|
||||||
|
|
||||||
> +<device>:*
|
|
||||||
+<device>:<param1>
|
|
||||||
...
|
|
||||||
+<device>:<paramN>
|
|
||||||
_
|
|
||||||
|
|
||||||
I think we need no special subscriptions to properties, as :reply_items should be
|
|
||||||
recognized by the updates. All other properties are not supposed to be changed during
|
|
||||||
an experiment (we might discuss this).
|
|
||||||
|
|
||||||
If an Unsubscribe Message would be implemented, it could be start with a '-'
|
|
||||||
|
|
||||||
#### Update
|
|
||||||
|
|
||||||
In order to stick to a strict request / reply mechanism I propose instead of a real
|
|
||||||
asynchronous communication to have an UpdateRequest. The reply of an UpdateRequest
|
|
||||||
might happen delayed.
|
|
||||||
|
|
||||||
- it replies immediately with a list of all subscripted updates, if some happend since
|
|
||||||
the last UpdateRequest
|
|
||||||
- if nothing has changed, the UpdateReply is sent as soon as any update happens
|
|
||||||
- if nothing happens within the time specified by :update_timeout
|
|
||||||
an empty reply is returned.
|
|
||||||
|
|
||||||
If a client detects no reply within :update_timeout plus ::reply_timeout,
|
|
||||||
it can assume the the SEC Node is dead.
|
|
||||||
|
|
||||||
The UpdateRequest may be just an empty line (my favorite) or, if you prefer an
|
|
||||||
question mark:
|
|
||||||
|
|
||||||
> ?
|
|
||||||
<device1>=<value1>
|
|
||||||
<device2>.<paramX>=<value2>
|
|
||||||
_
|
|
||||||
|
|
||||||
With no update during :update_timeout seconds, the reply would be
|
|
||||||
|
|
||||||
> ?
|
|
||||||
_
|
|
||||||
|
|
||||||
|
|
||||||
#### Additional Messages
|
|
||||||
|
|
||||||
I list here some additional messages, which could be useful, but wich were not yet
|
|
||||||
identified as special messages. They all follow the same syntax, which means that
|
|
||||||
it is probably no extra effort for the implementation.
|
|
||||||
|
|
||||||
Interestingly, we have defined ReadPropertiesOfAllDevices, but not Read a specific
|
|
||||||
property of all parameters. At least reading the value properties is useful:
|
|
||||||
|
|
||||||
> *:*
|
|
||||||
|
|
||||||
List all device classes (assuming a device property "class")
|
|
||||||
|
|
||||||
> *::class
|
|
||||||
<device1>::class=<class1>
|
|
||||||
<device2>::class=<class2>
|
|
||||||
...
|
|
||||||
<deviceN>::class=<classN>
|
|
||||||
_
|
|
||||||
|
|
||||||
The property meaning is for saying: this device is important for the experimentalist,
|
|
||||||
and has the indicated meaning. It might be used by the ECS to skip devices, which
|
|
||||||
are of no interest for non experts. Example:
|
|
||||||
|
|
||||||
> *::meaning
|
|
||||||
ts::meaning=sample temperature
|
|
||||||
mf::meaning=magnetic field
|
|
||||||
_
|
|
||||||
|
|
||||||
We might find other useful messages, which can be implemented without any additional
|
|
||||||
syntax.
|
|
||||||
|
|
||||||
|
|
||||||
#### A possible syntax extension:
|
|
||||||
|
|
||||||
Allow a comma separated list for path items:
|
|
||||||
|
|
||||||
> ts,mf
|
|
||||||
ts=1.65
|
|
||||||
mf=5.13
|
|
||||||
_
|
|
||||||
|
|
||||||
> ts::.,t,s
|
|
||||||
ts=<value>
|
|
||||||
ts::t=<timestamp>
|
|
||||||
ts::s=<sigma>
|
|
||||||
_
|
|
||||||
|
|
||||||
If somebody does not like the :reply_items mechanism, we could us the latter example
|
|
||||||
as alternative for reading values together with timestamp and sigma.
|
|
279
doc/messages.md
279
doc/messages.md
@ -1,279 +0,0 @@
|
|||||||
|
|
||||||
(Outdated!)
|
|
||||||
|
|
||||||
Struktur der Messages
|
|
||||||
=====================
|
|
||||||
|
|
||||||
Es gibt folgende Messagetypen:
|
|
||||||
|
|
||||||
* LIST (listet namen einer Ebene auf)
|
|
||||||
* READ+WRITE (addressiert einen spezifischen Wert)
|
|
||||||
* FETCH (kombiniert LIST+READ, antwort ist multi)
|
|
||||||
* COMMAND (um Befehle aufzurufen: stop(), init(),...)
|
|
||||||
* (UN)SUBSCRIBE (bucht events, bestellt sie ab, für devices/params)
|
|
||||||
* EVENT (ASYNC!)
|
|
||||||
* ERROR
|
|
||||||
* POLL (wie FETCH, aber fragt vorher die HW, kann dauern)
|
|
||||||
* TRIGGER (Wie POLL, aber die Antworten kommen als Events, return sofort)
|
|
||||||
|
|
||||||
Außer EVENT und ERROR (beides nur als Reply) gibts es jede Message als Request und als Reply.
|
|
||||||
Das Parsing einer Message ist eindeutig, so hat jeder reply mindestens ein '=', jede Mehrfachantwort endet mit '`#<anzahl messages>`', uswusf.
|
|
||||||
Für das Parsing wird eine Regexp empfohlen, da die syntax nicht sonderlich parsingfreundlich ist.
|
|
||||||
|
|
||||||
Um auszuwählen, auf welche Objekte eine Nachricht wirkt, werden folgende Argumente verwendet:
|
|
||||||
|
|
||||||
- `*` wirkt auf alle devices
|
|
||||||
- `device` wirkt auf das Device
|
|
||||||
- `device:*` wirkt auf alle parameter des gegebenen devices
|
|
||||||
- `device:param` wirkt auf den Parameter des Device
|
|
||||||
- `device:param:*` wirkt auf alle properties des gegebenen parameters
|
|
||||||
- `device:param:property` wirkt auf die property
|
|
||||||
|
|
||||||
Properties sind immer ReadOnly Softwarewerte. Somit haben WRITE, TRIGGER, (UN)SUBSCRIBE auf properties keinen sinn und sind mit einem Error zu beantworten.
|
|
||||||
(welcher? ProtokollError?=
|
|
||||||
|
|
||||||
Replies enthalten immer genau eine Antwort.
|
|
||||||
Der immer anzugebende 'Antwortwert' wird durch `=` von einer kopie des requestes abgetrennt.
|
|
||||||
Für Multi-Antworten endet die Antwort in `#<number of replyitems>\n` statt in `\n`.
|
|
||||||
Hier ist kein '=' zusätzlich anzugeben. Nach dieser 'Eröffnungsnachricht' kommen die angegebene Anzahl Antworten als Read-Replies.
|
|
||||||
|
|
||||||
Damit ergeben sich folgende Kombinationen (immer zuerst der Request, direkt drunter der Reply, direkt drunter die Beschreibung):
|
|
||||||
Danach die 'dringlichkeit des implementierens':
|
|
||||||
MANDATORY > RECOMMENDED > OPTIONAL
|
|
||||||
|
|
||||||
Werte sind entweder Zahlen (`1.23`) oder Strings (`"Ein String"` oder `Text`).
|
|
||||||
Solange eindeutigkeit besteht (kein '" ", ",", oder " im String) können die `"` weggelassen werden. Beispiel: unit=T
|
|
||||||
|
|
||||||
|
|
||||||
LIST
|
|
||||||
----
|
|
||||||
|
|
||||||
* 'LIST *' oder 'LIST'
|
|
||||||
* 'LIST *=mf,tc1,tc1,ts,...' oder 'LIST=mf,tc1,...'
|
|
||||||
* ListDevices: returns ',' separated list of devicenames
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
* 'LIST `<devname>`'
|
|
||||||
* 'LIST `<devname>`=status, target, value,...'
|
|
||||||
* ListParameters: returns ',' separated list of parameternames for a device
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
* 'LIST `<devname>:<paramname>`'
|
|
||||||
* 'LIST `<devname>:<paramname>`=timestamp, unit, description,...'
|
|
||||||
* ListProperties: returns ',' separated list of propertynames for a parameter
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
|
|
||||||
READ/WRITE
|
|
||||||
----------
|
|
||||||
|
|
||||||
* 'READ `<devname>`'
|
|
||||||
* 'READ `<devname>=<value>; [<qualname> '=' <qualvalue> ';']`'
|
|
||||||
* ReadDevice: returns current device value + qualifiers
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
---------
|
|
||||||
|
|
||||||
* 'READ `<devname>:<paramname>`'
|
|
||||||
* 'READ `<devname>:<paramname>=<value>; [<qualname> '=' <qualvalue> ';']`'
|
|
||||||
* ReadParameter: returns current parameter value (+ qualifiers?)
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'READ `<devname>:<paramname>:<property>`'
|
|
||||||
* 'READ `<devname>:<paramname>:<property>=<value>;`'
|
|
||||||
* ReadProperty: returns curent value of property
|
|
||||||
* RECOMMENDED
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'WRITE `<devname>=<value>`'
|
|
||||||
* 'WRITE `<devname>=<value>=<readbackvalue>; [<qualname> '=' <qualvalue> ';']`'
|
|
||||||
* WriteDevice: sets new device-value and returns read-back target value + non-empty qualifiers! (at least the `;` must be present)
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'WRITE `<devname>:<paramname>=<value>`'
|
|
||||||
* 'WRITE `<devname>:<paramname>=<value>=<readbackvalue>; [<qualname> '=' <qualvalue> ';']`'
|
|
||||||
* WriteParameter: sets new parameter-value and returns read-back value + non-empty qualifiers! (at least the `;` must be present)
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
|
|
||||||
COMMAND
|
|
||||||
-------
|
|
||||||
|
|
||||||
* 'COMMAND `<device>:<command>'(' [<argument> ','] ')'`'
|
|
||||||
* 'COMMAND `<device>:<command>'(' [<argument> ','] ')=' result`;'
|
|
||||||
* ExecuteCommand: führt command mit den gegebenen Arguments aus.
|
|
||||||
result=(ein) Rückgabewert, kann auch "OK" sein, falls kein Rückgabewert definiert wurde.
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
commands sind parameter deren name auf '()' endet.
|
|
||||||
(oder die argumenttypen in () enthält?)
|
|
||||||
|
|
||||||
(UN)SUBSCRIBE
|
|
||||||
-------------
|
|
||||||
|
|
||||||
* 'SUBSCRIBE `<device>`'
|
|
||||||
* 'SUBSCRIBE `<device>=OK`;'
|
|
||||||
* SubscribeDevice: subscribed auf den devicevalue (evtl auch auf den status?)
|
|
||||||
* RECOMMENDED
|
|
||||||
* possible extension: include a 'FETCH `<device>`' reply as Multi
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'SUBSCRIBE `<device>`'
|
|
||||||
* 'SUBSCRIBE `<device>=<list_of_subscribed_parameternames>`;'
|
|
||||||
* SubscribeALLParameter: subscribed alle parameter eines device
|
|
||||||
* RECOMMENDED
|
|
||||||
* possible extension: include a 'FETCH `<device>:`' reply as Multi
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'SUBSCRIBE `<device>:<param>`'
|
|
||||||
* 'SUBSCRIBE `<device>:<param>=OK`;'
|
|
||||||
* SubscribeParameter: subscribed auf den parameter
|
|
||||||
* RECOMMENDED
|
|
||||||
* possible extension: include a 'FETCH `<device>:<param>`' reply as Multi
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'UNSUBSCRIBE `<device>`'
|
|
||||||
* 'UNSUBSCRIBE `<device>=OK`;'
|
|
||||||
* UNSubscribeDevice: unsubscribed auf den devicevalue
|
|
||||||
* RECOMMENDED
|
|
||||||
* possible extension: return list of remaining subscriptions as multi
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'UNSUBSCRIBE `<device>:`'
|
|
||||||
* 'UNSUBSCRIBE `<device>:=OK`;'
|
|
||||||
* UNSubscribeALLParameter: unsubscribed alle parameter eines device
|
|
||||||
* RECOMMENDED
|
|
||||||
* possible extension: return list of remaining subscriptions as multi
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'UNSUBSCRIBE `<device>:<param>`'
|
|
||||||
* 'UNSUBSCRIBE `<device>:<param>=OK`;'
|
|
||||||
* UNSubscribeParameter: unsubscribed auf den parameter
|
|
||||||
* RECOMMENDED
|
|
||||||
* possible extension: return list of remaining subscriptions as multi
|
|
||||||
|
|
||||||
Was ist zu tun bei einem unsubscribe auf einen nicht subscribten wert?
|
|
||||||
(doppeltes unsubscribe nach subscribe, etc...)
|
|
||||||
|
|
||||||
EVENT
|
|
||||||
-----
|
|
||||||
|
|
||||||
* EVENT gibt es nicht als Request, da es nur als async reply auftaucht
|
|
||||||
* '`#3\n`EVENT READ `mf=1.2\n`EVENT READ `mf:target=2.0\n`EVENT READ `mf:status="BUSY"\n`'
|
|
||||||
* Event: sendet ein subscribed event, kann 0..N READ-replies beinhalten
|
|
||||||
* RECOMMENDED
|
|
||||||
|
|
||||||
FETCH/POLL
|
|
||||||
----------
|
|
||||||
|
|
||||||
* 'FETCH :' oder 'FETCH'
|
|
||||||
* 'FETCH `:#2\nREAD mf=1.2\nREAD ts=3.4\n`' oder 'FETCH`#2\nREAD mf=1.2\nREAD ts=3.4\n`'
|
|
||||||
* FetchDevices: reads and returns the values of all (interesting?) devices
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'FETCH `<device>`'
|
|
||||||
* 'FETCH mf#2\nREAD mf:value=1.2\nREAD mf:status="IDLE"\n`'
|
|
||||||
* FetchDevice: reads and returns the (interesting?) parameters of a device
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'FETCH `<device>:`'
|
|
||||||
* 'FETCH `mf:#3\nREAD mf:value=1.2\nREAD mf:target=1.2\nREAD mf:status="IDLE"\n`'
|
|
||||||
* FetchParameters: reads and returns the values of all parameters of a device
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'FETCH `<device>:<parameter>`'
|
|
||||||
* 'FETCH `mf:value#2\nREAD mf:value:unit="T"\nREAD mf:value:type=float\n`'
|
|
||||||
* FetchParameter: reads and returns the properties of a single parameter
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'FETCH `<device>:<parameter>:`'
|
|
||||||
* 'FETCH `mf:value:#2\nREAD mf:value:unit="T"\nREAD mf:value:type=float\n`'
|
|
||||||
* FetchProperties: reads and returns the values of all properties of a parameter
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
POLL wird wie FETCH kodiert, fragt aber die HW vor der Antwort, FECTH liefert zwischengespeicherte Werte.
|
|
||||||
|
|
||||||
TRIGGER
|
|
||||||
-------
|
|
||||||
|
|
||||||
* 'TRIGGER :' oder 'TRIGGER'
|
|
||||||
* 'TRIGGER :=OK' oder 'TRIGGER=OK'
|
|
||||||
* TriggerDeviceReads: startet auslesen aller devices und übertragen der (subscribed) values als events
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'TRIGGER `<device>`'
|
|
||||||
* 'TRIGGER `mf=OK`'
|
|
||||||
* TriggerDeviceRead: startet auslesen eines Devices
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'TRIGGER `<device>:`'
|
|
||||||
* 'TRIGGER `mf:=OK`'
|
|
||||||
* TriggerParameterReads: startet auslesen aller paremeter und übertragen der subscribed parameter als events
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
* 'TRIGGER `<device>:<parameter>`'
|
|
||||||
* 'TRIGGER `mf:value=OK`'
|
|
||||||
* FetchProperties: reads and returns the values of all properties of a parameter
|
|
||||||
* OPTIONAL
|
|
||||||
|
|
||||||
ERROR
|
|
||||||
-----
|
|
||||||
|
|
||||||
* ERROR gibt es nicht als request, da es nur als reply auftaucht
|
|
||||||
* 'ERROR `<errorclass> "<copy of request>" [<additional text>]`'
|
|
||||||
* Error: zeigt einen Fehler an. folgende <errorclass> sind definiert:
|
|
||||||
* NoSuchDevice
|
|
||||||
* NoSuchParameter
|
|
||||||
* NoSuchCommand
|
|
||||||
* NoSuchProperty
|
|
||||||
* CommandFailed
|
|
||||||
* ReadOnly
|
|
||||||
* BadValue
|
|
||||||
* CommunicationFailed
|
|
||||||
* IsBusy
|
|
||||||
* IsError
|
|
||||||
* ProtocolError
|
|
||||||
* SyntaxError
|
|
||||||
* MANDATORY
|
|
||||||
|
|
||||||
|
|
||||||
Möglich Erweiterung: für device/param/property kann statt eines einzelnamens auch eine ',' separierte Liste verwendet werden.
|
|
||||||
Außerdem könnte auch ein '*' für 'ALLE' stehen.
|
|
||||||
Die Antworten sind dann auf jeden Fall als Multi zu kodieren. Beispiel:
|
|
||||||
|
|
||||||
> READ mf:target,value
|
|
||||||
> > READ mf:target,value#2
|
|
||||||
>
|
|
||||||
> > READ mf:target=1.23
|
|
||||||
>
|
|
||||||
> > READ mf:value=0.73
|
|
||||||
>
|
|
||||||
|
|
39
doc/notes.md
39
doc/notes.md
@ -1,39 +0,0 @@
|
|||||||
------
|
|
||||||
No installation required or recommended.
|
|
||||||
-----
|
|
||||||
|
|
||||||
everything runs directly from the checkout.
|
|
||||||
|
|
||||||
you need:
|
|
||||||
- python2.7.*
|
|
||||||
- pip
|
|
||||||
- linux OS (Mac may work as well)
|
|
||||||
|
|
||||||
install requirements with pip:
|
|
||||||
$ sudo pip install -r requirements.txt
|
|
||||||
|
|
||||||
to execute a program, prefix its name with bin/, e.g.:
|
|
||||||
$ bin/make_doc.py
|
|
||||||
$ bin/server.py start test
|
|
||||||
|
|
||||||
a testsuite is planned but nothing is there yet.
|
|
||||||
|
|
||||||
## structure ##
|
|
||||||
|
|
||||||
* bin contains the executables (make_doc.py, server.py)
|
|
||||||
* doc is the root node of the docu (see index.md)
|
|
||||||
* etc contains the configurations for the server(s) and devices
|
|
||||||
* html contains the docu after make_doc.py was run
|
|
||||||
* log contains some (hopefully) log output from the servers
|
|
||||||
* pid contains pidfiles if a server is running
|
|
||||||
* src contains the python source
|
|
||||||
* src/client: client specific stuff (proxy)
|
|
||||||
* src/devices: devices to be used by the server (and exported via SECoP)
|
|
||||||
* src/lib: helper stuff (startup, pidfiles, etc)
|
|
||||||
* src/protocol: protocol specific stuff
|
|
||||||
* src/errors.py: internal errors
|
|
||||||
* src/server.py: device-managing part of the server (transport is in src/protocol/transport)
|
|
||||||
* src/validators.py: validators used by the devices. may be moved to src/protocol
|
|
||||||
|
|
||||||
# THERE IS STILL MUCH WORK TO DO! #
|
|
||||||
|
|
@ -1,372 +0,0 @@
|
|||||||
Simple communication protocol
|
|
||||||
=============================
|
|
||||||
| *Version 0.0.2*
|
|
||||||
| *Copyright 2012: Alexander Lenz, Dr. Enrico Faulhaber*
|
|
||||||
|
|
||||||
|
|
||||||
Table of contents
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
.. sectnum::
|
|
||||||
|
|
||||||
Disambiguation
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Device
|
|
||||||
''''''
|
|
||||||
A device is a logical part of the complete system. This may be any piece of hardware which
|
|
||||||
can be accessed seperately. Also a logical axis, implemented with multiple motors can be a device.
|
|
||||||
|
|
||||||
Parameter
|
|
||||||
'''''''''
|
|
||||||
A parameter is a device depended value which represents (usually) a physical value.
|
|
||||||
It can be read only or read-/writeable.
|
|
||||||
|
|
||||||
Messages
|
|
||||||
--------
|
|
||||||
|
|
||||||
The messages are devided into commands and responses.
|
|
||||||
|
|
||||||
A command consists of the device of interest, the relevant parameter, an operator
|
|
||||||
that specifies what should happen, and a value if neccessary.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Commands: <device>/<parameter><operator><value_if_any>\n
|
|
||||||
|
|
||||||
You will get a response for each command (\ **even if it failed!**\ ).
|
|
||||||
These reponses consist of an error code, the mirrored command (to verify for what command the response is related)
|
|
||||||
and a value if requested.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Response: <error_code> <mirrored_command><value_if_any>\n
|
|
||||||
|
|
||||||
|
|
||||||
For limitations regarding the message contents, have a look at: `Limitations`_
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Operators
|
|
||||||
---------
|
|
||||||
|
|
||||||
? (Request)
|
|
||||||
'''''''''''
|
|
||||||
This operator can be used to request data.
|
|
||||||
In the most cases, you want to request the value of device parameter:
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
::
|
|
||||||
|
|
||||||
<device>/<parameter>?\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
::
|
|
||||||
|
|
||||||
<error_code> <device>/<parameter>=<value_if_success>\n
|
|
||||||
|
|
||||||
= (Set)
|
|
||||||
'''''''
|
|
||||||
This operator can be used to write a device value.
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
::
|
|
||||||
|
|
||||||
<device>/<parameter>=<value>\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
::
|
|
||||||
|
|
||||||
<error_code> <device>/<parameter>=<value>\n
|
|
||||||
|
|
||||||
|
|
||||||
Protocol error codes
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
In case of an error, you get the following response:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
<error_code> <mirrored_command>
|
|
||||||
|
|
||||||
|
|
||||||
The following errors describe errors of the protocol, not the device.
|
|
||||||
|
|
||||||
======================= ==============
|
|
||||||
**Error** **Error code**
|
|
||||||
======================= ==============
|
|
||||||
No error 0
|
|
||||||
Unknown error 1
|
|
||||||
Connection error 2
|
|
||||||
Command unknown 3
|
|
||||||
Device unknown 4
|
|
||||||
Parameter unknown 5
|
|
||||||
Format error 6
|
|
||||||
Value out of limits 7
|
|
||||||
Param not writable 8
|
|
||||||
Not allowed 9
|
|
||||||
======================= ==============
|
|
||||||
|
|
||||||
Device stati
|
|
||||||
------------
|
|
||||||
|
|
||||||
The following status codes describe the device status and can be requested via:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
<device>/status:\n
|
|
||||||
|
|
||||||
|
|
||||||
========== ===========
|
|
||||||
**Status** **Meaning**
|
|
||||||
========== ===========
|
|
||||||
IDLE Device is alive and ready to accept commands.
|
|
||||||
BUSY Device is performing some action and therefore busy. It doesn't accept new commands. All Parameters can be read.
|
|
||||||
ERROR Something bad happened, a manual action is required. Some command could unexpectedly not be performed.
|
|
||||||
UNKNOWN Unknown device state.
|
|
||||||
========== ===========
|
|
||||||
|
|
||||||
|
|
||||||
Limitations
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Naming & Formatting
|
|
||||||
'''''''''''''''''''
|
|
||||||
|
|
||||||
- Device names are all lower case and can consist of letters, numbers and underscores (no whitespace!).
|
|
||||||
- Device names consist of up to 80 characters.
|
|
||||||
- Parameter names are all lower case and can consist of letters, numbers and underscores (no whitespace!).
|
|
||||||
- Parameter names consist of up to 80 characters.
|
|
||||||
- Floating point numbers are using a decimal point (5.23).
|
|
||||||
- Lists are commma-separated and enclosed by square brackets ([entry1,entry2,entry3]).
|
|
||||||
- Strings are enclosed by single ticks ('str').
|
|
||||||
- Messages consist of up to 256 characters.
|
|
||||||
|
|
||||||
Devices
|
|
||||||
'''''''
|
|
||||||
|
|
||||||
General
|
|
||||||
"""""""
|
|
||||||
All devices have to support at least the following parameters:
|
|
||||||
|
|
||||||
**status**
|
|
||||||
This **read only** parameters describes the current device state.
|
|
||||||
It contains a list with two items.
|
|
||||||
|
|
||||||
1. A short constant status string (Have a look at: `Device stati`_)
|
|
||||||
2. A longer description which can contain any character except a comma!
|
|
||||||
|
|
||||||
**parameters**
|
|
||||||
This **read only** parameter represents a list of all available parameters of the given device.
|
|
||||||
It contains a comma seperated list with all parameter names.
|
|
||||||
|
|
||||||
Readable
|
|
||||||
""""""""
|
|
||||||
All devices which provide any type of readable value have to support the general parameters and at leas the following:
|
|
||||||
**value**
|
|
||||||
This **read only** parameter represents the current 'main value'.
|
|
||||||
It contains a single value which can be a float or integer number, or a string.
|
|
||||||
|
|
||||||
Writable
|
|
||||||
""""""""
|
|
||||||
All devices for which you can set a value have to support at least the general parameters, all parameters of `Readable`_ devices and the following:
|
|
||||||
**target**
|
|
||||||
This **read/write** parameter represents the device's target value.
|
|
||||||
It contains a single value which can be a float or integer number, or a string.
|
|
||||||
If you set the target value, the device goes into 'BUSY' state and tries to reach that value.
|
|
||||||
The current value can be requested by the 'value' parameter.
|
|
||||||
|
|
||||||
Server device
|
|
||||||
"""""""""""""
|
|
||||||
The server have to provide a device for direct communication with the protocol server.
|
|
||||||
It has to provide at least the parameters of a general device (`Devices`_) plus the following:
|
|
||||||
|
|
||||||
**devices**
|
|
||||||
A list of all available devices.
|
|
||||||
**version**
|
|
||||||
A version string which identifies the protocol version, the server implements.
|
|
||||||
|
|
||||||
The server device can be queried by omitting the <device> parameter (+ the '/').
|
|
||||||
::
|
|
||||||
|
|
||||||
devices?\n
|
|
||||||
version?\n
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
Let's have a look at some examples:
|
|
||||||
|
|
||||||
+---------------+---------------------------------+
|
|
||||||
|**Device:** |temp_ctrl |
|
|
||||||
+---------------+---------------------------------+
|
|
||||||
|**Type:** |Temperature controller (Moveable)|
|
|
||||||
+---------------+---------------------------------+
|
|
||||||
|**Parameters:**| - status **(mandatory)** |
|
|
||||||
| | - parameters **(mandatory)** |
|
|
||||||
| | - value **(mandatory)** |
|
|
||||||
| | - target **(mandatory)** |
|
|
||||||
| | - ... |
|
|
||||||
+---------------+---------------------------------+
|
|
||||||
|
|
||||||
Requesting the current setpoint (target)
|
|
||||||
''''''''''''''''''''''''''''''''''''''''
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
temp_ctrl/target?\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
0 temp_ctrl/target=0.42\n
|
|
||||||
|
|
||||||
Setting the setpoint (target)
|
|
||||||
'''''''''''''''''''''''''''''
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
temp_ctrl/target=0.21\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
0 temp_ctrl/target=0.21\n
|
|
||||||
|
|
||||||
Setting an out-of-bounds setpoint (target)
|
|
||||||
''''''''''''''''''''''''''''''''''''''''''
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
temp_ctrl/target=-7.5\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
7 temp_ctrl/target=-7.5\n
|
|
||||||
|
|
||||||
|
|
||||||
Requesting the status
|
|
||||||
'''''''''''''''''''''
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
temp_ctrl/status?\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
0 temp_ctrl/status=BUSY,I'm ramping!\n
|
|
||||||
|
|
||||||
Requesting the device list
|
|
||||||
''''''''''''''''''''''''''
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
/devices?\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
0 /devices=temp_ctrl,another_dev1,another_dev2\n
|
|
||||||
|
|
||||||
.. Allowed extensions
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Additional operators
|
|
||||||
''''''''''''''''''''
|
|
||||||
|
|
||||||
\* (Wildcard)
|
|
||||||
"""""""""""""
|
|
||||||
This operator is a little more advanced than the others.
|
|
||||||
It represents a wild card and can be combined with other operators.
|
|
||||||
The response you will get, are multiple messages which contain:
|
|
||||||
::
|
|
||||||
|
|
||||||
<error_code> <the_mirrored_command> <answer_for_the_operator>
|
|
||||||
|
|
||||||
If you want to request all parameters of a device, it will be:
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
::
|
|
||||||
|
|
||||||
<device>/*?\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
*Multiple*
|
|
||||||
::
|
|
||||||
|
|
||||||
<error_code> <device>/*? <device>/<parameter>=<value>\n
|
|
||||||
|
|
||||||
Examples
|
|
||||||
^^^^^^^^
|
|
||||||
Requesting all parameters
|
|
||||||
*************************
|
|
||||||
|
|
||||||
**Command**
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
temp_ctrl/*?\n
|
|
||||||
|
|
||||||
**Response**
|
|
||||||
::
|
|
||||||
|
|
||||||
0 temp_ctrl/*? temp_ctrl/status=BUSY,I'm ramping!\n
|
|
||||||
0 temp_ctrl/*? temp_ctrl/parameters=status,parameters,value,target\n
|
|
||||||
0 temp_ctrl/*? temp_ctrl/value=0.21\n
|
|
||||||
0 temp_ctrl/*? temp_ctrl/target=0.42\n
|
|
||||||
|
|
||||||
Recommendations
|
|
||||||
---------------
|
|
||||||
Interfaces
|
|
||||||
''''''''''
|
|
||||||
|
|
||||||
We provide some recommendations for the interface configuration when using the simple communication protocol:
|
|
||||||
|
|
||||||
Serial (RS232)
|
|
||||||
""""""""""""""
|
|
||||||
|
|
||||||
If you are using a serial connection, you should use the following configuration:
|
|
||||||
|
|
||||||
============= ==============
|
|
||||||
**Baudrate** 9600 or 115200
|
|
||||||
**Data bits** 8
|
|
||||||
**Parity** None
|
|
||||||
**Stop bits** 1
|
|
||||||
============= ==============
|
|
||||||
|
|
||||||
Network (TCP)
|
|
||||||
"""""""""""""
|
|
||||||
|
|
||||||
If you are using a TCP based network connection, you should use the following configuration:
|
|
||||||
|
|
||||||
======== =====
|
|
||||||
**Port** 14728
|
|
||||||
======== =====
|
|
||||||
|
|
||||||
Network (UDP)
|
|
||||||
"""""""""""""
|
|
||||||
|
|
||||||
We recommend not to use UDP connections at all, as the protocol was not designed for such connections.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ from os import path
|
|||||||
# sys.path.insert(0, os.path.abspath('.'))
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
# Add import path for inplace usage
|
# Add import path for inplace usage
|
||||||
sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), '..', '..', '..')))
|
sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), '..', '..')))
|
||||||
|
|
||||||
from secop.version import get_version
|
from secop.version import get_version
|
||||||
|
|
@ -11,7 +11,9 @@ Protocol documentation
|
|||||||
timeformat
|
timeformat
|
||||||
modsubset
|
modsubset
|
||||||
heartbeat
|
heartbeat
|
||||||
|
jsonstruct
|
||||||
todo
|
todo
|
||||||
|
notes
|
||||||
history
|
history
|
||||||
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
|||||||
|
JSON structure
|
||||||
|
==============
|
||||||
|
|
||||||
> Mit JSON Freeze meine ich nur Arrays von Objekten also:
|
> Mit JSON Freeze meine ich nur Arrays von Objekten also:
|
||||||
> -Node hat ein Array von Properties und ein Array von Modulen
|
> -Node hat ein Array von Properties und ein Array von Modulen
|
||||||
> -Module haben ein Array von Properties, ein Array von Parametern und ein Array von Commands
|
> -Module haben ein Array von Properties, ein Array von Parametern und ein Array von Commands
|
||||||
@ -18,7 +21,7 @@ property = { 'property-name' : 'property-value' }
|
|||||||
|
|
||||||
|
|
||||||
ODER
|
ODER
|
||||||
====
|
----
|
||||||
|
|
||||||
node = [ <array_of_properties>, <array_of_modules> ]
|
node = [ <array_of_properties>, <array_of_modules> ]
|
||||||
|
|
42
doc/source/protocol/notes.rst
Normal file
42
doc/source/protocol/notes.rst
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
Notes
|
||||||
|
=====
|
||||||
|
|
||||||
|
No installation required or recommended
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
everything runs directly from the checkout.
|
||||||
|
|
||||||
|
you need:
|
||||||
|
- python2.7.*
|
||||||
|
- pip
|
||||||
|
- linux OS (Mac may work as well)
|
||||||
|
|
||||||
|
install requirements with pip:
|
||||||
|
$ sudo pip install -r requirements.txt
|
||||||
|
|
||||||
|
to execute a program, prefix its name with bin/, e.g.:
|
||||||
|
$ bin/make_doc.py
|
||||||
|
$ bin/server.py start test
|
||||||
|
|
||||||
|
a testsuite is planned but nothing is there yet.
|
||||||
|
|
||||||
|
Structure
|
||||||
|
---------
|
||||||
|
|
||||||
|
* bin contains the executables (make_doc.py, server.py)
|
||||||
|
* doc is the root node of the docu (see index.md)
|
||||||
|
* etc contains the configurations for the server(s) and devices
|
||||||
|
* html contains the docu after make_doc.py was run
|
||||||
|
* log contains some (hopefully) log output from the servers
|
||||||
|
* pid contains pidfiles if a server is running
|
||||||
|
* src contains the python source
|
||||||
|
|
||||||
|
* src/client: client specific stuff (proxy)
|
||||||
|
* src/devices: devices to be used by the server (and exported via SECoP)
|
||||||
|
* src/lib: helper stuff (startup, pidfiles, etc)
|
||||||
|
* src/protocol: protocol specific stuff
|
||||||
|
* src/errors.py: internal errors
|
||||||
|
* src/server.py: device-managing part of the server (transport is in src/protocol/transport)
|
||||||
|
* src/validators.py: validators used by the devices. may be moved to src/protocol
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user