From d15f246cd739abebf550b8c058a1166608a487c8 Mon Sep 17 00:00:00 2001 From: Ole Artz Date: Mon, 14 Aug 2017 11:50:48 +0200 Subject: [PATCH] DASH: Use CA monitor w/ callbacks Instead of our own thread continuously polling the PVs we now use the built-in CA *monitor* capabilities to be informed about PV status changes (connected/disconnected, value change) via callback functions. --- python_suite/dashboard/dashboard.py | 69 ++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/python_suite/dashboard/dashboard.py b/python_suite/dashboard/dashboard.py index 38d9837..5c3b242 100755 --- a/python_suite/dashboard/dashboard.py +++ b/python_suite/dashboard/dashboard.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -import json, threading +import json, threading, time import epics from bottle import route, run, static_file @@ -9,12 +9,44 @@ from bottle import jinja2_view as view CONFIG = None PVS = {} -def update_values(): +def cb_connection_change(**kwargs): global CONFIG + + if kwargs['conn']: + pass + # We are now connected + def fetch_ctrlvars(): + #print("Started thread for ", kwargs['pvname']) + #start = time.time() + p = PVS[kwargs['pvname']] + p.get_ctrlvars() + #end = time.time() + #print("Finished thread for ", kwargs['pvname'], " in ", end-start, " s. Unit: ", p.units) + #for group in CONFIG['groups']: + # for pv in group['PVs']: + # if pv['name'] != kwargs['pvname']: continue + # pv['unit'] = p.units or '' + tid = threading.Thread(target=fetch_ctrlvars) + tid.daemon = True + tid.start() + return + + # Otherwise: we are disconnected from the IOC! for group in CONFIG['groups']: for pv in group['PVs']: - p = PVS[pv['name']] - p.get_ctrlvars() + if pv['name'] != kwargs['pvname']: continue + + pv['value'] = '- disconnected -' + pv['unit'] = '' + pv['classes'] = 'disconnected' + + +def cb_value_update(**kwargs): + global CONFIG + for group in CONFIG['groups']: + for pv in group['PVs']: + if pv['name'] != kwargs['pvname']: continue + class_map = { epics.NO_ALARM : "", epics.MINOR_ALARM : "minor_alarm", @@ -22,20 +54,21 @@ def update_values(): epics.INVALID_ALARM : "invalid_alarm", None : "disconnected", } - pv['classes'] = class_map[p.severity] - if 'enum' in p.type: - pv['value'] = p.char_value + pv['classes'] = class_map[kwargs['severity']] + #print(kwargs['pvname'], kwargs['type']) + #print(kwargs) + if 'enum' in kwargs['type']: + if type(kwargs['char_value']) is bytes: + pv['value'] = kwargs['char_value'].decode('ascii') + else: + pv['value'] = kwargs['char_value'] else: - pv['value'] = p.value + pv['value'] = kwargs['value'] if pv['value'] is None: pv['value'] = '- disconnected -' - pv['unit'] = p.units or '' + pv['unit'] = kwargs['units'] or '' if pv['value'] == 'OFF': pv['value'] = '- OFF -' if pv['value'] == 'ON': pv['value'] = '- ON -' -def update_values_continuous(): - while True: - update_values() - @route('/') @view('pv_overview.jinja2') def index(): @@ -74,14 +107,10 @@ def main(): for group in CONFIG['groups']: for pv in group['PVs']: - PVS[pv['name']] = epics.PV(pv['name'], auto_monitor=True) - pv['value'] = 'Undefined' + pv['value'] = '- disconnected (initial) -' pv['unit'] = '' - pv['classes'] = '' - - uvt = threading.Thread(target=update_values_continuous) - uvt.daemon = True - uvt.start() + pv['classes'] = 'disconnected' + PVS[pv['name']] = epics.PV(pv['name'], auto_monitor=True, form='ctrl', callback=cb_value_update, connection_callback=cb_connection_change) run(host=args.host, port=args.port, debug=args.debug) -- 2.43.0