From 752f8f8093df2caf916f43182ead2deefd3ac8e7 Mon Sep 17 00:00:00 2001 From: Enrico Faulhaber Date: Thu, 28 Mar 2019 17:46:46 +0100 Subject: [PATCH] remove support for declaring parameters/commands as accessibles use parameters/commands for this Change-Id: I41f68c7f65f0ea451e639092a44a8ff8f5710bfc Reviewed-on: https://forge.frm2.tum.de/review/20275 Tested-by: JenkinsCodeReview Reviewed-by: Markus Zolliker Reviewed-by: Enrico Faulhaber Tested-by: Enrico Faulhaber --- secop/features.py | 22 +++++++++++----------- secop/metaclass.py | 5 ++--- secop/modules.py | 8 ++++---- secop_demo/modules.py | 14 +++++++------- secop_demo/test.py | 4 ++-- secop_ess/epics.py | 6 +++--- secop_mlz/amagnet.py | 2 +- secop_mlz/entangle.py | 22 +++++++++++----------- test/test_modules.py | 8 +++----- 9 files changed, 44 insertions(+), 47 deletions(-) diff --git a/secop/features.py b/secop/features.py index 35060ea..8c7fed8 100644 --- a/secop/features.py +++ b/secop/features.py @@ -42,7 +42,7 @@ class HAS_PID(Feature): # note: (i would still but them in the same group, though) # note: if extra elements are implemented in the pid struct they MUST BE # properly described in the description of the pid Parameter - accessibles = { + parameters = { 'use_pid' : Parameter('use the pid mode', datatype=EnumType(openloop=0, pid_control=1), ), 'p' : Parameter('proportional part of the regulation', datatype=FloatRange(0), ), 'i' : Parameter('(optional) integral part', datatype=FloatRange(0), optional=True), @@ -60,7 +60,7 @@ class HAS_PID(Feature): class Has_PIDTable(HAS_PID): - accessibles = { + parameters = { 'use_pidtable' : Parameter('use the zoning mode', datatype=EnumType(fixed_pid=0, zone_mode=1)), 'pidtable' : Parameter('Table of pid-values vs. target temperature', datatype=ArrayOf(TupleOf(FloatRange(0), StructOf(p=FloatRange(0), @@ -78,7 +78,7 @@ class HAS_Persistent(Feature): # 'coupled' : Status.BUSY+2, # to be discussed. # 'decoupling' : Status.BUSY+3, # to be discussed. #} - accessibles = { + parameters = { 'persistent_mode': Parameter('Use persistent mode', datatype=EnumType(off=0,on=1), default=0, readonly=False), @@ -95,7 +95,7 @@ class HAS_Tolerance(Feature): # detects IDLE status by checking if the value lies in a given window: # tolerance is the maximum allowed deviation from target, value must lie in this interval # for at least ´timewindow´ seconds. - accessibles = { + parameters = { 'tolerance': Parameter('Half height of the Window', datatype=FloatRange(0), default=1, unit='$'), 'timewindow': Parameter('Length of the timewindow to check', @@ -105,7 +105,7 @@ class HAS_Tolerance(Feature): class HAS_Timeout(Feature): - accessibles = { + parameters = { 'timeout': Parameter('timeout for movement', datatype=FloatRange(0), default=0, unit='s'), } @@ -113,7 +113,7 @@ class HAS_Timeout(Feature): class HAS_Pause(Feature): # just a proposal, can't agree on it.... - accessibles = { + parameters = { 'pause': Command('pauses movement', argument=None, result=None), 'go': Command('continues movement or start a new one if target was change since the last pause', argument=None, result=None), @@ -121,7 +121,7 @@ class HAS_Pause(Feature): class HAS_Ramp(Feature): - accessibles = { + parameters = { 'ramp': Parameter('speed of movement', unit='$/min', datatype=FloatRange(0)), 'use_ramp': Parameter('use the ramping of the setpoint, or jump', @@ -134,14 +134,14 @@ class HAS_Ramp(Feature): class HAS_Speed(Feature): - accessibles = { + parameters = { 'speed' : Parameter('(maximum) speed of movement (of the main value)', unit='$/s', datatype=FloatRange(0)), } class HAS_Accel(HAS_Speed): - accessibles = { + parameters = { 'accel' : Parameter('acceleration of movement', unit='$/s^2', datatype=FloatRange(0)), 'decel' : Parameter('deceleration of movement', unit='$/s^2', @@ -150,7 +150,7 @@ class HAS_Accel(HAS_Speed): class HAS_MotorCurrents(Feature): - accessibles = { + parameters = { 'movecurrent' : Parameter('Current while moving', datatype=FloatRange(0)), 'idlecurrent' : Parameter('Current while idle', @@ -160,7 +160,7 @@ class HAS_MotorCurrents(Feature): class HAS_Curve(Feature): # proposed, not yet agreed upon! - accessibles = { + parameters = { 'curve' : Parameter('Calibration curve', datatype=StringType(80), default=''), # XXX: tbd. (how to upload/download/select a curve?) } diff --git a/secop/metaclass.py b/secop/metaclass.py index d3a5892..b5ca89f 100644 --- a/secop/metaclass.py +++ b/secop/metaclass.py @@ -88,7 +88,7 @@ class ModuleMeta(type): for base in reversed(bases): if hasattr(base, "accessibles"): accessibles_list.append(base.accessibles) - for accessibles in [attrs.get('accessibles', {}), parameters, commands, overrides]: + for accessibles in [parameters, commands, overrides]: accessibles_list.append(accessibles) accessibles = {} # unordered dict of accessibles, will be sorted later for accessibles_dict in accessibles_list: @@ -121,10 +121,9 @@ class ModuleMeta(type): if isinstance(v.datatype, EnumType) and not v.datatype._enum.name: v.datatype._enum.name = k - # newtype.accessibles will be used in 3 places only: + # newtype.accessibles will be used in 2 places only: # 1) for inheritance (see above) # 2) for the describing message - # 3) by code needing to access the Parameter/Command object (i.e. checking datatypes) newtype.accessibles = OrderedDict(sorted(accessibles.items(), key=lambda item: item[1].ctr)) # check validity of Parameter entries diff --git a/secop/modules.py b/secop/modules.py index ba2eb75..fff3a92 100644 --- a/secop/modules.py +++ b/secop/modules.py @@ -73,8 +73,8 @@ class Module(object): # what else? } - # properties, parameter and commands are auto-merged upon subclassing - accessibles = {} + # properties, parameters and commands are auto-merged upon subclassing + parameters = {} commands = {} # reference to the dispatcher (used for sending async updates) @@ -246,7 +246,7 @@ class Readable(Module): DISABLED = 500, UNKNOWN = 0, ) - accessibles = { + parameters = { 'value': Parameter('current value of the Module', readonly=True, default=0., datatype=FloatRange(), unit='', poll=True, @@ -313,7 +313,7 @@ class Writable(Readable): providing a settable 'target' parameter to those of a Readable """ - accessibles = { + parameters = { 'target': Parameter('target value of the Module', default=0., readonly=False, datatype=FloatRange(), ), diff --git a/secop_demo/modules.py b/secop_demo/modules.py index bb66945..6f3a4b8 100644 --- a/secop_demo/modules.py +++ b/secop_demo/modules.py @@ -35,7 +35,7 @@ from secop.modules import Drivable, Override, Parameter, Readable class Switch(Drivable): """switch it on or off.... """ - accessibles = { + parameters = { 'value': Override('current state (on or off)', datatype=EnumType(on=1, off=0), default=0, ), @@ -97,7 +97,7 @@ class Switch(Drivable): class MagneticField(Drivable): """a liquid magnet """ - accessibles = { + parameters = { 'value': Override('current field in T', unit='T', datatype=FloatRange(-15, 15), default=0, ), @@ -197,7 +197,7 @@ class MagneticField(Drivable): class CoilTemp(Readable): """a coil temperature """ - accessibles = { + parameters = { 'value': Override('Coil temperatur', unit='K', datatype=FloatRange(), default=0, ), @@ -213,7 +213,7 @@ class CoilTemp(Readable): class SampleTemp(Drivable): """a sample temperature """ - accessibles = { + parameters = { 'value': Override('Sample temperature', unit='K', datatype=FloatRange(), default=10, ), @@ -260,7 +260,7 @@ class Label(Readable): of several subdevices. used for demoing connections between modules. """ - accessibles = { + parameters = { 'system': Parameter("Name of the magnet system", datatype=StringType, export=False, ), @@ -305,7 +305,7 @@ class Label(Readable): class DatatypesTest(Readable): """for demoing all datatypes """ - accessibles = { + parameters = { 'enum': Parameter('enum', datatype=EnumType(boo=None, faar=None, z=9), readonly=False, default=1), 'tupleof': Parameter('tuple of int, float and str', @@ -327,7 +327,7 @@ class DatatypesTest(Readable): class ArrayTest(Readable): - accessibles = { + parameters = { "x": Parameter('value', datatype=ArrayOf(FloatRange(), 0, 100000), default = 100000 * [0]), } diff --git a/secop_demo/test.py b/secop_demo/test.py index cdbf06b..f827aaa 100644 --- a/secop_demo/test.py +++ b/secop_demo/test.py @@ -54,7 +54,7 @@ class Heater(Drivable): class name indicates it to be some heating element, but the implementation may do anything """ - accessibles = { + parameters = { 'maxheaterpower': Parameter('maximum allowed heater power', datatype=FloatRange(0, 100), unit='W', ), @@ -73,7 +73,7 @@ class Temp(Drivable): class name indicates it to be some temperature controller, but the implementation may do anything """ - accessibles = { + parameters = { 'sensor': Parameter( "Sensor number or calibration id", datatype=StringType( diff --git a/secop_ess/epics.py b/secop_ess/epics.py index 3590899..bcf4ebd 100644 --- a/secop_ess/epics.py +++ b/secop_ess/epics.py @@ -59,7 +59,7 @@ except ImportError: class EpicsReadable(Readable): """EpicsDrivable handles a Drivable interfacing to EPICS v4""" # Commmon parameter for all EPICS devices - accessibles = { + parameters = { 'value': Parameter('EPICS generic value', datatype=FloatRange(), default=300.0,), @@ -119,7 +119,7 @@ class EpicsReadable(Readable): class EpicsDrivable(Drivable): """EpicsDrivable handles a Drivable interfacing to EPICS v4""" # Commmon parameter for all EPICS devices - accessibles = { + parameters = { 'target': Parameter('EPICS generic target', datatype=FloatRange(), default=300.0, readonly=False), 'value': Parameter('EPICS generic value', datatype=FloatRange(), @@ -192,7 +192,7 @@ class EpicsDrivable(Drivable): class EpicsTempCtrl(EpicsDrivable): - accessibles = { + parameters = { # TODO: restrict possible values with oneof datatype 'heaterrange': Parameter('Heater range', datatype=StringType(), default='Off', readonly=False,), diff --git a/secop_mlz/amagnet.py b/secop_mlz/amagnet.py index 3f6c9d5..b65c761 100644 --- a/secop_mlz/amagnet.py +++ b/secop_mlz/amagnet.py @@ -48,7 +48,7 @@ class GarfieldMagnet(SequencerMixin, Drivable): the symmetry setting selects which. """ - accessibles = { + parameters = { 'subdev_currentsource': Parameter('(bipolar) Powersupply', datatype=StringType(), readonly=True, export=False), 'subdev_enable': Parameter('Switch to set for on/off', datatype=StringType(), readonly=True, export=False), 'subdev_polswitch': Parameter('Switch to set for polarity', datatype=StringType(), readonly=True, export=False), diff --git a/secop_mlz/entangle.py b/secop_mlz/entangle.py index 48d4221..fcbe879 100644 --- a/secop_mlz/entangle.py +++ b/secop_mlz/entangle.py @@ -159,7 +159,7 @@ class PyTangoDevice(Module): execution and attribute operations with logging and exception mapping. """ - accessibles = { + parameters = { 'comtries': Parameter('Maximum retries for communication', datatype=IntRange(1, 100), default=3, readonly=False, group='communication'), @@ -426,7 +426,7 @@ class AnalogOutput(PyTangoDevice, Drivable): controllers, ... """ - accessibles = { + parameters = { 'userlimits': Parameter('User defined limits of device value', datatype=TupleOf(FloatRange(), FloatRange()), default=(float('-Inf'), float('+Inf')), @@ -604,7 +604,7 @@ class Actuator(AnalogOutput): """ # for secop: support the speed and ramp parameters - accessibles = { + parameters = { 'speed': Parameter('The speed of changing the value', unit='main/s', readonly=False, datatype=FloatRange(0), ), @@ -644,7 +644,7 @@ class Motor(Actuator): It has the ability to move a real object from one place to another place. """ - accessibles = { + parameters = { 'refpos': Parameter('Reference position', datatype=FloatRange(), unit='main', ), @@ -684,7 +684,7 @@ class TemperatureController(Actuator): """A temperature control loop device. """ - accessibles = { + parameters = { 'p': Parameter('Proportional control Parameter', datatype=FloatRange(), readonly=False, group='pid', ), @@ -759,7 +759,7 @@ class PowerSupply(Actuator): """A power supply (voltage and current) device. """ - accessibles = { + parameters = { 'ramp': Parameter('Current/voltage ramp', unit='main/min', datatype=FloatRange(), readonly=False, poll=30,), 'voltage': Parameter('Actual voltage', unit='V', @@ -797,7 +797,7 @@ class NamedDigitalInput(DigitalInput): """A DigitalInput with numeric values mapped to names. """ - accessibles = { + parameters = { 'mapping': Parameter('A dictionary mapping state names to integers', datatype=StringType(), export=False), # XXX:!!! } @@ -820,7 +820,7 @@ class PartialDigitalInput(NamedDigitalInput): bit width accessed. """ - accessibles = { + parameters = { 'startbit': Parameter('Number of the first bit', datatype=IntRange(0), default=0), 'bitwidth': Parameter('Number of bits', @@ -864,7 +864,7 @@ class NamedDigitalOutput(DigitalOutput): """A DigitalOutput with numeric values mapped to names. """ - accessibles = { + parameters = { 'mapping': Parameter('A dictionary mapping state names to integers', datatype=StringType(), export=False), } @@ -890,7 +890,7 @@ class PartialDigitalOutput(NamedDigitalOutput): bit width accessed. """ - accessibles = { + parameters = { 'startbit': Parameter('Number of the first bit', datatype=IntRange(0), default=0), 'bitwidth': Parameter('Number of bits', @@ -921,7 +921,7 @@ class StringIO(PyTangoDevice, Module): receives strings. """ - accessibles = { + parameters = { 'bustimeout': Parameter('Communication timeout', datatype=FloatRange(), readonly=False, unit='s', group='communication'), diff --git a/test/test_modules.py b/test/test_modules.py index bb7d74f..f08f09d 100644 --- a/test/test_modules.py +++ b/test/test_modules.py @@ -65,14 +65,12 @@ def test_ModuleMeta(): 'pollinterval': Override(reorder=True), 'param1' : Parameter('param1', datatype=BoolType(), default=False), 'param2': Parameter('param2', datatype=BoolType(), default=True), + "cmd": Command('stuff', BoolType(), BoolType()) }, "commands": { - "cmd": Command('stuff',BoolType(), BoolType()) - }, - "accessibles": { 'a1': Parameter('a1', datatype=BoolType(), default=False), 'a2': Parameter('a2', datatype=BoolType(), default=True), - 'value':Override(datatype=BoolType(), default = True), + 'value': Override(datatype=BoolType(), default=True), 'cmd2': Command('another stuff', BoolType(), BoolType()), }, "do_cmd": lambda self, arg: not arg, @@ -89,7 +87,7 @@ def test_ModuleMeta(): 'param1', 'param2', 'cmd', 'a1', 'a2', 'cmd2'] newclass2 = ModuleMeta.__new__(ModuleMeta, 'UpperClass', (newclass1,), { - "accessibles": { + "parameters": { 'cmd2': Override('another stuff'), 'a1': Override(datatype=FloatRange(), reorder=True), 'b2': Parameter('a2', datatype=BoolType(), default=True),