class HealthStateAggregator: """ Health State Aggregator class """ def __init__(self, logger=None): if logger == None: self.logger = logging.getLogger(__name__) else: self.logger = logger self.subarray_ln_health_state_map = {} self.mccs_ln_health_event_id = {} self.this_server = TangoServerHelper.get_instance() self.device_data = DeviceData.get_instance() mccs_subarray_ln_fqdn = "" property_val = self.this_server.read_property("MccsSubarrayLNFQDN") mccs_subarray_ln_fqdn = mccs_subarray_ln_fqdn.join(property_val) self.mccs_client = TangoClient(mccs_subarray_ln_fqdn) def subscribe(self): # Subscribe cspsubarrayHealthState (forwarded attribute) of CspSubarray mccs_event_id = self.mccs_client.subscribe_attribute( const.EVT_MCCSSA_HEALTH, self.health_state_cb) self.mccs_ln_health_event_id[self.mccs_client] = mccs_event_id log_msg = f"{const.STR_SUB_ATTR_MCCS_SALN_HEALTH_SUCCESS}{self.mccs_ln_health_event_id}" self.logger.debug(log_msg) self.logger.info(const.STR_SUB_ATTR_MCCS_SALN_HEALTH_SUCCESS) def health_state_cb(self, event): """ Receives the subscribed health states, aggregates them to calculate the overall subarray health state. :param evt: A event on MCCS Subarray healthState. :type: Event object It has the following members: - date (event timestamp) - reception_date (event reception timestamp) - type (event type) - dev_name (device name) - name (attribute name) - value (event value) :return: None """ device_name = event.device.dev_name() if not event.err: event_health_state = event.attr_value.value self.subarray_ln_health_state_map[device_name] = event_health_state log_message = self.generate_health_state_log_msg( event_health_state, device_name, event) self.this_server.write_attr("activityMessage", log_message, False) self.device_data._subarray_health_state = self.calculate_health_state( self.subarray_ln_health_state_map.values()) else: log_message = f"{const.ERR_SUBSR_SA_HEALTH_STATE}{device_name}{event}" self.this_server.write_attr("activityMessage", log_message, False) def generate_health_state_log_msg(self, health_state, device_name, event): if isinstance(health_state, HealthState): return f"{const.STR_HEALTH_STATE}{device_name}{const.STR_ARROW}{health_state.name.upper()}" else: return f"{const.STR_HEALTH_STATE_UNKNOWN_VAL}{event}" def calculate_health_state(self, health_states): """ Calculates aggregated health state of SubarrayLow. """ unique_states = set(health_states) if unique_states == set([HealthState.OK]): return HealthState.OK elif HealthState.FAILED in unique_states: return HealthState.FAILED elif HealthState.DEGRADED in unique_states: return HealthState.DEGRADED else: return HealthState.UNKNOWN def unsubscribe(self): """ This function unsubscribes all health state events given by the event ids and their corresponding DeviceProxy objects. :param : None :return: None """ for tango_client, event_id in self.mccs_ln_health_event_id.items(): tango_client.unsubscribe_attribute(event_id)
class ObsStateAggregator: """ Observation State Aggregator class """ def __init__(self, logger=None): if logger is None: self.logger = logging.getLogger(__name__) else: self.logger = logger self._mccs_sa_obs_state = None self.mccs_obs_state_event_id = {} self.this_server = TangoServerHelper.get_instance() self.device_data = DeviceData.get_instance() def subscribe(self): mccs_subarray_ln_fqdn = "" property_val = self.this_server.read_property("MccsSubarrayLNFQDN") mccs_subarray_ln_fqdn = mccs_subarray_ln_fqdn.join(property_val) self.mccs_client = TangoClient(mccs_subarray_ln_fqdn) # Subscribe mccsSubarrayObsState (forwarded attribute) of mccsSubarray mccs_event_id = self.mccs_client.subscribe_attribute( const.EVT_MCCSSA_OBS_STATE, self.observation_state_cb) self.mccs_obs_state_event_id[self.mccs_client] = mccs_event_id log_msg = f"{const.STR_SUB_ATTR_MCCS_SALN_OBSTATE_SUCCESS}{self.mccs_obs_state_event_id}" self.logger.info(log_msg) def unsubscribe(self): """ This function unsubscribes all Observation state events given by the event ids and their corresponding DeviceProxy objects. :param : None :return: None """ for tango_client, event_id in self.mccs_obs_state_event_id.items(): tango_client.unsubscribe_attribute(event_id) def observation_state_cb(self, evt): """ Receives the subscribed MCCS Subarray obsState. :param evt: A event on MCCS Subarray ObsState. :type: Event object It has the following members: - date (event timestamp) - reception_date (event reception timestamp) - type (event type) - dev_name (device name) - name (attribute name) - value (event value) :return: None :raises: KeyError if error occurs while setting SubarrayNode's ObsState. """ try: if not evt.err: event_observation_state = evt.attr_value.value if const.PROP_DEF_VAL_TMMCCS_MID_SALN in evt.attr_name: # Typacasted the event values to obsState ENUM labels. self._mccs_sa_obs_state = ObsState(event_observation_state) self.this_server.write_attr( "activityMessage", f"{const.STR_MCCS_SUBARRAY_OBS_STATE}{event_observation_state}", False) else: self.logger.info(const.EVT_UNKNOWN) self.this_server.write_attr("activityMessage", const.EVT_UNKNOWN, False) self.calculate_observation_state() else: log_msg = f"{const.ERR_SUBSR_MCCSSA_OBS_STATE}{evt}" self.logger.info(log_msg) self.this_server.write_attr("activityMessage", log_msg, False) except KeyError as key_error: log_msg = f"{const.ERR_MCCS_SUBARRAY_OBS_STATE}{key_error}" self.logger.error(log_msg) self.this_server.write_attr( "activityMessage", f"{const.ERR_MCCS_SUBARRAY_OBS_STATE}{key_error}", False) def calculate_observation_state(self): """ Calculates aggregated observation state of Subarray. """ log_msg = f"MCCS ObsState is: {self._mccs_sa_obs_state}" self.logger.info(log_msg) if self._mccs_sa_obs_state == ObsState.EMPTY: if self.device_data.is_release_resources: self.logger.info( "Calling ReleaseAllResource command succeeded() method") self.this_server.device.release.succeeded() elif self.device_data.is_restart_command_executed: self.logger.info("Calling Restart command succeeded() method") self.this_server.device.restart.succeeded() elif self._mccs_sa_obs_state == ObsState.READY: if self.device_data.is_scan_completed: self.logger.info("Calling EndScan command succeeded() method") self.this_server.device.endscan.succeeded() else: # Configure command success self.logger.info( "Calling Configure command succeeded() method") self.this_server.device.configure.succeeded() elif self._mccs_sa_obs_state == ObsState.IDLE: if self.device_data.is_end_command: # End command success self.logger.info("Calling End command succeeded() method") self.this_server.device.end.succeeded() elif self.device_data.is_obsreset_command_executed: # ObsReset command success self.logger.info("Calling ObsReset command succeeded() method") self.this_server.device.obsreset.succeeded() else: # Assign Resource command success self.logger.info( "Calling AssignResource command succeeded() method") self.this_server.device.assign.succeeded() elif self._mccs_sa_obs_state == ObsState.ABORTED: try: retry_count = 0 while retry_count < 3: if self.device_data.is_abort_command_executed: # Abort command success self.logger.info( "Calling Abort command succeeded() method") self.this_server.device.abort.succeeded() break sleep(0.1) retry_count += 1 except Exception as e: self.logger(str(e))
class AssignedResourcesMaintainer: """ Assigned Resources Maintainer class for tmc Low. """ def __init__(self, logger=None): if logger == None: self.logger = logging.getLogger(__name__) else: self.logger = logger self.mccs_ln_asigned_res_event_id = {} self.this_server = TangoServerHelper.get_instance() self.device_data = DeviceData.get_instance() mccs_subarray_ln_fqdn = self.this_server.read_property( "MccsSubarrayLNFQDN")[0] self.mccs_client = TangoClient(mccs_subarray_ln_fqdn) def subscribe(self): # Subscribe assignedResources (forwarded attribute) of MccsSubarrayLeafNode mccs_event_id = self.mccs_client.subscribe_attribute( const.EVT_MCCSSA_ASSIGNED_RESOURCES, self.assigned_resources_cb) self.mccs_ln_asigned_res_event_id[self.mccs_client] = mccs_event_id log_msg = f"{const.STR_SUB_ATTR_MCCS_SALN_ASSIGNED_RESOURCES_SUCCESS}" \ f"{self.mccs_ln_asigned_res_event_id}" self.logger.info(log_msg) self.logger.info( const.STR_SUB_ATTR_MCCS_SALN_ASSIGNED_RESOURCES_SUCCESS) def assigned_resources_cb(self, event): """ Receives the subscribed assigned_resources attribute value. :param evt: Tango event on MCCS Subarray assigned_resources attribute. :type: Event object It has the following members: - date (event timestamp) - reception_date (event reception timestamp) - type (event type) - dev_name (device name) - name (attribute name) - value (event value) :return: None """ device_name = event.device.dev_name() log_msg = "Event on assigned_resources attribute is: {}".format( str(event)) self.logger.info(log_msg) if not event.err: self.device_data.assignd_resources_by_mccs = event.attr_value.value log_msg = "Event on assigned_resources attribute is: {}".format( str(event)) self.logger.info(log_msg) self.update_assigned_resources_attribute( self.device_data.assignd_resources_by_mccs) self.logger.info( const.STR_SUB_ATTR_MCCS_SALN_ASSIGNED_RESOURCES_SUCCESS) log_msg = "MccsSubarray.assigned_resources attribute value is: {}".format( str(self.device_data.assignd_resources_by_mccs)) self.logger.info(log_msg) else: log_message = f"{const.ERR_SUBSR_MCCSSA_ASSIGNED_RES_ATTR}{device_name}{event}" self.logger.info(log_message) self.this_server.write_attr("activityMessage", log_message, False) def update_assigned_resources_attribute(self, mccs_assigned_resources): """ This method updates the SubarrayNode.assigned_resources attribute. """ if mccs_assigned_resources: input_json_arg = json.loads(mccs_assigned_resources) del input_json_arg["interface"] json_argument = {} json_argument[ "interface"] = "https://schema.skatelescope.org/ska-low-tmc-assignedresources/1.0" json_argument["mccs"] = input_json_arg self.this_server.write_attr("assigned_resources", json.dumps(json_argument)) log_msg = "assigned_resources attribute value is: {}".format( str(json.dumps(json_argument))) self.logger.info(log_msg) def unsubscribe(self): """ This function unsubscribes MccsSubarray.assigned_resources attribute. :param : None :return: None """ for tango_client, event_id in self.mccs_ln_asigned_res_event_id.items( ): tango_client.unsubscribe_attribute(event_id)