Commit 2bcee3af authored by Elisabetta Giani's avatar Elisabetta Giani
Browse files

CT-60: Implemented Off and ObsReset commands. Fix some bugs in

receptors handling.
More tests.
parent 5de54e49
Loading
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
0.6.3
- use ska-python-buildenv and runtime 9.3.2
- use lmcbaseclasses ver 0.6.3
- Add support for Off and ObsReset commands
- Fix type_in argument for Scan (now it accepts a DevString instead of a DevStringVarArray)
- EndScan to discuss actual implementation

0.6.2
- Finalized support for Configure command.
- Added GoToIdle command subclassing the ActionCommand class.
+147 −37
Original line number Diff line number Diff line
@@ -129,7 +129,6 @@ class CspSubarray(SKASubarray):

            device = self.target
            device._build_state = '{}, {}, {}'.format(release.name, release.version, release.description)
            self.logger.info("Initial state is:{}".format(device.get_state()))
            device._version_id = release.version
            # connect to CSP.LMC TANGO DB
            # _config_delay_expected: inherited from the SKAObsDevice base class
@@ -306,13 +305,10 @@ class CspSubarray(SKASubarray):
            device._assigned_timing_beams= []
            device._assigned_vlbi_beams = []      
                                                               
            self.logger.info("1")
            # Try connection with the CBF sub-array
            device.connect_to_subarray_subcomponent(device.CbfSubarray)
            self.logger.info("2")
            # Try connection with the PSS sub-array
            device.connect_to_subarray_subcomponent(device.PssSubarray)
            self.logger.info("3")
                    
            # to use the push model in command_inout_asynch (the one with the callback parameter),
            # change the global TANGO model to PUSH_CALLBACK.
@@ -327,7 +323,7 @@ class CspSubarray(SKASubarray):
        def do(self):
            super().do()
            device = self.target
            self.logger.info("Call to OnCommand")
            self.logger.info("Call On Command")
            for fqdn in device._sc_subarray_fqdn:
                try:
                    (result_code, message) = device._sc_subarray_proxies[fqdn].On()
@@ -345,6 +341,28 @@ class CspSubarray(SKASubarray):
            self.logger.info(message)
            return (ResultCode.OK, message)

    class OffCommand(SKASubarray.OffCommand):
        def do(self):
            super().do()
            device = self.target
            self.logger.info("Call Off Command")
            for fqdn in device._sc_subarray_fqdn:
                try:
                    (result_code, message) = device._sc_subarray_proxies[fqdn].Off()
                    if result_code == ResultCode.FAILED:
                        self.logger.error("Off command failed on device {}".format(fqdn))
                        if fqdn != device.CbfSubarray:
                            device._health_state = HealthState.DEGRADED
                            continue
                        else:
                            return (ResultCode.FAILED, message)
                except tango.DevFailed as tango_err:
                    message = str(tango_err.args[0].desc)
                    return (ResultCode.FAILED, message)
            message = "Off command completed OK"
            self.logger.info(message)
            return (ResultCode.OK, message)

    class ConfigureCommand(SKASubarray.ConfigureCommand):

        def do(self, argin):
@@ -353,7 +371,6 @@ class CspSubarray(SKASubarray):
           
            # the dictionary with the scan configuration

            self.logger.info("CspSubarray.Configure do method")
            target_device = self.target
            try:
                # if the stored configuration attribute is not empty, check
@@ -366,7 +383,7 @@ class CspSubarray(SKASubarray):
                        # state of the subarray is READY than subarray is not re-configured.
                        if (stored_configuration == received_configuration) and (target_device._obs_state == ObsState.READY):
                            self.logger.info("Subarray is going to use the same configuration")
                            return (ResultCode.OK, msg)
                            return (ResultCode.OK, "Configure command OK")
                    except Exception as e:
                        self.logger.warning(str(e))
                # go ahead and parse the received configuration
