diff --git a/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py b/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py index b28c7fe51c71ffb4756804c4d7a19e5c5e0cdc6f..ae00635acf68e059c62faf7a5b8d27a2ca435eec 100644 --- a/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py +++ b/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py @@ -2,7 +2,7 @@ from operator import mul from functools import reduce from tango.server import attribute -from tango import AttrWriteType +from tango import AttrWriteType, AttReqType from tangostationcontrol.devices.device_decorators import fault_on_error import logging @@ -117,6 +117,11 @@ class attribute_wrapper(attribute): """ read_func_wrapper reads the attribute value, stores it and returns it" """ + + # lofar.read_attribute ignores fisallowed. So check again if we're allowed to read. + if not device.is_attribute_access_allowed(AttReqType.READ_REQ): + return None + try: io = self.get_attribute_io(device) @@ -134,6 +139,11 @@ class attribute_wrapper(attribute): """ read_func_wrapper reads the attribute value, stores it and returns it" """ + + # lofar.read_attribute ignores fisallowed. So check again if we're allowed to read. + if not device.is_attribute_access_allowed(AttReqType.READ_REQ): + return None + try: io = self.get_attribute_io(device) diff --git a/tangostationcontrol/tangostationcontrol/common/states.py b/tangostationcontrol/tangostationcontrol/common/states.py new file mode 100644 index 0000000000000000000000000000000000000000..27bc5c481a9b7c33e347d68acf8f17b45f2f2315 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/common/states.py @@ -0,0 +1,12 @@ +from tango import DevState + +# The Device states in which we consider our device operational, +# and thus allow interaction. +OPERATIONAL_STATES = [DevState.ON, DevState.ALARM] + +# States in which Initialise() has happened, and the hardware +# can thus be configured or otherwise interacted with. +INITIALISED_STATES = OPERATIONAL_STATES + [DevState.STANDBY] + +# States in which most commands are allowed +DEFAULT_COMMAND_STATES = INITIALISED_STATES diff --git a/tangostationcontrol/tangostationcontrol/devices/apsct.py b/tangostationcontrol/tangostationcontrol/devices/apsct.py index e4e411e115713931e20bceb7c290242710156c3e..18a7f6fd7e49aeffdd1091e7e6a65766835be74a 100644 --- a/tangostationcontrol/tangostationcontrol/devices/apsct.py +++ b/tangostationcontrol/tangostationcontrol/devices/apsct.py @@ -21,9 +21,9 @@ import numpy from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.common.lofar_logging import device_logging_to_python +from tangostationcontrol.common.states import DEFAULT_COMMAND_STATES from tangostationcontrol.devices.device_decorators import only_in_states from tangostationcontrol.devices.opcua_device import opcua_device -from tangostationcontrol.devices.lofar_device import lofar_device import logging logger = logging.getLogger() @@ -97,8 +97,8 @@ class APSCT(opcua_device): self.read_attribute("APSCT_PLL_160MHz_locked_R") and self.read_attribute("APSCT_PLL_160MHz_error_R")] return any(errors) - APSCT_TEMP_error_R = attribute(dtype=bool, polling_period=1000) - APSCT_VOUT_error_R = attribute(dtype=bool) + APSCT_TEMP_error_R = attribute(dtype=bool, fisallowed="is_attribute_access_allowed", polling_period=1000) + APSCT_VOUT_error_R = attribute(dtype=bool, fisallowed="is_attribute_access_allowed") def read_APSCT_TEMP_error_R(self): return (self.alarm_val("APSCT_TEMP_R")) @@ -139,7 +139,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def APSCT_off(self): """ @@ -149,7 +149,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def APSCT_200MHz_on(self): """ @@ -159,7 +159,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def APSCT_160MHz_on(self): """ diff --git a/tangostationcontrol/tangostationcontrol/devices/apspu.py b/tangostationcontrol/tangostationcontrol/devices/apspu.py index ff32c3c9d9befb2563be1999f7ab3616fcf51456..7f40116222956f6066d2e00324ba18bfdaa43352 100644 --- a/tangostationcontrol/tangostationcontrol/devices/apspu.py +++ b/tangostationcontrol/tangostationcontrol/devices/apspu.py @@ -63,7 +63,7 @@ class APSPU(opcua_device): # ---------- # Summarising Attributes # ---------- - APSPU_error_R = attribute(dtype=bool) + APSPU_error_R = attribute(dtype=bool, fisallowed="is_attribute_access_allowed") def read_APSPU_error_R(self): return ((self.read_attribute("APSPUTR_I2C_error_R") > 0) diff --git a/tangostationcontrol/tangostationcontrol/devices/beam_device.py b/tangostationcontrol/tangostationcontrol/devices/beam_device.py index 3bf7d49932742dde3140d532b1b2c07aebcd991e..1d5e7143fbc7afd2385c063b4aab04b30347c00f 100644 --- a/tangostationcontrol/tangostationcontrol/devices/beam_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/beam_device.py @@ -20,6 +20,7 @@ from tango import AttrWriteType, DebugIt, DevVarStringArray, DevVarDoubleArray, from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.common.measures import get_measures_directory, get_available_measures_directories, download_measures, use_measures_directory, restart_python from tangostationcontrol.common.lofar_logging import log_exceptions +from tangostationcontrol.common.states import DEFAULT_COMMAND_STATES from tangostationcontrol.devices.device_decorators import TimeIt, only_in_states, fault_on_error from tangostationcontrol.beam.delays import delay_calculator from tangostationcontrol.devices.lofar_device import lofar_device @@ -206,7 +207,7 @@ class beam_device(lofar_device): @command(dtype_in=DevVarStringArray) @DebugIt() @log_exceptions() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def set_pointing(self, pointing_direction: list): """ Compute and uploads the hardware-specific delays based on a given pointing direction @@ -220,7 +221,7 @@ class beam_device(lofar_device): @command(dtype_in = DevString) @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def set_pointing_for_specific_time(self, parameters: DevString = None): """ Compute and uploads the hardware-specific delays based on a given pointing direction @@ -245,7 +246,7 @@ class beam_device(lofar_device): @command(dtype_in=DevVarStringArray, dtype_out=DevVarDoubleArray) @DebugIt() @log_exceptions() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def delays(self, pointing_direction: numpy.array): """ Calculate the delays based on the pointing list and the timestamp diff --git a/tangostationcontrol/tangostationcontrol/devices/boot.py b/tangostationcontrol/tangostationcontrol/devices/boot.py index d5834e231da0423df69ba48050da5abd08d8865c..8a7c08403d9c3c7a634d8151baef8bcd8fd501c2 100644 --- a/tangostationcontrol/tangostationcontrol/devices/boot.py +++ b/tangostationcontrol/tangostationcontrol/devices/boot.py @@ -26,6 +26,7 @@ from tangostationcontrol.devices.device_decorators import only_in_states from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.devices.lofar_device import lofar_device from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.common.states import OPERATIONAL_STATES import logging logger = logging.getLogger() @@ -153,7 +154,7 @@ class DevicesInitialiser(object): continue if self.is_available(device): - if self.reboot or self.devices[device].state() not in lofar_device.OPERATIONAL_STATES: + if self.reboot or self.devices[device].state() not in OPERATIONAL_STATES: self.stop_device(device) self.boot_device(device) @@ -204,7 +205,7 @@ class DevicesInitialiser(object): else: proxy.warm_boot() - if proxy.state() not in lofar_device.OPERATIONAL_STATES: + if proxy.state() not in OPERATIONAL_STATES: raise InitialisationException(f"Could not boot device {device_name}. It reports status: {proxy.status()}") self.set_status(f"[restarting {device_name}] Succesfully booted.") @@ -317,14 +318,14 @@ class Boot(lofar_device): @command() @DebugIt() - @only_in_states(lofar_device.OPERATIONAL_STATES) + @only_in_states(OPERATIONAL_STATES) @log_exceptions() def boot(self): self._boot(reboot=False, initialise_hardware=self.Initialise_Hardware) @command() @DebugIt() - @only_in_states(lofar_device.OPERATIONAL_STATES) + @only_in_states(OPERATIONAL_STATES) @log_exceptions() def reboot(self): self._boot(reboot=True, initialise_hardware=self.Initialise_Hardware) diff --git a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py index 4b594bd30f89e26585a63e3424d4c73129ae521a..3f127261973bda750d246a35bd514a868592d6ec 100644 --- a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py @@ -23,6 +23,7 @@ import textwrap from tangostationcontrol import __version__ as version from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper from tangostationcontrol.common.lofar_logging import log_exceptions +from tangostationcontrol.common.states import DEFAULT_COMMAND_STATES, INITIALISED_STATES from tangostationcontrol.devices.device_decorators import only_in_states, fault_on_error from tangostationcontrol.toolkit.archiver import Archiver @@ -60,17 +61,6 @@ class lofar_device(Device, metaclass=DeviceMeta): The user triggers their transitions by the commands reflecting the target state (Initialise(), On(), Fault()). """ - # The Device states in which we consider our device operational, - # and thus allow interaction. - OPERATIONAL_STATES = [DevState.ON, DevState.ALARM] - - # States in which Initialise() has happened, and the hardware - # can thus be configured or otherwise interacted with. - INITIALISED_STATES = OPERATIONAL_STATES + [DevState.STANDBY] - - # States in which most commands are allowed - DEFAULT_COMMAND_STATES = INITIALISED_STATES - # ---------- # Attributes # ---------- @@ -96,7 +86,7 @@ class lofar_device(Device, metaclass=DeviceMeta): def is_attribute_access_allowed(self, req_type): """ Returns whether an attribute wrapped by the attribute_wrapper be accessed. """ - return self.get_state() in [DevState.STANDBY, DevState.ON, DevState.ALARM] + return self.get_state() in INITIALISED_STATES @log_exceptions() def init_device(self): diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py index 9fd0d8697ada0a60d0c35c7e32d29fd1f2845d42..ff2e4166fca4ba038895de25d268792274b90702 100644 --- a/tangostationcontrol/tangostationcontrol/devices/recv.py +++ b/tangostationcontrol/tangostationcontrol/devices/recv.py @@ -22,10 +22,10 @@ import numpy # Additional import from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.common.lofar_logging import device_logging_to_python +from tangostationcontrol.common.states import DEFAULT_COMMAND_STATES from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper from tangostationcontrol.devices.device_decorators import only_in_states from tangostationcontrol.devices.opcua_device import opcua_device -from tangostationcontrol.devices.lofar_device import lofar_device import logging logger = logging.getLogger() @@ -194,9 +194,9 @@ class RECV(opcua_device): ~self.read_attribute("RCU_ADC_locked_R") ) - RECV_IOUT_error_R = attribute(dtype=(bool,), max_dim_x=96) - RECV_TEMP_error_R = attribute(dtype=(bool,), max_dim_x=32, polling_period=1000) - RECV_VOUT_error_R = attribute(dtype=(bool,), max_dim_x=96) + RECV_IOUT_error_R = attribute(dtype=(bool,), max_dim_x=96, fisallowed="is_attribute_access_allowed") + RECV_TEMP_error_R = attribute(dtype=(bool,), max_dim_x=32, fisallowed="is_attribute_access_allowed", polling_period=1000) + RECV_VOUT_error_R = attribute(dtype=(bool,), max_dim_x=32, fisallowed="is_attribute_access_allowed") def read_RECV_IOUT_error_R(self): return self.read_attribute("ANT_mask_RW") & ( @@ -281,7 +281,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def RCU_off(self): """ @@ -291,7 +291,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def RCU_on(self): """ @@ -301,7 +301,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def RCU_DTH_off(self): """ @@ -311,7 +311,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def RCU_DTH_on(self): """ diff --git a/tangostationcontrol/tangostationcontrol/devices/unb2.py b/tangostationcontrol/tangostationcontrol/devices/unb2.py index 1725acc4002c2d84f9bec0553b3ceb18db4095a2..3168621529a30a3c9b9690f2a07883ae04a965db 100644 --- a/tangostationcontrol/tangostationcontrol/devices/unb2.py +++ b/tangostationcontrol/tangostationcontrol/devices/unb2.py @@ -19,8 +19,8 @@ from tango import AttrWriteType, DebugIt from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper from tangostationcontrol.devices.opcua_device import opcua_device -from tangostationcontrol.devices.lofar_device import lofar_device from tangostationcontrol.common.lofar_logging import device_logging_to_python +from tangostationcontrol.common.states import DEFAULT_COMMAND_STATES from tangostationcontrol.devices.device_decorators import only_in_states import numpy @@ -204,7 +204,7 @@ class UNB2(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def UNB2_off(self): """ @@ -214,7 +214,7 @@ class UNB2(opcua_device): @command() @DebugIt() - @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) + @only_in_states(DEFAULT_COMMAND_STATES) def UNB2_on(self): """ diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_temperature_manager.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_temperature_manager.py index 7944ac7434b94ad2268f642a711470ac2190640f..4ba379bb19e6e25c0406cec3301d77137719c317 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_temperature_manager.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_temperature_manager.py @@ -9,7 +9,6 @@ from .base import AbstractTestBases from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy from tango._tango import DevState -from tango import DeviceProxy import time @@ -59,8 +58,8 @@ class TestDeviceTemperatureManager(AbstractTestBases.TestDeviceBase): self.proxy.initialise() self.proxy.on() - devices = [DeviceProxy("STAT/SDP/1"), DeviceProxy("STAT/UNB2/1"), DeviceProxy("STAT/RECV/1"), - DeviceProxy("STAT/APSCT/1"), DeviceProxy("STAT/APSPU/1"), DeviceProxy("STAT/PSOC/1")] + devices = [TestDeviceProxy("STAT/SDP/1"), TestDeviceProxy("STAT/UNB2/1"), self.recv_proxy, + TestDeviceProxy("STAT/APSCT/1"), TestDeviceProxy("STAT/APSPU/1"), TestDeviceProxy("STAT/PSOC/1")] # make sure none of the devices are in the OFF state. Any other state is fine for dev in devices: