def __init__(self, pv_name_list: list): self.ctx = Context() self._pv_data = {} # full PV name and last update value self._pv_last_update = {} # full PV name and last update time self.pv_name_list = pv_name_list # list of PVs to monitor self.subscriptions = {} self._channel_data = []
def test_trigger_mode(): """ Do the two TriggerMode IntEnums agree? Do all the NewPerkinElmerDetector.TriggertModes read and write as expected? """ with ioc_process() as ioc: client = CaprotoThreadingClient() setpoint_pv, readback_pv = client.get_pvs( "Sim[det1]:cam1:TriggerMode", "Sim[det1]:cam1:TriggerMode_RBV") trigger_mode_setpoint = setpoint_pv.read().data trigger_mode_readback = readback_pv.read().data # expect the trigger mode to be INTERNAL when the IOC starts up assert (trigger_mode_setpoint == SimulatedPerkinElmerDetectorIoc.TriggerMode.INTERNAL) assert (trigger_mode_readback == SimulatedPerkinElmerDetectorIoc.TriggerMode.INTERNAL) assert trigger_mode_setpoint == NewPerkinElmerDetector.TriggerMode.INTERNAL assert trigger_mode_readback == NewPerkinElmerDetector.TriggerMode.INTERNAL for trigger_mode_client, trigger_mode_server in zip( NewPerkinElmerDetector.TriggerMode, SimulatedPerkinElmerDetectorIoc.TriggerMode, ): setpoint_pv.write(trigger_mode_client) trigger_mode_setpoint = setpoint_pv.read().data trigger_mode_readback = readback_pv.read().data assert trigger_mode_setpoint == trigger_mode_client assert trigger_mode_readback == trigger_mode_client assert trigger_mode_setpoint == trigger_mode_server assert trigger_mode_readback == trigger_mode_server
def test_specified_port(monkeypatch, context, ioc): pv, = context.get_pvs(ioc.pvs['float']) pv.wait_for_connection(timeout=10) circuit = pv.circuit_manager.circuit address_list = list(caproto.get_address_list()) address_list.append('{}:{}'.format(circuit.host, circuit.port)) def get_address_list(): return address_list for module in (caproto._utils, caproto, caproto.threading.client): if hasattr(module, 'get_address_list'): print('patching', module) monkeypatch.setattr(module, 'get_address_list', get_address_list) print() print('- address list is now:', address_list) shared_broadcaster = SharedBroadcaster() new_context = Context(shared_broadcaster) pv1, = new_context.get_pvs(ioc.pvs['float']) pv1.wait_for_connection() assert pv1.connected pv1.read() new_context.disconnect()
def __init__(self, prefix): from caproto.threading.client import Context self.prefix = prefix self.ctx = Context() self.RBV, = self.ctx.get_pvs(self.prefix + 'RBV') self.VAL, = self.ctx.get_pvs(self.prefix + 'VAL') self.VELO, = self.ctx.get_pvs(self.prefix + 'VELO') self.VALVE, = self.ctx.get_pvs(self.prefix + 'VALVE')
def __init__(self): self.io_push_queue = None self.io_pull_queue = None self.dt = 0.1 from caproto.threading.client import Context ctx = Context() record_name = 'simple_dl' self.lst, = ctx.get_pvs(f'{record_name}:LIST')
def cntx(request, shared_broadcaster): cntx = Context(broadcaster=shared_broadcaster, log_level='DEBUG') cntx.register() def cleanup(): cntx.disconnect() request.addfinalizer(cleanup) return cntx
def __init__(self, device_ca_server_prefix='device_mock:'): """ ToDo: rewrite the function to include the list of PVs. - restructure subscription to PVs to be saved as a dictionary. this will allow potential future expansions. """ from caproto.threading.client import Context self.ctx = Context() self.ca_name = device_ca_server_prefix self.dio, = self.ctx.get_pvs(f'{self.ca_name}dio', )
def __init__(self): from caproto.threading.client import Context ctx = Context() dt, t, cpu, memory, battery = ctx.get_pvs('simple_daq:dt', 'simple_daq:TIME', 'simple_daq:CPU', 'simple_daq:MEMORY', 'simple_daq:BATTERY') self.dt, self.t, self.cpu, self.memory, self.battery = dt, t, cpu, memory, battery
def test_client_and_host_name(shared_broadcaster): ctx = Context(broadcaster=shared_broadcaster, host_name='foo') assert ctx.host_name == 'foo' ctx = Context(broadcaster=shared_broadcaster, client_name='bar') assert ctx.client_name == 'bar' # test defaults ctx = Context(broadcaster=shared_broadcaster) assert ctx.host_name == socket.gethostname() assert ctx.client_name == getpass.getuser()
def __init__(self, pvs): from caproto.threading.client import Context ctx = Context() self.pvs = {} self.sub = {} self.token = {} for pv in pvs: print(f"subscribing to {pv}") self.pvs[pv], = ctx.get_pvs(pv) self.sub[pv] = self.pvs[pv].subscribe() self.token['MOCK:Nested_Indices'] = self.sub['MOCK:Nested_Indices'].add_callback(self.monitor)
def caproto_context_test(): ctx = CaprotoContext() pva, = ctx.get_pvs(pvnamea) # Ignore bulk conn option pva.read() start = time.time() pvb, = ctx.get_pvs(pvnameb) mid = time.time() val = pvb.read() end = time.time() print(mid - start) print(end - mid)
def context(request, shared_broadcaster): context = Context(broadcaster=shared_broadcaster) sb = shared_broadcaster yield context print('*** Cleaning up the context!') context.disconnect() assert not context._process_search_results_thread.is_alive() assert not context._activate_subscriptions_thread.is_alive() assert not context.selector.thread.is_alive() sb.disconnect() assert not sb._command_thread.is_alive() assert not sb.selector.thread.is_alive() assert not sb._retry_unanswered_searches_thread.is_alive()
def main(pvname1='int', pvname2='str'): '''Simple example which connects to two motorsim PVs (by default). It tests reading, writing, and subscriptions. ''' shared_broadcaster = SharedBroadcaster() ctx = Context(broadcaster=shared_broadcaster) # Some user function to call when subscriptions receive data. called = [] def user_callback(command): print("Subscription has received data: {}".format(command)) called.append(command) pv1, pv2 = ctx.get_pvs(pvname1, pvname2) pv1.wait_for_connection() pv2.wait_for_connection() # Read and subscribe to pv1 reading = pv1.read() print(f'{pv1} read back: {reading}') sub = pv1.subscribe() sub.add_callback(user_callback) print(f'{pv2} read back: {pv2.read()}') # Test writing a couple values: value1, value2 = [val + 1 for val in reading.data], reading.data pv1.write(value1, timeout=5) reading = pv1.read() print(f'wrote {value1} and read back: {reading.data}') time.sleep(0.1) pv1.write(value2, timeout=5) reading = pv1.read() print(f'wrote {value2} and read back: {reading.data}') time.sleep(0.1) # Clean up the subscription sub.clear() pv2.go_idle() pv1.go_idle() print('The subscription callback saw the following data:') for command in called: print(f' * {command.data}')
class Client(object): RBV = None VAL = None VELO = None VALVE = None def __init__(self, prefix): from caproto.threading.client import Context self.prefix = prefix self.ctx = Context() self.RBV, = self.ctx.get_pvs(self.prefix + 'RBV') self.VAL, = self.ctx.get_pvs(self.prefix + 'VAL') self.VELO, = self.ctx.get_pvs(self.prefix + 'VELO') self.VALVE, = self.ctx.get_pvs(self.prefix + 'VALVE')
def __init__( self, producer: KafkaProducer, context: CAContext, pv_name: str, output_topic: str, schema: str, periodic_update_ms: Optional[int] = None, ): self._logger = get_logger() self._producer = producer self._output_topic = output_topic (self._pv, ) = context.get_pvs(pv_name) # Subscribe with "data_type='time'" to get timestamp and alarm fields sub = self._pv.subscribe(data_type="time") sub.add_callback(self._monitor_callback) self._cached_update: Optional[Tuple[ReadNotifyResponse, int]] = None self._output_type = None self._repeating_timer = None self._cache_lock = Lock() try: self._message_publisher = schema_publishers[schema] except KeyError: raise ValueError( f"{schema} is not a recognised supported schema, use one of {list(schema_publishers.keys())}" ) if periodic_update_ms is not None: self._repeating_timer = RepeatTimer( milliseconds_to_seconds(periodic_update_ms), self.publish_cached_update) self._repeating_timer.start()
def setup_module(module): default_setup_module(module) shared_broadcaster = SharedBroadcaster() PV._default_context = Context(broadcaster=shared_broadcaster, log_level='DEBUG') thread_client._dflt_context = thread_client.PVContext(shared_broadcaster) PV._default_context.register()
def get_connected_pvs(pv_list, timeout=TIMEOUT): """ Returns a list of connected PVs from the given PV list. Args: pv_list (list): The full PV names list. timeout (int, optional): PV connection timeout. Returns: (list): The connected PVs. """ ctx = Context() pvs = ctx.get_pvs(*pv_list, timeout=timeout) time.sleep(timeout) return [pv.name for pv in pvs if pv.connected]
def __init__(self,device_ca_server_prefix = 'device_mock:'): """ ToDo: rewrite the function to include the list of PVs. - restructure subscription to PVs to be saved as a dictionary. this will allow potential future expansions. """ from caproto.threading.client import Context self.ctx = Context() self.ca_name = device_ca_server_prefix self.pv_names = ['freq', 'dio', 'queue_length', 'data', 'peek_data', 'packet_shape', 'LIST'] self.pvs = {} for item in self.pv_names: self.pvs[item], = self.ctx.get_pvs(f'{self.ca_name}{item}',)
def setup_module(module): from conftest import start_repeater start_repeater() shared_broadcaster = SharedBroadcaster() PV._default_context = Context(broadcaster=shared_broadcaster, log_level='DEBUG') thread_client._dflt_context = thread_client.PVContext(shared_broadcaster) PV._default_context.register()
def test_thread_pv(threading_broadcaster): from caproto.threading.client import Context, PV pv1 = "XF:31IDA-OP{Tbl-Ax:X1}Mtr.VAL" # pv2 = "XF:31IDA-OP{Tbl-Ax:X2}Mtr.VAL" # Some user function to call when subscriptions receive data. called = [] def user_callback(*, value, **kwargs): print() print('-- user callback', value) called.append(True) ctx = Context(threading_broadcaster, log_level='DEBUG') ctx.register() time_pv = PV(pv1, context=ctx, form='time') ctrl_pv = PV(pv1, context=ctx, form='ctrl') time_pv.wait_for_connection() time_pv.add_callback(user_callback) print('time read', time_pv.get()) print('ctrl read', ctrl_pv.get()) time_pv.put(3, wait=True) time_pv.put(6, wait=True) time.sleep(0.1) assert time_pv.get() == 6 assert called print('read', time_pv.get()) print('done') repr(time_pv) for k, v in PV.__dict__.items(): if isinstance(v, property): getattr(time_pv, k) getattr(ctrl_pv, k)
def setup_pvs(pv_config): logger.debug("pv_config = %s", pv_config) ctx = Context() pv_names = [cfg['pv'] for cfg in pv_config['message']] subscribe_pvs(ctx, pv_names, data_callback) pv_names = [cfg['pv'] for cfg in pv_config['trigger']] subscribe_pvs(ctx, pv_names, trigger_callback) global_data['timestamp'] = 0
def save(prefix='13SIM1:', cam='cam1:', image='image1:'): sim_detector_pvs = { 'acquire': f'{prefix}{cam}Acquire', 'image_mode': f'{prefix}{cam}ImageMode', 'image_source': f'{prefix}{image}NDArrayPort', 'enabled': f'{prefix}{image}EnableCallbacks', 'unique_id': f'{prefix}{image}UniqueId_RBV', 'array_size0': f'{prefix}{image}ArraySize0_RBV', 'array_size1': f'{prefix}{image}ArraySize1_RBV', 'array_size2': f'{prefix}{image}ArraySize2_RBV', 'bayer_pattern': f'{prefix}{image}BayerPattern_RBV', 'array_data': f'{prefix}{image}ArrayData', 'color_mode': f'{prefix}{cam}ColorMode', 'color_mode_rbv': f'{prefix}{cam}ColorMode_RBV', } with Context() as ctx: ns = get_pv_container(ctx, sim_detector_pvs) for attr in sim_detector_pvs: print(attr, '=', getattr(ns, attr).read().data) ns.image_source.write('SIM1') ns.image_mode.write('Single', data_type=ChannelType.STRING) color_modes = [ enum_string.decode('ascii') for enum_string in ns.color_mode_rbv.read( data_type='control').metadata.enum_strings ] for color_mode in color_modes: ns.color_mode.write(color_mode, data_type=ChannelType.STRING, wait=True) time.sleep(0.1) ns.acquire.write(1, wait=True) image = ns.array_data.read().data array_size = [ size.read().data[0] for size in (ns.array_size0, ns.array_size1, ns.array_size2) ] print(color_mode, array_size, image.shape, image.dtype, image) with open(f'{color_mode}.{image.dtype.name}.npz', 'wb') as f: np.savez_compressed(f, array_size=array_size, image=image, color_mode=color_mode)
class Client(): def __init__(self, device_ca_server_prefix='device_mock:'): """ ToDo: rewrite the function to include the list of PVs. - restructure subscription to PVs to be saved as a dictionary. this will allow potential future expansions. """ from caproto.threading.client import Context self.ctx = Context() self.ca_name = device_ca_server_prefix self.dio, = self.ctx.get_pvs(f'{self.ca_name}dio', ) def get_dio(self): """ a wrapper to get digital state from the device handler process Parameters ---------- Returns ------- value :: integer Examples -------- >>> value = client.get_dio() """ return self.dio.read().data[0] def set_dio(self, value): """ a wrapper to get digital state from the device handler process Parameters ---------- value :: integer Returns ------- Examples -------- >>> client.set_dio(127) """ result = self.dio.write(value)
def main(pv1="XF:31IDA-OP{Tbl-Ax:X1}Mtr.VAL", pv2="XF:31IDA-OP{Tbl-Ax:X2}Mtr.VAL"): '''Simple example which connects to two motorsim PVs (by default). It tests reading, writing, and subscriptions. ''' shared_broadcaster = SharedBroadcaster() pv1 = "XF:31IDA-OP{Tbl-Ax:X1}Mtr.VAL" pv2 = "XF:31IDA-OP{Tbl-Ax:X2}Mtr.VAL" # Some user function to call when subscriptions receive data. called = [] def user_callback(command): print("Subscription has received data: {}".format(command)) called.append(True) ctx = Context(broadcaster=shared_broadcaster, log_level='DEBUG') ctx.register() ctx.search(pv1) ctx.search(pv2) # Send out connection requests without waiting for responses... chan1 = ctx.create_channel(pv1) chan2 = ctx.create_channel(pv2) # Set up a function to call when subscriptions are received. chan1.register_user_callback(user_callback) reading = chan1.read() print('reading:', reading) chan1.subscribe() chan2.read() chan1.unsubscribe(0) chan1.write((5, )) reading = chan1.read() assert reading.data == 5 print('reading:', reading) chan1.write((6, )) reading = chan1.read() assert reading.data == 6 print('reading:', reading) chan2.disconnect() chan1.disconnect() assert called
def simulated_traffic(send_queue, receive_queue): while True: item = send_queue.get() time.sleep(random.random()) receive_queue.put(item) receive_queue = queue.Queue() traffic_thread = threading.Thread(target=simulated_traffic, args=(send_queue, receive_queue)) traffic_thread.start() # Subscribe to position ctx = Context() pv, = ctx.get_pvs('random_walk:pos') pos_subscription = pv.subscribe(data_type='time') pos_readings = [] def append_pos_reading(reading): pos_readings.append(reading) pos_subscription.add_callback(append_pos_reading) def plan(threshold): yield from bps.open_run() yield from bps.kickoff(det, wait=True)
#!/usr/bin/env python3 from caproto.threading.client import Context ctx = Context() dt,t,cpu,memory,battery = ctx.get_pvs('simple:dt','simple:TIME','simple:CPU','simple:MEMORY','simple:BATTERY')
#!/usr/bin/env python3 from caproto.threading.client import Context prefix = 'wt:' ctx = Context() request, response = ctx.get_pvs(prefix + 'request', prefix + 'response') request.read() response.read()
def __init__(self): self.ctx = Context(timeout=5)
class PVDataSource: def __init__(self): self.ctx = Context(timeout=5) @rest_request_handler @require_authentication(permission='Read') async def read_pvs(self, request): post_data = await request.json() # strip non-ascii characters jso_str = json.dumps(post_data) jso_str = jso_str.encode('ascii', errors='ignore').decode() pv_names = json.loads(jso_str) pvs = self.ctx.get_pvs(*pv_names) data_list = [] for pv in pvs: data = self.pv_to_data(pv) data_list.append(data) return data_list @rest_request_handler @require_authentication(permission='Read') async def read_pv(self, request): pv_name = request.match_info.get('pv_name') pv = self.ctx.get_pvs(pv_name)[0] data = self.pv_to_data(pv) return data @rest_request_handler @require_authentication(permission='Write') async def write_pv(self, request): pv_name = request.match_info.get('pv_name') skip_wait = False if request.match_info.get('skip_wait'): skip_wait = True post_data = await request.json() # strip non-ascii characters jso_str = json.dumps(post_data) jso_str = jso_str.encode('ascii', errors='ignore').decode() post_data = json.loads(jso_str) pv = self.ctx.get_pvs(pv_name)[0] enum_post_data = post_data control_pv = pv.read(data_type='control') if 'ENUM' in control_pv.data_type.name: enum_post_data = [] for val in post_data: if isinstance(val, int): enum_post_data.append(val) else: enum_val = control_pv.metadata.enum_strings.index( val.encode()) enum_post_data.append(enum_val) result = pv.write(enum_post_data, wait=not skip_wait) if skip_wait or result.status.success == 1: data = self.pv_to_data(pv) return { 'status': 'success', 'message': 'PV value updated', 'data': data, } else: return { 'status': 'fail', 'message': result.status.description, } def pv_to_data(self, pv): if not pv.connected: return {'name': pv.name} pv_value = pv.read(data_type='time') data_type = pv_value.data_type.name meta_data = pv_value.metadata data_list = [] timestamp = 0 if 'ENUM' in data_type: timestamp = meta_data.timestamp * 1000 control_pv = pv.read(data_type='control') for data in pv_value.data: enum_val = control_pv.metadata.enum_strings[data] if type(enum_val) is bytes: data_list.append(enum_val.decode("utf-8")) else: data_list.append(enum_val) else: timestamp = meta_data.stamp.as_datetime().timestamp() * 1000 for data in pv_value.data: if type(data) is bytes: data_list.append(data.decode("utf-8")) else: data_list = pv_value.data.tolist() break return { 'data_type': pv_value.data_type.name, 'time_stamp': timestamp, 'alarm_status': caproto.AlarmStatus(meta_data.status).name, 'alarm_severity': caproto.AlarmSeverity(meta_data.severity).name, 'data': data_list, 'name': pv.name }
from caproto.threading.client import Context prefix = 'bitmap_generator:' ctx = Context() t1, = ctx.get_pvs(prefix + 't1') shape, = ctx.get_pvs(prefix + 'shape') image, = ctx.get_pvs(prefix + 'image')