diff --git a/devices/toolkit/archiver.py b/devices/toolkit/archiver.py index ec359c2a81bb427d54149275b9d4a3168c674922..0b7d8b31112f1fb9dc399bc7fc088494e48df846 100644 --- a/devices/toolkit/archiver.py +++ b/devices/toolkit/archiver.py @@ -3,7 +3,7 @@ from logging import raiseExceptions import traceback from clients.attribute_wrapper import attribute_wrapper -from tango import DeviceProxy +from tango import DeviceProxy, AttributeProxy from datetime import datetime, timedelta import time @@ -38,12 +38,37 @@ class Archiver(): self.cm.write_attribute('SetPollingPeriod', polling_period) self.cm.write_attribute('SetPeriodEvent', event_period) self.cm.AttributeAdd() + print('Attribute %s added to archiving list!' % attribute_name) except Exception as e: if 'already archived' not in str(e).lower(): traceback.format_exc() else: print('Attribute %s already in archiving list!' % attribute_name) + def add_attributes_to_archiver(self,device_name,global_archive_period:int = None, exclude:list = ['Status','State']): + """ + Add sequentially all the attributes of the selected device in the event subscriber list, if not already present + """ + d = DeviceProxy(device_name) + attrs_list = list(d.get_attribute_list()) # cast to list otherwise removal is not allowed + try: + for a in exclude: attrs_list.remove(a) + except: + pass + for a in attrs_list: + attr_fullname = str(device_name+'/'+a).lower() + attr_proxy = AttributeProxy(attr_fullname) + if attr_proxy.is_polled() is True: # if not polled attribute is also not archived + try: + if self.es.AttributeList is None or not(self.cm.AttributeSearch(a)): + polling_period = attr_proxy.get_poll_period() + archive_period = global_archive_period or int(attr_proxy.get_property('archive_period')['archive_period'][0]) + self.add_attribute_to_archiver(attr_fullname,polling_period=polling_period, + event_period=archive_period) + #time.sleep(0.5) + except: + print(traceback.format_exc()) + def remove_attribute_from_archiver(self, attribute_name:str): """ Stops the data archiving of the attribute passed as input, and remove it from the subscriber's list. @@ -53,11 +78,26 @@ class Archiver(): try: self.cm.AttributeStop(attribute_name) self.cm.AttributeRemove(attribute_name) + print('Attribute %s removed!' % attribute_name) except Exception as e: if 'attribute not found' not in str(e).lower(): traceback.format_exc() else: print('Attribute %s not found!' % attribute_name) + + def remove_attributes_by_device(self,device_name:str): + """ + Stops the data archiving of all the attributes of the selected device, and remove them from the + subscriber's list + """ + d = DeviceProxy(device_name) + attrs_list = d.get_attribute_list() + for a in attrs_list: + try: + attr_fullname = str(device_name+'/'+a).lower() + self.remove_attribute_from_archiver(attr_fullname) + except: + print(traceback.format_exc()) def start_archiving_attribute(self, attribute_name:str): """ @@ -109,16 +149,16 @@ class Archiver(): """ try: self.remove_attribute_from_archiver(attribute_name) - time.sleep(3) + time.sleep(1) self.add_attribute_to_archiver(attribute_name,polling_period,event_period,strategy) - time.sleep(3) + time.sleep(1) self.start_archiving_attribute(attribute_name) except: print(traceback.format_exc()) def get_subscriber_attributes(self,es_name:str = None): """ - Returns the list of attributes managed by the event subscriber + Return the list of attributes managed by the event subscriber """ if es_name is not None: es = DeviceProxy(es_name) @@ -127,6 +167,48 @@ class Archiver(): attrs = es.AttributeList or [] return attrs + def get_subscriber_errors(self,es_name:str = None): + """ + Return a dictionary of the attributes currently in error, defined as AttributeName -> AttributeError + """ + if es_name is not None: + es = DeviceProxy(es_name) + else: + es = self.es + try: + attrs = es.AttributeList or [] + errs = es.AttributeErrorList or [] + return dict((a,e) for a,e in zip(attrs,errs) if e) + except: + print('No attribute errors in the subscriber') + return {} + + def get_attribute_errors(self,attribute_name:str): + """ + Return the error related to the attribute + """ + if (len(attribute_name.split('/'))!=4): + raise AttributeFormatException + errs_dict = self.get_subscriber_errors() + for e in errs_dict: + if attribute_name in e: + return errs_dict.get(e) + return None + + def get_subscriber_load(self,use_freq=True,es_name:str = None): + """ + Return the estimated load of an archiver, in frequency of records or number + of attributes + """ + if es_name is not None: + es = DeviceProxy(es_name) + else: + es = self.es + if use_freq: + return str(es.AttributeRecordFreq)+(' events/period' ) + else: + return len(es.AttributeList) + class AttributeFormatException(Exception): """ Exception that handles wrong attribute naming