def test_limit_fields_and_description(request, prefix, context): pv = f'{prefix}C' run_example_ioc('caproto.ioc_examples.mocking_records', request=request, args=['--prefix', prefix], pv_to_check=pv) PV = get_pv(pv, context=context) def check_fields(): for k, v in PV.get_ctrlvars().items(): if k in field_map: fv, = read(f'{pv}.{field_map[k]}').data assert v == fv check_fields() for v in field_map.values(): work_pv = f'{pv}.{v}' write(work_pv, 2 * read(work_pv).data) check_fields() def string_read(pv): return b''.join(read(pv, data_type=ChannelType.STRING).data) assert string_read(f'{pv}.DESC') == b'The C pvproperty' write(f'{pv}.DESC', 'a new description', notify=True) assert string_read(f'{pv}.DESC') == b'a new description'
def test_pvproperty_string_array(request, ioc_name): info = conftest.run_example_ioc_by_name(ioc_name, request=request) array_string_pv = f'{info.prefix}array_string' sync.write(array_string_pv, ['array', 'of', 'strings'], notify=True) time.sleep(0.5) assert sync.read(array_string_pv).data == [b'array', b'of', b'strings']
def test_char_write(request, prefix): pv = f'{prefix}chararray' run_example_ioc('caproto.ioc_examples.type_varieties', request=request, args=['--prefix', prefix], pv_to_check=pv) write(pv, b'testtesttest', notify=True) response = read(pv) assert ''.join(chr(c) for c in response.data) == 'testtesttest'
def test_process_field(request, prefix, async_lib): run_example_ioc('caproto.tests.ioc_process', request=request, args=['--prefix', prefix, '--async-lib', async_lib], pv_to_check=f'{prefix}record.PROC') write(f'{prefix}record.PROC', [1], notify=True) write(f'{prefix}record.PROC', [1], notify=True) assert read(f'{prefix}count').data[0] == 2
def test_raw_timestamp(request): info = conftest.run_example_ioc_by_name( "caproto.ioc_examples.advanced.raw_timestamp", request=request) print("Triggering an update of value.") sync.write(f'{info.prefix}update', 1, notify=True) time.sleep(0.5) print("Reading back ``value``...") data = sync.read(f'{info.prefix}value', data_type='time') print(f"data={data} stamp={data.metadata.stamp}") assert data.metadata.stamp.nanoSeconds == 2**16 - 1
async def AdjustedAcquire(self, instance, value): self._capture_goal = read(self.hdf5_prefix + 'NumCapture').data # write(self.shutter_prefix + 'TriggerEnabled', [int(value)]) # write(self.hdf5_prefix + 'Capture', [value]) print(f'comparing: {value} {instance.value}') if value != instance.value: write(self.camera_prefix + 'Acquire', [0]) # import time # time.sleep(1) write(self.camera_prefix + 'Acquire', [1]) # time.sleep(1) return value
def test_write_without_notify(request, prefix, async_lib): pv = f'{prefix}pi' run_example_ioc('caproto.ioc_examples.type_varieties', request=request, args=['--prefix', prefix, '--async-lib', async_lib], pv_to_check=pv) write(pv, 3.179, notify=False) # We do not get notified so we have to poll for an update. for _attempt in range(20): if read(pv).data[0] > 3.178: break time.sleep(0.1) else: raise AssertionError("Server never processed WriteRequest.")
def test_pvproperty_string_array(request, prefix): from .conftest import run_example_ioc run_example_ioc('caproto.ioc_examples.scalars_and_arrays', request=request, args=['--prefix', prefix], pv_to_check=f'{prefix}scalar_int') from caproto.sync.client import read, write array_string_pv = f'{prefix}array_string' write(array_string_pv, ['array', 'of', 'strings'], notify=True) time.sleep(0.5) assert read(array_string_pv).data == [b'array', b'of', b'strings']
def test_records_subclass(request, prefix, ioc_name): info = conftest.run_example_ioc_by_name(ioc_name, request=request) prefix = info.prefix motor = f'{prefix}motor1' motor_val = f'{motor}.VAL' motor_rbv = f'{motor}.RBV' motor_drbv = f'{motor}.DRBV' sync.write(motor_val, 100, notify=True) # sleep for a few pollling periods: time.sleep(0.5) assert abs(sync.read(motor_rbv).data[0] - 100) < 0.1 assert abs(sync.read(motor_drbv).data[0] - 100) < 0.1
def test_limits_enforced(request, caproto_ioc): pv = caproto_ioc.pvs['float'] write(pv, 3.101, notify=True) # within limit write(pv, 3.179, notify=True) # within limit with pytest.raises(ErrorResponseReceived): write(pv, 3.09, notify=True) # beyond limit with pytest.raises(ErrorResponseReceived): write(pv, 3.181, notify=True) # beyond limit
def test_enum_linking(request, ioc_name): info = conftest.run_example_ioc_by_name(ioc_name, request=request) prefix = info.prefix def string_read(pv): return b''.join(sync.read(pv, data_type=ca.ChannelType.STRING).data) for pv, znam, onam in [(f'{prefix}bi', b'a', b'b'), (f'{prefix}bo', b'Zero Value', b'One Value')]: assert string_read(f'{pv}.ZNAM') == znam assert string_read(f'{pv}.ONAM') == onam for value, expected in ([0, znam], [1, onam]): sync.write(pv, [value], notify=True) assert string_read(pv) == expected
async def AdjustedAcquirePeriod(self, instance, value): readout_time = self.parent.ReadoutTime.value open_delay = read(self.parent.shutter_prefix + 'ShutterOpenDelay_RBV').data close_delay = read(self.parent.shutter_prefix + 'ShutterCloseDelay_RBV').data if not value - open_delay - close_delay >= self.parent.AdjustedAcquireTime.readback.value: await self.parent.AdjustedAcquireTime.setpoint.write(value - open_delay - close_delay) write(self.parent.camera_prefix + 'AcquirePeriod', value) write(self.parent.shutter_prefix + 'TriggerRate', 1. / value) await self.readback.write(value) return value
async def AdjustedAcquireTime(self, instance, value): open_delay = read(self.parent.shutter_prefix + 'ShutterOpenDelay_RBV').data close_delay = read(self.parent.shutter_prefix + 'ShutterCloseDelay_RBV').data if not open_delay + value + close_delay <= self.parent.AdjustedAcquirePeriod.readback.value: await self.parent.AdjustedAcquirePeriod.setpoint.write(open_delay + value + close_delay) write(self.parent.camera_prefix + 'AcquireTime', value + close_delay + open_delay) write(self.parent.shutter_prefix + 'ShutterTime', value + open_delay) await self.readback.write(value) return value
def test_mocking_records_subclass(request, prefix): from .conftest import run_example_ioc run_example_ioc('caproto.ioc_examples.mocking_records_subclass', request=request, args=['--prefix', prefix], pv_to_check=f'{prefix}motor1') from caproto.sync.client import read, write motor = f'{prefix}motor1' motor_val = f'{motor}.VAL' motor_rbv = f'{motor}.RBV' motor_drbv = f'{motor}.DRBV' write(motor_val, 100, notify=True) # sleep for a few pollling periods: time.sleep(0.5) assert abs(read(motor_rbv).data[0] - 100) < 0.1 assert abs(read(motor_drbv).data[0] - 100) < 0.1
def test_limit_fields(request, prefix, context): pv = f'{prefix}C' run_example_ioc('caproto.ioc_examples.mocking_records', request=request, args=['--prefix', prefix], pv_to_check=pv) PV = get_pv(pv, context=context) def check_fields(): for k, v in PV.get_ctrlvars().items(): if k in field_map: fv, = read(f'{pv}.{field_map[k]}').data assert v == fv check_fields() for v in field_map.values(): work_pv = f'{pv}.{v}' write(work_pv, 2 * read(work_pv).data) check_fields()
def test_limits_enforced(request, prefix): pv = f'{prefix}pi' run_example_ioc('caproto.ioc_examples.type_varieties', request=request, args=['--prefix', prefix], pv_to_check=pv) write(pv, 3.101, notify=True) # within limit write(pv, 3.179, notify=True) # within limit with pytest.raises(ErrorResponseReceived): write(pv, 3.09, notify=True) # beyond limit with pytest.raises(ErrorResponseReceived): write(pv, 3.181, notify=True) # beyond limit
def test_ioc_examples(request, module_name, async_lib): from caproto.server import PvpropertyReadOnlyData info = conftest.run_example_ioc_by_name(module_name, async_lib=async_lib, request=request) put_values = [ (PvpropertyReadOnlyData, None), (ca.ChannelNumeric, [1]), (ca.ChannelString, ['USD']), (ca.ChannelChar, 'USD'), (ca.ChannelByte, b'USD'), (ca.ChannelEnum, [0]), ] skip_pvs = [('ophyd', ':exit')] def find_put_value(pv, channeldata): 'Determine value to write to pv' for skip_ioc, skip_suffix in skip_pvs: if skip_ioc in module_name: if pv.endswith(skip_suffix): return None for put_class, put_value in put_values: if isinstance(channeldata, put_class): return put_value else: raise Exception('Failed to set default value for channeldata:' f'{channeldata.__class__}') for pv, channeldata in info.pvdb.items(): value = find_put_value(pv, channeldata) if value is None: print(f'Skipping write to {pv}') continue print(f'Writing {value} to {pv}') sync.write(pv, value, timeout=15) value = sync.read(pv, timeout=15) print(f'Read {pv} = {value}')
def test_enum_linking(request, prefix): from .conftest import run_example_ioc run_example_ioc('caproto.ioc_examples.enums', request=request, args=['--prefix', prefix], pv_to_check=f'{prefix}bi') from caproto.sync.client import read, write def string_read(pv): return b''.join(read(pv, data_type=ca.ChannelType.STRING).data) for pv, znam, onam in [(f'{prefix}bi', b'a', b'b'), (f'{prefix}bo', b'Zero Value', b'One Value')]: assert string_read(f'{pv}.ZNAM') == znam assert string_read(f'{pv}.ONAM') == onam for value, expected in ([0, znam], [1, onam]): write(pv, [value], notify=True) assert string_read(pv) == expected
def test_records(request): info = conftest.run_example_ioc_by_name( 'caproto.ioc_examples.records', request=request, ) prefix = info.prefix # check that the alarm fields are linked b = f'{prefix}B' b_val = f'{prefix}B.VAL' b_stat = f'{prefix}B.STAT' b_severity = f'{prefix}B.SEVR' sync.write(b_val, 0, notify=True) assert list(sync.read(b_val).data) == [0] assert list(sync.read(b_stat).data) == [b'NO_ALARM'] assert list(sync.read(b_severity).data) == [b'NO_ALARM'] # write a special value that causes it to fail with pytest.raises(ca.ErrorResponseReceived): sync.write(b_val, 1, notify=True) # status should be WRITE, MAJOR assert list(sync.read(b_val).data) == [0] assert list(sync.read(b_stat).data) == [b'WRITE'] assert list(sync.read(b_severity).data) == [b'MAJOR'] # now a field that's linked back to the precision metadata: b_precision = f'{prefix}B.PREC' assert list(sync.read(b_precision).data) == [3] sync.write(b_precision, 4, notify=True) assert list(sync.read(b_precision).data) == [4] # does writing to .PREC update the ChannelData metadata? data = sync.read(b, data_type=ca.ChannelType.CTRL_DOUBLE) assert data.metadata.precision == 4
def _run(self): from caproto.sync.client import (read, write, subscribe) if self.acquire: write(self.pvs['enabled'], [1]) write(self.pvs['image_mode'], 'Continuous', data_type=ChannelType.STRING) write(self.pvs['acquire'], [1], notify=False) width = read(self.pvs['array_size0']).data[0] height = read(self.pvs['array_size1']).data[0] depth = read(self.pvs['array_size2']).data[0] color_mode = read(self.pvs['color_mode']).data[0].decode('ascii') bayer_pattern = read(self.pvs['bayer_pattern']) bayer_pattern = bayer_pattern.data[0].decode('ascii') self.new_image_size.emit(width, height, depth, color_mode, bayer_pattern) print(f'width: {width} height: {height} depth: {depth} ' f'color_mode: {color_mode}') def update(response): if self.stop_event.is_set(): raise KeyboardInterrupt native_type = ca.field_types['native'][response.data_type] self.new_image.emit(response.metadata.timestamp, width, height, depth, color_mode, bayer_pattern, native_type, response.data) if self.barrier is not None: # Synchronize with image viewer widget, if necessary self.barrier.wait() sub = subscribe(self.pvs['array_data'], data_type='time') sub.add_callback(update) sub.block() self.stop_event.wait()
def test_mocking_records(request, prefix): from .conftest import run_example_ioc run_example_ioc('caproto.ioc_examples.mocking_records', request=request, args=['--prefix', prefix], pv_to_check=f'{prefix}A') from caproto.sync.client import read, write # check that the alarm fields are linked b = f'{prefix}B' b_val = f'{prefix}B.VAL' b_stat = f'{prefix}B.STAT' b_severity = f'{prefix}B.SEVR' write(b_val, 0, notify=True) assert list(read(b_val).data) == [0] assert list(read(b_stat).data) == [b'NO_ALARM'] assert list(read(b_severity).data) == [b'NO_ALARM'] # write a special value that causes it to fail with pytest.raises(ca.ErrorResponseReceived): write(b_val, 1, notify=True) # status should be WRITE, MAJOR assert list(read(b_val).data) == [0] assert list(read(b_stat).data) == [b'WRITE'] assert list(read(b_severity).data) == [b'MAJOR'] # now a field that's linked back to the precision metadata: b_precision = f'{prefix}B.PREC' assert list(read(b_precision).data) == [3] write(b_precision, 4, notify=True) assert list(read(b_precision).data) == [4] # does writing to .PREC update the ChannelData metadata? data = read(b, data_type=ca.ChannelType.CTRL_DOUBLE) assert data.metadata.precision == 4
def _test_ioc_examples(request, module_name, pvdb_class_name, class_kwargs, prefix, async_lib='curio'): from .conftest import run_example_ioc from caproto.sync.client import read, write from caproto.server import PvpropertyReadOnlyData import subprocess module = __import__(module_name, fromlist=(module_name.rsplit('.', 1)[-1], )) pvdb_class = getattr(module, pvdb_class_name) print(f'Prefix: {prefix} PVDB class: {pvdb_class}') pvdb = pvdb_class(prefix=prefix, **class_kwargs).pvdb pvs = list(pvdb.keys()) pv_to_check = pvs[0] print(f'PVs:', pvs) print(f'PV to check: {pv_to_check}') stdin = (subprocess.DEVNULL if 'io_interrupt' in module_name else None) print('stdin=', stdin) run_example_ioc(module_name, request=request, args=['--prefix', prefix, '--async-lib', async_lib], pv_to_check=pv_to_check, stdin=stdin) print(f'{module_name} IOC now running') put_values = [ (PvpropertyReadOnlyData, None), (ca.ChannelNumeric, [1]), (ca.ChannelString, ['USD']), ] skip_pvs = [('ophyd', ':exit')] def find_put_value(pv): 'Determine value to write to pv' for skip_ioc, skip_suffix in skip_pvs: if skip_ioc in module_name: if pv.endswith(skip_suffix): return None for put_class, put_value in put_values: if isinstance(channeldata, put_class): return put_value else: raise Exception('Failed to set default value for channeldata:' f'{channeldata.__class__}') for pv, channeldata in pvdb.items(): value = find_put_value(pv) if value is None: print(f'Skipping write to {pv}') continue print(f'Writing {value} to {pv}') write(pv, value) value = read(pv) print(f'Read {pv} = {value}')
'data': { 'x': det_reading.data[0], 'pos': pos_reading.data[0] }, 'timestamps': { 'x': det_reading.metadata.timestamp, 'pos': pos_reading.metadata.timestamp }, 'time': i, 'seq_num': i } det = Detector('random_walk', name='det') pos = EpicsSignal('random_walk:pos', name='pos') write('random_walk:dt', 0.1) def fake_kafka(q): sub = subscribe('random_walk:x', data_type='time') def put_into_bus(det_reading): if not pos_readings: # print('no pos readings') return pos_reading = pos_readings[-1] # print(f'x={det_reading.data[0]:.3} pos={pos_reading.data[0]:.3}') q.put((det_reading, pos_reading)) sub.add_callback(put_into_bus) sub.block()
def test_char_write(request, caproto_ioc): pv = caproto_ioc.pvs['chararray'] write(pv, b'testtesttest', notify=True) response = read(pv) assert ''.join(chr(c) for c in response.data) == 'testtesttest'
def set_VAL(self, value): from caproto.sync.client import write write(self.prefix + 'VAL', value)
async def AdjustedAcquire(self, instance, async_lib): # write to Acquire to start the camera up in tv mode write(self.camera_prefix + 'Acquire', [1])
#!/usr/bin/env python3 import time from caproto.sync.client import read, write def sleep(seconds): print("sleeping for %s seconds" % seconds) time.sleep(seconds) print("Value of a: %s" % read('simple:A').data[0]) print("Value of b: %s" % read('simple:B').data[0]) sleep(1) print("Setting value of b to: %s" % 5) write('simple:B', 5, notify=True) sleep(1) print("Value of b now: %s" % read('simple:B').data[0])