@@ -417,15 +434,23 @@ class CspSubarray(SKASubarray):
                # NOTE: CBF/PSS sub-array checks for the validity of its
                # configuration. Failure in configuration throws an exception that is
                # caught via the _cmd_ended_cb callback

                """
                try:
                    # read the timeout configured for the operation on the device
                    target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] = target_device._get_expected_delay(proxy, "configureDelayExpected")
                    self.logger.info("config delay: {}".format(target_device._sc_subarray_cmd_duration_expected[device]['configurescan']))
                    self._sc_subarray_cmd_duration_expected[device]['configurescan'] = proxy.configureDelayExpected
                except AttributeError as attr_err:
                    self.logger.info("No attribute {} on device {}".format(str(attr_err), device))
                """

                try:
                    # read the timeout configured for the operation on the device
                    target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] = target_device._get_expected_delay(proxy, "configureDelayExpected")
                    #self.logger.info("config delay: {}".format(target_device._sc_subarray_cmd_duration_expected[device]['configurescan']))
                except tango.DevFailed as tango_err:
                    self.logger.info("No attribute {} on device {}".format(tango_err.args[0].desc, device))
                try:
                    self.logger.info("Issue the command")
                    target_device._timeout_expired = False
                    target_device._failure_raised = False
                    proxy.command_inout_asynch("ConfigureScan",
                                               target_device._sc_subarray_scan_configuration[device],
                                               target_device._cmd_ended_cb)
@@ -462,7 +487,6 @@ class CspSubarray(SKASubarray):
            target_device._abort_command_event.clear()
            target_device._cmd_execution_state['configurescan'] = CmdExecState.RUNNING
            target_device._cmd_duration_measured['configurescan'] = 0
            self.logger.info("Thread started!")
            target_device._command_thread['configurescan'].start()
            message = "Configure command started"
            self.logger.info(message)
