Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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