Ejemplo n.º 1
0
    def test_alarm_propagation(self):
        device_name = '%s/sub1/1' % self.DOMAIN_NAME
        members_template = ['%s/capability/sub1cap1', '%s/capability/sub1cap2']
        members = [member % self.DOMAIN_NAME for member in members_template]

        self.add_members(device_name, 'tiles', members)
        dp = DeviceProxy(device_name)
        self.assertNotEqual(dp.state(), AttrQuality.ATTR_ALARM)
        member_dp = DeviceProxy(members[0])
        alarm_data = json.dumps({
            'name': 'an_attr',
            'min_alarm': '20',
            'max_alarm': '50'
        })
        member_dp.command_inout('set_attribute_alarm', alarm_data)
        member_dp.an_attr = 10
        attr = AttributeProxy(members[0] + '/an_attr')
        self.assertEqual(attr.read().quality, AttrQuality.ATTR_ALARM)
        self.assertEqual(member_dp.state(), PyTango._PyTango.DevState.ALARM)
        i = 0
        while (dp.state() != PyTango._PyTango.DevState.ALARM) and i < 3:
            sleep(1)
            i += 1

        self.assertEqual(dp.state(), PyTango._PyTango.DevState.ALARM)
Ejemplo n.º 2
0
    def make_test(self, attr=None):
        """
        Performs a full test of the tango server device
        If the attribute is given - trying to read it as well
        :param attr:
        :return:
        """
        #@TODO : test database
        res = True
        try:
            d = DeviceProxy(self.device)
            self.debug("Device ({}) ping value ({})".format(
                self.device, d.ping()))

            state = d.state()

            if state == DevState.FAULT or state == DevState.UNKNOWN:
                raise DevFailed

            if self.testString(attr):
                v = d.read_attribute(attr)

        except (DevFailed, AttributeError) as e:
            res = False

        return res
Ejemplo n.º 3
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.º 4
0
    def run(self):
        """
        Starts a process
        :return:
        """
        self.debug("Starting a door command ({}, {})".format(
            self.door, self.args))

        info, error, output = "", "", ""

        try:
            # connect to the door, run macro
            d = DeviceProxy(self.door)
            state = d.state()

            d.RunMacro(self.args)

            state = d.state()
            while (True):
                time.sleep(0.2)
                if state == DevState.ON or state == DevState.ALARM:
                    break
                state = d.state()

            output = d.read_attribute("output").value
            info = d.read_attribute("info").value
            error = d.read_attribute("error").value
        except (DevFailed, AttributeError) as e:
            output = "Door connection error ({})".format(self.door)
            self.error(output)

        self.debug(
            "Received information from the door \nOutput: {}\nInfo: {}\nError: {}"
            .format(output, info, error))

        if output is None:
            output = []
        if info is None:
            info = []
        if error is None:
            error = []

        if self.bresponse:
            self.emitter.emitSignal(output, info, error)
Ejemplo n.º 5
0
    def run(self):
        """
        Starts a process
        :return:
        """
        self.debug("Starting a pytango runner ({}/{}/{})".format(
            self.device, self.attr, self.value))

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

            state = d.state()
            if state == DevState.FAULT:
                raise DevFailed

            d.write_attribute(self.attr, self.value)
        except DevFailed:
            self.error("Error with the pytango runner ({}/{}/{})".format(
                self.device, self.attr, self.value))
