class Monitor(Logger): def __init__(self, devName, attrName, minPeriod=0.1, minChange=0.001, callbacks=None, *args, **kwargs): super(Monitor, self).__init__(*args, **kwargs) self._devName = devName self._attrName = attrName self._name = "%s/%s" % (devName, attrName) try: self._proxy = DeviceProxy(self._devName) except: raise ReferenceError("DeviceProxy for %s not available" % self._name) self._eventId = None self._value = None self._quality = None self._minPeriod = minPeriod self._minChange = minChange self._timestamp = None self._callbacks = callbacks self.subscribe() def __del__(self): self.unsubscribe() def subscribe(self): self._eventId = self._proxy.subscribe_event(self._attrName, EventType.CHANGE_EVENT, self, stateless=True) self.debug("%s subscribed: %d" % (self._name, self._eventId)) def unsubscribe(self): if hasattr(self, '_proxy') and self._proxy is not None: self._proxy.unsubscribe_event(self._eventId) def push_event(self, event): if event is not None and event.attr_value is not None: if self._checkPeriod(event.attr_value.time.totime()): self._timestamp = event.attr_value.time.totime() if self._checkChange(event.attr_value.value): self._value = event.attr_value.value self._quality = event.attr_value.quality self.info("%s new value %s (%s, %s)" % (self._name, self._value, self._quality, self._timestamp)) self._reviewCallbacks() @property def minPeriod(self): return self._minPeriod @minPeriod.setter def minPeriod(self, value): self._minPeriod = float(value) def _checkPeriod(self, timestamp): if self._timestamp is None: self.debug("%s: No previous timestamp" % (self._name)) return True else: t_diff = timestamp - self._timestamp if t_diff > self._minPeriod: self.debug("%s: old enough value (%f)" % (self._name, t_diff)) return True self.debug("%s: to recent (%f)" % (self._name, t_diff)) return False @property def minChange(self): return self._minChange @minChange.setter def minChange(self, value): self._minChange = float(value) def _checkChange(self, value): if self._value is None: self.debug("%s: No previous value" % (self._name)) return True else: v_diff = abs(value - self._value) if v_diff > self._minChange: self.debug("%s: change enough value (%f)" % (self._name, v_diff)) return True self.debug("%s: to small change (%f)" % (self._name, v_diff)) return False def _value_getter(self): return self._value value = property(_value_getter) @property def timestamp(self): return self._timestamp @property def quality(self): return self._quality @property def callbacks(self): return self._callbacks def appendCb(self, function): if hasattr(function, '__call__'): if self._callbacks is None: self._callbacks = [] self._callbacks.append(function) def _reviewCallbacks(self): if self._callbacks is not None: for callback in self._callbacks: callback()
class _DeviceHelper(object): __CMD_FILTER = set(("init", "state", "status")) __ATTR_FILTER = set(("state", "status")) def __init__(self, dev_name, *args, **kwargs): self.dev_name = dev_name self.device = Device(dev_name, *args, **kwargs) self.slots = weakref.WeakKeyDictionary() def connect(self, signal, slot, event_type=PyTango.EventType.CHANGE_EVENT): i = self.device.subscribe_event(signal, event_type, slot) self.slots[slot] = i return i def disconnect(self, signal, slot): i = self.slots.pop(slot) self.device.unsubscribe_event(i) def get_attr_cache(self, refresh=False): try: cache = self.__attr_cache if not cache: refresh = True except AttributeError: refresh = True if refresh: cache = {} dev = self.device try: for attr_info in dev.attribute_list_query_ex(): attr_name = attr_info.name if attr_name.lower() in self.__ATTR_FILTER: continue cache[attr_name] = attr_info except PyTango.DevFailed: pass self.__attr_cache = cache return cache def get_attr_info(self, name): cache = self.get_attr_cache() result = cache.get(name) if result: return result else: cache = self.get_attr_cache(refresh=True) return cache.get(name) def get_cmd_cache(self, refresh=False): try: cache = self.__cmd_cache if not cache: refresh = True except AttributeError: refresh = True if refresh: cache = {} dev = self.device try: for cmd_info in dev.command_list_query(): cmd_name = cmd_info.cmd_name if cmd_name.lower() in self.__CMD_FILTER: continue cmd_func = functools.partial(_command, dev, cmd_info) cmd_func.__name__ = cmd_name cmd_func.__doc__ = cmd_info.in_type_desc cmd_info.func = cmd_func cache[cmd_name] = cmd_info except PyTango.DevFailed: pass self.__cmd_cache = cache return cache def get_cmd_info(self, name): cache = self.get_cmd_cache() result = cache.get(name) if result: return result else: cache = self.get_cmd_cache(refresh=True) return cache.get(name) def is_cmd(self, name): return name.lower() in self.get_cmd_cache() def members(self): result = self.get_attr_cache().keys() result.extend(self.get_cmd_cache().keys()) return result def get(self, name): dev = self.device result = self.get_attr_info(name) if result: result = dev.read_attribute(name) value = result.value if result.type == PyTango.DevEncoded: result = loads(*value) else: result = value return result result = self.get_cmd_info(name) if result is None: raise KeyError("Unknown %s" % name) return result def set(self, name, value): result = self.get_attr_info(name) if result is None: raise KeyError("Unknown attribute %s" % name) if result.data_type == PyTango.DevEncoded: self.device.write_attribute(name, dumps(value)) else: self.device.write_attribute(name, value) def get_info(self): try: return self.__info except AttributeError: pass try: info = self.device.info() self.__dict__["__info"] = info return info except PyTango.DevFailed: return None def __str__(self): return self.dstr() def __repr__(self): return str(self) def dstr(self): info = self.get_info() klass = "Device" if info: klass = info.dev_class return "{0}({1})".format(klass, self.dev_name)
from flask import Flask, request, session, g, redirect, url_for, abort, \ render_template, flash import click from PyTango import DeviceProxy from PyTango import EventType from datetime import datetime def callback(event): print("callback called:" + str(datetime.now())) if (event.err != "False"): print(event.attr_value.value) app = Flask(__name__) # create the application instance :) app.config.from_envvar('FLASKR_SETTINGS', silent=True) tango_test = DeviceProxy("sys/tg_test/1") event_id = tango_test.subscribe_event("Status", EventType.CHANGE_EVENT, callback, [], True) @app.route('/') def getRoot(): print("in getRoot ") return "hello world"
class TangoConnector(Connector): value_changed = pyqtSignal(str, name="valueChanged") def __init__(self, uri=None, attributes=[], policy=UpdatePolicy.POLLING, interval=1.0): #QThread.__init__(self) self.alive = False self.connected = False self.poll_attributes = {} self.thread = threading.Thread(target=self.run, name=uri) try: self.proxy = DeviceProxy(uri) self.connected = True except: self.attributes["state"]["value"] = State.UNKNOWN self.janus.utils["logger"].error("TangoConnector(" + self.uri + ").__init__() " + "connection failed") self.janus.utils["logger"].debug("", exc_info=True) Connector.__init__(self, uri, attributes, policy, interval) def add_attribute(self, attribute=None): Connector.add_attribute(self, attribute=attribute) if type(attribute) is not dict or "attr" not in attribute: return if "mode" in attribute and attribute["mode"] == "execute": return if "name" in attribute: name = attribute["name"] else: name = attribute["attr"].lower() self.poll_attributes[attribute["attr"]] = name def update_policy(self, policy=UpdatePolicy.POLLING, interval=1.0): self.interval = interval if policy != UpdatePolicy.POLLING and self.isRunning(): self.stop() elif policy != UpdatePolicy.EVENTBASED: for attr in self.attributes.keys(): if "event" not in self.attributes[attr]: continue try: self.proxy.unsubscribe_event( self.attributes[attr]["event"]) except: self.janus.utils["logger"].error( "TangoConnector(" + self.uri + ").update_policy() " + "failed to unsubscribe from tango event") self.janus.utils["logger"].debug("", exc_info=True) del self.attributes[attr]["event"] if policy == UpdatePolicy.POLLING and not self.thread.is_alive(): self.thread.start() elif policy == UpdatePolicy.EVENTBASED: for attr in self.attributes.keys: try: self.attributes[attr]["event"] = \ self.proxy.subscribe_event(EventType.CHANGE_EVENT, \ self.on_tango_event, [], False) except: self.janus.utils["logger"].error( "TangoConnector(" + self.uri + ").update_policy() " + "failed to subscribe to tango event") self.janus.utils["logger"].debug("", exc_info=True) self.policy = policy def on_tango_event(self, event): try: name = event.attr_name value = event.attr_value.value except: self.janus.utils["logger"].warning("TangoConnector(" + self.uri + ").on_tango_event() " + "invalid tango event type") self.janus.utils["logger"].debug("", exc_info=True) self.attributes[self.poll_attributes[name]]["value"] = value self.value_changed.emit(self.poll_attributes[name]) def stop_device(self): self.stop() def stop(self): self.alive = False self.thread.join() pass def run(self): print("thread started: {} ({})".format( threading.get_ident(), threading.currentThread().getName())) self.alive = True while self.alive: #remember when we started timestamp = time.time() #try to poll attributes try: attrs = self.proxy.read_attributes( list(self.poll_attributes.keys())) except: self.attributes["state"]["value"] = State.UNKNOWN self.janus.utils["logger"].error( "TangoConnector(" + self.uri + ").run() " + "reading tango attributes failed") self.janus.utils["logger"].debug("", exc_info=True) attrs = [] #assign attribute values and fire change signal if necessary for attr in attrs: name = self.poll_attributes[attr.name] changed = False if "delta" in self.attributes[name]: if self.attributes[name]["value"] is None or \ abs(self.attributes[name]["value"] - attr.value) > \ self.attributes[name]["delta"]: changed = True elif name == "state" and \ int(self.attributes[name]["value"]) != int(attr.value): changed = True elif name == "image_8": changed = True elif self.attributes[name]["value"] != attr.value: changed = True if changed: if name == "state": self.attributes[name]["value"] = State(int(attr.value)) else: self.attributes[name]["value"] = attr.value self.value_changed.emit(name) if not self.alive: break #wait for the rest of the polling interval interval = int((self.interval - (time.time() - timestamp))) while interval > 0: if interval > 0.05: time.sleep(0.05) interval -= 0.05 else: time.sleep(interval) interval = 0 if not self.alive: break print("closing thread: {} ({})".format( threading.get_ident(), threading.currentThread().getName())) def state(self, refresh=False): if refresh: try: self.attributes["state"]["value"] = State( int(self.proxy.state())) except: self.attributes["state"]["value"] = State.UNKNOWN self.janus.utils["logger"].error("TangoConnector(" + self.uri + ").state() " + "reading tango state failed") self.janus.utils["logger"].debug("", exc_info=True) return self.attributes["state"]["value"] def read(self, attribute=None, refresh=False, alt=None): if refresh or self.attributes[attribute]["value"] is None: try: self.attributes[attribute]["value"] = \ self.proxy.read_attribute(self.attributes[attribute]["attr"]).value except: self.janus.utils["logger"].error( "TangoConnector(" + self.uri + ")" + ".read(" + attribute + ") " + "reading tango attribute failed") self.janus.utils["logger"].debug("", exc_info=True) if self.attributes[attribute]["value"] is None \ and alt is not None: return alt return self.attributes[attribute]["value"] def write(self, attribute=None, value=None): try: self.proxy.write_attribute(self.attributes[attribute]["attr"], value) return True except: self.janus.utils["logger"].error("TangoConnector(" + self.uri + ")" + ".write(" + attribute + ") " + "writing tango attribute failed") self.janus.utils["logger"].debug("", exc_info=True) return False def execute(self, command=None, *values): try: if len(values) == 0: value = self.proxy.command_inout( self.attributes[command]["attr"]) else: value = self.proxy.command_inout( self.attributes[command]["attr"], values) except Exception as e: self.janus.utils["logger"].error("TangoConnector(" + self.uri + ")" + ".execute(" + command + ") " + "executing tango command failed") self.janus.utils["logger"].debug("", exc_info=True) return None return value