worked on tutorial

Change-Id: I630e7379e35cc0146d58f9abe10cb19283191ca8
This commit is contained in:
2021-01-21 08:42:43 +01:00
parent ad9defab0f
commit e411ded55b

View File

@ -3,7 +3,19 @@ Frappy Programming Guide
Introduction
------------
*Frappy* is a Python framework for creating Sample Environment Control Nodes (SEC Node) with a SECoP interface. A *SEC Node* is a service, running usually a computer or microcomputer, which accesses the hardware over the interfaces given by the manufacturer of the used electronic devices. It provides access to the data in an abstracted form over the SECoP interface. [*SECoP*](https://github.com/SampleEnvironment/SECoP/tree/master/protocol) is a protocol for communicating with Sample Environment and other mobile devices, specified by a committee of the [ISSE](https://sampleenvironment.org). The Frappy framework deals with all the details of the SECoP protocol, so the programmer can concentrate on the details of accessing the hardware with support for different types of interfaces (TCP or Serial, ASCII or binary). However, the programmer should be aware of the basic principle of the SECoP protocol: the hardware abstraction.
*Frappy* is a Python framework for creating Sample Environment Control Nodes (SEC Node) with
a SECoP interface. A *SEC Node* is a service, running usually a computer or microcomputer,
which accesses the hardware over the interfaces given by the manufacturer of the used
electronic devices. It provides access to the data in an abstracted form over the SECoP interface.
`SECoP <https://github.com/SampleEnvironment/SECoP/tree/master/protocol>`_ is a protocol for
communicating with Sample Environment and other mobile devices, specified by a committee of
the `ISSE <https://sampleenvironment.org>`_.
The Frappy framework deals with all the details of the SECoP protocol, so the programmer
can concentrate on the details of accessing the hardware with support for different types
of interfaces (TCP or Serial, ASCII or binary). However, the programmer should be aware of
the basic principle of the SECoP protocol: the hardware abstraction.
Hardware Abstraction
--------------------
@ -38,60 +50,20 @@ As soon as the target value is reached, the status code changes back to an idle
**Programmers Hint:** before starting to code, choose carefully the main SECoP modules you have to provide
to the user.
Tutorial Example
----------------
For this tutorial we choose as an example a cryostat with a LakeShore 336 temperature controller, a level
meter and a motorized needle value. Let us start with the level meter, as this is the simplest module.
Configuration
-------------
Before we start coding, we create a configuration file. The frappy framework usually has all present code
in the directory tree, and the server is started with the configuration as an argument, determining which
modules are to be configured, ans which code is effectively to be used. We choose the name *example_cryo*
and create therefore a configuration file *example_cryo.cfg* in the *cfg* subdirectory.
Let us start with a simple configuration for the level meter only:
``cfg/example_cryo.cfg``:
.. code:: ini
[NODE]
description = this is an example cryostat for the Frappy tutorial
id = example_cryo.sampleenvironment.org
[INTERFACE]
uri = tcp://5000
[helev]
description = He level of the cryostat He reservoir
class = secop_psi.ccu4.HeLevel
uri = linse-moxa-4.psi.ch:3001
# TO BE MOVED
[tmain]
description = main (heat exchange) temperature
class = secop_psi.ls336.ControlledChannel
iodev = lsio
The configuration file contains several section starting with a line in rectangular brackets.
The *NODE* section describes the main properties of the SEC Node: a description of the node and
an id, which should be globally unique.
The *INTERFACE* section defines the address of the server, usually the only important value here
is the TCP port under which the server will be accessible. Currently only tcp is supported.
All the other sections define the SECoP modules to be used. A module section at least contain a
human readable *description*, and the Python *class* used. Other properties or parameter values may
follow, in this case the *uri* for the communication with the He level monitor.
Code the Python Class for the Module
------------------------------------
Coding the HeLevel Driver
-------------------------
As mentioned in the introduction, we have to code the access to the hardware (driver), and the Frappy
framework will deal with the SECoP interface. The code for the driver is located in a subdirectory
named after the facility or institute programming the driver in our case *secop_psi*.
We create a file named from the electronic device CCU4 we use here for the He level reading.
CCU4 luckily has a very simple and logical protocol:
* ``<name>=<value>\n`` sets the parameter named ``<name>`` to the value ``<value>``
@ -106,10 +78,17 @@ CCU4 luckily has a very simple and logical protocol:
from secop.core import Readable, Parameter, Override, FloatRange, BoolType, \
StringIO, HasIodev
# inheriting HasIodev mixin creates us the things needed for talking
# the class used for communication
class CCU4IO(StringIO):
# on connect, we send 'cid' and expect a reply starting with 'CCU4'
identification = [('cid', r'CCU4.*')]
end_of_line = '\n'
# inheriting the HasIodev mixin creates us the things needed for talking
# with a device by means of the sendRecv method
# Readable as a base class defines the value and status parameters
class HeLevel(HasIodev, Readable):
"""He Level channel of CCU4"""
@ -119,8 +98,8 @@ CCU4 luckily has a very simple and logical protocol:
# parameter, therefore 'Override'
'value': Override(unit='%'),
}
# tells us how to communicate. StringIO is using \n as line end, which fits
iodevClass = StringIO
# define the communication class to create the IO module
iodevClass = CCU4IO
def read_value(self):
# method for reading the main value
@ -131,12 +110,14 @@ CCU4 luckily has a very simple and logical protocol:
This is already a very simple working He Level meter driver. For a next step, we want to improve it:
* We should tell the client, when there is an error. That is what the *status* parameter is for.
We do not need to declare the status parameter, as it is inherited from *Readable*.
* We want to be able to configure the He Level sensor and we want to be able to switch the
Level Monitor to fast reading before we start to fill.
* We should inform the client about errors. That is what the *status* parameter is for.
* We want to be able to configure the He Level sensor.
* We want to be able to switch the Level Monitor to fast reading before we start to fill.
Let us start to code these additions:
Let us start to code these additions. We do not need to declare the status parameter,
as it is inherited from *Readable*. But we declare the new parameters *empty*, *full* and *fast*,
and we have to code the communication and convert the status codes from the hardware to
the standard SECoP status codes.
.. code:: python
@ -186,7 +167,7 @@ Let us start to code these additions:
...
We realize now, that we will repeat similar code for other parameters, which means it might be
Here we start to realize, that we will repeat similar code for other parameters, which means it might be
worth to create our own *_sendRecv* method, and then the *read_<param>* and *write_<param>* methods
will become shorter:
@ -226,3 +207,50 @@ will become shorter:
def write_fast(self, value):
return self._sendRecv('hf=%s' % value)
Configuration
-------------
Before we continue coding, we may try out what we have coded and create a configuration file.
The directory tree of the Frappy framework contains the code for all drivers, but the configuration
file determines, which code will finally be loaded. We choose the name *example_cryo*
and create therefore a configuration file *example_cryo.cfg* in the *cfg* subdirectory:
``cfg/example_cryo.cfg``:
.. code:: ini
[NODE]
description = this is an example cryostat for the Frappy tutorial
id = example_cryo.sampleenvironment.org
[INTERFACE]
uri = tcp://5000
[helev]
description = He level of the cryostat He reservoir
class = secop_psi.ccu4.HeLevel
uri = linse-moxa-4.psi.ch:3001
empty = 380
full = 0
A configuration file contains several sections with a header encloded by rectangular brackets.
The *NODE* section describes the main properties of the SEC Node: a description of the node and
an id, which should be globally unique.
The *INTERFACE* section defines the address of the server, usually the only important value here
is the TCP port under which the server will be accessible. Currently only tcp is supported.
All the other sections define the SECoP modules to be used. A module section at least contains a
human readable *description*, and the Python *class* used. Other properties or parameter values may
follow, in this case the *uri* for the communication with the He level monitor and the values for
configuring the He Level sensor. We might also alter parameter properties, for example we may hide
the parameters *empty* and *full* from the client by defining:
.. code:: ini
empty.export = False
full.export = False
However, we do not do this here, as it is nice to try out chaning parameters for a test!