# -*- coding: utf-8 -*- # # This file is part of the CspSubElementMaster project # # INAF-SKA Telescope # # Distributed under the terms of the GPL license. # See LICENSE.txt for more info. """ CSP.LMC Sub-element Master A base class for the Master of a SKA Sub-element. """ # PyTango imports import tango from tango import DebugIt from tango.server import run from tango.server import Device from tango.server import attribute, command from tango.server import device_property from tango import AttrQuality, DispLevel, DevState from tango import AttrWriteType, PipeWriteType from collections import defaultdict # Additional import # PROTECTED REGION ID(CspSubElementMaster.additionnal_import) ENABLED START # from ska.base import SKAMaster from ska.base.control_model import HealthState, AdminMode, LoggingLevel from csp_lmc_common.utils.cspcommons import CmdExecState from csp_lmc_common.utils.decorators import AdminModeCheck from .decorators import IsCommandAllowed from . import release # PROTECTED REGION END # // CspSubElementMaster.additionnal_import __all__ = ["CspSubElementMaster", "main"] class CspSubElementMaster(SKAMaster): """ A base class for the Master of a SKA Sub-element. **Properties:** - Device Property Racks - The list with the FQDNs of the sub-element racks devices. - Type:'DevVarStringArray' """ # PROTECTED REGION ID(CspSubElementMaster.class_variable) ENABLED START # # PROTECTED REGION END # // CspSubElementMaster.class_variable # ----------------- # Device Properties # ----------------- Racks = device_property( dtype='DevVarStringArray', ) # ---------- # Attributes # ---------- numOfDevCompletedTask = attribute( dtype='DevUShort', label="Number of devices that completed the task", doc="Number of devices that completed the task", ) onCmdFailure = attribute( dtype='DevBoolean', label="CBF command failure flag", #polling_period=1000, doc="Failure flag set when the On command fails with error(s).", ) onFailureMessage = attribute( dtype='DevString', label="On execution failure message", doc="Failure message when the On command fails with error(s).", ) offCmdFailure = attribute( dtype='DevBoolean', label="Off execution failure flag", doc="Failure flag set when the Off command fails with error(s).", ) offFailureMessage = attribute( dtype='DevString', label="Off execution failure message", doc="Failure message when the Off command fails with error(s).", ) standbyCmdFailure = attribute( dtype='DevBoolean', label="Standby execution failure message", doc="Failure flag set when the Standby command fails with error(s).", ) standbyFailureMessage = attribute( dtype='DevString', label="Standby execution failure message", doc="Failure message when the Standby command fails with error(s).", ) adminMode = attribute( dtype=AdminMode, access=AttrWriteType.READ_WRITE, memorized=True, doc="The admin mode reported for this device. It may interpret the current device condition \nand condition of all managed devices to set this. Most possibly an aggregate attribute.", ) onCommandProgress = attribute( dtype='DevUShort', label="Progress percentage for the On command", abs_change=10, max_value=100, min_value=0, doc="Percentage progress implemented for commands that result in state/mode transitions for a large \nnumber of components and/or are executed in stages (e.g power up, power down)", ) offCommandProgress = attribute( dtype='DevUShort', label="Progress percentage for the Off command", abs_change=10, max_value=100, min_value=0, doc="Percentage progress implemented for commands that result in state/mode transitions for a large \nnumber of components and/or are executed in stages (e.g power up, power down)", ) standbyCommandProgress = attribute( dtype='DevUShort', label="Progress percentage for the Standby command", abs_change=10, max_value=100, min_value=0, doc="Percentage progress implemented for commands that result in state/mode transitions for a large \nnumber of components and/or are executed in stages (e.g power up, power down)", ) onCmdDurationExpected = attribute( dtype='DevUShort', access=AttrWriteType.READ_WRITE, label="Expected duration (sec) of the On command execution", abs_change=0, max_value=100, min_value=0, memorized=True, doc="Set/Report the duration expected for the On command execution", ) offCmdDurationExpected = attribute( dtype='DevUShort', access=AttrWriteType.READ_WRITE, label="Expected duration (sec) of the Off command", abs_change=0, max_value=100, min_value=0, memorized=True, doc="Set/Report the duration expected for the Off command execution", ) standbyCmdDurationExpected = attribute( dtype='DevUShort', access=AttrWriteType.READ_WRITE, label="Expected duration (sec) of the Standby command", abs_change=0, max_value=100, min_value=0, memorized=True, doc="Set/Report the duration expected for the Standby command", ) onCmdDurationMeasured = attribute( dtype='DevUShort', label="Measured duration (sec) of the On command execution", abs_change=0, max_value=100, min_value=0, doc="Report the measured duration of the On command execution", ) offCmdDurationMeasured = attribute( dtype='DevUShort', label="Measured duration (sec) of the Off command", abs_change=0, max_value=100, min_value=0, doc="Report the measured duration of the Off command execution", ) standbyCmdDurationMeasured = attribute( dtype='DevUShort', label="Measured duration (sec) of the Standby command", abs_change=0, max_value=100, min_value=0, doc="Report the measured duration of the Standby command", ) onCmdTimeoutExpired = attribute( dtype='DevBoolean', label="On execution timeout flag", doc="Signal the occurence of a timeout during the execution of the on command.", ) offCmdTimeoutExpired = attribute( dtype='DevBoolean', label="Off execution timeout flag", doc="Signal the occurence of a timeout during the execution of the Off command.", ) standbyCmdTimeoutExpired = attribute( dtype='DevBoolean', label="Standby execution timeout flag.", doc="Signal the occurence of a timeout during the execution of the Standby command.", ) listOfDevCompletedTask = attribute( dtype=('DevString',), max_dim_x=100, label="List of devices that completed the task", doc="List of devices that completed the task", ) listOfComponents = attribute( dtype=('DevString',), max_dim_x=100, label="List of sub-element components", doc="The list o the FQDNs of the sub-element components.", ) # --------------- # General methods # --------------- def init_device(self): """Initialises the attributes and properties of the CspSubElementMaster.""" SKAMaster.init_device(self) self.set_state(tango.DevState.INIT) # PROTECTED REGION ID(CspSubElementMaster.init_device) ENABLED START # # PROTECTED REGION ID(CspSubElementMaster.init_device) ENABLED START # # _cmd_execution_state: implement the execution state of a long-running # command for the whole CSP. Setting this attribute prevent the execution # of the same command while it is already running. # implemented as a default dictionary: # keys: command name # values:command state self._cmd_execution_state = defaultdict(lambda: CmdExecState.IDLE) # _cmd_progress: report the execution progress of a long-running command # implemented as a dictionary: # keys: command name ('on', 'off'..) # values: the percentage self._cmd_progress = defaultdict(lambda: 0) # _cmd_duration_expected: store the duration (in sec.) configured for # a long-running command # Implemented asdefault dictionary # keys: command name ('on', 'off',..) # values: the duration (in sec) self._cmd_duration_expected = defaultdict(lambda: 30) # _cmd_duration_measured: report the measured duration (in sec.) for # a long-running command # Implemented as default dictionary # keys: command name ('on', 'off',..) # values: the duration (in sec) self._cmd_duration_measured = defaultdict(lambda: 0) # _timeout_expired: report the timeout flag # Implemented as a dictionary # keys: command name ('on', 'off', 'standby'..) # values: True/False self._timeout_expired = defaultdict(lambda: False) # _failure_raised: report the failure flag # Implemented as a dictionary # keys: command name ('on', 'off', 'standby'..) # values: True/False self._failure_raised = defaultdict(lambda: False) # _failure_message: report the failure message # Implemented as a dictionary # keys: command name ('on', 'off', 'standby'..) # values: the message self._failure_message = defaultdict(lambda: '') # _list_dev_completed_task: for each long-running command report the list # of subordinate sub-element components that completed the task # Implemented as a dictionary # keys: the command name ('on', 'off',...) # values: the list of components self._list_dev_completed_task = defaultdict(lambda: []) # _list_of_components: report the list of subordinate # sub-element components. # Implemented as a list of FQDNs self._list_of_components = [] # _num_dev_completed_task: for each long-running command report the number # of subordinate components that completed the task # Implemented as a dictionary # keys: the command name ('on', 'off',...) # values: the number of components self._num_dev_completed_task = defaultdict(lambda:0) # the last executed command self._last_executed_command = "none" # PROTECTED REGION END # // CspSubElementMaster.init_device def always_executed_hook(self): """Method always executed before any TANGO command is executed.""" # PROTECTED REGION ID(CspSubElementMaster.always_executed_hook) ENABLED START # # PROTECTED REGION END # // CspSubElementMaster.always_executed_hook 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. """ # PROTECTED REGION ID(CspSubElementMaster.delete_device) ENABLED START # # PROTECTED REGION END # // CspSubElementMaster.delete_device # ------------------ # Attributes methods # ------------------ def read_numOfDevCompletedTask(self): # PROTECTED REGION ID(CspSubElementMaster.numOfDevCompletedTask_read) ENABLED START # """Return the numOfDevCompletedTask attribute.""" return self._num_dev_completed_task[self._last_executed_command] # PROTECTED REGION END # // CspSubElementMaster.numOfDevCompletedTask_read def read_onCmdFailure(self): # PROTECTED REGION ID(CspSubElementMaster.onCmdFailure_read) ENABLED START # """Return the onCmdFailure attribute.""" return self._failure_raised['on'] # PROTECTED REGION END # // CspSubElementMaster.onCmdFailure_read def read_onFailureMessage(self): # PROTECTED REGION ID(CspSubElementMaster.onFailureMessage_read) ENABLED START # """Return the onFailureMessage attribute.""" return self._failure_message['on'] # PROTECTED REGION END # // CspSubElementMaster.onFailureMessage_read def read_offCmdFailure(self): # PROTECTED REGION ID(CspSubElementMaster.offCmdFailure_read) ENABLED START # """Return the offCmdFailure attribute.""" return self._failure_raised['off'] # PROTECTED REGION END # // CspSubElementMaster.offCmdFailure_read def read_offFailureMessage(self): # PROTECTED REGION ID(CspSubElementMaster.offFailureMessage_read) ENABLED START # """Return the offFailureMessage attribute.""" return self._failure_message['off'] # PROTECTED REGION END # // CspSubElementMaster.offFailureMessage_read def read_standbyCmdFailure(self): # PROTECTED REGION ID(CspSubElementMaster.standbyCmdFailure_read) ENABLED START # """Return the standbyCmdFailure attribute.""" return self._failure_raised['standby'] # PROTECTED REGION END # // CspSubElementMaster.standbyCmdFailure_read def read_standbyFailureMessage(self): # PROTECTED REGION ID(CspSubElementMaster.standbyFailureMessage_read) ENABLED START # """Return the standbyFailureMessage attribute.""" return self._failure_message['standby'] # PROTECTED REGION END # // CspSubElementMaster.standbyFailureMessage_read def read_adminMode(self): # PROTECTED REGION ID(CspSubElementMaster.adminMode_read) ENABLED START # """Return the adminMode attribute.""" return self._admin_mode # PROTECTED REGION END # // CspSubElementMaster.adminMode_read def write_adminMode(self, value): # PROTECTED REGION ID(CspSubElementMaster.adminMode_write) ENABLED START # """Set the adminMode attribute.""" self._admin_mode = value if self._admin_mode not in [AdminMode.ONLINE, AdminMode.MAINTENANCE]: self.set_state(tango.DevState.DISABLE) # PROTECTED REGION END # // CspSubElementMaster.adminMode_write def read_onCommandProgress(self): # PROTECTED REGION ID(CspSubElementMaster.onCommandProgress_read) ENABLED START # """Return the onCommandProgress attribute.""" return self._cmd_progress['on'] # PROTECTED REGION END # // CspSubElementMaster.onCommandProgress_read def read_offCommandProgress(self): # PROTECTED REGION ID(CspSubElementMaster.offCommandProgress_read) ENABLED START # """Return the offCommandProgress attribute.""" return self._cmd_progress['off'] # PROTECTED REGION END # // CspSubElementMaster.offCommandProgress_read def read_standbyCommandProgress(self): # PROTECTED REGION ID(CspSubElementMaster.standbyCommandProgress_read) ENABLED START # """Return the standbyCommandProgress attribute.""" return self._cmd_progress['standby'] # PROTECTED REGION END # // CspSubElementMaster.standbyCommandProgress_read def read_onCmdDurationExpected(self): # PROTECTED REGION ID(CspSubElementMaster.onCmdDurationExpected_read) ENABLED START # """Return the onCmdDurationExpected attribute.""" return self._cmd_duration_expected['on'] # PROTECTED REGION END # // CspSubElementMaster.onCmdDurationExpected_read def write_onCmdDurationExpected(self, value): # PROTECTED REGION ID(CspSubElementMaster.onCmdDurationExpected_write) ENABLED START # """Set the onCmdDurationExpected attribute.""" self._cmd_duration_expected['on'] = value # PROTECTED REGION END # // CspSubElementMaster.onCmdDurationExpected_write def read_offCmdDurationExpected(self): # PROTECTED REGION ID(CspSubElementMaster.offCmdDurationExpected_read) ENABLED START # """Return the offCmdDurationExpected attribute.""" return self._cmd_duration_expected['off'] # PROTECTED REGION END # // CspSubElementMaster.offCmdDurationExpected_read def write_offCmdDurationExpected(self, value): # PROTECTED REGION ID(CspSubElementMaster.offCmdDurationExpected_write) ENABLED START # """Set the offCmdDurationExpected attribute.""" self._cmd_duration_expected['off'] = value # PROTECTED REGION END # // CspSubElementMaster.offCmdDurationExpected_write def read_standbyCmdDurationExpected(self): # PROTECTED REGION ID(CspSubElementMaster.standbyCmdDurationExpected_read) ENABLED START # """Return the standbyCmdDurationExpected attribute.""" return self._cmd_duration_expected['standby'] # PROTECTED REGION END # // CspSubElementMaster.standbyCmdDurationExpected_read def write_standbyCmdDurationExpected(self, value): # PROTECTED REGION ID(CspSubElementMaster.standbyCmdDurationExpected_write) ENABLED START # """Set the standbyCmdDurationExpected attribute.""" self._cmd_duration_expected['standby'] = value # PROTECTED REGION END # // CspSubElementMaster.standbyCmdDurationExpected_write def read_onCmdDurationMeasured(self): # PROTECTED REGION ID(CspSubElementMaster.onCmdDurationMeasured_read) ENABLED START # """Return the onCmdDurationMeasured attribute.""" return self._cmd_duration_measured['on'] # PROTECTED REGION END # // CspSubElementMaster.onCmdDurationMeasured_read def read_offCmdDurationMeasured(self): # PROTECTED REGION ID(CspSubElementMaster.offCmdDurationMeasured_read) ENABLED START # """Return the offCmdDurationMeasured attribute.""" return self._cmd_duration_measured['off'] # PROTECTED REGION END # // CspSubElementMaster.offCmdDurationMeasured_read def read_standbyCmdDurationMeasured(self): # PROTECTED REGION ID(CspSubElementMaster.standbyCmdDurationMeasured_read) ENABLED START # """Return the standbyCmdDurationMeasured attribute.""" return self._cmd_duration_measured['standby'] # PROTECTED REGION END # // CspSubElementMaster.standbyCmdDurationMeasured_read def read_onCmdTimeoutExpired(self): # PROTECTED REGION ID(CspSubElementMaster.onCmdTimeoutExpired_read) ENABLED START # """Return the onCmdTimeoutExpired attribute.""" return self._timeout_expired['on'] # PROTECTED REGION END # // CspSubElementMaster.onCmdTimeoutExpired_read def read_offCmdTimeoutExpired(self): # PROTECTED REGION ID(CspSubElementMaster.offCmdTimeoutExpired_read) ENABLED START # """Return the offCmdTimeoutExpired attribute.""" return self._timeout_expired['off'] # PROTECTED REGION END # // CspSubElementMaster.offCmdTimeoutExpired_read def read_standbyCmdTimeoutExpired(self): # PROTECTED REGION ID(CspSubElementMaster.standbyCmdTimeoutExpired_read) ENABLED START # """Return the standbyCmdTimeoutExpired attribute.""" return self._timeout_expired['standby'] # PROTECTED REGION END # // CspSubElementMaster.standbyCmdTimeoutExpired_read def read_listOfDevCompletedTask(self): # PROTECTED REGION ID(CspSubElementMaster.listOfDevCompletedTask_read) ENABLED START # """Return the listOfDevCompletedTask attribute.""" return self._list_dev_completed_task[self._last_executed_command] # PROTECTED REGION END # // CspSubElementMaster.listOfDevCompletedTask_read def read_listOfComponents(self): # PROTECTED REGION ID(CspSubElementMaster.listOfComponents_read) ENABLED START # """Return the listOfComponents attribute.""" return self._list_of_components # PROTECTED REGION END # // CspSubElementMaster.listOfComponents_read # -------- # Commands # -------- @command( dtype_in='DevVarStringArray', doc_in="The list of sub-element components FQDNs to switch-on or an empty list to switch-on the whole " "CSP Sub-element." " " "If the array length is 0, the command applies to the whole CSP Sub-Element. If the " "array length is > 1, each array element specifies the FQDN of the" "CSP SubElement component to switch ON.", ) @DebugIt() @IsCommandAllowed() @AdminModeCheck('On') def On(self, argin): # PROTECTED REGION ID(CspSubElementMaster.On) ENABLED START # """ Switch-on the CSP sub-element components specified by the input argument. If no argument is specified, the command is issued on all the CSP sub-element components. The command is executed if the *AdminMode* is ONLINE or *MAINTENANCE*. If the AdminMode is *OFFLINE*, *NOT-FITTED* or *RESERVED*, the method throws an exception. :param argin: 'DevVarStringArray' The list of sub-element components FQDNs to switch-on or an empty list to switch-on the whole CSP Sub-element. If the array length is 0, the command applies to the whole CSP Sub-Element. If the array length is > 1, each array element specifies the FQDN of the CSP SubElement component to switch ON. :return:None """ pass # PROTECTED REGION END # // CspSubElementMaster.On @command( dtype_in='DevVarStringArray', doc_in="If the array length is 0, the command applies to the whole" "CSP Sub-element." "If the array length is > 1, each array element specifies the FQDN of the" "CSP SubElement component to switch OFF.", ) @DebugIt() @IsCommandAllowed() @AdminModeCheck('Off') def Off(self, argin): # PROTECTED REGION ID(CspSubElementMaster.Off) ENABLED START # """ Switch-off the CSP sub-element components specified by the input argument. If no argument is specified, the command is issued to all the CSP sub-element components. :param argin: 'DevVarStringArray' If the array length is 0, the command applies to the whole CSP Sub-element. If the array length is > 1, each array element specifies the FQDN of the CSP SubElement component to switch OFF. :return:None """ pass # PROTECTED REGION END # // CspSubElementMaster.Off @command( dtype_in='DevVarStringArray', doc_in="If the array length is 0, the command applies to the whole" "CSP sub-element." "If the array length is > 1, each array element specifies the FQDN of the" "CSP SubElement icomponent to put in STANDBY mode.", ) @DebugIt() @IsCommandAllowed() @AdminModeCheck('Standby') def Standby(self, argin): # PROTECTED REGION ID(CspSubElementMaster.Standby) ENABLED START # """ Transit the CSP Sub-element or one or more CSP SubElement components from ON/OFF to STANDBY. :param argin: 'DevVarStringArray' If the array length is 0, the command applies to the whole CSP sub-element. If the array length is > 1, each array element specifies the FQDN of the CSP SubElement icomponent to put in STANDBY mode. :return:None """ pass # PROTECTED REGION END # // CspSubElementMaster.Standby @command( ) @DebugIt() def Upgrade(self): # PROTECTED REGION ID(CspSubElementMaster.Upgrade) ENABLED START # """ :return:None """ pass # PROTECTED REGION END # // CspSubElementMaster.Upgrade # ---------- # Run server # ---------- def main(args=None, **kwargs): """Main function of the CspSubElementMaster module.""" # PROTECTED REGION ID(CspSubElementMaster.main) ENABLED START # return run((CspSubElementMaster,), args=args, **kwargs) # PROTECTED REGION END # // CspSubElementMaster.main if __name__ == '__main__': main()