Ejemplo n.º 1
0
    def read_attributes(self, attrs):
        """
        Reads attribute value, returns none in case of na error
        :param attr:
        :return:
        """
        res = []
        try:
            if not self.test(self.device):
                raise ValueError

            d = DeviceProxy(self.device)
            d.ping()

            self.debug("Device ({}) is online".format(self.device))

            state = d.state()
            values = None

            # read value only if the state is fine
            if state != DevState.FAULT and state != DevState.UNKNOWN:
                values = d.read_attributes(attrs)

                for value in values:
                    res.append(value.value)

            self.debug("Attributes value ({}/{}/{})".format(state, attrs, res))
        except DevFailed:
            self.error(
                "There is an error with access to the device ({})".format(
                    self.device))
        except ValueError:
            self.error("User has not provided a valid device name")

        return res
Ejemplo n.º 2
0
class TangoDevice(object):
    """
    Wrapper for basic Tango device.
    It provides registering device, halting device and executing commands
    """
    POLL_STATE_TIME = 0.5
    TEST_MODE = False

    def __init__(self, devicePath=None):
        """
        Class constructor
        @type devicePath: String
        """
        self.devicePath = devicePath
        self.maxValue = False
        self.minValue = False
        self.name = "Generic device"
        self.output = {}
        self.profiling = False
        self.deviceError = False
        self.defaultClass = self.__class__

        # state change marker
        self._bstate_changed = False
        self.old_state = None

        self.__thread = None

        try:
            self.__device_init()
        except:
            logging.error(
                str("Device %s could not be connected" % self.devicePath))
            self.name = self.devicePath
            if config.DEVICE_ALLOW_RETRY:
                self._retry_device()
                #raise Exception(str("Device %s could not be connected" % self.devicePath))
                # logging.error(str("Device %s could not be connected" % self.devicePath))
                #else:

                #raise Exception(str("Device %s could not be connected" % self.devicePath))

    def __postInit__(self):
        pass

    def __device_init(self):
        self.device = DeviceProxy(self.devicePath)
        info = self.device.import_info()
        self.name = info.name

        if (self.name in DEVICE_NAMES):
            self.name = DEVICE_NAMES[self.name]

        self.deviceError = False
        self.__postInit__()

    def _retry_device(self, callback=None):
        self.deviceError = True
        thread = Thread(target=self.__retry_routine, args=([callback]))
        threads.add_thread(thread)
        thread.start()
        self.__class__ = DummyDevice

    def __retry_routine(self, callback):
        retrySleep = [True]
        while (retrySleep[0] and threads.THREAD_KEEP_ALIVE):
            try:
                DeviceProxy(self.devicePath).state()
                logging.error("Device online: %s" % (self.devicePath))
                retrySleep = [False]
            except:
                logging.error("Device offline, retrying: %s" %
                              (self.devicePath))
            threads.thread_sleep(config.DEVICE_RETRY_INTERVAL,
                                 sleepFlags=retrySleep)
        if threads.THREAD_KEEP_ALIVE == True:
            self.__class__ = self.defaultClass
            self.__device_init()
            if callback: callback()
        return True

    def isDeviceError(self):
        return self.deviceError

    def halt(self, callBack=None):
        """
        Stop device
        """
        pass

    def running_remove(self, *args):
        """
        Remove device from all running devices set
        """
        try:
            if (not stopDevices):
                runningDevices.remove(self)
        except:
            pass

    def running_add(self):
        """
        Add device to all runing devices set
        """
        global runningDevices
        runningDevices.add(self)

    def is_connected(self):
        """
        Return true if device is connected
        @rtype: bool
        """
        if self.device is None: return False
        else: return True

    def read_attributes(self, attributes):
        try:
            return self.device.read_attributes(attributes)
        except:
            logging.error("Device read attribute error: retrying device")
            if not config.DEVICE_ALLOW_RETRY:
                raise Exception(
                    str("Device %s could not be connected" % self.devicePath))
            else:
                self._retry_device()
                return self.read_attributes(attributes)

    def read_attribute(self, attribute):
        try:
            return self.device.read_attribute(attribute)
        except:
            if not config.DEVICE_ALLOW_RETRY:
                raise Exception(
                    str("Device %s could not be connected" % self.devicePath))
            else:
                self._retry_device()
                return self.read_attribute(attribute)

    def write_attributes(self, attributes):
        """
        Write attribute to device
        @type attributes: list
        @rtype: String
        """
        res = None
        if self.device:
            for attribute in attributes:
                logging.info("Attribute: %s wrote on device: %s", attribute[0],
                             self.devicePath)

            try:
                self.device.state()
                res = self.device.write_attributes(attributes)
            except (DevFailed, AttributeError) as e:
                pass
        return res

    def write_attributes_async(self, attributes, callback=None):
        res = None
        if self.device:
            for attribute in attributes:
                logging.info("Attribute: %s wrote on device: %s", attribute[0],
                             self.devicePath)

            try:
                self.device.state()
                res = self.device.write_attributes_asynch(attributes, callback)
            except (DevFailed, AttributeError) as e:
                pass
        return res

    def execute_command(self, commandName, commandParam=None):
        """
        Execute command on device
        @type commandName: String
        @type commandParam: String
        @rtype: String
        """
        try:
            if self.device:
                return self.device.command_inout(commandName, commandParam)
        except:
            if not config.DEVICE_ALLOW_RETRY:
                raise Exception(
                    str("Device %s could not be connected" % self.devicePath))
            else:
                self._retry_device()
                return self.execute_command(commandName, commandParam)

    def wait_for_state(self, state, callback=None):
        """
        Wait for state
        @type state: DevState.state
        """
        if self.device:
            while (self.device.state() == state):
                sleep(self.POLL_STATE_TIME)
            if not (callback is None): callback(self)

    def wait_seconds(self, duration=1):
        """
        Wait for a time duration
        @type duration: float if not config.DEVICE_ALLOW_RETRY: 
                raise Exception(str("Device %s could not be connected" % self.devicePath))
            else: 
                self._retry_device()
                return self.execute_command(commandName, commandParam)
        """
        if self.device:
            sleep(duration)

    def poll(self,
             commandName,
             duration=0.1,
             commandResult=True,
             callback=None,
             commandParam=None):
        """
        Poll device with command
        @type commandName: String
        @type duration: float
        @type callback: fun
        @type commandParam: String  
        """
        while (self.execute_command(commandName, commandParam) == commandResult
               and threads.THREAD_KEEP_ALIVE):
            self.wait_seconds(duration)
        if not (callback is None): callback(self)

    def poll_attribute(self,
                       attrName,
                       duration=0.1,
                       attributeResult=True,
                       callback=None,
                       commandParam=None):
        """
        Poll device with command
        @type attrName: String
        @type duration: float
        @type callback: fun
        @type commandParam: String
        """
        while (self.read_attribute(attrName).value == attributeResult
               and threads.THREAD_KEEP_ALIVE):
            self.wait_seconds(duration)
        if not (callback is None): callback(self)

    def check_idle(self):
        """
        Check if device id idle
        """
        pass

    def is_idle(self):
        """
        Return True if is idle, False if not and None if unknown 
        """
        return None

    def start_profiling(self):
        if self.profiling: return False
        self.profiling = True
        logging.info("Profiling of device %s started" % self.devicePath)
        return True

    def stop_profiling(self):
        self.profiling = False
        self.cleanup_thread()

    def current_value(self, value):
        return self.read_attribute(value).value

    def __profiling_routine(self):
        pass

    @property
    def thread(self):
        return self.__thread

    def start_external_profiling(self, func):
        """
        Starts profiling with an external function
        """
        self.profiling = True

        if self.__thread is None:
            thread = threads.threading.Thread(target=func, args=([self]))
            threads.add_thread(thread)
            thread.start()

            self.__thread = thread

    def cleanup_thread(self):
        if self.__thread is not None:
            self.profiling = False
            threads.join_thread(self.__thread)
            self.__thread = None

    def state(self):
        """
        Overload of the state function to keep track of old states
        :return:
        """
        state = None
        try:
            state = DeviceProxy(self.devicePath).state()

            self._bstate_changed = False
            if state != self.old_state:
                self.old_state = state
                self._bstate_changed = True
        except DevFailed:
            pass
        return state

    def is_state_changed(self):
        return self._bstate_changed
Ejemplo n.º 3
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