@@ -503,7 +527,6 @@ class CspSubarray(SKASubarray):
            device_list = input_arg[0]
            self.logger.info("device_list:{}".format(device_list))
            while True:
                self.logger.info("inside the loop!!!")
                command_progress = 0
                for device in device_list:
                    self.logger.info("Command {} obs_state: {}".format(cmd_name,
@@ -537,7 +560,7 @@ class CspSubarray(SKASubarray):
                    # Note: the second check, can be useful if the timeout event is not received
                    # (for example for a temporary connection timeout)
                    elapsed_time = time.time() - target_device._sc_subarray_cmd_starting_time[device]
                    self.logger.info("elapsed_time:{}".format(elapsed_time))
                    self.logger.debug("elapsed_time:{}".format(elapsed_time))

                    if (elapsed_time > target_device._sc_subarray_cmd_duration_expected[device][cmd_name] or
                        target_device._sc_subarray_cmd_exec_state[device][cmd_name] == CmdExecState.TIMEOUT):
@@ -573,6 +596,7 @@ class CspSubarray(SKASubarray):
                    break
                # TODO:
                # check for abort request.
                self.logger.debug("Sleep for 0.1")
                time.sleep(0.1)
            # end of the while loop
            # check for timeout/failure conditions on each sub-component
@@ -616,7 +640,6 @@ class CspSubarray(SKASubarray):
            :raises: tango.DevFailed exception
            """

            self.logger.info("CspSubarray validate_scan")
            target_device = self.target
            try:
                json_dict = json.loads(argin)
@@ -644,14 +667,13 @@ class CspSubarray(SKASubarray):
        def do(self, argin):
            target_device = self.target
            try:
                target_device._scan_id = int(argin[0])
                target_device._scan_id = int(argin)
            except (ValueError, Exception) as err:
                msg = "Scan command invalid argument:{}".format(str(err))
                self.logging.error(msg)
                return (ResultCode.FAILED, msg) 
            # invoke the constructor for the command thread
            self.logger.info("Received Scan command with id:{}".format(target_device._scan_id))
            self.logger.info("sc_subarray_assigned_fqdn: {}".format(target_device._sc_subarray_assigned_fqdn))
            for device in target_device._sc_subarray_assigned_fqdn:
                try:
                    proxy = target_device._sc_subarray_proxies[device]
@@ -666,9 +688,9 @@ class CspSubarray(SKASubarray):
                except tango.DevFailed as tango_err:
                    self.logger.info(tango_err.args[0].desc)
                try:
                    self.logger.info("Forwarding scan")
                    proxy.command_inout_asynch("Scan", argin[0], target_device._cmd_ended_cb)
                    self.logger.info("after Forwarding scan")
                    target_device._timeout_expired = False
                    target_device._failure_raised = False
                    proxy.command_inout_asynch("Scan", target_device._scan_id, target_device._cmd_ended_cb)
                except tango.DevFailed as tango_err:
                    self.logger.info(tango_err.args[0].desc)
                    # TODO: add check on the failed device. If CBF
@@ -717,6 +739,7 @@ class CspSubarray(SKASubarray):
                    # if the sub-component execution flag is no more RUNNING, the command has
                    # ended with or without success. Go to check next device state.
                    if target_device._sc_subarray_obs_state[device] == dev_successful_state:
                        self.logger.info("end scan set: {}".format(format(target_device._end_scan_event.is_set())))
                        if target_device._end_scan_event.is_set():
                            self.logger.info("Command {} ended with success on device {}.".format(cmd_name,
                                                                                                device))
@@ -744,24 +767,21 @@ class CspSubarray(SKASubarray):
                    self.logger.info("All devices have been handled!")
                    break
                self.logger.info("Going to sleep")
                time.sleep(0.2)
                time.sleep(0.1)
                           
            # end of the while loop
            target_device._cmd_execution_state[cmd_name] = CmdExecState.IDLE
            # check for timeout/failure conditions on each sub-component
            if any(target_device._sc_subarray_cmd_exec_state[device][cmd_name] == CmdExecState.FAILED for device in device_list):
                target_device._failure_raised = True
                #return target_device.scan_cmd_obj.failed()
                return 
                return target_device.scan_cmd_obj.failed()
                # update the progress counter at the end of the loop 
            if all(target_device._sc_subarray_obs_state[fqdn] == dev_successful_state for fqdn in device_list):
                target_device._cmd_progress[cmd_name] = 100
                elapsed_time = time.time() - starting_time 
                self.logger.info("Scan elapsed time:{}".format(elapsed_time))
                target_device._last_executed_command = cmd_name
                #return target_device.scan_cmd_obj.succeeded()
                self.logger.info("Exiting from the scan thread!")
                return
                return target_device.scan_cmd_obj.succeeded()

    class EndScanCommand(SKASubarray.EndScanCommand):

@@ -786,7 +806,89 @@ class CspSubarray(SKASubarray):
                    # signal the failure raising the failure flag?
            # set the threading endScan event 
            target_device._end_scan_event.set()
            return (ResultCode.STARTED, "EndScan command executed STARTED")
            return (ResultCode.OK, "EndScan command executed OK")

    class ObsResetCommand(SKASubarray.ObsResetCommand):
        def do(self):
            self.logger.info("Call ObsReset")
            target_device = self.target
            devices_to_reset = []
            device_list = target_device._sc_subarray_assigned_fqdn
            if not any(target_device._sc_subarray_assigned_fqdn):
                # need to add a check also on PSTBeams belonging to subarray
                device_list = target_device._sc_subarray_fqdn
            for device in device_list:
                if target_device._sc_subarray_obs_state[device] == ObsState.FAULT:
                    devices_to_reset.append(device)
            self.logger.info("devices_to_reset:{}".format(devices_to_reset))
            if not any(devices_to_reset):
                return (ResultCode.OK, "ObsReset command OK")
            for device in devices_to_reset:
                try:
                    proxy = target_device._sc_subarray_proxies[device]
                    target_device._timeout_expired = False
                    target_device._failure_raised = False
                    proxy.command_inout_asynch("ObsReset", target_device._cmd_ended_cb)
                except KeyError as key_err:
                    self.logger.warning("No key {} found".format(key_err))
                except tango.DevFailed as tango_err:
                    self.logger.warning(tango_err.args[0].desc)
                    # TODO: address this case!
                    # signal the failure raising the failure flag?
            target_device._command_thread['obsreset'] = threading.Thread(target=self._monitor_obsreset,
                                                               name="Thread-ObsReset",
                                                               args=(devices_to_reset,))
            target_device._command_thread['obsreset'].start()
            # set the threading endScan event 
            return (ResultCode.STARTED, "ObsReset command executed STARTED")

        def _monitor_obsreset(self, device_list):
            cmd_name = 'obsreset'
            target_device = self.target
            dev_successful_state = ObsState.IDLE
            target_device._cmd_progress[cmd_name] = 0
            device_done = defaultdict(lambda:False)
            # inside the end-less loop check the obsState of each sub-component
            self.logger.debug("device_list:{}".format(device_list))
            while True:
                self.logger.info("Going to sleep")
                time.sleep(0.1)
                for device in device_list:
                    if device_done[device] == True:
                        continue
                    # if the sub-component execution flag is no more RUNNING, the command has
                    # ended with or without success. Go to check next device state.
                    self.logger.info("device {} obs_state:{}".format(device, target_device._sc_subarray_obs_state[device]))
                    if target_device._sc_subarray_obs_state[device] == dev_successful_state: 
                       self.logger.info("Command {} ended with success on device {}.".format(cmd_name,
                                                                                               device))
                       target_device._sc_subarray_cmd_exec_state[device][cmd_name] = CmdExecState.IDLE
                       target_device._sc_subarray_cmd_progress[device][cmd_name] = 100
                       # command success: step to next device
                       device_done[device] = True
                        # check if sub-element command ended throwing an exception: in this case the
                        # 'cmd_ended_cb' callback is invoked.
                    if target_device._sc_subarray_cmd_exec_state[device][cmd_name] == CmdExecState.FAILED or\
                            target_device._sc_subarray_obs_state[device] == ObsState.FAULT:
                        # execution ended for this sub-element, skip to the next one
                        target_device._failure_raised = True
                        device_done[device] = True
                        target_device._sc_subarray_cmd_exec_state[device][cmd_name] = CmdExecState.IDLE
                
                if any(device_done.values()) and all(value == True for value in device_done.values()):
                    self.logger.info("All devices have been handled!")
                    break
                           
            # end of the while loop
            # check for timeout/failure conditions on each sub-component
            if target_device._failure_raised or target_device._timeout_expired:
                return target_device.obsreset_cmd_obj.failed()

            if all(target_device._sc_subarray_obs_state[fqdn] == dev_successful_state for fqdn in device_list):
                target_device._cmd_progress[cmd_name] = 100
                target_device._last_executed_command = cmd_name
                self.logger.info("ObsReset ends with success")
                return target_device.obsreset_cmd_obj.succeeded()

    '''
    class AbortCommand(SKASubarray.AbortCommand):
@@ -845,6 +947,8 @@ class CspSubarray(SKASubarray):
                    proxy = target_device._sc_subarray_proxies[device]
                    # register the starting time for the command
                    target_device._sc_subarray_cmd_starting_time[device] = time.time()
                    target_device._timeout_expired = False
                    target_device._failure_raised = False
                    proxy.command_inout_asynch("GoToIdle", target_device._cmd_ended_cb)
                    # read the timeout attribute configured for this command
                    # if not implemented an AttributeError exception is thrown
@@ -1071,9 +1175,7 @@ class CspSubarray(SKASubarray):
                self.logger.info(log_msg)
                # update CSP sub-array SCM
                if evt.attr_value.name.lower() in ["state", "healthstate", "adminmode", "obsstate"]:
                    self.logger.info("call to update_subarray_state()")
                    self.update_subarray_state()
                    self.logger.info("after update_subarray_state()")
            except tango.DevFailed as df:
                self.logger.error(str(df.args[0].desc))
            except Exception as except_occurred:
@@ -1186,7 +1288,9 @@ class CspSubarray(SKASubarray):
                    msg += " Desc: {}".format(evt.errors[0].desc)
                    self.logger.info(msg)
                    self._sc_subarray_cmd_exec_state[evt.device.dev_name()][evt.cmd_name.lower()] = CmdExecState.FAILED
                    self.logger.info("2")
                    self._failure_message[evt.cmd_name.lower()] += msg
                    self.logger.info("3")
                    # obsState and obsMode values take on the CbfSubarray's values via
                    # the subscribe/publish mechanism
            else:
@@ -1219,7 +1323,7 @@ class CspSubarray(SKASubarray):
            a = [self._command_thread[cmd_name].is_alive() for cmd_name in self._command_thread.keys()]
            self.logger.info("list of running threds:{}".format(a))
            if any(self._command_thread[cmd_name].is_alive() for cmd_name in self._command_thread.keys()):
                self.logger.info("A command is running don't update state!")
                self.logger.info("A command is already running...the obsState is not updated")
                return False
        # CSP state reflects the status of CBF. Only if CBF is present
        # CSP can work. The state of PSS and PST sub-elements only contributes
@@ -1322,9 +1426,13 @@ class CspSubarray(SKASubarray):
        device_proxy = DeviceProxy(fqdn)
        return device_proxy

    def _get_expected_delay(self, attr_name, proxy):
    def _get_expected_delay(self, proxy,attr_name):
        try:
            attr_value = proxy.read_attribute(attr_name)
            return attr_value.value()
        except AttributeError as attr_err:
            self.logger.info("No attribute {} on device {}".format(str(attr_err), proxy))
            tango.Except.throw_exception("Attribute Error", str(attr_err), "", tango.ErrSeverity.ERR)


    def connect_to_subarray_subcomponent(self, fqdn):
@@ -1482,9 +1590,11 @@ class CspSubarray(SKASubarray):
        self.on_cmd_obj = self.OnCommand(*args)
        self.scan_cmd_obj = self.ScanCommand(*args)
        self.gotoidle_cmd_obj = self.GoToIdleCommand(*args)
        self.obsreset_cmd_obj = self.ObsResetCommand(*args)
        self.register_command_object("GoToIdle", self.GoToIdleCommand(*args))
        self.register_command_object("Configure", self.ConfigureCommand(*args))
        self.register_command_object("Scan", self.ScanCommand(*args))
        self.register_command_object("ObsReset", self.ObsResetCommand(*args))


    # ----------------
@@ -2382,7 +2492,7 @@ class CspSubarray(SKASubarray):
    # --------

    @command(
        dtype_in='DevVarStringArray',
        dtype_in='DevString',
        dtype_out='DevVarLongStringArray',
    )
    @DebugIt()
@@ -2396,7 +2506,7 @@ class CspSubarray(SKASubarray):

        :return: 'DevVarLongStringArray'
        """
        self.logger.info("Call to method Scan")
        self.logger.info("Call Scan command")
        handler = self.get_command_object("Scan")
        (result_code, message) = handler(argin)
        return [[result_code], [message]] 
@@ -2426,7 +2536,7 @@ class CspSubarray(SKASubarray):
            tango.DevFailed exception if the CspSubarray ObsState is not valid or if an exception\
            is caught during command execution.
        """
        self.logger.info("Call to method Configure")
        self.logger.info("Call Configure command")
        handler = self.get_command_object("Configure")
        (result_code, message) = handler(argin)
        return [[result_code], [message]] 
@@ -2443,7 +2553,7 @@ class CspSubarray(SKASubarray):

        :return: None
        """
        self.logger.info("Call to GoToIdle method")
        self.logger.info("Call GoToIdle command")
        handler = self.get_command_object("GoToIdle")
        (result_code, message) = handler()
        return [[result_code], [message]] 
+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@
"""Release information for Python Package"""

name = """csp-lmc-common"""
version = "0.6.2"
version = "0.6.3"
version_info = version.split(".")
description = """SKA CSP.LMC Common Software"""
author = "INAF-OAA"
+3 −3
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
"""Release information for Python Package"""

name = """csplmc-common"""
version = "0.6.2"
version = "0.6.3"
version_info = version.split(".")
description = """SKA CSP.LMC Common Classe"""
author = "E.G"
@@ -18,5 +18,5 @@ license = """BSD-3-Clause"""
url = """www.tango-controls.org"""
copyright = """"""

release=0.6.2
tag=csp-lmc-common-0.6.2
release=0.6.3
tag=csp-lmc-common-0.6.3
+2 −2
Original line number Diff line number Diff line
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.1 AS buildenv
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.1 AS runtime
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2 AS buildenv
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.2 AS runtime

# create ipython profile to so that itango doesn't fail if ipython hasn't run yet
RUN ipython profile create
Loading