diff --git a/devices/APSCTL.py b/devices/APSCTL.py index e4c4dd38eaa9ab3aa18665093275749a54f3d94f..820f542dcc812d3cdef4eb1a9f6db50f63fb7972 100644 --- a/devices/APSCTL.py +++ b/devices/APSCTL.py @@ -15,18 +15,19 @@ from tango.server import run from tango.server import device_property from tango import AttrWriteType - -#attribute extention and hardware device imports -from src.attribute_wrapper import attribute_wrapper -from src.hardware_device import hardware_device -import numpy # Additional import from clients.opcua_connection import OPCUAConnection +from util.attribute_wrapper import attribute_wrapper +from util.hardware_device import hardware_device +from util.lofar_logging import device_logging_to_python, log_exceptions + +import numpy __all__ = ["APSCTL", "main"] +@device_logging_to_python({"device": "APSCTL"}) class APSCTL(hardware_device): """ @@ -132,7 +133,7 @@ class APSCTL(hardware_device): UNB2_FPGA_POL_PGM_IOUT_R = attribute_wrapper(comms_annotation=["2:UNB2_FPGA_POL_PGM_IOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga)) UNB2_FPGA_POL_PGM_TEMP_R = attribute_wrapper(comms_annotation=["2:UNB2_FPGA_POL_PGM_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga)) - + @log_exceptions() def delete_device(self): """Hook to delete resources allocated in init_device. @@ -148,13 +149,15 @@ class APSCTL(hardware_device): # -------- # overloaded functions # -------- - def off(self): + @log_exceptions() + def configure_for_off(self): """ user code here. is called when the state is set to OFF """ # Stop keep-alive self.opcua_connection.stop() - def initialise(self): + @log_exceptions() + def configure_for_initialise(self): """ user code here. is called when the sate is set to INIT """ """Initialises the attributes and properties of the PCC.""" diff --git a/devices/HW_device_template.py b/devices/HW_device_template.py new file mode 100644 index 0000000000000000000000000000000000000000..dd6cad99bd5824bd1b8a37a471aeb7796f32a05d --- /dev/null +++ b/devices/HW_device_template.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# +# This file wraps around a tango device class and provides a number of abstractions useful for hardware devices. It works together +# +# Distributed under the terms of the APACHE license. +# See LICENSE.txt for more info. + +""" + +""" + +# PyTango imports +from tango.server import run +from tango import AttrWriteType +# Additional import + +from util.attribute_wrapper import attribute_wrapper +from util.hardware_device import hardware_device + +__all__ = ["HW_dev"] + + +class HW_dev(hardware_device): + """ + This class is the minimal (read empty) implementation of a class using 'hardware_device' + """ + + # ---------- + # Attributes + # ---------- + """ + attribute wrapper objects can be declared here. All attribute wrapper objects will get automatically put in a list (attr_list) for easy access + + example = attribute_wrapper(comms_annotation="this is an example", datatype=numpy.double, dims=(8, 2), access=AttrWriteType.READ_WRITE) + ... + + """ + + def always_executed_hook(self): + """Method always executed before any TANGO command is executed.""" + pass + + def delete_device(self): + """Hook to delete resources allocated in init_device. + + This method allows for any memory or other resources allocated in the + init_device method to be released. This method is called by the device + destructor and by the device Init command (a Tango built-in). + """ + self.debug_stream("Shutting down...") + + self.Off() + self.debug_stream("Shut down. Good bye.") + + # -------- + # overloaded functions + # -------- + def fault(self): + """ user code here. is called when the state is set to FAULT """ + pass + + def off(self): + """ user code here. is called when the state is set to OFF """ + pass + + def on(self): + """ user code here. is called when the state is set to ON """ + + pass + + def standby(self): + """ user code here. is called when the state is set to STANDBY """ + pass + + def initialise(self): + """ user code here. is called when the sate is set to INIT """ + pass + + +# ---------- +# Run server +# ---------- +def main(args=None, **kwargs): + """Main function of the hardware device module.""" + return run((HW_dev,), args=args, **kwargs) + + +if __name__ == '__main__': + main() diff --git a/devices/PCC.py b/devices/PCC.py index 266725ab410b9b56c6d326a61f22cd8e332d54d6..ff0ed0914f43272ab195b8a55f8f550e7fdd3ceb 100644 --- a/devices/PCC.py +++ b/devices/PCC.py @@ -117,13 +117,13 @@ class PCC(hardware_device): # overloaded functions # -------- @log_exceptions() - def off(self): + def configure_for_off(self): """ user code here. is called when the state is set to OFF """ # Stop keep-alive self.OPCua_client.stop() @log_exceptions() - def initialise(self): + def configure_for_initialise(self): """ user code here. is called when the state is set to INIT """ # Init the dict that contains function to OPC-UA function mappings. diff --git a/devices/SDP.py b/devices/SDP.py index 25e1accc6e308212fe931a9bb261c428e74732f5..f344b5d26482d1b294b80a5e6da898f9da6be002 100644 --- a/devices/SDP.py +++ b/devices/SDP.py @@ -99,14 +99,14 @@ class SDP(hardware_device): # overloaded functions # -------- @log_exceptions() - def off(self): + def configure_for_off(self): """ user code here. is called when the state is set to OFF """ # Stop keep-alive self.opcua_connection.stop() @log_exceptions() - def initialise(self): + def configure_for_initialise(self): """ user code here. is called when the sate is set to INIT """ """Initialises the attributes and properties of the SDP.""" diff --git a/devices/SNMP.py b/devices/SNMP.py index 7efe8157b482b25b95307d51a727b29248d07f5d..120e1d113e6bae1e05f8100512aec4cec41fb328 100644 --- a/devices/SNMP.py +++ b/devices/SNMP.py @@ -15,11 +15,11 @@ from tango.server import run from tango.server import device_property from tango import AttrWriteType -# Additional import +# Additional import from clients.SNMP_client import SNMP_client -from src.attribute_wrapper import attribute_wrapper -from src.hardware_device import hardware_device +from util.attribute_wrapper import attribute_wrapper +from util.hardware_device import hardware_device import numpy @@ -70,7 +70,7 @@ class SNMP(hardware_device): ip_route_mask_127_0_0_1_R = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.4.21.1.11.127.0.0.1", "type": "IpAddress"}, datatype=numpy.str_) TCP_active_open_R = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.6.5.0", "type": "Counter32"}, datatype=numpy.str_) - sys_contact_RW = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.1.4.0"}, datatype=numpy.str_, access= AttrWriteType.READ_WRITE) + sys_contact_RW = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.1.4.0"}, datatype=numpy.str_, access=AttrWriteType.READ_WRITE) sys_contact_R = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.1.4.0"}, datatype=numpy.str_) TCP_Curr_estab_R = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.6.9.0", "type": "Gauge"}, datatype=numpy.int64) @@ -97,7 +97,7 @@ class SNMP(hardware_device): # -------- # overloaded functions # -------- - def initialise(self): + def configure_for_initialise(self): """ user code here. is called when the state is set to STANDBY """ # set up the SNMP ua client diff --git a/devices/clients/SNMP_client.py b/devices/clients/SNMP_client.py new file mode 100644 index 0000000000000000000000000000000000000000..7e774745d863640231a3d6d46b73c883bba6e155 --- /dev/null +++ b/devices/clients/SNMP_client.py @@ -0,0 +1,185 @@ +from util.comms_client import CommClient +import snmp +import numpy +import traceback + +__all__ = ["SNMP_client"] + + +snmp_to_numpy_dict = { + snmp.types.INTEGER: numpy.int64, + snmp.types.TimeTicks: numpy.int64, + snmp.types.OCTET_STRING: str, + snmp.types.OID: str +} + +snmp_types = { + "Integer": numpy.int64, + "Gauge": numpy.int64, + "TimeTick": numpy.int64, + "Counter32": numpy.int64, + "OctetString": str, + "IpAddress": str, + "OID": str, +} + + +# numpy_to_snmp_dict = { +# numpy.int64, +# numpy.int64, +# str, +# } + + +class SNMP_client(CommClient): + """ + messages to keep a check on the connection. On connection failure, reconnects once. + """ + + def start(self): + super().start() + + def __init__(self, community, host, timeout, fault_func, streams, try_interval=2): + """ + Create the SNMP and connect() to it + """ + super().__init__(fault_func, streams, try_interval) + + self.community = community + self.host = host + self.manager = snmp.Manager(community=bytes(community, "utf8")) + + # Explicitly connect + if not self.connect(): + # hardware or infra is down -- needs fixing first + fault_func() + return + + def connect(self): + """ + Try to connect to the client + """ + self.streams.debug_stream("Connecting to community: %s, host: %s", self.community, self.host) + + self.connected = True + return True + + def ping(self): + """ + ping the client to make sure the connection with the client is still functional. + """ + pass + + def _setup_annotation(self, annotation): + """ + This class's Implementation of the get_mapping function. returns the read and write functions + """ + + if isinstance(annotation, dict): + # check if required path inarg is present + if annotation.get('oids') is None: + AssertionError("SNMP get attributes require an oid") + oids = annotation.get("oids") # required + else: + TypeError("SNMP attributes require a dict with oid(s)") + return + + if annotation.get('type') is not None: + dtype = annotation.get("type") # required + # actual_type = snmp_types[dtype] + else: + dtype = None + + return oids, dtype + + def setup_value_conversion(self, attribute): + """ + gives the client access to the attribute_wrapper object in order to access all data it could potentially need. + """ + + dim_x = attribute.dim_x + dim_y = attribute.dim_y + + return dim_x, dim_y + + def get_oids(self, x, y, in_oid): + + if x == 0: + x = 1 + if y == 0: + y = 1 + + nof_oids = x * y + + if nof_oids == 1: + # is scalar + if type(in_oid) is str: + # for ease of handling put single oid in a 1 element list + in_oid = [in_oid] + return in_oid + + elif type(in_oid) is list and len(in_oid) == nof_oids: + # already is an array and of the right length + return in_oid + elif type(in_oid) is list and len(in_oid) != nof_oids: + # already is an array but the wrong length. Unable to handle this + raise ValueError("SNMP oids need to either be a single value or an array the size of the attribute dimensions. got: {} expected: {}x{}={}".format(len(in_oid),x,y,x*y)) + else: + out_oids = [] + + for i in range(nof_oids): + out_oids.append(in_oid + ".{}".format(i+1)) + + return out_oids + + def setup_attribute(self, annotation, attribute): + """ + MANDATORY function: is used by the attribute wrapper to get read/write functions. must return the read and write functions + """ + + # process the annotation + oids, dtype = self._setup_annotation(annotation) + + # get all the necessary data to set up the read/write functions from the attribute_wrapper + dim_x, dim_y = self.setup_value_conversion(attribute) + oids = self.get_oids(dim_x, dim_y, oids) + + if dtype is None: + + def _read_function(): + vars = self.manager.get(self.host, *oids) + + value = [] + for i in vars: + val = snmp_to_numpy_dict[type(i.value)](str(i.value)) + value.append(val) + return value + + def _write_function(value): + if len(oids) == 1 and type(value) != list: + value = [value] + else: + for i in range(len(oids)): + self.manager.set(self.host, oids[i], value[i]) + + else: + def _read_function(): + vars = self.manager.get(self.host, *oids) + + value = [] + for i in vars: + val = snmp_to_numpy_dict[type(i.value)](str(i.value)) + value.append(val) + return value + + def _write_function(value): + if len(oids) == 1 and type(value) != list: + value = [value] + else: + for i in range(len(oids)): + self.manager.set(self.host, oids[i], snmp_types[dtype](value[i])) + + # return the read/write functions + return _read_function, _write_function + + diff --git a/devices/clients/ini_client.py b/devices/clients/ini_client.py index 701bd7a9096fe59e5b02f4d4ec4f947789031c9f..e94c2f9240f84974e10575c6c05d40dc7f6ae065 100644 --- a/devices/clients/ini_client.py +++ b/devices/clients/ini_client.py @@ -1,4 +1,4 @@ -from src.comms_client import CommClient +from util.comms_client import CommClient import configparser import numpy @@ -6,19 +6,28 @@ import numpy numpy_to_ini_dict = { numpy.int64: int, numpy.double: float, + numpy.float64: float, numpy.bool_: bool, str: str } + +numpy_to_ini_get_dict = { + numpy.int64: configparser.ConfigParser.getint, + numpy.double: configparser.ConfigParser.getfloat, + numpy.float64: configparser.ConfigParser.getfloat, + numpy.bool_: configparser.ConfigParser.getboolean, + str: str +} + ini_to_numpy_dict = { int: numpy.int64, - float: numpy.double, + float: numpy.float64, bool: numpy.bool_, - str: str + str: numpy.str_ } import os - class ini_client(CommClient): """ this class provides an example implementation of a comms_client. @@ -50,7 +59,13 @@ class ini_client(CommClient): def connect(self): files_path = [os.path.abspath(x) for x in os.listdir()] self.streams.debug_stream(" %s", files_path) - self.config_file = open(self.filename, "rw") + + try: + write_config(self.filename) + self.config_file = open(self.filename, "r") + except FileNotFoundError: + write_config(self.filename) + self.config_file = open(self.filename, "r") self.connected = True # set connected to true return True # if succesfull, return true. otherwise return false @@ -88,26 +103,48 @@ class ini_client(CommClient): necessary data such as dimensionality and data type """ - if attribute.dim_y > 1: - dims = (attribute.dim_y, attribute.dim_x) - else: - dims = (attribute.dim_x,) + dim_y = attribute.dim_y + dim_x = attribute.dim_x dtype = attribute.numpy_type - return dims, dtype + return dim_y, dim_x, dtype - def _setup_mapping(self, name, section, dtype): + def _setup_mapping(self, name, section, dtype, dim_y, dim_x): """ takes all gathered data to configure and return the correct read and write functions """ def read_function(): + self.config.read_file(self.config_file) value = self.config.get(section, name) - value = ini_to_numpy_dict[dtype](value) + + print("pre conversion: ", value, type(value)) # pre conversion + value = array(value, dtype) + + # convert values from buildin type to numpy type + value = dtype(value) + print("post conversion: ", value, type(value)) # pre conversion + if dim_y > 1: + # if data is an image, slice it according to the y dimensions + value = numpy.array(numpy.split(numpy.array(value), indices_or_sections=dim_y)) + return value - def write_function(write_value): + def write_function(value): + + if type(value) is list: + write_value = "" + + for i in value: + write_value = write_value + str(value) + ", " + + # strip the extra ", " at the end + write_value = write_value[:-2] + else: + write_value = str(value) + + self.config.read_file(self.config_file) self.config.set(section, name, write_value) fp = open(self.filename, 'w') self.config.write(fp) @@ -124,38 +161,72 @@ class ini_client(CommClient): section, name = self._setup_annotation(annotation) # get all the necessary data to set up the read/write functions from the attribute_wrapper - dims, dtype = self._setup_value_conversion(attribute) + dim_y, dim_x, dtype = self._setup_value_conversion(attribute) # configure and return the read/write functions - read_function, write_function = self._setup_mapping(name, section, dtype) + read_function, write_function = self._setup_mapping(name, section, dtype, dim_y, dim_x) # return the read/write functions return read_function, write_function +def array(string, dtype): + array = [] + + if dtype is numpy.bool_: + # Handle special case for Bools + for i in string.split(","): + i.replace("", "") + if "True" in i: + array.append(True) + elif "False" in i: + array.append(False) + else: + raise ValueError("String to bool failed. String is not True/False, but is: '{}'".format(i)) + elif dtype is numpy.str_: + for i in string.split(","): + value = i + array.append(value) + else: + # regular case, go through the separator + for i in string.split(","): + i.replace(" ", "") + value = dtype(i) + array.append(value) + + return array + +def write_config(filename): + with open(filename, 'w') as configfile: + + config = configparser.ConfigParser() + config['scalar'] = {} + config['scalar']['double_scalar_R'] = '1.2' + config['scalar']['double_scalar_RW'] = '3.4' + config['scalar']['bool_scalar_R'] = 'True' + config['scalar']['bool_scalar_RW'] = 'False' + config['scalar']['int_scalar_R'] = '5' + config['scalar']['int_scalar_RW'] = '6' + config['scalar']['str_scalar_R'] = 'this is' + config['scalar']['str_scalar_RW'] = 'a test' + + config['spectrum'] = {} + config['spectrum']['double_spectrum_R'] = '1.2, 2.3, 3.4, 4.5' + config['spectrum']['double_spectrum_RW'] = '5.6, 6.7, 7.8, 9.0' + config['spectrum']['bool_spectrum_R'] = 'True, True, False, False' + config['spectrum']['bool_spectrum_RW'] = 'False, False, True, True' + config['spectrum']['int_spectrum_R'] = '1, 2, 3, 4' + config['spectrum']['int_spectrum_RW'] = '6, 7, 8, 9' + config['spectrum']['str_spectrum_R'] = '"a", "b", "c", "d"' + config['spectrum']['str_spectrum_RW'] = '"D", "E", "F", "G"' + + config['image'] = {} + config['image']['double_image_R'] = '1.2, 2.3, 3.4, 4.5, 5.6, 6.7' + config['image']['double_image_RW'] = '5.6, 6.7, 7.8, 9.0, 1.2, 3.4' + config['image']['bool_image_R'] = 'True, True, False, False, True, False' + config['image']['bool_image_RW'] = 'False, False, True, True, False, Trie' + config['image']['int_image_R'] = '1, 2, 3, 4, 5, 6' + config['image']['int_image_RW'] = '6, 7, 8, 9, 10, 11' + config['image']['str_image_R'] = '"a", "b", "c", "d", "e", "f"' + config['image']['str_image_RW'] = '"D", "E", "F", "G", "H", "I"' -def write_config(): - config = configparser.ConfigParser() - config['scalar'] = {} - config['scalar']['double_scalar'] = '1.2' - config['scalar']['double_scalar'] = '3.4' - config['scalar']['bool_scalar'] = 'True' - config['scalar']['bool_scalar'] = 'False' - config['scalar']['int_scalar'] = '5' - config['scalar']['int_scalar'] = '6' - config['scalar']['str_scalar'] = 'this is' - config['scalar']['str_scalar'] = 'a test' - - config['spectrum'] = {} - config['spectrum']['double_scalar'] = '[1.2, 2.3, 3.4]' - config['spectrum']['double_scalar'] = '[5.6, 6.7, 7.8]' - config['spectrum']['bool_scalar'] = '[True, True, False]' - config['spectrum']['bool_scalar'] = '[False, False, True]' - config['spectrum']['int_scalar'] = '[5' - config['spectrum']['int_scalar'] = '[6,7,8,9]' - config['spectrum']['str_scalar'] = '["a", "b", "c"]' - config['spectrum']['str_scalar'] = '["D", "E", "F"]' - - - - with open('example.ini', 'w') as configfile: config.write(configfile) diff --git a/devices/ini_device.py b/devices/ini_device.py index 5b11d236017c19bea6bd951e694518a08ec1900c..326e677f35d74f675da03f8ac28e0f99c6e67adf 100644 --- a/devices/ini_device.py +++ b/devices/ini_device.py @@ -15,10 +15,8 @@ from tango.server import device_property from tango import AttrWriteType from tango import DevState # Additional import -from src.attribute_wrapper import attribute_wrapper -from src.hardware_device import hardware_device - - +from util.attribute_wrapper import attribute_wrapper +from util.hardware_device import hardware_device from clients.ini_client import * @@ -41,32 +39,37 @@ class ini_device(hardware_device): ... """ - double_scalar_RW = attribute_wrapper(comms_annotation={"section": "scalar", "name": "double_scalar"}, datatype=numpy.double, access=AttrWriteType.READ_WRITE) - double_scalar_R = attribute_wrapper(comms_annotation={"section": "scalar", "name": "double_scalar"}, datatype=numpy.double) - bool_scalar_RW = attribute_wrapper(comms_annotation={"section": "scalar", "name": "bool_scalar"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE) - bool_scalar_R = attribute_wrapper(comms_annotation={"section": "scalar", "name": "bool_scalar"}, datatype=numpy.bool_) - int_scalar_RW = attribute_wrapper(comms_annotation={"section": "scalar", "name": "int_scalar"}, datatype=numpy.int64, access=AttrWriteType.READ_WRITE) - int_scalar_R = attribute_wrapper(comms_annotation={"section": "scalar", "name": "int_scalar"}, datatype=numpy.int64) - str_scalar_RW = attribute_wrapper(comms_annotation={"section": "scalar", "name": "str_scalar"}, datatype=numpy.str, access=AttrWriteType.READ_WRITE) - str_scalar_R = attribute_wrapper(comms_annotation={"section": "scalar", "name": "str_scalar"}, datatype=numpy.str) - - double_spectrum_RW = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "double_spectrum"}, datatype=numpy.double, dims=(4,), access=AttrWriteType.READ_WRITE) - double_spectrum_R = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "double_spectrum"}, datatype=numpy.double, dims=(4,)) - bool_spectrum_RW = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "bool_spectrum"}, datatype=numpy.bool_, dims=(4,), access=AttrWriteType.READ_WRITE) - bool_spectrum_R = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "bool_spectrum"}, datatype=numpy.bool_, dims=(4,)) - int_spectrum_RW = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "int_spectrum"}, datatype=numpy.int64, dims=(4,), access=AttrWriteType.READ_WRITE) - int_spectrum_R = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "int_spectrum"}, datatype=numpy.int64, dims=(4,)) - str_spectrum_RW = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "str_spectrum"}, datatype=numpy.str, dims=(4,), access=AttrWriteType.READ_WRITE) - str_spectrum_R = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "str_spectrum"}, datatype=numpy.str, dims=(4,)) - - double_image_RW = attribute_wrapper(comms_annotation={"section": "image", "name": "double_image"}, datatype=numpy.double, dims=(3, 2), access=AttrWriteType.READ_WRITE) - double_image_R = attribute_wrapper(comms_annotation={"section": "image", "name": "double_image"}, datatype=numpy.double, dims=(3, 2)) - bool_image_RW = attribute_wrapper(comms_annotation={"section": "image", "name": "bool_image"}, datatype=numpy.bool_, dims=(3, 2), access=AttrWriteType.READ_WRITE) - bool_image_R = attribute_wrapper(comms_annotation={"section": "image", "name": "bool_image"}, datatype=numpy.bool_, dims=(3, 2)) - int_image_RW = attribute_wrapper(comms_annotation={"section": "image", "name": "int_image"}, datatype=numpy.int64, dims=(3, 2), access=AttrWriteType.READ_WRITE) - int_image_R = attribute_wrapper(comms_annotation={"section": "image", "name": "int_image"}, datatype=numpy.int64, dims=(3, 2)) - str_image_RW = attribute_wrapper(comms_annotation={"section": "image", "name": "str_image"}, datatype=numpy.str, dims=(3, 2), access=AttrWriteType.READ_WRITE) - str_image_R = attribute_wrapper(comms_annotation={"section": "image", "name": "str_image"}, datatype=numpy.str, dims=(3, 2)) + double_scalar_RW = attribute_wrapper(comms_annotation={"section": "scalar", "name": "double_scalar_RW"}, datatype=numpy.double, access=AttrWriteType.READ_WRITE) + double_scalar_R = attribute_wrapper(comms_annotation={"section": "scalar", "name": "double_scalar_R"}, datatype=numpy.double) + bool_scalar_RW = attribute_wrapper(comms_annotation={"section": "scalar", "name": "bool_scalar_RW"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE) + bool_scalar_R = attribute_wrapper(comms_annotation={"section": "scalar", "name": "bool_scalar_R"}, datatype=numpy.bool_) + int_scalar_RW = attribute_wrapper(comms_annotation={"section": "scalar", "name": "int_scalar_RW"}, datatype=numpy.int64, access=AttrWriteType.READ_WRITE) + int_scalar_R = attribute_wrapper(comms_annotation={"section": "scalar", "name": "int_scalar_R"}, datatype=numpy.int64) + str_scalar_RW = attribute_wrapper(comms_annotation={"section": "scalar", "name": "str_scalar_RW"}, datatype=numpy.str_, access=AttrWriteType.READ_WRITE) + str_scalar_R = attribute_wrapper(comms_annotation={"section": "scalar", "name": "str_scalar_R"}, datatype=numpy.str_) + + double_spectrum_RW = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "double_spectrum_RW"}, datatype=numpy.double, dims=(4,), access=AttrWriteType.READ_WRITE) + double_spectrum_R = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "double_spectrum_R"}, datatype=numpy.double, dims=(4,)) + bool_spectrum_RW = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "bool_spectrum_RW"}, datatype=numpy.bool_, dims=(4,), access=AttrWriteType.READ_WRITE) + bool_spectrum_R = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "bool_spectrum_R"}, datatype=numpy.bool_, dims=(4,)) + int_spectrum_RW = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "int_spectrum_RW"}, datatype=numpy.int64, dims=(4,), access=AttrWriteType.READ_WRITE) + int_spectrum_R = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "int_spectrum_R"}, datatype=numpy.int64, dims=(4,)) + str_spectrum_RW = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "str_spectrum_RW"}, datatype=numpy.str_, dims=(4,), access=AttrWriteType.READ_WRITE) + str_spectrum_R = attribute_wrapper(comms_annotation={"section": "spectrum", "name": "str_spectrum_R"}, datatype=numpy.str_, dims=(4,)) + + double_image_RW = attribute_wrapper(comms_annotation={"section": "image", "name": "double_image_RW"}, datatype=numpy.double, dims=(3, 2), access=AttrWriteType.READ_WRITE) + double_image_R = attribute_wrapper(comms_annotation={"section": "image", "name": "double_image_R"}, datatype=numpy.double, dims=(3, 2)) + bool_image_RW = attribute_wrapper(comms_annotation={"section": "image", "name": "bool_image_RW"}, datatype=numpy.bool_, dims=(3, 2), access=AttrWriteType.READ_WRITE) + bool_image_R = attribute_wrapper(comms_annotation={"section": "image", "name": "bool_image_R"}, datatype=numpy.bool_, dims=(3, 2)) + int_image_RW = attribute_wrapper(comms_annotation={"section": "image", "name": "int_image_RW"}, datatype=numpy.int64, dims=(3, 2), access=AttrWriteType.READ_WRITE) + int_image_R = attribute_wrapper(comms_annotation={"section": "image", "name": "int_image_R"}, datatype=numpy.int64, dims=(3, 2)) + str_image_RW = attribute_wrapper(comms_annotation={"section": "image", "name": "str_image_RW"}, datatype=numpy.str_, dims=(3, 2), access=AttrWriteType.READ_WRITE) + str_image_R = attribute_wrapper(comms_annotation={"section": "image", "name": "str_image_R"}, datatype=numpy.str_, dims=(3, 2)) + + @classmethod + def attr_list(cls): + """ Return a list of all the attribute_wrapper members of this class. """ + return [v for k, v in cls.__dict__.items() if type(v) == attribute_wrapper] def always_executed_hook(self): @@ -88,14 +91,14 @@ class ini_device(hardware_device): # -------- # overloaded functions # -------- - def initialise(self): + def configure_for_initialise(self): """ user code here. is called when the sate is set to INIT """ """Initialises the attributes and properties of the PCC.""" self.set_state(DevState.INIT) # set up the OPC ua client - self.ini_client = ini_client("example/example.ini", self.Fault, self) + self.ini_client = ini_client("example.ini", self.Fault, self) # map an access helper class for i in self.attr_list(): diff --git a/devices/test_device.py b/devices/test_device.py index 5659da595706cded1e786a479a12238d723e5f1c..6a62907112ea1cf081436285aa0d21532ba24d0a 100644 --- a/devices/test_device.py +++ b/devices/test_device.py @@ -64,7 +64,7 @@ class test_device(hardware_device): # -------- # overloaded functions # -------- - def initialise(self): + def configure_for_initialise(self): """ user code here. is called when the sate is set to INIT """ """Initialises the attributes and properties of the PCC.""" diff --git a/devices/util/hardware_device.py b/devices/util/hardware_device.py index 7d547447260e249d571bdd46d077a32ecc6ac58e..e0c9154c703a7cb82c42e9cdd7db76d68a011e05 100644 --- a/devices/util/hardware_device.py +++ b/devices/util/hardware_device.py @@ -23,7 +23,7 @@ __all__ = ["hardware_device"] from util.wrappers import only_in_states, fault_on_error -#@log_exceptions +#@log_exceptions() class hardware_device(Device): """ @@ -85,7 +85,7 @@ class hardware_device(Device): self.set_state(DevState.INIT) self.setup_value_dict() - self.initialise() + self.configure_for_initialise() self.set_state(DevState.STANDBY) @@ -100,7 +100,7 @@ class hardware_device(Device): :return:None """ - self.on() + self.configure_for_on() self.set_state(DevState.ON) @command() @@ -119,7 +119,7 @@ class hardware_device(Device): # Turn off self.set_state(DevState.OFF) - self.off() + self.configure_for_off() # Turn off again, in case of race conditions through reconnecting self.set_state(DevState.OFF) @@ -138,18 +138,18 @@ class hardware_device(Device): :return:None """ - self.fault() + self.configure_for_fault() self.set_state(DevState.FAULT) # functions that can be overloaded - def fault(self): + def configure_for_fault(self): pass - def off(self): + def configure_for_off(self): pass - def on(self): + def configure_for_on(self): pass - def initialise(self): + def configure_for_initialise(self): pass def always_executed_hook(self): diff --git a/devices/util/lofar_logging.py b/devices/util/lofar_logging.py index aa7d3633138679c63fd1934cf8d5638df7b1cedf..9adcc58eb97e751fdf4d211b8759e8be431edbff 100644 --- a/devices/util/lofar_logging.py +++ b/devices/util/lofar_logging.py @@ -63,7 +63,7 @@ def log_exceptions(): try: return func(self, *args, **kwargs) except Exception as e: - self.error_stream("Caught exception: %s: %s", e.__class__.__name__, e, exc_info=1) + self.error_stream("Caught exception: %s: %s", e.__class__.__name__, e) raise e return inner diff --git a/devices/util/startup.py b/devices/util/startup.py index f98097f994afc340fdb168311bcb524445658f1d..81f851733edce55240b60d80d2a7bd83e6575692 100755 --- a/devices/util/startup.py +++ b/devices/util/startup.py @@ -12,7 +12,7 @@ def startup(device: str, force_restart: bool): if force_restart is True: print("Forcing device {} restart.".format(device)) - proxy.off() + proxy.configure_for_off() state = proxy.state() if state is not tango._tango.DevState.OFF: print("Device {} cannot perform off although restart has been enforced, state = {}. Please investigate.".format(device, state)) @@ -21,13 +21,13 @@ def startup(device: str, force_restart: bool): print("Device {} is not in OFF state, cannot start it. state = {}".format(device, state)) return proxy print("Device {} is in OFF, performing initialisation.".format(device)) - proxy.initialise() + proxy.configure_for_initialise() state = proxy.state() if state is not tango._tango.DevState.STANDBY: print("Device {} cannot perform initialise, state = {}. Please investigate.".format(device, state)) return proxy print("Device {} is in STANDBY, performing on.".format(device)) - proxy.on() + proxy.configure_for_on() state = proxy.state() if state is not tango._tango.DevState.ON: print("Device {} cannot perform on, state = {}. Please investigate.".format(device, state))