def initContexts(self, attrlist=[], sid=None): """ This method overrides SnapDialog.initContexts() """ #self.contextComboBox.blockSignals(True) #self.contextComboBox.clear() contexts = None self._Form.setWindowTitle( QtGui.QApplication.translate( "Form", fandango.get_tango_host().split(':', 1)[0] + ' -> Snapshoting', None, QtGui.QApplication.UnicodeUTF8)) print('SnapForm.initContexts(%s(%s),%s(%s))' % (type(attrlist), attrlist, type(sid), sid)) try: if attrlist: if all(map(fandango.isNumber, (attrlist, sid))): print('SnapForm.initContexts(int(%s),%s)' % (attrlist, sid)) contexts = {attrlist: self.snapapi.get_context(attrlist)} self._Form.setWindowTitle( QtGui.QApplication.translate( "Form", fandango.get_tango_host().split(':', 1)[0] + ' -> Snapshots for Context "' + str( self.snapapi.db.get_id_contexts(attrlist)[0] ['name']) + '"', None, QtGui.QApplication.UnicodeUTF8)) elif fandango.isSequence(attrlist): contexts = dict( (ID, self.snapapi.get_context(ID)) for ID in self.snapapi.db.find_context_for_attribute( attrlist)) self._Form.setWindowTitle( QtGui.QApplication.translate( "Form", fandango.get_tango_host().split(':', 1)[0] + ' -> Snapshots filtered by window content', None, QtGui.QApplication.UnicodeUTF8)) else: contexts = self.snapapi.get_contexts() except: Qt.QMessageBox.critical(self,"Tango Archiving Problem", "Could not talk with SnapManager DS.<br>" + \ "Please check if DS is running.") if contexts is not None: ctxs = sorted(contexts.values(), key=lambda s: s.name.lower()) for context in ctxs: self.contextComboBox.addItem( "%s [%d]" % (context.name, context.ID), Qt.QVariant(context.ID)) #self.contextComboBox.model().sort(0, Qt.Qt.AscendingOrder) if sid >= 0: self.listWidget.setCurrentRow(sid)
def __new__(cls,*p,**k): trend = p and p[0] or k['trend'] override = k.get('override',False) tango_host = k.get('tango_host',None) or fn.get_tango_host(fqdn=True) schema = k.get('schema','*') if not getattr(trend,'_ArchiveLoggers',None): trend._ArchiveLoggers = {} #cls.__instances if override or tango_host not in trend._ArchiveLoggers: trend._ArchiveLoggers[tango_host] = object.__new__(cls) trend._ArchiveLoggers[tango_host].setup(*p,**k) return trend._ArchiveLoggers[tango_host]
def __new__(cls, *p, **k): trend = p and p[0] or k['trend'] override = k.get('override', False) tango_host = k.get('tango_host', None) or fn.get_tango_host(fqdn=True) schema = k.get('schema', '*') if not getattr(trend, '_ArchiveLoggers', None): trend._ArchiveLoggers = {} #cls.__instances if override or tango_host not in trend._ArchiveLoggers: trend._ArchiveLoggers[tango_host] = object.__new__(cls) trend._ArchiveLoggers[tango_host].setup(*p, **k) return trend._ArchiveLoggers[tango_host]
def main(args=None): """ --range=YYYY/MM/DD_HH:mm,XXh """ import sys opts = dict(a.split('=', 1) for a in args if a.startswith('-')) print(opts) args = [a for a in args if not a.startswith('-')] print(args) #from taurus.qt.qtgui.container import TaurusMainWindow tmw = Qt.QMainWindow() #TaurusMainWindow() tmw.setWindowTitle('Tango Attribute Search (%s)' % (fn.get_tango_host())) table = ArchivingBrowser(domains=args, USE_SCROLL=True, USE_TREND=True) tmw.setCentralWidget(table) use_toolbar = True if use_toolbar: toolbar = QDictToolBar(tmw) toolbar.set_toolbar([ ##('PDFs','icon-all.gif',[ #('Pdf Q1','icon-all.gif',lambda:launch('%s %s'%('kpdf','TC_Q1.pdf'))), #('Pdf Q2','icon-all.gif',lambda:launch('%s %s'%('kpdf','TC_Q2.pdf'))), #('Pdf Q3','icon-all.gif',lambda:launch('%s %s'%('kpdf','TC_Q3.pdf'))), #('Pdf Q4','icon-all.gif',lambda:launch('%s %s'%('kpdf','TC_Q4.pdf'))), ## ]), #('Archiving Viewer','Mambo-icon.ico', lambda:launch('mambo')), ('Show New Trend', 'qwtplot.png', table.open_new_trend), ]) toolbar.add_to_main_window(tmw, where=Qt.Qt.BottomToolBarArea) tmw.show() if args: table.updateSearch(*args) if '--range' in opts: tracer('Setting trend range to %s' % opts['--range']) table.trend.applyNewDates(opts['--range'].replace('_', ' ').split(',')) return tmw
def init_ui(self, parent, mainwindow): try: PARENT_CLASS.__init__(self, parent) self._connected = False self._ui = Ui_AlarmList() self._ui.setupUi(self) if mainwindow: mainwindow = self.init_mw(mainwindow) self.mainwindow = mainwindow url = os.path.dirname( panic.__file__) + '/gui/icon/panic-6-banner.png' trace('... splash ...') px = Qt.QPixmap(url) self.splash = Qt.QSplashScreen(px) self.splash.showMessage('initializing application...') self.splash.show() trace('showing splash ... %s' % px.size()) except: print traceback.format_exc() if self.mainwindow: self.mainwindow.setWindowTitle( 'PANIC %s (%s[%s]@%s)' % (panic.__RELEASE__, self.scope, self.default_regEx, fn.get_tango_host().split(':')[0])) icon = '/gui/icon/panic-6-big.png' #'.svg' url = os.path.dirname(panic.__file__) + icon px = Qt.QPixmap(url) self.mainwindow.setWindowIcon(Qt.QIcon(px)) self.setExpertView(True) self._message = Qt.QMessageBox(self) self._message.setWindowTitle("Empty fields") self._message.setIcon(Qt.QMessageBox.Critical)
def load(tango_host, instance, devices, replace={}, overwrite=False, def_class='SimulatorDS'): """ the tango_host variable must match with the current tango_host; it is used to avoid accidental loading load .json files into simulated devices; one .json file per device devices may be a list of devices, a list of files or a dictionary {device:filename} """ assert tango_host == fn.get_tango_host() done = [] if isMapping(devices): filenames = devices else: devices = fn.toList(devices) filenames = {} for dd in devices: if os.path.isfile(dd): df, dd = dd, file2dev(dd) else: df, dd = dev2file(dd), dd filenames[dd] = df for dd, df in filenames.items(): exists = ft.get_matching_devices(dd) if exists and not overwrite: raise Exception('Device %s Already Exists!!!' % dd) data = json.load(open(df)) props = data['properties'] props = dict((str(k), map(str, v)) for k, v in props.items()) for r, rr in replace.items(): dd = clsub(r, rr, dd) for p, pp in props.items(): for i, l in enumerate(pp): props[p][i] = clsub(r, rr, l) if overwrite: props['polled_attr'] = [] props['polled_cmd'] = [] if data['dev_class'] == 'PyAlarm': if not exists: ft.add_new_device('PyAlarm/' + instance, 'PyAlarm', dd) props['AlarmReceivers'] = [] ft.put_device_property(dd, props) else: if not exists: ft.add_new_device(def_class + '/' + instance, def_class, dd) ft.put_device_property(dd, props) #if data['dev_class'] not in ('PySignalSimulator','PyAttributeProcessor','PyStateComposer','CopyCatDS'): vals = dict((str(k), v['value'] if v else 0) for k, v in data['attributes'].items()) dynattrs = [] attrprops = fn.dicts.defaultdict(dict) for k, v in sorted(vals.items()): if k.lower() in ('state', 'status'): continue if v is None: continue t = type(v).__name__ if t == 'unicode': t = 'str' v = str(v) if t != 'str' else "'%s'" % v dynattrs.append( #'%s = %s(%s) #%s'%( '%s = %s(VAR(%s,default=%s,WRITE=True)) #%s' % (k, k, t, v, data['attributes'][k]['data_type'])) attrprops[dd][k] = dict((p, data['attributes'][k].get(p, '')) for p in ('format', 'label', 'unit', 'min_alarm', 'max_alarm')) ft.put_device_property(dd, 'DynamicAttributes', dynattrs) try: ft.get_database().put_device_attribute_property( dd, dict((k, v) for k, v in attrprops[dd].items() if v)) except: fn.time.sleep(3.) done.append(dd) return done
def setupUi(self, Form, load=True): Snap_Core_Ui_Form.setupUi(self, Form) self.context = None self.snapshots = [] self.snapapi = SnapAPI() self._Form = Form Form.setWindowTitle( QtGui.QApplication.translate( "Form", '!:' + fandango.get_tango_host().split(':', 1)[0] + ' Snaps', None, QtGui.QApplication.UnicodeUTF8)) self.contextComboBox.setToolTip( QtGui.QApplication.translate("Form", "Choose a Context", None, QtGui.QApplication.UnicodeUTF8)) print 'connecting signals ...' QtCore.QObject.connect(self.contextComboBox, QtCore.SIGNAL("currentIndexChanged(int)"), self.onContextChanged) QtCore.QObject.connect(self.contextComboBox, QtCore.SIGNAL("activated(int)"), self.onContextChanged) self.contextComboBox.setMaximumWidth(250) self.comboLabel.setText( QtGui.QApplication.translate("Form", "Context:", None, QtGui.QApplication.UnicodeUTF8)) self.buttonNew.setText( QtGui.QApplication.translate("Form", "New", None, QtGui.QApplication.UnicodeUTF8)) icon_view = QtGui.QIcon(":/actions/document-new.svg") self.buttonNew.setIcon(icon_view) QtCore.QObject.connect(self.buttonNew, QtCore.SIGNAL("pressed()"), self.onNewPressed) self.buttonNew.setToolTip( QtGui.QApplication.translate("Form", "New Context", None, QtGui.QApplication.UnicodeUTF8)) self.buttonEditCtx.setText( QtGui.QApplication.translate("Form", "Edit", None, QtGui.QApplication.UnicodeUTF8)) icon_view = QtGui.QIcon(":/apps/accessories-text-editor.svg") self.buttonEditCtx.setIcon(icon_view) QtCore.QObject.connect(self.buttonEditCtx, QtCore.SIGNAL("pressed()"), self.onEditPressed) self.buttonEditCtx.setToolTip( QtGui.QApplication.translate("Form", "Edit Context", None, QtGui.QApplication.UnicodeUTF8)) print 'connected signals ...' self.filterLabel.setText( QtGui.QApplication.translate("Form", "Filter:", None, QtGui.QApplication.UnicodeUTF8)) self.filterComboBox.addItem('Name') self.filterComboBox.addItem('Reason') self.filterComboBox.addItem('Attributes') self.filterComboBox.setMaximumWidth(90) self.filterComboBox2.setEditable(True) QtCore.QObject.connect(self.filterComboBox, QtCore.SIGNAL("currentIndexChanged(int)"), self.onFilterComboChanged) refresh_icon = QtGui.QIcon(":/actions/view-refresh.svg") self.refreshButton.setIcon(refresh_icon) QtCore.QObject.connect(self.refreshButton, QtCore.SIGNAL("pressed()"), self.onRefreshPressed) self.refreshButton.setToolTip( QtGui.QApplication.translate("Form", "Refresh List", None, QtGui.QApplication.UnicodeUTF8)) self.infoLabel1_1.setText( QtGui.QApplication.translate("Form", "Author:", None, QtGui.QApplication.UnicodeUTF8)) self.infoLabel2_1.setText( QtGui.QApplication.translate("Form", "Reason:", None, QtGui.QApplication.UnicodeUTF8)) self.infoLabel3_1.setText( QtGui.QApplication.translate("Form", "Description:", None, QtGui.QApplication.UnicodeUTF8)) self.infoLabel4_1.setText( QtGui.QApplication.translate("Form", "Snapshots:", None, QtGui.QApplication.UnicodeUTF8)) self.buttonTake.setText( QtGui.QApplication.translate("Form", "Take Snapshot", None, QtGui.QApplication.UnicodeUTF8)) self.buttonTake.setToolTip( QtGui.QApplication.translate("Form", "Save Snapshot in Database", None, QtGui.QApplication.UnicodeUTF8)) icon_save = QtGui.QIcon(":/devices/camera-photo.svg") #icon_save=QtGui.QIcon(":/actions/document-save.svg")not_archived_HDB = [a for a in [t for t in csv if 'HDB' in csv[t]] if a not in last_values_HDB or last_values_HDB[a] is None] self.buttonTake.setIcon(icon_save) QtCore.QObject.connect(self.buttonTake, QtCore.SIGNAL("pressed()"), self.onSavePressed) self.buttonLoad.setText( QtGui.QApplication.translate("Form", "Load to Devices", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QObject.connect(self.buttonLoad, QtCore.SIGNAL("pressed()"), self.onLoadPressed) self.buttonLoad.setToolTip( QtGui.QApplication.translate("Form", "Load Snapshot to Devices", None, QtGui.QApplication.UnicodeUTF8)) icon_load = QtGui.QIcon(":/actions/go-jump.svg") self.buttonLoad.setIcon(icon_load) self.buttonImport.setText( QtGui.QApplication.translate("Form", "Import from CSV", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QObject.connect(self.buttonImport, QtCore.SIGNAL("pressed()"), self.onImportPressed) self.buttonImport.setToolTip( QtGui.QApplication.translate("Form", "Import from CSV File", None, QtGui.QApplication.UnicodeUTF8)) icon_csv = QtGui.QIcon(":/actions/document-open.svg") self.buttonImport.setIcon(icon_csv) self.buttonExport.setText( QtGui.QApplication.translate("Form", "Export to CSV", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QObject.connect(self.buttonExport, QtCore.SIGNAL("pressed()"), self.onExportPressed) self.buttonExport.setToolTip( QtGui.QApplication.translate("Form", "Export to CSV File", None, QtGui.QApplication.UnicodeUTF8)) icon_csv = QtGui.QIcon(":/actions/document-save-as.svg") self.buttonExport.setIcon(icon_csv) self.buttonDelSnap.setText( QtGui.QApplication.translate("Form", "Delete", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QObject.connect(self.buttonDelSnap, QtCore.SIGNAL("pressed()"), self.onDelSnapPressed) self.buttonDelSnap.setToolTip( QtGui.QApplication.translate("Form", "Delete Snapshot", None, QtGui.QApplication.UnicodeUTF8)) icon_csv = QtGui.QIcon(":/actions/edit-clear.svg") self.buttonDelSnap.setIcon(icon_csv) self.buttonEditSnap.setText( QtGui.QApplication.translate("Form", "Edit", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QObject.connect(self.buttonEditSnap, QtCore.SIGNAL("pressed()"), self.onEditSnapPressed) self.buttonEditSnap.setToolTip( QtGui.QApplication.translate("Form", "Edit Snap Comment", None, QtGui.QApplication.UnicodeUTF8)) icon_csv = QtGui.QIcon(":/apps/accessories-text-editor.svg") self.buttonEditSnap.setIcon(icon_csv) self.buttonDelCtx.setText( QtGui.QApplication.translate("Form", "Delete", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QObject.connect(self.buttonDelCtx, QtCore.SIGNAL("pressed()"), self.onDelCtxPressed) self.buttonDelCtx.setToolTip( QtGui.QApplication.translate("Form", "Delete Context", None, QtGui.QApplication.UnicodeUTF8)) icon_csv = QtGui.QIcon(":/actions/mail-mark-junk.svg") self.buttonDelCtx.setIcon(icon_csv) QtCore.QObject.connect(self.buttonClose, QtCore.SIGNAL("pressed()"), self.onClosePressed) self.tableLabel.setText( QtGui.QApplication.translate("Form", "Attribute list:", None, QtGui.QApplication.UnicodeUTF8)) self.tableWidget.setSelectionBehavior( QtGui.QAbstractItemView.SelectRows) self.listWidget.setSelectionMode( QtGui.QAbstractItemView.SingleSelection) QtCore.QObject.connect( self.listWidget, QtCore.SIGNAL( "currentItemChanged (QListWidgetItem *,QListWidgetItem *)"), self.onSnapshotChanged) QtCore.QObject.connect(self.viewComboBox, QtCore.SIGNAL("currentIndexChanged(int)"), self.changeView) #self.frame.setMaximumWidth(450) self.comp = diffWidget() self.comp.setMinimumWidth(450) QtCore.QObject.connect(self.comp._wi.diffButtonCompare, QtCore.SIGNAL("pressed()"), self.onCompareButtonPressed) self.viewComboBox.setToolTip( QtGui.QApplication.translate("Form", "Change View Mode", None, QtGui.QApplication.UnicodeUTF8)) self.comboLabel.show() self.gridLayout.addWidget(self.tableWidget) self.gridLayout.addWidget(self.taurusForm) self.gridLayout.addWidget(self.comp) if load: self.initContexts()
def setModel(self, model=None, rows=0, cols=0, side=0, fontsize=0, **kwargs): print('QAlarmPanel.setModel(%s)' % model) import panic, math if isinstance(model, AlarmView): self.view = model self.api = self.view.api else: #if fd.isString(model): self.api = panic.AlarmAPI(model, extended=True) self.view = AlarmView(api=self.api, verbose=False) self.tags = self.view.sort(sortkey=('priority', 'tag'), keep=False) self.alarms = self.view.alarms self.old_devs = set() self.actives = [] self.panels = [] self.setCurrentAlarm(None) self.fontsize = fontsize if rows and not cols: self.rows = int(rows) self.cols = int(math.ceil((1 + len(self.tags)) / self.rows)) elif cols and not rows: self.rows = int(math.ceil((1 + len(self.tags)) / cols)) self.cols = int(cols) else: self.cols = int(cols or math.ceil(math.sqrt(1 + len(self.tags)))) self.rows = int( rows or ((self.cols - 1) if self.cols * (self.cols - 1) >= 1 + len(self.tags) else self.cols)) self.setLayout(Qt.QGridLayout()) self.labels = [] for i in range(self.rows): self.labels.append([]) for j in range(self.cols): self.labels[i].append(QAlarmPanelLabel(self)) self.layout().addWidget(self.labels[i][j], i, j, 1, 1) self.logo = self.labels[-1][-1] self.logo.setClickHook(self.showGUI) self._title = 'PANIC Alarm Panel (%s)' % str(model or fd.get_tango_host()) self.setWindowTitle(self._title) url = os.path.dirname(panic.__file__) + '/gui/icon/panic-6-big.png' px = Qt.QPixmap(url) self.setWindowIcon(Qt.QIcon(px)) #self.labels[self.rows-1][self.cols-1].resize(50,50) print('QAlarmPanel(%s): %d alarms , %d cols, %d rows: %s' % (model, len(self.tags), self.cols, self.rows, fd.log.shortstr(self.tags)) + '\n' + '#' * 80) self.refreshTimer = Qt.QTimer() Qt.QObject.connect(self.refreshTimer, Qt.SIGNAL("timeout()"), self.updateAlarms) self.refreshTimer.start(self.REFRESH_TIME) side = side or (min((self.rows, self.cols)) == 1 and 50) or 50 #70#120 if all((cols, rows, side)): width, height = side * cols, side * rows self.logo.setPixmap(px.scaled(side, side)) else: width, height = min((800, side * self.cols)), min( (800, side * self.rows)) self.logo.setPixmap(px.scaled(side, side)) #70,70)) #px.scaled(height/self.rows,height/self.rows)) #if (width/self.rows)>=50: self.resize(width, height) self.show()
def load(tango_host,instance,devices,replace={},overwrite=False): """ the tango_host variable must match with the current tango_host; it is used to avoid accidental loading load .json files into simulated devices devices may be a list of devices, a list of files or a dictionary {device:filename} """ assert tango_host == fn.get_tango_host() done = [] if isMapping(devices): filenames = devices else: devices = fn.toList(devices) filenames = {} for dd in devices: if os.path.isfile(dd): df,dd = dd,file2dev(dd) else: df,dd = dev2file(dd),dd filenames[dd] = df for dd,df in filenames.items(): exists = ft.get_matching_devices(dd) if exists and not overwrite: raise Exception('Device %s Already Exists!!!'%dd) data = json.load(open(df)) props = data['properties'] props = dict((str(k),map(str,v)) for k,v in props.items()) for r,rr in replace.items(): dd = clsub(r,rr,dd) for p,pp in props.items(): for i,l in enumerate(pp): props[p][i] = clsub(r,rr,l) if overwrite: props['polled_attr'] = [] props['polled_cmd'] = [] if data['dev_class'] == 'PyAlarm': if not exists: ft.add_new_device('PyAlarm/'+instance,'PyAlarm',dd) props['AlarmReceivers'] = [] ft.put_device_property(dd,props) else: if not exists: ft.add_new_device('PyAttributeProcessor/'+instance,'PyAttributeProcessor',dd) ft.put_device_property(dd,props) #if data['dev_class'] not in ('PySignalSimulator','PyAttributeProcessor','PyStateComposer','CopyCatDS'): vals = dict((str(k),v['value'] if v else 0) for k,v in data['attributes'].items()) dynattrs = [] attrprops = fn.dicts.defaultdict(dict) for k,v in sorted(vals.items()): if k.lower() in ('state','status'): continue if v is None: continue t = type(v).__name__ if t == 'unicode': t = 'str' v = str(v) if t!='str' else "'%s'"%v dynattrs.append( #'%s = %s(%s) #%s'%( '%s = %s(VAR(%s,default=%s,WRITE=True)) #%s'%(k, k,t,v,data['attributes'][k]['data_type'])) attrprops[dd][k] = dict((p,data['attributes'][k].get(p,'')) for p in ('format','label','unit','min_alarm','max_alarm')) ft.put_device_property(dd,'DynamicAttributes',dynattrs) try: ft.get_database().put_device_attribute_property(dd, dict((k,v) for k,v in attrprops[dd].items() if v)) except: fn.time.sleep(3.) done.append(dd) return done
def get_panic_report(api=None,timeout=3000.,tries=3, devfilter = '*', attr = 'ActiveAlarms', trace=False): """ The key of the results: key.count('/') == 0 : alarm == 1: server == 2: device == 4: summary """ if api is None: api = panic.api() elif isString(api): api = panic.api(api) if not len(api.servers): if devfilter == '*': api.servers.load_by_name('PyAlarm/*') elif isString(devfilter): api.servers.load_by_name(devfilter) else: [api.servers.load_by_name(d) for d in devfilter] alldevs = fd.tango.get_all_devices(exported=True) #print('%d devices in %s'%(len(alldevs),fd.tango.get_tango_host())) result = fd.dicts.defaultdict(dict) result['//alarms//'] = api.alarms.keys() result['//devices//'] = api.devices.keys() result['//servers//'] = api.servers.keys() result['//attrs//'] = [] off = [] hung = [] slow = [] aslow = [] errors = {} for s,ss in api.servers.items(): admin = ss.get_admin_name() try: admin = fd.parse_tango_model(admin)['device'] except: print('unable to parse %s'%admin) continue if admin.lower() not in alldevs: off.append(admin) result[s]['devices'] = ss.get_classes()['PyAlarm'] for d in result[s]['devices']: if isSequence(devfilter): if d not in devfilter: continue elif not clsearch(devfilter,d): continue if admin in off: t = END_OF_TIME off.append(d) else: proxy = fd.get_device(d) t = get_device_timeout(d,timeout,tries,alldevs, proxy,trace=False,attr=attr) if t == END_OF_TIME: hung.append(d) if t*1e3 > timeout: slow.append(d) result[d]['timeout'] = t result[d]['attrs'] = 0 result[d]['alarms'] = len(api.devices[d].alarms) polling = float(api.devices[d].config['PollingPeriod']) result[d]['polling'] = polling try: evals = get_device_eval_times(proxy,timeout) teval = sum(evals.values()) ratio = teval/float(polling) result[d]['eval'],result[d]['ratio'] = teval,ratio except: evals = {} result[d]['eval'],result[d]['ratio'] = -1,-1 for a,aa in api.devices[d].alarms.items(): attrs = api.parse_attributes(aa['formula']) result[d]['attrs'] += len(attrs) result[a]['device'] = d result[a]['attrs'] = attrs result['//attrs//'].extend(attrs) result[a]['timeout'] = evals.get(a,-1) if result[a]['timeout'] > polling/result[d]['alarms']: aslow.append(a) result['//attrs//'] = sorted(set(map(str.lower,result['//attrs//']))) result['//off//'] = off result['//bloat//'] = [k for k in result if k.count('/')==2 and result[k].get('ratio',-1)>=1.] result['//hung//'] = hung result['//slow_devices//'] = slow result['//slow_alarms//'] = aslow #print('off devices: %s\n'%(off)) #print('hung devices: %s\n'%(hung)) #print('slow devices: %s\n'%(slow)) #print('bloat devices: %s\n'%([k for k in result #if '/' in k and result[k].get('ratio',-1)>=1.])) #print('slow alarms: %s\n'%aslow) if '-v' in opts: print(fd.get_tango_host()) for k,v in sorted(result.items()): if fd.isSequence(v): print('%s: %d'%(k,len(v))) elif fd.isNumber(v): print('%s: %d'%(k,v))