global_previous_state = {} class GetStatus(): """This class calculates the highest priority alarm active for all parts of the source id. It scans the active alarms list, splits each source id and returns the highest priority alarm to a dict object id_to_status. It stores the previuos state of the dict object and compares current to previous. ALARMST tags are then updated if they have been removed, added or the value changed Args: whid : Warehouse id for the project/ tag provider(string) alarm_data: Current active alarms(dict) KeyError: N/A""" def __init__(self, whid, alarm_data): self.whid = whid self.alarm_data = alarm_data self.id_to_status = {} self.tag_provider = "[%s_SCADA_TAG_PROVIDER]" % (whid) self.logger = system.util.getLogger("%s-Update-Visualisation" % (whid)) def update_status(self, item, priority): if(self.id_to_status.get(item) is None or self.id_to_status.get(item) < priority): self.id_to_status[item] = priority def build_status(self): for k, v in self.alarm_data.items(): equipment, device, sub_device = "","","" alarm_dict = v source_id = alarm_dict.get("sourceId") priority = alarm_dict.get("priority") state = alarm_dict.get("state") if state != 2: id_elements = source_id.split("/") controller = id_elements[0] if len(id_elements) > 4: self.logger.error("Incorrect length for source id") else: while True: path = "/".join(id_elements) self.update_status(path, priority) id_elements.pop() if len(id_elements) == 0: break global global_previous_state self.calculate_diff() global_previous_state = self.id_to_status def build_alarm_paths_and_values(self, keys, paths, values): for item in keys: value = self.id_to_status.get(item) tag_path = "%s%s/%s" % (self.tag_provider, item, "ALARMST") paths.append(tag_path) values.append(value) return paths, values def write_to_tags(self, message, paths, values): system.tag.writeBlocking(paths, values) self.logger.info(message + str(paths)) def calculate_diff(self): set_previous_values = set(global_previous_state.keys()) set_current_values = set(self.id_to_status.keys()) intersect = set_current_values.intersection(set_previous_values) removed_keys = set_previous_values - intersect added_keys = set_current_values - intersect changed_values = set(k for k in intersect if global_previous_state[k] != self.id_to_status[k]) tag_paths_to_delete = [] values_to_delete = [] for i in removed_keys: tag_path = "%s%s/%s" % (self.tag_provider, i, "ALARMST") tag_paths_to_delete.append(tag_path) values_to_delete.append(0) tag_paths_to_add, values_to_add = self.build_alarm_paths_and_values(added_keys, [], []) for item in added_keys: self.create_alarm_state_tags(self.tag_provider + item) changed_tag_paths, changed_values = self.build_alarm_paths_and_values(changed_values, [], []) if changed_tag_paths: self.write_to_tags("Changed paths = ", changed_tag_paths, changed_values) if tag_paths_to_add: self.write_to_tags("Paths added = ", tag_paths_to_add, values_to_add) if tag_paths_to_delete: self.write_to_tags("Deleted paths = ", tag_paths_to_delete, values_to_delete) def write_data(self): status_encoded = system.util.jsonEncode(self.id_to_status) system.tag.writeAsync([self.tag_provider + "System/IdToStatus"], [status_encoded] ) def create_alarm_state_tags(self, source_id): if not system.tag.exists(source_id +"/ALARMST"): tag = {"name": "ALARMST", "valueSource": "memory", "dataType": "Int1", "value": 0} create_tag = system.tag.configure(source_id, tag) if not create_tag[0].isGood(): logger.warn("Failed to create tag: " + str(source_id)) def reset_tags(provider, query): results = system.tag.query(provider, query) tags_to_write = [] values_to_write = [] for i in results: tags_to_write.append(str(i["fullPath"])) values_to_write.append(0) if tags_to_write: system.tag.writeBlocking(tags_to_write, values_to_write) def reset_alarms(whid): logger_name = "%s-Alarm-Reset" % (whid) logger = system.util.getLogger(logger_name) logger.warn("Alarms have been reset") provider = "%s_SCADA_TAG_PROVIDER" % (whid) limit = 100 query = { "options": { "includeUdtMembers": True, "includeUdtDefinitions": False }, "condition": { "path": "*ALARMST*", "attributes": { "values": [], "requireAll": True } }, "returnProperties": [ "tagType", "quality" ] } reset_tags(provider, query) def reset_disconnects(whid): logger_name = "%s-Disconnects-Reset" % (whid) logger = system.util.getLogger(logger_name) provider = "%s_SCADA_TAG_PROVIDER" % (whid) limit = 100 query = { "options": { "includeUdtMembers": True, "includeUdtDefinitions": False }, "condition": { "path": "*DCN*", "attributes": { "values": [], "requireAll": True } }, "returnProperties": [ "tagType", "quality" ] } reset_tags(provider, query) logger.warn("DCN tags have been reset")