wip galil rio
This commit is contained in:
@@ -6,10 +6,8 @@ Link to the Galil RIO vendor page:
|
||||
https://www.galil.com/plcs/remote-io/rio-471xx
|
||||
|
||||
This module provides the GalilRIOController for communication with the RIO controller
|
||||
over TCP/IP as well as a read-only Ophyd Signal, which reads from all 8 analog input channels.
|
||||
This signal can be used to create virtual devices in BEC that process the analog input values
|
||||
and combine them into more complex signals. For this purpose, the GalilRIOSignal should be
|
||||
integrated as a 'monitored' or 'baseline' signal in the device config of BEC.
|
||||
over TCP/IP. It also provides a device integration that interfaces to these
|
||||
8 analog channels.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -70,33 +68,67 @@ 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.
|
||||
"""
|
||||
|
||||
def __init__(self, signal_name: str, channel: int, **kwargs):
|
||||
super().__init__(signal_name, **kwargs)
|
||||
_NUM_ANALOG_CHANNELS = 8
|
||||
|
||||
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
|
||||
|
||||
def _socket_get(self) -> float:
|
||||
"""Get command for the readback signal"""
|
||||
cmd = f"MG@AN[{self._channel}]"
|
||||
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
|
||||
return float(ret.strip().split(" ")[0])
|
||||
# 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."""
|
||||
old_val = self._readback
|
||||
if time.monotonic() - self.parent._last_readback < 0.5:
|
||||
return self._readback
|
||||
self._readback = self._socket_get()
|
||||
self._run_subs(
|
||||
sub_type=self.SUB_VALUE,
|
||||
old_value=old_val,
|
||||
value=self._readback,
|
||||
timestamp=self._metadata.get("timestamp", time.time()),
|
||||
)
|
||||
self.parent._last_readback = time.monotonic()
|
||||
return self._readback
|
||||
|
||||
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.
|
||||
|
||||
Args:
|
||||
values (list[float]): List of 8 float values corresponding to the analog channels.
|
||||
They must be in order from an_ch0 to an_ch7.
|
||||
"""
|
||||
for walk in self.parent.walk_signals():
|
||||
if walk.item.attr_name.startswith("an_ch"):
|
||||
channel_index = int(walk.item.attr_name.split("_")[-1])
|
||||
if 0 <= channel_index < len(values):
|
||||
old_val = walk.item._readback
|
||||
new_val = values[channel_index]
|
||||
timestamp = time.time()
|
||||
walk.item._metadata["timestamp"] = timestamp
|
||||
walk.item._readback = new_val
|
||||
walk.item._run_subs(
|
||||
sub_type=walk.item.SUB_VALUE,
|
||||
old_value=old_val,
|
||||
value=new_val,
|
||||
timestamp=timestamp,
|
||||
)
|
||||
|
||||
|
||||
class GalilRIO(PSIDeviceBase):
|
||||
"""Base integration for the Galil RIO card in BEC."""
|
||||
@@ -127,6 +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()
|
||||
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
|
||||
@@ -145,27 +178,29 @@ class GalilRIO(PSIDeviceBase):
|
||||
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."""
|
||||
# Get number of channels
|
||||
channels: list[tuple[int, str]] = []
|
||||
res = {}
|
||||
# def read(self):
|
||||
# """Read all 8 analog input channels from the Galil RIO controller."""
|
||||
# if time.monotonic() - self._last_readback < 0.5:
|
||||
|
||||
# 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))
|
||||
# # Get number of channels
|
||||
# channels: list[tuple[int, str]] = []
|
||||
# res = {}
|
||||
|
||||
# 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
|
||||
# # 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__":
|
||||
|
||||
Reference in New Issue
Block a user