Commit b5e4b82a authored by Elisabetta Giani's avatar Elisabetta Giani
Browse files

CT-57: Add RemoveReceptors command class.

parent 10dca534
Loading
Loading
Loading
Loading
Loading
+142 −101
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ from tango import AttrWriteType, DeviceProxy
# Additional import
# PROTECTED REGION ID(MidCspSubarray.additional_import) ENABLED START #
#from ska.base import SKAMaster
from ska.base.commands import ResponseCommand, ResultCode
from ska.base.commands import ActionCommand, ResponseCommand, ResultCode
from ska.base.faults import CapabilityValidationError
from ska.base.control_model import HealthState, AdminMode, ObsState
# import CSP.LMC Common package
@@ -50,18 +50,38 @@ from csp_lmc_common.CspSubarray import CspSubarray, CspSubarrayStateModel
__all__ = ["MidCspSubarrayBase", "main"]

class MidCspSubarrayStateModel(CspSubarrayStateModel):
    _subarray_transitions = {
            ('EMPTY', 'add_receptors_succeeded'): (
    _mid_subarray_transitions = {
        ('RESOURCING', 'add_receptors_succeeded'): (
        "IDLE",
        lambda self: self._set_dev_state(ObsState.IDLE)
        lambda self: self._set_obs_state(ObsState.IDLE)
        ),
        ('EMPTY', 'add_receptors_started'): (
        "RESOURCING",
        lambda self: self._set_dev_state(ObsState.RESOURCING)
        lambda self: self._set_obs_state(ObsState.RESOURCING)
        ),
    ('EMPTY', 'add_receptor_failed'): (
     ('IDLE', 'add_receptors_started'): (
        "RESOURCING",
        lambda self: self._set_obs_state(ObsState.RESOURCING)
    ),
    ('EMPTY', 'add_receptors_failed'): (
        "OBSFAULT",
        lambda self: self._set_dev_state(DevState.FAULT)
    ),
    ('IDLE', 'add_receptors_failed'): (
        "OBSFAULT",
        lambda self: self._set_dev_state(DevState.FAULT)
    ),
     ('IDLE', 'remove_receptors_started'): (
        "RESOURCING",
        lambda self: self._set_obs_state(ObsState.RESOURCING)
    ),
    ('IDLE', 'remove_receptors_failed'): (
        "OBSFAULT",
        lambda self: self._set_dev_state(DevState.FAULT)
    ),
        ('RESOURCING', 'remove_receptors_succeeded'): (
        "IDLE",
        lambda self: self._set_obs_state(ObsState.IDLE)
    ),
    }

@@ -73,7 +93,7 @@ class MidCspSubarrayStateModel(CspSubarrayStateModel):
        super().__init__(
            dev_state_callback=dev_state_callback,
        )
        self.update_transitions(self._subarray_transitions)
        self.update_transitions(self._mid_subarray_transitions)

class MidCspSubarrayBase(CspSubarray):
    """
@@ -123,7 +143,13 @@ class MidCspSubarrayBase(CspSubarray):
            self.logger.info("On eseguito nel MID")
            return (ResultCode.OK, "On exeguito correttamente")

    class AddReceptorsCommand(ResponseCommand):
    class AddReceptorsCommand(ActionCommand):
        def __init__(self, target, state_model, logger=None):

            super().__init__(
                target, state_model, "add_receptors", start_action=True, logger=logger
            )

        def do(self, argin):
            device = self.target
            # PROTECTED REGION ID(CspSubarray.AddReceptors) ENABLED START #
@@ -161,18 +187,16 @@ class MidCspSubarrayBase(CspSubarray):
                    log_msg = "No available receptor to add to subarray {}".format(
                        device.SubID)
                    self.logger.warning(log_msg)
                    return
                    return (ResultCode.OK, "AddREsources OK")
                receptor_membership = csp_master_proxy.receptorMembership
            except tango.DevFailed as df:
                msg = "Failure in getting receptors information:" + \
                    str(df.args[0].reason)
                tango.Except.throw_exception("Command failed", msg,
                                             "AddReceptors", tango.ErrSeverity.ERR)
                return (ResultCode.FAILED, msg)
            except AttributeError as attr_err:
                msg = "Failure in reading {}: {}".format(
                    str(attr_err.args[0]), attr_err.__doc__)
                tango.Except.throw_exception("Command failed", msg,
                                             "AddReceptors", tango.ErrSeverity.ERR)
                return (ResultCode.FAILED, msg)
            for receptorId in argin:
                # check if the specified receptor id is a valid number (that is, belongs to the list
                # of provided receptors)
@@ -194,17 +218,14 @@ class MidCspSubarrayBase(CspSubarray):
            if not receptor_to_assign:
                log_msg = "No receptors to assign to the subarray"
                self.logger.info(log_msg)
                return
                return (ResultCode.OK, log_msg)

            # check if the CbfSubarray TANGO device is already running
            # and the proxy registered
            if not device._is_sc_subarray_running(device.CbfSubarray):
                log_msg = "Device {} is not running!".format(str(device.CbfSubarray))
                self.logger.error(log_msg)
                tango.Except.throw_exception("Command failed",
                                             log_msg,
                                             "AddReceptors",
                                             tango.ErrSeverity.ERR)
                return (ResultCode.FAILED, log_msg)
            proxy = device._sc_subarray_proxies[device.CbfSubarray]
            # remove possible receptor repetition
            tmp = set(receptor_to_assign)
@@ -230,6 +251,93 @@ class MidCspSubarrayBase(CspSubarray):
                return (ResultCode.FAILED, "Failure in AddReceptors")

            # PROTECTED REGION END #    //  MidCspSubarrayBase.AddReceptors
        #def succeeded(self):
        #    self.logger.info("Eccomi")
        #    action = "add_receptors_succeeded"
        #    self.state_model.perform_action(action)
        #    self.logger.info("ObsState:{}".format(self.state_model.obs_state))


    class RemoveReceptorsCommand(ActionCommand):
        def __init__(self, target, state_model, logger=None):

            super().__init__(
                target, state_model, "remove_receptors", start_action=True, logger=logger
            )
        def do(self, argin):
            device = self.target
            # check if the CspSubarray is already connected to the CbfSubarray
            if not device._is_sc_subarray_running(device.CbfSubarray):
                log_msg = "Subarray {} not registered!".format( str(device.CbfSubarray))
                self.logger.error(log_msg)
                return (ResultCode.FAILED, log_msg)
            try:
                proxy = device._sc_subarray_proxies[device.CbfSubarray]
                # read from CbfSubarray the list of assigned receptors
                # failure in reading attribute raises an AttributeError (not tangoDevFailed!!)
                receptors = proxy.receptors
                #!!!!!!!!!!!!!!!!!
                # 2019-09-20:  New images for TANGO and PyTango images has been released. PyTango
                # is now compiled with th numpy support. In this case the proxy.receptors call
                # does no more return an empty tuple but an empty numpy array.
                # Checks on receptors content need to be changed (see below)
                # NB: the receptors attribute implemented by the CbfSubarray is declared as RW.
                # In this case the read method returns an empty numpy array ([]) whose length is 0.
                #!!!!!!!!!!!!!!!!!

                # check if the list of assigned receptors is empty
                if len(receptors):
                    receptors_to_remove = []
                    # check if the receptors to remove belong to the subarray
                    for receptor_id in argin:
                        if receptor_id in receptors:
                            receptors_to_remove.append(receptor_id)
                    if any(receptors_to_remove):
                        # TODO: add reading of CbfSubarray removeReceptorsCmdDurationExpected
                        # attribute, if implemented, otherwise use the default value

                        # subscribes attributes to track progress and timeout: if these
                        # attributes are not implemented at CbfSubarray level, the warning
                        # is only logged because is not a fatal error.
                        for attr in ['removeReceptorsCmdProgress', 'timeoutExpiredFlag']:
                            try:
                                if device._sc_subarray_event_id[device.CbfSubarray][attr.lower()] == 0:
                                    evt_id = proxy.subscribe_event(attr, tango.EventType.CHANGE_EVENT,
                                                                   device._attributes_change_evt_cb, stateless=False)
                                    device._sc_subarray_event_id[device.CbfSubarray][attr.lower()] = evt_id
                            except tango.DevFailed as tango_err:
                                self.logger.info(tango_err.args[0].desc)
                        # forward the command to CbfSubarray
                        proxy.command_inout_asynch("RemoveReceptors", receptors_to_remove, device._cmd_ended_cb)
                        if device._cmd_execution_state['removereceptors'] != CmdExecState.FAILED:
                            device._cmd_execution_state['removereceptors'] = CmdExecState.RUNNING
                        device._sc_subarray_cmd_starting_time[device.CbfSubarray] = time.time()
                        # Note: rembember to put the comma in args=(receptors_to_remove,) otherwise
                        # the list is received as a numpy array!
                        device._command_thread['removereceptors'] = threading.Thread(target=device._monitor_remove_receptors,
                                                                                   name="Thread-RemoveReceptors",
                                                                                   args=(receptors_to_remove,))
                        device._command_thread['removereceptors'].start()
                    else : 
                        return (ResultCode.OK, f"No receptor to remove from subarray {device.get_name()}")
                device._cmd_execution_state['removereceptors'] = CmdExecState.IDLE
                return (ResultCode.STARTED, "RemoveReceptor started")
            except tango.DevFailed as tango_err:
                #tango.Except.throw_exception("Command failed",
                #                             tango_err.args[0].desc,
                #                             "RemoveReceptors",
                #                             tango.ErrSeverity.ERR)
                message = str(tango_err.args[0].desc)
            except AttributeError as attr_err:
                #log_msg = "RemoveReceptors:" + str(attr_err)
                #self.logger.error(log_msg)
                #tango.Except.throw_exception("Command failed",
                #                             str(attr_err),
                #                             "RemoveReceptors",
                #                             tango.ErrSeverity.ERR)
                message = str(attr_err)
            return (ResultCode.FAILED, message)    


    def _get_cbfsubarray_assigned_receptors(self, device_proxy):
        """
@@ -311,11 +419,13 @@ class MidCspSubarrayBase(CspSubarray):
        # reset the command execution state
        self._sc_subarray_cmd_exec_state[device][cmd_name] = CmdExecState.IDLE
        self._cmd_execution_state[cmd_name] = CmdExecState.IDLE
        return (ResultCode.OK, "All receptor assigned!!")
        self.logger.info("AddReceptors end!")
        #self.AddReceptorsCommand.succeeded()
        self._add_receptors_cmd.succeeded()

     # PROTECTED REGION END #    //  MidCspSubarrayBase.private_methods

    def __monitor_remove_receptors(self, receptor_list, args_dict=None):
    def _monitor_remove_receptors(self, receptor_list, args_dict=None):
        cmd_name = 'removereceptors'
        device = self.CbfSubarray
        self._num_dev_completed_task[cmd_name] = 0
@@ -380,13 +490,16 @@ class MidCspSubarrayBase(CspSubarray):
                                                                                self._sc_subarray_state[self.CbfSubarray]))
            self.logger.warning(self._failure_message[device])
            self._failure_raised = True
            return (ResultCode.FAILED, "RemoveReceptors ended with failure")
        if self._sc_subarray_cmd_exec_state[device][cmd_name] == CmdExecState.TIMEOUT:
            self._timeout_expired = True
            return (ResultCode.FAILED, "RemoveReceptors ended with timeout")
        self.logger.info("CspSubarray failure flag:{}".format(self._failure_raised))
        self.logger.info("CspSubarray timeout flag:{}".format(self._timeout_expired))
        # reset the command exeuction state
        self._sc_subarray_cmd_exec_state[device][cmd_name] = CmdExecState.IDLE
        self._cmd_execution_state[cmd_name] = CmdExecState.IDLE
        self._remove_receptors_cmd.succeeded()

    def validate_scan_configuration(self, argin):
        """
@@ -475,6 +588,7 @@ class MidCspSubarrayBase(CspSubarray):
        self.state_model = MidCspSubarrayStateModel(
            dev_state_callback=self._update_state,
        )
        self.logger.info("state_mode: {}".format(self.state_model._transitions))

    def init_command_objects(self):
        """
@@ -483,7 +597,10 @@ class MidCspSubarrayBase(CspSubarray):
        super().init_command_objects()
        self.logger.info("MID call to init_commands")
        args = (self, self.state_model, self.logger)
        self._add_receptors_cmd = self.AddReceptorsCommand(*args)
        self._remove_receptors_cmd = self.RemoveReceptorsCommand(*args)
        self.register_command_object("AddReceptors", self.AddReceptorsCommand(*args))
        self.register_command_object("RemoveReceptors", self.RemoveReceptorsCommand(*args))

    
    # PROTECTED REGION END #    //  MidCspSubarrayBase.private_methods
@@ -696,18 +813,12 @@ class MidCspSubarrayBase(CspSubarray):
        (result_code, message) = handler(argin)
        return [[result_code], [message]]

    @AdminModeCheck('RemoveReceptors')
    def is_RemoveReceptors_allowed(self):

        return self._is_subarray_composition_allowed()

    @command(
        dtype_in='DevVarUShortArray',
        doc_in="The list with the receptor IDs to remove",
        dtype_out='DevVarLongStringArray',
    )
    @DebugIt()
    @ObsStateCheck('removeresources')
    @SubarrayRejectCmd(['AddReceptors', 'Configure'])
    def RemoveReceptors(self, argin):
        # PROTECTED REGION ID(MidCspSubarrayBase.RemoveReceptors) ENABLED START #
        """
@@ -722,79 +833,9 @@ class MidCspSubarrayBase(CspSubarray):
                    when an exception is caught during command execution.
        """
        # PROTECTED REGION ID(CspSubarray.RemoveReceptors) ENABLED START #

        # check if the CspSubarray is already connected to the CbfSubarray
        if not self._is_sc_subarray_running(self.CbfSubarray):
            log_msg = "Subarray {} not registered!".format( str(self.CbfSubarray))
            self.logger.error(log_msg)
            tango.Except.throw_exception("Command failed",
                                         log_msg,
                                         "RemoveReceptors",
                                         tango.ErrSeverity.ERR)
        try:
            proxy = self._sc_subarray_proxies[self.CbfSubarray]
            # read from CbfSubarray the list of assigned receptors
            # failure in reading attribute raises an AttributeError (not tangoDevFailed!!)
            receptors = proxy.receptors
            #!!!!!!!!!!!!!!!!!
            # 2019-09-20:  New images for TANGO and PyTango images has been released. PyTango
            # is now compiled with th numpy support. In this case the proxy.receptors call
            # does no more return an empty tuple but an empty numpy array.
            # Checks on receptors content need to be changed (see below)
            # NB: the receptors attribute implemented by the CbfSubarray is declared as RW.
            # In this case the read method returns an empty numpy array ([]) whose length is 0.
            #!!!!!!!!!!!!!!!!!

            # check if the list of assigned receptors is empty
            if len(receptors):
                receptors_to_remove = []
                # check if the receptors to remove belong to the subarray
                for receptor_id in argin:
                    if receptor_id in receptors:
                        receptors_to_remove.append(receptor_id)
                if any(receptors_to_remove):
                    # TODO: add reading of CbfSubarray removeReceptorsCmdDurationExpected
                    # attribute, if implemented, otherwise use the default value

                    # subscribes attributes to track progress and timeout: if these
                    # attributes are not implemented at CbfSubarray level, the warning
                    # is only logged because is not a fatal error.
                    for attr in ['removeReceptorsCmdProgress', 'timeoutExpiredFlag']:
                        try:
                            if self._sc_subarray_event_id[self.CbfSubarray][attr.lower()] == 0:
                                evt_id = proxy.subscribe_event(attr, tango.EventType.CHANGE_EVENT,
                                                               self._attributes_change_evt_cb, stateless=False)
                                self._sc_subarray_event_id[self.CbfSubarray][attr.lower()] = evt_id
                        except tango.DevFailed as tango_err:
                            self.logger.info(tango_err.args[0].desc)
                    # forward the command to CbfSubarray
                    proxy.command_inout_asynch("RemoveReceptors", receptors_to_remove, self._cmd_ended_cb)
                    if self._cmd_execution_state['removereceptors'] != CmdExecState.FAILED:
                        self._cmd_execution_state['removereceptors'] = CmdExecState.RUNNING
                    self._sc_subarray_cmd_starting_time[self.CbfSubarray] = time.time()
                    # Note: rembember to put the comma in args=(receptors_to_remove,) otherwise
                    # the list is received as a numpy array!
                    self._command_thread['removereceptors'] = threading.Thread(target=self.__monitor_remove_receptors,
                                                                               name="Thread-RemoveReceptors",
                                                                               args=(receptors_to_remove,))
                    self._command_thread['removereceptors'].start()
                    return
            self.logger.info(
                "No receptor to remove from subarray {}".format(self.get_name()))
            self._cmd_execution_state['removereceptors'] = CmdExecState.IDLE
            return
        except tango.DevFailed as tango_err:
            tango.Except.throw_exception("Command failed",
                                         tango_err.args[0].desc,
                                         "RemoveReceptors",
                                         tango.ErrSeverity.ERR)
        except AttributeError as attr_err:
            log_msg = "RemoveReceptors:" + str(attr_err)
            self.logger.error(log_msg)
            tango.Except.throw_exception("Command failed",
                                         str(attr_err),
                                         "RemoveReceptors",
                                         tango.ErrSeverity.ERR)
        handler = self.get_command_object("RemoveReceptors")
        (result_code, message) = handler(argin)
        return [[result_code], [message]]

        # PROTECTED REGION END #    //  MidCspSubarrayBase.RemoveReceptors
    @AdminModeCheck('RemoveAllReceptors')