From 30ec9f15aa533796cce4b557effcdda303144089 Mon Sep 17 00:00:00 2001 From: appel_c Date: Mon, 26 Jan 2026 09:49:19 +0100 Subject: [PATCH] w --- csaxs_bec/devices/omny/galil/galil_rio.py | 63 +++++++---------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/csaxs_bec/devices/omny/galil/galil_rio.py b/csaxs_bec/devices/omny/galil/galil_rio.py index f5f3eb4..4fd4c22 100644 --- a/csaxs_bec/devices/omny/galil/galil_rio.py +++ b/csaxs_bec/devices/omny/galil/galil_rio.py @@ -68,46 +68,40 @@ class GalilRIOController(Controller): class GalilRIOSignalRO(GalilSignalRO): """ Read-only Signal for reading a single analog input channel from the Galil RIO controller. - If the last reading of the controller is less than 0.5 seconds old, the cached value is returned. + It always read all 8 analog channels at once, and updates the reabacks of all channels. + Further reads within 0.5 seconds return the last readback value without querying the controller again. """ _NUM_ANALOG_CHANNELS = 8 + _READ_TIMEOUT = 0.5 # seconds def __init__(self, signal_name: str, channel: int, parent: GalilRIO, **kwargs): super().__init__(signal_name, parent=parent, **kwargs) self._channel = channel self._metadata["connected"] = False - self._last_readback = self.parent._last_readback + self.last_readback = self.parent.last_readback def _socket_get(self) -> float: """Get command for the readback signal""" cmd = "MG@" + ",@".join([f"AN[{ii}]" for ii in range(self._NUM_ANALOG_CHANNELS)]) - # old_val = self._readback - # cmd = f"MG@AN[{self._channel}]" ret = self.controller.socket_put_and_receive(cmd) - # timestamp = time.time() - # self._metadata["timestamp"] = timestamp values = [float(val) for val in ret.strip().split(" ")] # This updates all channels' readbacks, including self._readback self._update_all_channels(values) return self._readback - # new_val = float(ret.strip().split(" ")[0]) - # self._run_subs( - # sub_type=self.SUB_VALUE, old_value=old_val, value=new_val, timestamp=timestamp - # ) - # return float(ret.strip().split(" ")[0]) def get(self): """Get current analog channel values from the Galil RIO controller.""" - if time.monotonic() - self.parent._last_readback < 0.5: - return self._readback - self._readback = self._socket_get() - + # If the last readback has happend more than 0.5 seconds ago, read all channels again + if time.monotonic() - self.last_readback > self._READ_TIMEOUT: + self._readback = self._socket_get() return self._readback + # pylint: disable=protected-access def _update_all_channels(self, values: list[float]) -> None: """ - Update all analog channels an_ch0 to an_ch7 from receiving the readback update on a signal. + Update all analog channel readbacks based on the provided list of values. + List of values must be in order from an_ch0 to an_ch7. Args: values (list[float]): List of 8 float values corresponding to the analog channels. @@ -121,10 +115,9 @@ class GalilRIOSignalRO(GalilSignalRO): old_val = walk.item._readback new_val = values[idx] walk.item._metadata["timestamp"] = timestamp - walk.item.timestamp = timestamp walk.item._readback = new_val # NOTE: Update parent's last readback before running subscriptions!! - self.parent._last_readback = time.monotonic() + self.parent.last_readback = time.monotonic() walk.item._run_subs( sub_type=walk.item.SUB_VALUE, old_value=old_val, @@ -134,7 +127,10 @@ class GalilRIOSignalRO(GalilSignalRO): class GalilRIO(PSIDeviceBase): - """Base integration for the Galil RIO card in BEC.""" + """ + Galil RIO controller integration with 8 analog input channels. To implement the device, + please provide the appropriate host and port (default port is 23). + """ SUB_CONNECTION_CHANGE = "connection_change" @@ -149,6 +145,7 @@ class GalilRIO(PSIDeviceBase): def __init__( self, + *, name: str, host: str, device_manager: DeviceManagerDS, @@ -162,7 +159,7 @@ class GalilRIO(PSIDeviceBase): self.controller = GalilRIOController( socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager ) - self._last_readback: float = time.monotonic() + self.last_readback: float = time.monotonic() super().__init__(name=name, device_manager=device_manager, scan_info=scan_info, **kwargs) self.controller.subscribe( self._update_connection_state, event_type=self.SUB_CONNECTION_CHANGE @@ -174,37 +171,13 @@ class GalilRIO(PSIDeviceBase): def destroy(self) -> None: """Make sure to turn off the controller socket on destroy.""" - self.controller.off() + self.controller.off(update_config=False) return super().destroy() def _update_connection_state(self, **kwargs): for walk in self.walk_signals(): walk.item._metadata["connected"] = self.controller.connected - # def read(self): - # """Read all 8 analog input channels from the Galil RIO controller.""" - # if time.monotonic() - self._last_readback < 0.5: - - # # Get number of channels - # channels: list[tuple[int, str]] = [] - # res = {} - - # # This yields tuples of cpt, signal - # for walk in self.walk_signals(): - # if isinstance(walk.item, GalilRIOSignalRO): - # # pylint: disable=protected-access - # channels.append((walk.item._channel, walk.item.name)) - - # # Read all channels in one command - # cmd = "MG@" + ",@".join([f"AN[{ii}]" for ii, _ in channels]) - # logger.info(f"Reading Galil RIO channels with command: {cmd}") - # ret = self.controller.socket_put_and_receive(cmd) - # timestamp = time.time() - # values = [float(val) for val in ret.strip().split(" ")] - # for val, (_, signal_name) in zip(values, channels): - # res[signal_name] = {"value": val, "timestamp": timestamp} - # return res - if __name__ == "__main__": host = "129.129.98.64"