Ejemplo n.º 6
0
class TangoResolutionComplex(BaseHardwareObjects.Equipment):
#     resoState = {
#         None: 'unknown',
#         'UNKNOWN': 'unknown',
#         'CLOSE': 'closed',
#         'OPEN': 'opened',
#         'MOVING': 'moving',
#         'FAULT': 'fault',
#         'DISABLE': 'disabled',
#         'OFF': 'fault',
#         'ON': 'unknown'
#         }
        
    stateDict = {
         "UNKNOWN": 0,
         "OFF":     1,
         "ALARM":   1,
         "STANDBY": 2,
         "RUNNING": 4,
         "MOVING":  4,
         "2":       2,
         "1":       1}
   
    
    def _init(self):
        self.currentResolution = None
        self.currentDistance = None
        self.currentWavelength = None
        self.currentEnergy = None
        self.connect("equipmentReady", self.equipmentReady)
        self.connect("equipmentNotReady", self.equipmentNotReady)
        #self.device = SimpleDevice(self.getProperty("tangoname"), waitMoves = False, verbose=False)
        self.device = DeviceProxy(self.getProperty("tangoname"))
        #self.device.timeout = 3000 # Setting timeout to 3 sec
        
        #self.monodevice = SimpleDevice(self.getProperty("tangoname2"), waitMoves = False, verbose=False)

        hobj = self.getProperty("BLEnergy")
        logging.getLogger("HWR").debug('TangoResolution: load specify the %s hardware object' % hobj)
        self.blenergyHO = None
        if hobj is not None:
            try:
                self.blenergyHO=HardwareRepository.HardwareRepository().getHardwareObject(hobj)
            except:
                logging.getLogger("HWR").error('TangoResolutionComplex: BLEnergy is not defined in resolution equipment %s', str(self.name()))
       
        if self.blenergyHO is not None:
            #self.connect(self.blenergyHO, "energyChanged",self.energyChanged)
            self.blenergyHO.connect("energyChanged",self.energyChanged)
        else:
            logging.info('TANGORESOLUTION : BLENERGY is not defined in TangoResolution equipment %s', str(self.name()))

        #self.connect(self.blenergyHO,, "energyChanged",self.energyChanged)
        #self.connect(self.beam_info_hwobj, 
        #                 "beamPosChanged", 
        #                 self.beam_position_changed)
            #self.blenergyHO.connectSignal('energyChanged', self.energyChanged)
        # creer un chanel sur l'energy: pour faire un update 
        positChan = self.getChannelObject("position") # utile seulement si statechan n'est pas defini dans le code
        positChan.connectSignal("update", self.positionChanged)
        stateChan = self.getChannelObject("state") # utile seulement si statechan n'est pas defini dans le code
        stateChan.connectSignal("update", self.stateChanged)
        
        self.currentDistance = self.device.position
        self.currentEnergy = self.blenergyHO.getCurrentEnergy()
        self.currentWavelength = self.blenergyHO.getCurrentWavelength()
        return BaseHardwareObjects.Equipment._init(self)

        
    def init(self):
        #self.detm = self.getDeviceByRole("detm")
        #self.dtox = self.getDeviceByRole("dtox")
        #self.dist2res = self.getCommandObject("dist2res")
        #self.res2dist = self.getCommandObject("res2dist")
        self.__resLimitsCallback = None
        
        
        self.__resLimitsErrCallback = None
        self.__resLimits = {}

        #self.connect(self.device, "stateChanged", self.detmStateChanged)
        #self.dist2res.connectSignal("commandReplyArrived", self.newResolution)
        #self.res2dist.connectSignal("commandReplyArrived", self.newDistance)
    
    def positionChanged(self, value):
        res = self.dist2res(value)
        try:
            logging.getLogger("HWR").debug("%s: TangoResolution.positionChanged: %.3f", self.name(), res)
        except:
            logging.getLogger("HWR").error("%s: TangoResolution not responding, %s", self.name(), '')       
        self.emit('positionChanged', (res,))

    
    def getState(self):
        return TangoResolutionComplex.stateDict[str(self.device.State())] 

                
    def equipmentReady(self):
        self.emit("deviceReady")


    def equipmentNotReady(self):    
        self.emit("deviceNotReady")
        

    def get_value(self):
        return self.getPosition()
        

    def getPosition(self):
        #if self.currentResolution is None:
        self.recalculateResolution()
        return self.currentResolution

    def energyChanged(self, energy,wave=None):
        #logging.getLogger("HWR").debug(" %s energychanged : %.3f wave is %.3f", self.name(), energy,wave)
        if self.currentEnergy is None:
            self.currentEnergy = energy
        if type(energy) is not float:
            logging.getLogger("HWR").error("%s: TangoResolution Energy not a float: %s", energy, '')
            return
        if abs(self.currentEnergy - energy) > 0.0002:
            self.currentEnergy = energy # self.blenergyHO.getCurrentEnergy()
            self.wavelengthChanged(self.blenergyHO.getCurrentWavelength())
        
    def wavelengthChanged(self, wavelength):
        self.currentWavelength = wavelength
        self.recalculateResolution()
        
    def recalculateResolution(self):
        self.currentDistance = self.device.position
        self.currentResolution = self.dist2res(self.currentDistance)
        if self.currentResolution is None:
            return
        self.newResolution(self.currentResolution) 

    def newResolution(self, res):      
        if self.currentResolution is None:
            self.currentResolution = self.recalculateResolution()
        logging.getLogger().info("new resolution = %.3f" % res)
        self.currentResolution = res
        self.emit("positionChanged", (res, ))
    
    def connectNotify(self, signal):
        #logging.getLogger("HWR").debug("%s: TangoResolution.connectNotify, : %s", \
        #                                                  self.name(), signal)
        if signal == "stateChanged":
            self.stateChanged(self.getState())
        
        #elif signal == 'limitsChanged':
        #    self.motorLimitsChanged()
            
        elif signal == 'positionChanged':
            self.positionChanged(self.device.position)
