- before some chamges in the gerrit pipline Change-Id: I33eb2d75f83345a7039d0fb709e66defefb1c3e0
4.2 KiB
Coding
Coding a Class for a SECoP Module
A SECoP module is represented as an instance of a python class. For
programming such a class, typically you create a subclass of one of the
base classes Readable <frappy.modules.Readable>, Writable <frappy.modules.Writable> or Drivable <frappy.modules.Drivable>. It is also
quite common to inherit from classes created for similar modules, and or
to inherit from a mixin class like HasIO <frappy.io.HasIO>.
For creating the parameters <module structure parameters>, class
attributes are used, using the name of the parameter as the attribute
name and an instantiation of frappy.params.Parameter for defining the parameter.
If a parameter is already given by an inherited class, the parameter
declaration might be omitted, or just its altered properties have to be
given.
In addition, you might need one or several configurable items (see
properties <module structure properties>),
declared in the same way, with <property name> =
frappy.params.Property (...).
For each of the parameters, the behaviour has to be programmed with the following access methods:
- def read_*<parameter>*(self):
-
Called on a
readSECoP message and whenever the internal poll mechanism of Frappy tries to get a new value. The return value should be the retrieved value. This method might also be called internally, in case a fresh value of the parameter is needed.
polling
The Frappy framework has a built in polling <polling> mechanism, which calls above
method regularely. Each time read_<parameter> is
called, the Frappy framework ensures then that the value of the
parameter is updated and the activated clients will be notified by means
of an update message.
- def write_*<parameter>*(self, value):
-
Called on a
changeSECoP message. Thevalueargument is the value given by the change message, and the method should implement the change, typically by handing it over to the hardware. On success, the method must return the accepted value. If the value may be read back from the hardware, the readback value should be returned, which might be slighly altered for example by rounding. The idea is, that the returned value would be the same, as if it would be done by theread_<parameter>method. Often the easiest implementation is just returning the result of a call to theread_<parameter>method.
behind the scenes
Assigning a parameter to a value by setting the attribute via
self.<param> = <value> or
<module>.<param> = <value> includes a
type check <type check>, some type conversion
and ensures that a notification <client notification> with an
update message is sent to all activated clients.
Example code:
from frappy.core import HasIO, Drivable, Property, Parameter, StringType
class TemperatureLoop(HasIO, Drivable):
"""a temperature sensor with loop"""
# internal property to configure the channel
channel = Property('the Lakeshore channel', datatype=StringType())
# modifying a property of inherited parameters (unit is propagated to the FloatRange datatype)
value = Parameter(unit='K')
target = Parameter(unit='K')
def read_value(self):
# using the inherited HasIO.communicate method to send a command and get the reply
reply = self.communicate(f'KRDG?{self.channel}')
return float(reply)
def read_status(self):
... determine the status from the hardware and return it ...
return status_code, status_text
def read_target(self):
... read back the target value ...
return target
def write_target(self, target):
... write here the target to the hardware ...
# important: make sure that the status is changed to BUSY within this method:
self.status = BUSY, 'target changed'
return self.read_target() # return the read back value