fetched mlz version
- before some chamges in the gerrit pipline Change-Id: I33eb2d75f83345a7039d0fb709e66defefb1c3e0
This commit is contained in:
@ -8,7 +8,7 @@ meter, as this is the simplest module.
|
||||
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
|
||||
in our case *frappy_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:
|
||||
@ -17,12 +17,12 @@ CCU4 luckily has a very simple and logical protocol:
|
||||
* ``<name>\n`` reads the parameter named ``<name>``
|
||||
* in both cases, the reply is ``<name>=<value>\n``
|
||||
|
||||
``secop_psi/ccu4.py``:
|
||||
``frappy_psi/ccu4.py``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# the most common Frappy classes can be imported from secop.core
|
||||
from secop.core import Readable, Parameter, FloatRange, BoolType, StringIO, HasIO
|
||||
# the most common Frappy classes can be imported from frappy.core
|
||||
from frappy.core import Readable, Parameter, FloatRange, BoolType, StringIO, HasIO
|
||||
|
||||
|
||||
class CCU4IO(StringIO):
|
||||
@ -35,11 +35,11 @@ CCU4 luckily has a very simple and logical protocol:
|
||||
|
||||
|
||||
# inheriting HasIO allows us to use the communicate method for talking with the hardware
|
||||
# Readable as a base class defines the value and status parameters
|
||||
# 'Readable' as base class defines the value and status parameters
|
||||
class HeLevel(HasIO, Readable):
|
||||
"""He Level channel of CCU4"""
|
||||
|
||||
# define the communication class to create the IO module
|
||||
# define the communication class for automatic creation of the IO module
|
||||
ioClass = CCU4IO
|
||||
|
||||
# define or alter the parameters
|
||||
@ -51,10 +51,10 @@ CCU4 luckily has a very simple and logical protocol:
|
||||
reply = self.communicate('h') # send 'h\n' and get the reply 'h=<value>\n'
|
||||
name, txtvalue = reply.split('=')
|
||||
assert name == 'h' # check that we got a reply to our command
|
||||
return txtvalue # the framework will automatically convert the string to a float
|
||||
return float(txtvalue)
|
||||
|
||||
|
||||
The class :class:`secop_psi.ccu4.CCU4IO`, an extension of (:class:`secop.stringio.StringIO`)
|
||||
The class :class:`frappy_psi.ccu4.CCU4IO`, an extension of (:class:`frappy.stringio.StringIO`)
|
||||
serves as communication class.
|
||||
|
||||
:Note:
|
||||
@ -121,12 +121,12 @@ the status codes from the hardware to the standard SECoP status codes.
|
||||
def read_empty_length(self):
|
||||
name, txtvalue = self.communicate('hem').split('=')
|
||||
assert name == 'hem'
|
||||
return txtvalue
|
||||
return float(txtvalue)
|
||||
|
||||
def write_empty_length(self, value):
|
||||
name, txtvalue = self.communicate('hem=%g' % value).split('=')
|
||||
assert name == 'hem'
|
||||
return txtvalue
|
||||
return float(txtvalue)
|
||||
|
||||
...
|
||||
|
||||
@ -153,7 +153,7 @@ which means it might be worth to create a *query* method, and then the
|
||||
"""
|
||||
name, txtvalue = self.communicate(cmd).split('=')
|
||||
assert name == cmd.split('=')[0] # check that we got a reply to our command
|
||||
return txtvalue # Frappy will automatically convert the string to the needed data type
|
||||
return float(txtvalue)
|
||||
|
||||
def read_value(self):
|
||||
return self.query('h')
|
||||
@ -183,7 +183,7 @@ which means it might be worth to create a *query* method, and then the
|
||||
:Note:
|
||||
|
||||
It make sense to unify *empty_length* and *full_length* to one parameter *calibration*,
|
||||
as a :class:`secop.datatypes.StructOf` with members *empty_length* and *full_length*:
|
||||
as a :class:`frappy.datatypes.StructOf` with members *empty_length* and *full_length*:
|
||||
|
||||
.. code:: python
|
||||
|
||||
@ -196,7 +196,7 @@ which means it might be worth to create a *query* method, and then the
|
||||
For simplicity we stay with two float parameters for this tutorial.
|
||||
|
||||
|
||||
The full documentation of the example can be found here: :class:`secop_psi.ccu4.HeLevel`
|
||||
The full documentation of the example can be found here: :class:`frappy_psi.ccu4.HeLevel`
|
||||
|
||||
|
||||
Configuration
|
||||
@ -205,46 +205,50 @@ Before we continue coding, we may try out what we have coded and create a config
|
||||
The directory tree of the Frappy framework contains the code for all drivers, but the
|
||||
configuration file determines, which code will be loaded when a server is started.
|
||||
We choose the name *example_cryo* and create therefore a configuration file
|
||||
*example_cryo.cfg* in the *cfg* subdirectory:
|
||||
*example_cryo_cfg.py* in the *cfg* subdirectory:
|
||||
|
||||
``cfg/example_cryo.cfg``:
|
||||
``cfg/example_cryo_cfg.py``:
|
||||
|
||||
.. code:: ini
|
||||
.. code:: python
|
||||
|
||||
[NODE]
|
||||
description = this is an example cryostat for the Frappy tutorial
|
||||
id = example_cryo.psi.ch
|
||||
Node('example_cryo.psi.ch',
|
||||
'this is an example cryostat for the Frappy tutorial',
|
||||
interface='tcp://5000')
|
||||
Mod('helev',
|
||||
'frappy_psi.ccu4.HeLevel',
|
||||
'He level of the cryostat He reservoir',
|
||||
uri='linse-moxa-4.psi.ch:3001',
|
||||
empty_length=380,
|
||||
full_length=0)
|
||||
|
||||
[INTERFACE]
|
||||
uri = tcp://5000
|
||||
A configuration file contains a node configuration and one or several module configurations.
|
||||
|
||||
[helev]
|
||||
description = He level of the cryostat He reservoir
|
||||
class = secop_psi.ccu4.HeLevel
|
||||
uri = linse-moxa-4.psi.ch:3001
|
||||
empty_length = 380
|
||||
full_length = 0
|
||||
*Node* describes the main properties of the SEC Node: an id and a description of the node
|
||||
which should be globally unique, and an interface defining 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.
|
||||
|
||||
A configuration file contains several sections with a header enclosed by rectangular brackets.
|
||||
All the other sections define the SECoP modules to be used. This first arguments of *Mod(* are:
|
||||
|
||||
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 module name
|
||||
* the python class to be used for the creation of the module
|
||||
* a human readable description is its
|
||||
|
||||
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
|
||||
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_length* and *full_length* from the client by defining:
|
||||
|
||||
.. code:: ini
|
||||
.. code:: python
|
||||
|
||||
empty_length.export = False
|
||||
full_length.export = False
|
||||
Mod('helev',
|
||||
'frappy_psi.ccu4.HeLevel',
|
||||
'He level of the cryostat He reservoir',
|
||||
uri='linse-moxa-4.psi.ch:3001',
|
||||
empty_length=Param(380, export=False),
|
||||
full_length=Param(0, export=False))
|
||||
|
||||
However, we do not put this here, as it is nice to try out changing parameters for a test!
|
||||
As we configure more than just an initial value, we have to call *Param* and give the
|
||||
value as the first argument, and additional properties as keyworded arguments.
|
||||
|
||||
*to be continued*
|
||||
|
Reference in New Issue
Block a user