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
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
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