diff --git a/tangostationcontrol/tangostationcontrol/devices/apsct.py b/tangostationcontrol/tangostationcontrol/devices/apsct.py index dd8bd1c2a7698d2c2481dbb52d60e99541f7e43b..75ef8f612b3bfd44735444fba95d8927226fe55a 100644 --- a/tangostationcontrol/tangostationcontrol/devices/apsct.py +++ b/tangostationcontrol/tangostationcontrol/devices/apsct.py @@ -14,7 +14,7 @@ # PyTango imports from tango import DebugIt from tango.server import command, attribute, device_property -from tango import AttrWriteType, DevState +from tango import AttrWriteType import numpy # Additional import @@ -23,6 +23,7 @@ from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.common.lofar_logging import device_logging_to_python from tangostationcontrol.devices.device_decorators import * from tangostationcontrol.devices.opcua_device import opcua_device +from tangostationcontrol.devices.lofar_device import lofar_device import logging logger = logging.getLogger() @@ -138,7 +139,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def APSCT_off(self): """ @@ -148,7 +149,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def APSCT_200MHz_on(self): """ @@ -158,7 +159,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def APSCT_160MHz_on(self): """ diff --git a/tangostationcontrol/tangostationcontrol/devices/boot.py b/tangostationcontrol/tangostationcontrol/devices/boot.py index 59427165c20f5c8f9a65e9f59b0d85c4a3fa8837..47dcc3741e2f5e72aa3bb7fa2c6fb35f551d9fdc 100644 --- a/tangostationcontrol/tangostationcontrol/devices/boot.py +++ b/tangostationcontrol/tangostationcontrol/devices/boot.py @@ -153,7 +153,7 @@ class DevicesInitialiser(object): continue if self.is_available(device): - if self.reboot or self.devices[device].state() not in [DevState.ON, DevState.ALARM]: + if self.reboot or self.devices[device].state() not in lofar_device.OPERATIONAL_STATES: self.stop_device(device) self.boot_device(device) @@ -204,7 +204,7 @@ class DevicesInitialiser(object): else: proxy.warm_boot() - if proxy.state() not in [DevState.ON, DevState.ALARM]: # ALARM still means booting was succesful + if proxy.state() not in lofar_device.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.") @@ -313,14 +313,14 @@ class Boot(lofar_device): @command() @DebugIt() - @only_in_states([DevState.ON]) + @only_in_states(lofar_device.OPERATIONAL_STATES) @log_exceptions() def boot(self): self._boot(reboot=False, initialise_hardware=self.Initialise_Hardware) @command() @DebugIt() - @only_in_states([DevState.ON]) + @only_in_states(lofar_device.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 50368d15d59fd94794edfaafdb2c451513b60b24..cc276428d962fa006d2ef0619790b65c1f2ba270 100644 --- a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py @@ -41,6 +41,7 @@ class lofar_device(Device, metaclass=DeviceMeta): INIT = Device is initialising. STANDBY = Device is initialised, but pends external configuration and an explicit turning on, ON = Device is fully configured, functional, controls the hardware, and is possibly actively running, + ALARM = Device is operating but one of its attributes is out of range, FAULT = Device detected an unrecoverable error, and is thus malfunctional, OFF = Device is turned off, drops connection to the hardware, @@ -49,6 +50,7 @@ class lofar_device(Device, metaclass=DeviceMeta): OFF -> INIT: Triggered by device. Device will initialise (connect to hardware, other devices), INIT -> STANDBY: Triggered by device. Device is initialised, and is ready for additional configuration by the user, STANDBY -> ON: Triggered by user. Device reports to be functional, + ON -> ALARM: Triggered by tango. Device has attribute(s) with value(s) exceeding their alarm treshold, * -> FAULT: Triggered by device. Device has degraded to malfunctional, for example because the connection to the hardware is lost, * -> FAULT: Triggered by user. Emulate a forced malfunction for integration testing purposes, * -> OFF: Triggered by user. Device is turned off. Triggered by the Off() command, @@ -57,6 +59,17 @@ 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 # ---------- @@ -159,7 +172,7 @@ class lofar_device(Device, metaclass=DeviceMeta): self.set_status("Device is in the STANDBY state.") @command() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(INITIALISED_STATES) @DebugIt() @fault_on_error() @log_exceptions() @@ -204,7 +217,6 @@ class lofar_device(Device, metaclass=DeviceMeta): @command() - @only_in_states([DevState.ON, DevState.INIT, DevState.STANDBY, DevState.FAULT]) @DebugIt() @log_exceptions() def Fault(self, new_status="Device is in the FAULT state."): @@ -216,6 +228,9 @@ class lofar_device(Device, metaclass=DeviceMeta): :return:None """ + if self.get_state() == DevState.OFF: + raise Exception("IllegalCommand: Cannot go from FAULT -> OFF") + if self.get_state() == DevState.FAULT: # Already faulting. Don't complain. logger.warning("Requested to go to FAULT state, but am already in FAULT state.") @@ -272,7 +287,7 @@ class lofar_device(Device, metaclass=DeviceMeta): pass @command() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @DebugIt() @log_exceptions() def set_defaults(self): @@ -302,7 +317,7 @@ class lofar_device(Device, metaclass=DeviceMeta): self._set_defaults(attributes_to_set) - @only_in_states([DevState.STANDBY, DevState.INIT, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @fault_on_error() @command() def set_translator_defaults(self): @@ -311,7 +326,7 @@ class lofar_device(Device, metaclass=DeviceMeta): # This is just the command version of _set_translator_defaults(). self._set_translator_defaults() - @only_in_states([DevState.STANDBY, DevState.INIT, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @fault_on_error() @command() @DebugIt() @@ -321,7 +336,7 @@ class lofar_device(Device, metaclass=DeviceMeta): # This is just the command version of _prepare_hardware(). self._prepare_hardware() - @only_in_states([DevState.STANDBY, DevState.INIT, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @fault_on_error() @command() @DebugIt() @@ -331,7 +346,7 @@ class lofar_device(Device, metaclass=DeviceMeta): # This is just the command version of _initialise_hardware(). self._initialise_hardware() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @command(dtype_out = DevDouble) def max_archiving_load(self): """ Return the maximum archiving load for the device attributes """ diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py index 1c21c006221289d2847033f9830fef8760009c3e..ddac029a61102834374baa6d38745d59a0769739 100644 --- a/tangostationcontrol/tangostationcontrol/devices/recv.py +++ b/tangostationcontrol/tangostationcontrol/devices/recv.py @@ -16,7 +16,7 @@ from functools import partial from tango import DebugIt from tango.server import command from tango.server import device_property, attribute -from tango import AttrWriteType, DevState, DevVarFloatArray +from tango import AttrWriteType, DevVarFloatArray import numpy from math import pi @@ -29,6 +29,7 @@ from tangostationcontrol.common.lofar_logging import device_logging_to_python from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper from tangostationcontrol.devices.device_decorators import * from tangostationcontrol.devices.opcua_device import opcua_device +from tangostationcontrol.devices.lofar_device import lofar_device import logging logger = logging.getLogger() @@ -372,7 +373,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def RCU_off(self): """ @@ -382,7 +383,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def RCU_on(self): """ @@ -392,7 +393,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def RCU_DTH_off(self): """ @@ -402,7 +403,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def RCU_DTH_on(self): """ diff --git a/tangostationcontrol/tangostationcontrol/devices/tilebeam.py b/tangostationcontrol/tangostationcontrol/devices/tilebeam.py index aa83c96f142dae5e8dac24767f50cf89e38c6a7a..b31a1aaa6c5050dd2377ffe3b7fdbbee4e42f40f 100644 --- a/tangostationcontrol/tangostationcontrol/devices/tilebeam.py +++ b/tangostationcontrol/tangostationcontrol/devices/tilebeam.py @@ -12,7 +12,7 @@ import datetime from json import loads from threading import Thread, Lock, Condition -from tango import AttrWriteType, DebugIt, DevState, DeviceProxy, DevVarStringArray, DevVarDoubleArray, DevString, DevSource +from tango import AttrWriteType, DebugIt, DeviceProxy, DevVarStringArray, DevVarDoubleArray, DevString, DevSource from tango.server import attribute, command, device_property from tango import Util @@ -258,7 +258,7 @@ class TileBeam(lofar_device): @command(dtype_in=DevVarStringArray, dtype_out=DevVarDoubleArray) @DebugIt() @log_exceptions() - @only_in_states([DevState.ON, DevState.STANDBY]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def HBAT_delays(self, pointing_direction: numpy.array, timestamp: datetime.datetime = None): """ Calculate the delays (in seconds) based on the pointing list and the timestamp @@ -279,7 +279,7 @@ class TileBeam(lofar_device): @command(dtype_in=DevVarStringArray) @DebugIt() @log_exceptions() - @only_in_states([DevState.ON, DevState.STANDBY]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def HBAT_set_pointing(self, pointing_direction: list, timestamp: datetime.datetime = None): """ Uploads beam weights based on a given pointing direction 2D array (96 tiles x 3 parameters) @@ -297,7 +297,7 @@ class TileBeam(lofar_device): @command(dtype_in = DevString) @DebugIt() - @only_in_states([DevState.ON, DevState.STANDBY]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def HBAT_set_pointing_for_specific_time(self, parameters: DevString = None): """ Uploads beam weights based on a given pointing direction 2D array (96 tiles x 3 parameters) diff --git a/tangostationcontrol/tangostationcontrol/devices/unb2.py b/tangostationcontrol/tangostationcontrol/devices/unb2.py index 614055a716ce8a527197aaad159273ebfda220ef..a255cd7a25358e38ed8d807476b5786596acd773 100644 --- a/tangostationcontrol/tangostationcontrol/devices/unb2.py +++ b/tangostationcontrol/tangostationcontrol/devices/unb2.py @@ -13,12 +13,13 @@ # PyTango imports from tango.server import command, attribute, device_property -from tango import AttrWriteType, DebugIt, DevState +from tango import AttrWriteType, DebugIt # Additional import 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.devices.device_decorators import only_in_states @@ -203,7 +204,7 @@ class UNB2(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def UNB2_off(self): """ @@ -213,7 +214,7 @@ class UNB2(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def UNB2_on(self): """