#        self.setIsReady(True)

    def stateChanged(self, state):
        #logging.getLogger("HWR").debug("%s: TangoResolution.stateChanged: %s"\
        #                                            % (self.name(), state))
        try:
            self.emit('stateChanged', (TangoResolutionComplex.stateDict[str(state)], ))
        except KeyError:
            self.emit('stateChanged', (TangoResolutionComplex.stateDict['UNKNOWN'], )) #ms 2015-03-26 trying to get rid of the fatal error with connection to detector ts motor


    def getLimits(self, callback=None, error_callback=None):
        #low, high = self.device.getLimits("position")
        # MS 18.09.2012 adapted for use without SimpleDevice
        position_info = self.device.attribute_query("position")
        low  = float(position_info.min_value)
        high = float(position_info.max_value)
        logging.getLogger("HWR").debug("%s: DetectorDistance.getLimits: [%.2f - %.2f]"\
                                                    % (self.name(), low, high))
        
        if callable(callback):
            self.__resLimitsCallback = callback
            self.__resLimitsErrCallback = error_callback

            self.__resLimits = {}
            rlow = self.dist2res(low, callback=self.__resLowLimitCallback, \
                                   error_callback=self.__resLimitsErrCallback)
            rhigh = self.dist2res(high, callback=self.__resHighLimitCallback,\
                                   error_callback=self.__resLimitsErrCallback)
        else:
            #rlow, rhigh = map(self.dist2res, self.device.getLimits("position"))
            # MS 18.09.2012 adapted for use without SimpleDevice
            #rhigh = self.device.attribute_query("positon").max_value
            rlow  = self.dist2res(low)
            rhigh   = self.dist2res(high)
            #position_info = self.device.attribute_query("position")
            #rlow  = float(position_info.min_value)
            #rhigh = float(position_info.max_value)
            
        
        logging.getLogger("HWR").debug("%s: TangoResolution.getLimits: [%.3f - %.3f]"\
                                                     % (self.name(), rlow, rhigh))
        return (rlow, rhigh)


    def isSpecConnected(self):
        #logging.getLogger().debug("%s: TangoResolution.isSpecConnected()" % self.name())
        return True
    
    def __resLowLimitCallback(self, rlow):
        self.__resLimits["low"]=float(rlow)

        if len(self.__resLimits) == 2:
            if callable(self.__resLimitsCallback):
              self.__resLimitsCallback((self.__resLimits["low"], self.__resLimits["high"]))
            self.__resLimitsCallback = None
            self.__dist2resA1 = None
            self.__dist2resA2 = None


    def __resHighLimitCallback(self, rhigh):
        self.__resLimits["high"]=float(rhigh)

        if len(self.__resLimits) == 2:
            if callable(self.__resLimitsCallback):
              self.__resLimitsCallback((self.__resLimits["low"], self.__resLimits["high"]))
            self.__resLimitsCallback = None
            self.__dist2resA1 = None
            self.__dist2resA2 = None
            

    def __resLimitsErrCallback(self):
        if callable(self.__resLimitsErrCallback):
            self.__resLimitsErrCallback()
            self.__resLimitsErrCallback = None
            self.__dist2resA1 = None
            self.__dist2resA2 = None


    def move(self, res, mindist=114, maxdist=1000):
        self.currentWavelength = self.blenergyHO.getCurrentWavelength()
        distance = self.res2dist(res)
        if distance >= mindist and distance <= maxdist:
            self.device.position = distance
        elif distance < mindist:
            logging.getLogger("user_level_log").warning("TangoResolution: requested resolution is above limit for specified energy, moving to maximum allowed resolution")
            self.device.position = mindist
        elif distance > maxdist:
            logging.getLogger("user_level_log").warning("TangoResolution: requested resolution is below limit for specified energy, moving to minimum allowed resolution")
            self.device.position = maxdist
            

    def newDistance(self, dist):
        self.device.position = dist

    def motorIsMoving(self):
        return self.device.state().name in ['MOVING', 'RUNNING']
        
    def stop(self):
        try:
            self.device.Stop()
        except:
            logging.getLogger("HWR").err("%s: TangoResolution.stop: error while trying to stop!", self.name())
            pass
        
    def dist2res(self, Distance, callback=None, error_callback=None):

        #Distance = float(Distance)# MS 2015-03-26 moving statement inside try loop
        try:
            Distance = float(Distance)
            #Wavelength = self.monodevice._SimpleDevice__DevProxy.read_attribute("lambda").value
            if self.currentWavelength is None:
                self.currentWavelength = self.blenergyHO.getCurrentWavelength()
            thetaangle2 = math.atan(DETECTOR_DIAMETER/2./Distance)
            Resolution = 0.5*self.currentWavelength /math.sin(thetaangle2/2.)
            if callable(callback):
                callback(Resolution)
            return Resolution
        except:
            if callable(error_callback):
                error_callback()
    
    def dist2resWaveLenght(self,wavelength, Distance, callback=None, error_callback=None):

        #Distance = float(Distance)# MS 2015-03-26 moving statement inside try loop
        try:
            #Distance = Distance
            #Wavelength = self.monodevice._SimpleDevice__DevProxy.read_attribute("lambda").value
            
            thetaangle2 = math.atan(DETECTOR_DIAMETER/2./Distance)
            Resolution = 0.5*wavelength /math.sin(thetaangle2/2.)
            if callable(callback):
                callback(Resolution)
            return Resolution
        except:
            if callable(error_callback):
                error_callback()

    
    def res2dist(self, Resolution):
        #print "********* In res2dist with ", Resolution
        Resolution = float(Resolution)
        #Wavelength = self.monodevice._SimpleDevice__DevProxy.read_attribute("lambda").value
        if self.currentWavelength is None:
            self.currentWavelength = self.blenergyHO.getCurrentWavelength()
        thetaangle=math.asin(self.currentWavelength / 2. / Resolution)
        Distance=DETECTOR_DIAMETER/2./math.tan(2.*thetaangle)
        #print "********* Distance ", Distance
        return Distance
Ejemplo n.º 7
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.º 8
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