Loading csp-lmc-common/csp-lmc-common/CspMaster.py +63 −57 Original line number Diff line number Diff line Loading @@ -97,12 +97,18 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # PROTECTED REGION END # // CspMaster.class_variable # PROTECTED REGION ID(CspMaster.class_protected_methods) ENABLED START # # !! NOTE !!: # In methods and attributes of the class: # 'se' prefix stands for 'sub-element # 'cb' suffix stands for 'callback' #---------------- # Event Callback functions # --------------- def _se_scm_change_event_cb(self, evt): """ Class protected callback function. Class callback function. Retrieve the values of the sub-element SCM attributes subscribed for change event at device initialization. Loading Loading @@ -163,9 +169,9 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): def _attributes_change_evt_cb(self, evt): """ Class protected callback function. Retrieve the value of the sub-element xxxCommandProgress attribute subscribed for change event when a long-running command is issued Class callback function. Retrieve the value of the sub-element xxxCommandProgress and xxxcmdTimeoutExpired attributes subscribed for change event when a long-running command is issued on the sub-element device. :param evt: The event data Loading Loading @@ -242,7 +248,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): msg = "Error!!Command {} ended on device {}.\n".format(evt.cmd_name, evt.device.dev_name()) msg += " Desc: {}".format(evt.errors[0].desc) #self.dev_logging(msg, tango.LogLevel.LOG_ERROR) self.dev_logging(msg, tango.LogLevel.LOG_ERROR) print(msg) self._se_cmd_execution_state[evt.device.dev_name()][evt.cmd_name.lower()] = CmdExecState.IDLE # obsState and obsMode values take on the CbfSubarray's values via Loading @@ -259,32 +265,31 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self.dev_logging(msg, tango.LogLevel.LOG_ERROR) # --------------- # Class protected methods # Class methods # --------------- def _update_csp_state(self): """ Class protected method. Retrieve the State attribute values of the CSP sub-elements and aggregate them to build up the CSP global state. Class method. Retrieve the *State* attribute value of the CBF sub-element and build up the CSP global state: only if CBF sub-element is present CSP can work. The *State* of of PSS and PST sub-elements (if ONLINE/MAINTENANCE) only contributes to determine the CSP *healthState* :param: None :return: None """ self._update_csp_health_state() # 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 # to determine the CSP health state. self.set_state(self._se_state[self.CspCbf]) if self._admin_mode in [AdminMode.OFFLINE, AdminMode.NOTFITTED, AdminMode.RESERVED]: self.set_state[tango.DevState.DISABLE] def _update_csp_health_state(self): """ Class protected method. Retrieve the healthState attribute of the CSP sub-elements and aggregate them to build up the CSP health state Class method. Retrieve the *healthState* and *adminMode* attributes of the CSP sub-elements and aggregate them to build up the CSP *healthState*. :param: None Loading @@ -310,7 +315,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self._healthstate = HealthState.OK elif self._se_health_state[self.CspCbf] in [HealthState.FAILED, HealthState.UNKNOWN, HealthState.DEGREADED]: HealthState.DEGRADED]: self._healthstate = self._se_health_state[self.CbfSubarray] else: # if CBF is not ONLINE/MAINTENANCE .... Loading @@ -319,16 +324,12 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): def _connect_to_subelements (self): """ Class private method. Establish a *stateless* connection with each CSP sub-element. Retrieve from the CSP TANGO DB the memorized adminMode value for each sub-element. Exceptions are logged. Class method. Establish a *stateless* connection with each CSP sub-element and subscribe for the sub-element SCM attributes. :return: None """ for fqdn in self._se_fqdn: try: # DeviceProxy to sub-elements Loading @@ -345,7 +346,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # store the sub-element proxies self._se_proxies[fqdn] = device_proxy # subscription of SCM attributes (State, healthState and adminMode). # Note: subscription is performed also for devices not ONLINE or MAINTENANCE. # Note: subscription is performed also for devices not ONLINE/MAINTENANCE. # In this way the CspMaster is able to detect a change in the admin value. # if the sub-element device is running,the adminMode is updated here Loading @@ -368,8 +369,6 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self._se_scm_change_event_cb, stateless=True) self._se_event_id[fqdn]['healthState'] = ev_id except KeyError as key_err: log_msg = ("No key {} found".format(str(key_err))) self.dev_logging(log_msg, tango.LogLevel.LOG_WARN) Loading @@ -381,7 +380,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): def _is_se_device_running (self, subelement_name): """ *Class protected method.* *Class method.* Check if a sub-element is exported in the TANGO DB (i.e its TANGO device server is running). Loading Loading @@ -417,21 +416,20 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): def _issue_power_command(self, device_list, **args_dict): """ Target function called when the command threads start. The On, Standby and Off methods issue the command on the sub-element devices in a separate thread. Information about the command to execute and the list of devices are passed as argument when the target function is called' Target function called when the power command threads start. The *On*, *Standby* and *Off* methods issue the command on the sub-element devices in a separate thread. The target function accepts as input arguments the command to execute and the list of devices to command. :param device_list: tuple with the FQDN of the sub-element devices args_dict: dictionary with information about the command to execute. The dictionary keys are: - cmd_name : the TANGO command name to execute - attr_name: the corresponding command progress attribute to subscribe - dev_state: the expected finale state for the device transition - dev_state: the expected end state for the device transition """ #TODO: order the list alphabetically so that the CBF is always the first element to start # the TANGO command to execute tango_cmd_name = 0 # the command progress attribute to check subscription Loading Loading @@ -462,7 +460,6 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self._cmd_progress[cmd_name] = 0 # sub-element command execution measured time se_cmd_duration_measured = defaultdict(lambda:defaultdict(lambda:0)) # timer is started outside the for loop: it has to start only once. # loop on the devices and power-on them sequentially for device in device_list: # set the sub-element command execution flag Loading @@ -472,14 +469,16 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): device_proxy = self._se_proxies[device] print("Issue asynch command {} on device {}:".format(cmd_name, device)) # Note: if the command ends on the sub-element, the _cmd_ended_cb callback # is called.This callback sets the sub-element execution state to IDLE if # an exception is caught during the execution on the sub-element. In both # cases the command_state = IDLE is right. # Note: If the command is already running on the sub-element, this device has # to return without throwing any exception. In this case the current method enters # the while loop and the execution of the sub-element command is tracked in the # right way. # Note: when the command ends on the sub-element, the _cmd_ended_cb callback # is called. This callback sets the sub-element execution state to FAULT if # an exception is caught during the execution on the sub-element. # # !!Note!!: # If the command is issued while the same command is already running on a # sub-element, the sub-element should return without throwing any exception # (see "SKA System Control Guidelines"). # In this case the current method enters the while loop and the execution of the # sub-element command is tracked in the right way. device_proxy.command_inout_asynch(tango_cmd_name, self._cmd_ended_cb) # register the starting time for the command self._se_cmd_starting_time[device] = time.time() Loading Loading @@ -513,7 +512,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # check for other sub-element device State values if self._se_state[device] in [tango.DevState.FAULT, tango.DevState.ALARM]: self._se_cmd_execution_state[device][cmd_name] = CmdExecState.IDLE msg = ("Device {} is {}}".format(device, self.get_status())) msg = ("Device {} is {}".format(device, self.get_status())) print(msg) self.dev_logging(msg, tango.LogLevel.LOG_WARN) num_of_failed_device += 1 Loading Loading @@ -546,8 +545,12 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # if the CBF command timeout expires, the CSP power-on is stopped # TODO: verify if this behavior conflicts with ICD print("elapsed_time:{} device {}".format(elapsed_time, device)) if device.find("cbf") > -1: if device == self.CspCbf: self.dev_logging("CBF Timeout during power-on!!! Exit", tango.LogLevel.LOG_ERROR) self._se_timeout_expired[device][cmd_name] = True self._se_cmd_execution_state[device][cmd_name] = CmdExecState.IDLE self._timeout_expired[cmd_name] = True self._cmd_execution_state[cmd_name] = CmdExecState.IDLE return # timeout on the sub-element, skip to the next device break Loading @@ -562,11 +565,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): print("All devices have been handled!") # end of the command: the command has been issued on all the sub-element devices # reset the execution flag for the CSP self._cmd_execution_state[cmd_name] = CmdExecState.IDLE self._last_executed_command = cmd_name # if one or more sub-elements go in timeout, se the CSP timeout flag to True if num_of_failed_device > 0: self._timeout_expired[cmd_name] = True break except KeyError as key_err: msg = "No key {} found".format(str(key_err)) self.dev_logging(msg, tango.LogLevel.LOG_WARN) Loading @@ -574,6 +573,14 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # It should not happen! Verify msg = "Failure reason: {} Desc: {}".format(str(df.args[0].reason), str(df.args[0].desc)) self.dev_logging(msg, tango.LogLevel.LOG_ERROR) # out of the for loop self._cmd_execution_state[cmd_name] = CmdExecState.IDLE self._last_executed_command = cmd_name # if one or more sub-elements go in timeout, se the CSP timeout flag to True for device in device_list: if self._se_timeout_expired[device][cmd_name] == True: self._timeout_expired[cmd_name] = True self._se_timeout_expired[device][cmd_name] = False # PROTECTED REGION END # // CspMaster.class_protected_methods # ----------------- Loading Loading @@ -1092,7 +1099,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self._admin_mode = memorized_attr_dict['adminMode'] self._storage_logging_level = memorized_attr_dict['storageLoggingLevel'] except KeyError as key_err: self.dev_logging("Key {} not found".format(key_err), tango.LogLevel.INFO) self.dev_logging("Key {} not found".format(key_err), tango.LogLevel.LOG_INFO) # initialize list with CSP sub-element FQDNs self._se_fqdn = [] Loading Loading @@ -1811,8 +1818,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # The target thread function is common to all the invoked commands. Specifc information # are passed as arguments of the function # args: the list of sub-element FQDNS # args_dict: dictionary with the specifif command information print("ON {} STANDBY {}".format( tango.DevState.ON, tango.DevState.STANDBY)) # args_dict: dictionary with the specific command information args_dict = {'cmd_name':'On', 'attr_name': 'onCommandProgress', 'dev_state': tango.DevState.ON} self._command_thread['on'] = threading.Thread(target=self._issue_power_command, name="Thread-On", args=(device_list,), Loading csp-lmc-common/utils/decorators.py +62 −58 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
csp-lmc-common/csp-lmc-common/CspMaster.py +63 −57 Original line number Diff line number Diff line Loading @@ -97,12 +97,18 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # PROTECTED REGION END # // CspMaster.class_variable # PROTECTED REGION ID(CspMaster.class_protected_methods) ENABLED START # # !! NOTE !!: # In methods and attributes of the class: # 'se' prefix stands for 'sub-element # 'cb' suffix stands for 'callback' #---------------- # Event Callback functions # --------------- def _se_scm_change_event_cb(self, evt): """ Class protected callback function. Class callback function. Retrieve the values of the sub-element SCM attributes subscribed for change event at device initialization. Loading Loading @@ -163,9 +169,9 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): def _attributes_change_evt_cb(self, evt): """ Class protected callback function. Retrieve the value of the sub-element xxxCommandProgress attribute subscribed for change event when a long-running command is issued Class callback function. Retrieve the value of the sub-element xxxCommandProgress and xxxcmdTimeoutExpired attributes subscribed for change event when a long-running command is issued on the sub-element device. :param evt: The event data Loading Loading @@ -242,7 +248,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): msg = "Error!!Command {} ended on device {}.\n".format(evt.cmd_name, evt.device.dev_name()) msg += " Desc: {}".format(evt.errors[0].desc) #self.dev_logging(msg, tango.LogLevel.LOG_ERROR) self.dev_logging(msg, tango.LogLevel.LOG_ERROR) print(msg) self._se_cmd_execution_state[evt.device.dev_name()][evt.cmd_name.lower()] = CmdExecState.IDLE # obsState and obsMode values take on the CbfSubarray's values via Loading @@ -259,32 +265,31 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self.dev_logging(msg, tango.LogLevel.LOG_ERROR) # --------------- # Class protected methods # Class methods # --------------- def _update_csp_state(self): """ Class protected method. Retrieve the State attribute values of the CSP sub-elements and aggregate them to build up the CSP global state. Class method. Retrieve the *State* attribute value of the CBF sub-element and build up the CSP global state: only if CBF sub-element is present CSP can work. The *State* of of PSS and PST sub-elements (if ONLINE/MAINTENANCE) only contributes to determine the CSP *healthState* :param: None :return: None """ self._update_csp_health_state() # 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 # to determine the CSP health state. self.set_state(self._se_state[self.CspCbf]) if self._admin_mode in [AdminMode.OFFLINE, AdminMode.NOTFITTED, AdminMode.RESERVED]: self.set_state[tango.DevState.DISABLE] def _update_csp_health_state(self): """ Class protected method. Retrieve the healthState attribute of the CSP sub-elements and aggregate them to build up the CSP health state Class method. Retrieve the *healthState* and *adminMode* attributes of the CSP sub-elements and aggregate them to build up the CSP *healthState*. :param: None Loading @@ -310,7 +315,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self._healthstate = HealthState.OK elif self._se_health_state[self.CspCbf] in [HealthState.FAILED, HealthState.UNKNOWN, HealthState.DEGREADED]: HealthState.DEGRADED]: self._healthstate = self._se_health_state[self.CbfSubarray] else: # if CBF is not ONLINE/MAINTENANCE .... Loading @@ -319,16 +324,12 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): def _connect_to_subelements (self): """ Class private method. Establish a *stateless* connection with each CSP sub-element. Retrieve from the CSP TANGO DB the memorized adminMode value for each sub-element. Exceptions are logged. Class method. Establish a *stateless* connection with each CSP sub-element and subscribe for the sub-element SCM attributes. :return: None """ for fqdn in self._se_fqdn: try: # DeviceProxy to sub-elements Loading @@ -345,7 +346,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # store the sub-element proxies self._se_proxies[fqdn] = device_proxy # subscription of SCM attributes (State, healthState and adminMode). # Note: subscription is performed also for devices not ONLINE or MAINTENANCE. # Note: subscription is performed also for devices not ONLINE/MAINTENANCE. # In this way the CspMaster is able to detect a change in the admin value. # if the sub-element device is running,the adminMode is updated here Loading @@ -368,8 +369,6 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self._se_scm_change_event_cb, stateless=True) self._se_event_id[fqdn]['healthState'] = ev_id except KeyError as key_err: log_msg = ("No key {} found".format(str(key_err))) self.dev_logging(log_msg, tango.LogLevel.LOG_WARN) Loading @@ -381,7 +380,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): def _is_se_device_running (self, subelement_name): """ *Class protected method.* *Class method.* Check if a sub-element is exported in the TANGO DB (i.e its TANGO device server is running). Loading Loading @@ -417,21 +416,20 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): def _issue_power_command(self, device_list, **args_dict): """ Target function called when the command threads start. The On, Standby and Off methods issue the command on the sub-element devices in a separate thread. Information about the command to execute and the list of devices are passed as argument when the target function is called' Target function called when the power command threads start. The *On*, *Standby* and *Off* methods issue the command on the sub-element devices in a separate thread. The target function accepts as input arguments the command to execute and the list of devices to command. :param device_list: tuple with the FQDN of the sub-element devices args_dict: dictionary with information about the command to execute. The dictionary keys are: - cmd_name : the TANGO command name to execute - attr_name: the corresponding command progress attribute to subscribe - dev_state: the expected finale state for the device transition - dev_state: the expected end state for the device transition """ #TODO: order the list alphabetically so that the CBF is always the first element to start # the TANGO command to execute tango_cmd_name = 0 # the command progress attribute to check subscription Loading Loading @@ -462,7 +460,6 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self._cmd_progress[cmd_name] = 0 # sub-element command execution measured time se_cmd_duration_measured = defaultdict(lambda:defaultdict(lambda:0)) # timer is started outside the for loop: it has to start only once. # loop on the devices and power-on them sequentially for device in device_list: # set the sub-element command execution flag Loading @@ -472,14 +469,16 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): device_proxy = self._se_proxies[device] print("Issue asynch command {} on device {}:".format(cmd_name, device)) # Note: if the command ends on the sub-element, the _cmd_ended_cb callback # is called.This callback sets the sub-element execution state to IDLE if # an exception is caught during the execution on the sub-element. In both # cases the command_state = IDLE is right. # Note: If the command is already running on the sub-element, this device has # to return without throwing any exception. In this case the current method enters # the while loop and the execution of the sub-element command is tracked in the # right way. # Note: when the command ends on the sub-element, the _cmd_ended_cb callback # is called. This callback sets the sub-element execution state to FAULT if # an exception is caught during the execution on the sub-element. # # !!Note!!: # If the command is issued while the same command is already running on a # sub-element, the sub-element should return without throwing any exception # (see "SKA System Control Guidelines"). # In this case the current method enters the while loop and the execution of the # sub-element command is tracked in the right way. device_proxy.command_inout_asynch(tango_cmd_name, self._cmd_ended_cb) # register the starting time for the command self._se_cmd_starting_time[device] = time.time() Loading Loading @@ -513,7 +512,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # check for other sub-element device State values if self._se_state[device] in [tango.DevState.FAULT, tango.DevState.ALARM]: self._se_cmd_execution_state[device][cmd_name] = CmdExecState.IDLE msg = ("Device {} is {}}".format(device, self.get_status())) msg = ("Device {} is {}".format(device, self.get_status())) print(msg) self.dev_logging(msg, tango.LogLevel.LOG_WARN) num_of_failed_device += 1 Loading Loading @@ -546,8 +545,12 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # if the CBF command timeout expires, the CSP power-on is stopped # TODO: verify if this behavior conflicts with ICD print("elapsed_time:{} device {}".format(elapsed_time, device)) if device.find("cbf") > -1: if device == self.CspCbf: self.dev_logging("CBF Timeout during power-on!!! Exit", tango.LogLevel.LOG_ERROR) self._se_timeout_expired[device][cmd_name] = True self._se_cmd_execution_state[device][cmd_name] = CmdExecState.IDLE self._timeout_expired[cmd_name] = True self._cmd_execution_state[cmd_name] = CmdExecState.IDLE return # timeout on the sub-element, skip to the next device break Loading @@ -562,11 +565,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): print("All devices have been handled!") # end of the command: the command has been issued on all the sub-element devices # reset the execution flag for the CSP self._cmd_execution_state[cmd_name] = CmdExecState.IDLE self._last_executed_command = cmd_name # if one or more sub-elements go in timeout, se the CSP timeout flag to True if num_of_failed_device > 0: self._timeout_expired[cmd_name] = True break except KeyError as key_err: msg = "No key {} found".format(str(key_err)) self.dev_logging(msg, tango.LogLevel.LOG_WARN) Loading @@ -574,6 +573,14 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # It should not happen! Verify msg = "Failure reason: {} Desc: {}".format(str(df.args[0].reason), str(df.args[0].desc)) self.dev_logging(msg, tango.LogLevel.LOG_ERROR) # out of the for loop self._cmd_execution_state[cmd_name] = CmdExecState.IDLE self._last_executed_command = cmd_name # if one or more sub-elements go in timeout, se the CSP timeout flag to True for device in device_list: if self._se_timeout_expired[device][cmd_name] == True: self._timeout_expired[cmd_name] = True self._se_timeout_expired[device][cmd_name] = False # PROTECTED REGION END # // CspMaster.class_protected_methods # ----------------- Loading Loading @@ -1092,7 +1099,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): self._admin_mode = memorized_attr_dict['adminMode'] self._storage_logging_level = memorized_attr_dict['storageLoggingLevel'] except KeyError as key_err: self.dev_logging("Key {} not found".format(key_err), tango.LogLevel.INFO) self.dev_logging("Key {} not found".format(key_err), tango.LogLevel.LOG_INFO) # initialize list with CSP sub-element FQDNs self._se_fqdn = [] Loading Loading @@ -1811,8 +1818,7 @@ class CspMaster(with_metaclass(DeviceMeta, SKAMaster)): # The target thread function is common to all the invoked commands. Specifc information # are passed as arguments of the function # args: the list of sub-element FQDNS # args_dict: dictionary with the specifif command information print("ON {} STANDBY {}".format( tango.DevState.ON, tango.DevState.STANDBY)) # args_dict: dictionary with the specific command information args_dict = {'cmd_name':'On', 'attr_name': 'onCommandProgress', 'dev_state': tango.DevState.ON} self._command_thread['on'] = threading.Thread(target=self._issue_power_command, name="Thread-On", args=(device_list,), Loading
csp-lmc-common/utils/decorators.py +62 −58 File changed.Preview size limit exceeded, changes collapsed. Show changes