def add_callback(self, callback, *, index=None, run_now=False, with_ctrlvars=True, **kw): """add a callback to a PV. Optional keyword arguments set here will be preserved and passed on to the callback at runtime. Note that a PV may have multiple callbacks, so that each has a unique index (small integer) that is returned by add_callback. This index is needed to remove a callback.""" if not callable(callback): raise CaprotoValueError() if index is not None: raise CaprotoValueError("why do this") index = next(self._cb_count) self.callbacks[index] = (callback, kw) if self.connected: self._check_auto_monitor_sub() if with_ctrlvars and self.connected: self.get_ctrlvars() if run_now: self.get(as_string=True) if self.connected: self.run_callback(index) return index
def _pyepics_get_value(value, string_value, full_type, native_count, *, requested_count, enum_strings, as_string, as_numpy): 'Handle all the fun pyepics get() kwargs' if (as_string and (full_type in ca.char_types) or full_type in ca.string_types): return string_value if as_string and full_type in ca.enum_types: if enum_strings is None: raise CaprotoValueError('Enum strings unset') ret = [] for r in value: try: ret.append(enum_strings[r]) except IndexError: ret.append('') if len(ret) == 1: ret, = ret return ret elif native_count == 1 and len(value) == 1: if requested_count is None: return value.tolist()[0] else: return value elif not as_numpy: return value.tolist() return value
def caput_many(pvlist, values, wait=False, connection_timeout=None, put_timeout=60): """put values to a list of PVs, as fast as possible This does not maintain the PV objects it makes. If wait is 'each', *each* put operation will block until it is complete or until the put_timeout duration expires. If wait is 'all', this method will block until *all* put operations are complete, or until the put_timeout duration expires. Note that the behavior of 'wait' only applies to the put timeout, not the connection timeout. Returns a list of integers for each PV, 1 if the put was successful, or a negative number if the timeout was exceeded. """ if len(pvlist) != len(values): raise CaprotoValueError( "List of PV names must be equal to list of values.") # context = PV._default_context # TODO: context.get_pvs(...) out = [] pvs = [ PV(name, auto_monitor=False, connection_timeout=connection_timeout) for name in pvlist ] wait_all = (wait == 'all') wait_each = (wait == 'each') for p, v in zip(pvs, values): try: p.wait_for_connection(connection_timeout) p.put(v, wait=wait_each, timeout=put_timeout, use_complete=wait_all) except TimeoutError: out.append(-1) else: out.append(1) if not wait_all: return [o if o == 1 else -1 for o in out] start_time = time.time() while not all([(p.connected and p.put_complete) for p in pvs]): elapsed_time = time.time() - start_time if elapsed_time > put_timeout: break return [1 if (p.connected and p.put_complete) else -1 for p in pvs]
def put(self, value, *, wait=False, timeout=30.0, use_complete=False, callback=None, callback_data=None): """set value for PV, optionally waiting until the processing is complete, and optionally specifying a callback function to be run when the processing is complete. """ if callback_data is None: callback_data = () if not self._args['write_access']: raise AccessRightsException( 'Cannot put to PV according to write access') if self._args['typefull'] in ca.enum_types: if isinstance(value, str): try: value = self.enum_strs.index(value) except ValueError: raise CaprotoValueError('{} is not in Enum ({}'.format( value, self.enum_strs)) if isinstance(value, str): if self.typefull in ca.char_types: # have to add a null-terminator char value = value.encode(STR_ENC) + b'\0' else: value = (value, ) elif not isinstance(value, Iterable): value = (value, ) if len(value) and isinstance(value[0], str): value = tuple(v.encode(STR_ENC) for v in value) notify = any((use_complete, callback is not None, wait)) if callback is None and not use_complete: run_callback = None else: def run_callback(cmd): if use_complete: self._args['put_complete'] = True if callback is not None: callback(*callback_data) # So, in pyepics, put_complete strictly refers to the functionality # where we toggle 'put_complete' in the args after a # WriteNotifyResponse. if notify: if use_complete: self._args['put_complete'] = False else: wait = False self._caproto_pv.write(value, wait=wait, callback=run_callback, timeout=timeout, notify=notify)