def _pushAttrEvent(self, event): """Handler of (non-configuration) events from the PyTango layer. It handles the subscription and the (de)activation of polling :param event: (A PyTango event) :return: (evt_type, evt_value) Tuple containing the event type and the event value. evt_type is a `TaurusEventType` (or None to indicate that there should not be notification to listeners). evt_value is a TaurusValue, an Exception, or None. """ if not event.err: self.__attr_value, self.__attr_err = self.decode( event.attr_value), None self.__subscription_state = SubscriptionState.Subscribed self.__subscription_event.set() if not self.isPollingForced(): self._deactivatePolling() return TaurusEventType.Change, self.__attr_value elif event.errors[0].reason in EVENT_TO_POLLING_EXCEPTIONS: if not self.isPollingActive(): self.info("Activating polling. Reason: %s", event.errors[0].reason) self.__subscription_state = SubscriptionState.PendingSubscribe self._activatePolling() return None, None else: self.__attr_value, self.__attr_err = None, PyTango.DevFailed( *event.errors) self.__subscription_state = SubscriptionState.Subscribed self.__subscription_event.set() self._deactivatePolling() return TaurusEventType.Error, self.__attr_err
def push_event(self, event): """Method invoked by the PyTango layer when a change event occurs. Default implementation propagates the event to all listeners.""" curr_time = time.time() manager = Manager() sm = self.getSerializationMode() if not event.err: # if it is a configuration event if isinstance(event, PyTango.AttrConfEventData): event_type = TaurusEventType.Config self._decodeAttrInfoEx(event.attr_conf) # make sure that there is a self.__attr_value if self.__attr_value is None: # TODO: maybe we can avoid this read? self.__attr_value = self.getValueObj(cache=False) # if it is an attribute event else: event_type = TaurusEventType.Change self.__attr_value, self.__attr_err = self.decode( event.attr_value), None self.__subscription_state = SubscriptionState.Subscribed self.__subscription_event.set() if not self.isPollingForced(): self._deactivatePolling() # notify the listeners listeners = tuple(self._listeners) if sm == TaurusSerializationMode.Concurrent: manager.addJob(self.fireEvent, None, event_type, self.__attr_value, listeners=listeners) else: self.fireEvent(event_type, self.__attr_value, listeners=listeners) elif event.errors[0].reason in EVENT_TO_POLLING_EXCEPTIONS: if self.isPollingActive(): return self.info("Activating polling. Reason: %s", event.errors[0].reason) self.__subscription_state = SubscriptionState.PendingSubscribe self._activatePolling() else: self.__attr_value, self.__attr_err = None, PyTango.DevFailed( *event.errors) self.__subscription_state = SubscriptionState.Subscribed self.__subscription_event.set() self._deactivatePolling() listeners = tuple(self._listeners) if sm == TaurusSerializationMode.Concurrent: manager.addJob(self.fireEvent, None, TaurusEventType.Error, self.__attr_err, listeners=listeners) else: self.fireEvent(TaurusEventType.Error, self.__attr_err, listeners=listeners)
def power_on(self): motors = [] motors = motors + self.get_pool_motors('hfm_y') motors = motors + self.get_pool_motors('vfm_x1') motors = motors + self.get_pool_motors('vfm_x2') attrs = [] all_on = True for mot in motors: try: power_attr = AttributeProxy(mot.name + '/PowerOn') attrs.append(power_attr) if power_attr.read().value == False: power_attr.write(True) all_on = False except PyTango.DevFailed as e: self._log.warning( "Motor {} doesn't have a PowerOn attribute".format( mot.name)) starttime = time.time() while all_on == False: if time.time() - starttime > 2: raise PyTango.DevFailed( "Timeout while waiting for motors to power on") all_on = True time.sleep(0.1) for attr in attrs: if attr.read().value == False: all_on = False
def __init__(self, attr=None, pytango_dev_attr=None, config=None): # config parameter is kept for backwards compatibility only TaurusAttrValue.__init__(self) if config is not None: from taurus.core.util.log import deprecated deprecated(dep='"config" kwarg', alt='"attr"', rel='4.0') attr = config if attr is None: self._attrRef = None else: self._attrRef = weakref.proxy(attr) self.config = self._attrRef # bck-compat self._pytango_dev_attr = p = pytango_dev_attr if p is None: self._pytango_dev_attr = p = PyTango.DeviceAttribute() return if self._attrRef is None: return numerical = (PyTango.is_numerical_type(self._attrRef._tango_data_type, inc_array=True) or p.type == PyTango.CmdArgType.DevUChar) if p.has_failed: self.error = PyTango.DevFailed(*p.get_err_stack()) else: # spectra and images can be empty without failing if p.is_empty and self._attrRef.data_format != DataFormat._0D: dtype = FROM_TANGO_TO_NUMPY_TYPE.get( self._attrRef._tango_data_type) if self._attrRef.data_format == DataFormat._1D: shape = (0, ) elif self._attrRef.data_format == DataFormat._2D: shape = (0, 0) p.value = numpy.empty(shape, dtype=dtype) if not (numerical or self._attrRef.type == DataType.Boolean): # generate a nested empty list of given shape p.value = [] for _ in xrange(len(shape) - 1): p.value = [p.value] rvalue = p.value wvalue = p.w_value if numerical: units = self._attrRef._units if rvalue is not None: rvalue = Quantity(rvalue, units=units) if wvalue is not None: wvalue = Quantity(wvalue, units=units) elif isinstance(rvalue, PyTango._PyTango.DevState): rvalue = DevState[str(rvalue)] self.rvalue = rvalue self.wvalue = wvalue self.time = p.time # TODO: decode this into a TaurusTimeVal self.quality = quality_from_tango(p.quality)
def _fromTangoMotor(motor): import PyTango attrs = "base_rate", "velocity", "acceleration", "deceleration" attr_values = motor.read_attributes(attrs) v = [] for attr_value in attr_values: if attr_value.has_failed: raise PyTango.DevFailed(*attr_value.get_err_stack()) v.append(attr_value.value) return Motor(min_vel=v[0], max_vel=v[1], accel_time=v[2], decel_time=v[3])
def check_attribute(self, attr_name, dev_name, target_value, period=0.3, timeout=1.0, tolerance=None, write=True): """ Check an attribute to see if it reaches a target value. Returns a deferred for the result of the check. Upon calling the function the target is written to the attribute if the "write" parameter is True. Then reading the attribute is polled with the period "period" for a maximum number of retries. If the read value is within tolerance, the callback deferred is fired. If the read value is outside tolerance after retires attempts, the errback is fired. The maximum time to check is then period x retries :param attr_name: Tango name of the attribute to check, e.g. "position" :param dev_name: Tango device name to use, e.g. "gunlaser/motors/zaber01" :param target_value: Attribute value to wait for :param period: Polling period when checking the value :param timeout: Time to wait for the attribute to reach target value :param tolerance: Absolute tolerance for the value to be accepted :param write: Set to True if the target value should be written initially :return: Deferred that will fire depending on the result of the check """ self.logger.info("Check attribute \"{0}\" on \"{1}\"".format( attr_name, dev_name)) if dev_name in self.device_names: factory = self.device_factory_dict[self.device_names[dev_name]] d = factory.buildProtocol("check", attr_name, None, write=write, target_value=target_value, tolerance=tolerance, period=period, timeout=timeout) d.addCallback(self.update_attribute) else: self.logger.error("Device name {0} not found among {1}".format( dev_name, self.device_factory_dict)) err = tango.DevError( reason="Device {0} not used".format(dev_name), severety=tango.ErrSeverity.ERR, desc= "The device is not in the list of devices used by this controller", origin="check_attribute") d = Failure(tango.DevFailed(err)) return d
def get_device(self, device_name): self.logger.debug("{0} Returning device {1}".format(self, device_name)) try: dev = self.devices[device_name] except KeyError: # Maybe this should just raise an exception instead of auto-adding: task = self.add_device(device_name) try: dev = task.get_result(wait=True, timeout=self.timeout) if task.is_cancelled(): raise pt.DevFailed(dev) except AttributeError: pass return dev
def write_attribute(self, name, device_name, data): self.logger.info("Write attribute \"{0}\" on \"{1}\"".format( name, device_name)) if device_name in self.device_names: factory = self.device_factory_dict[self.device_names[device_name]] d = factory.buildProtocol("write", name, data) else: self.logger.error("Device name {0} not found among {1}".format( device_name, self.device_factory_dict)) err = tango.DevError( reason="Device {0} not used".format(device_name), severety=tango.ErrSeverity.ERR, desc= "The device is not in the list of devices used by this controller", origin="write_attribute") d = Failure(tango.DevFailed(err)) return d
def test_read_failure(self, monkeypatch): device_name = "sys/tg_test/1" attribute_name = "float_scalar" maxdelta = datetime.timedelta(seconds=5) s = TangoDeviceAttributeSource(device_name, attribute_name, metadata={"attribute": attribute_name}) ex = tango.DevFailed() # TODO: How to test handling of tango exceptions? def mockreturn(attribute_name): raise ex monkeypatch.setattr(s.device, 'read_attribute', mockreturn) data = s.read() now = datetime.datetime.now(timezone("Europe/Berlin")) assert data.timestamp - now < maxdelta assert data.failure is ex assert data.value is None assert data.metadata is not s.metadata assert data.metadata["attribute"] == attribute_name
def _pushConfEvent(self, event): """Handler of AttrConfEventData events from the PyTango layer. :param event: (PyTango.AttrConfEventData) :return: (evt_type, evt_value) Tuple containing the event type and the event value. evt_type is a `TaurusEventType` (or None to indicate that there should not be notification to listeners). evt_value is a TaurusValue, an Exception, or None. """ if not event.err: # update conf-related attributes self._decodeAttrInfoEx(event.attr_conf) # make sure that there is a self.__attr_value if self.__attr_value is None: # TODO: maybe we can avoid this read? self.__attr_value = self.getValueObj(cache=False) return TaurusEventType.Config, self.__attr_value else: self.__attr_value, self.__attr_err = None, PyTango.DevFailed( *event.errors) return TaurusEventType.Error, self.__attr_err
def mon(self, parameter_s=''): """Monitor a given attribute. %mon -a <attribute name> - activates monitoring of given attribute %mon -d <attribute name> - deactivates monitoring of given attribute %mon -r - deactivates monitoring of all attributes %mon -i <id> - displays detailed information for the event with given id %mon -l <dev filter> <attr filter> - shows event table filtered with the regular expression for attribute name %mon - shows event table (= %mon -i .* .*)""" db = __get_db() if db is None: print("You are not connected to any Tango Database.") return # make sure parameter_s is a str and not a unicode parameter_s = str(parameter_s) opts, args = self.parse_options(parameter_s, 'adril', mode='list') if len(args) > 3: raise UsageError("%mon: too many arguments") if 'd' in opts: try: todel = args[0] except IndexError: raise UsageError("%mon -d: must provide an attribute to unmonitor") else: try: dev, _, attr = todel.rpartition("/") subscriptions = __get_device_subscriptions(dev) attr_id = subscriptions[attr.lower()] del subscriptions[attr.lower()] d = __get_device_proxy(dev) d.unsubscribe_event(attr_id) print("Stopped monitoring '%s'" % todel) except KeyError: raise UsageError("%%mon -d: Not monitoring '%s'" % todel) elif 'a' in opts: try: toadd = args[0] except IndexError: raise UsageError("%mon -a: must provide an attribute to monitor") dev, _, attr = toadd.rpartition("/") subscriptions = __get_device_subscriptions(dev) attr_id = subscriptions.get(attr.lower()) if attr_id is not None: raise UsageError("%%mon -a: Already monitoring '%s'" % toadd) d = __get_device_proxy(dev) w = __get_event_log() model = w.model() attr_id = d.subscribe_event(attr, PyTango.EventType.CHANGE_EVENT, model, []) subscriptions[attr.lower()] = attr_id print("'%s' is now being monitored. Type 'mon' to see all events" % toadd) elif 'r' in opts: for d, v in db._db_cache.devices.items(): d, subs = v[3], v[4] for _id in subs.values(): d.unsubscribe_event(_id) v[4] = {} elif 'i' in opts: try: evtid = int(args[0]) except IndexError: raise UsageError("%mon -i: must provide an event ID") except ValueError: raise UsageError("%mon -i: must provide a valid event ID") try: w = __get_event_log() e = w.getEvents()[evtid] if e.err: print(str(PyTango.DevFailed(*e.errors))) else: print(str(e)) except IndexError: raise UsageError("%mon -i: must provide a valid event ID") elif 'l' in opts: try: dexpr = args[0] aexpr = args[1] except IndexError: raise UsageError("%mon -l: must provide valid device and " \ "attribute filters") w = __get_event_log() w.show(dexpr, aexpr) else: w = __get_event_log() w.show()
def data(self, index, role=Qt.Qt.DisplayRole): if not index.isValid() or not (0 <= index.row() < len(self._records)): return Qt.QVariant() column, row = index.column(), index.row() record = self._records[row] if record.err: err = PyTango.DevFailed(*record.errors) else: err = None name = record.s_attr_name.lower() if role == Qt.Qt.DisplayRole: if column == ID: return Qt.QVariant(row) if column == HOST: return Qt.QVariant(record.host) elif column == DEVICE: return Qt.QVariant(record.dev_name) elif column == ATTRIBUTE: return Qt.QVariant(record.s_attr_name) elif column == VALUE: if err is None: return Qt.QVariant( deviceAttributeValueStr(record.attr_value)) else: return Qt.QVariant(err[0].reason) elif column == TIME: if err is None: return Qt.QVariant( record.attr_value.time.strftime("%H:%M:%S.%f")) else: return Qt.QVariant( record.reception_date.strftime("%H:%M:%S.%f")) elif role == Qt.Qt.TextAlignmentRole: if column in (HOST, DEVICE, ATTRIBUTE): return Qt.QVariant(Qt.Qt.AlignLeft | Qt.Qt.AlignVCenter) return Qt.QVariant(Qt.Qt.AlignRight | Qt.Qt.AlignVCenter) elif role == Qt.Qt.BackgroundRole: if column == VALUE: if err is None: if name == "state": bg = getBrushForState(record.attr_value.value)[0] else: bg = getBrushForQuality(record.attr_value.quality)[0] else: bg = Qt.QBrush(Qt.Qt.red) else: if index.row() % 2: bg = self.DftOddRowBrush[0] else: bg = self.DftEvenRowBrush[0] return Qt.QVariant(bg) elif role == Qt.Qt.ForegroundRole: if column == VALUE: if err is None: if name == "state": fg = getBrushForState(record.attr_value.value)[1] else: fg = getBrushForQuality(record.attr_value.quality)[1] else: fg = Qt.QBrush(Qt.Qt.white) else: if index.row() % 2: fg = self.DftOddRowBrush[1] else: fg = self.DftEvenRowBrush[1] return Qt.QVariant(fg) elif role == Qt.Qt.ToolTipRole: if err is None: return Qt.QVariant(str(record.attr_value)) else: return Qt.QVariant(str(record)) elif role == Qt.Qt.SizeHintRole: return self._getSizeHint(column) #elif role == Qt.Qt.StatusTipRole: #elif role == Qt.Qt.CheckStateRole: elif role == Qt.Qt.FontRole: return Qt.QVariant(Qt.QFont("Mono", 8)) return Qt.QVariant()