wip beamline
This commit is contained in:
@@ -46,11 +46,12 @@ if __name__ == """__main__""":
|
||||
# # mock_server = TimePixFlyMockServer()
|
||||
# server = TimepixServer(name='server', prefix='X10DA-ES-TPX1:cam1:')
|
||||
# Create a Timepix object
|
||||
rest_url = "p4-0017.psi.ch:8452"
|
||||
ws_url = "p4-0017:8452/ws"
|
||||
data_server_host = "p4-0017.psi.ch"
|
||||
rest_url = "p4-0017.psi.ch:8453"
|
||||
ws_url = "p4-0017:8453/ws"
|
||||
# data_server_host = "x10da-bec-001.psi.ch"
|
||||
# port = 3030
|
||||
timepix = Timepix(
|
||||
name="TimePixDetector", rest_url=rest_url, ws_url=ws_url, data_server_host=data_server_host
|
||||
name="TimePixDetector", prefix='X10DA-ES-TPX1:', rest_url=rest_url, ws_url=ws_url
|
||||
)
|
||||
timepix.on_connected()
|
||||
timepix.wait_for_connection(all_signals=True, timeout=10)
|
||||
|
||||
@@ -10,6 +10,7 @@ import socket
|
||||
import threading
|
||||
import time
|
||||
from typing import Literal
|
||||
import atexit
|
||||
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import ADBase
|
||||
@@ -114,12 +115,15 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
DATA_SERVER_PORT = 3015 # Default data server port for TimePix detector
|
||||
rest_url = 'p4-0017.psi.ch:8452'
|
||||
ws_url = 'p4-0017:8452/ws'
|
||||
|
||||
Prefix of EPICS Control is 'X10DA-ES-TPX1:'
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
name,
|
||||
prefix:str,
|
||||
rest_url: str = "localhost:8452",
|
||||
ws_url: str = "localhost:8452/ws",
|
||||
scan_info=None,
|
||||
@@ -142,14 +146,17 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
data_server_port (int, optional): Port for the data server. Defaults to DATA_SERVER_PORT.
|
||||
**kwargs: Additional keyword arguments for the PSIDeviceBase class.
|
||||
"""
|
||||
super().__init__(name=name, scan_info=scan_info, device_manager=device_manager, **kwargs)
|
||||
super().__init__(name=name, prefix=prefix, scan_info=scan_info, device_manager=device_manager, **kwargs)
|
||||
self._ws_url = ws_url
|
||||
self._rest_url = rest_url
|
||||
self.timepix_fly_client = TimepixFlyClient(rest_url=rest_url, ws_url=ws_url, parent=self)
|
||||
if data_server_host is None or data_server_host == "localhost":
|
||||
if data_server_host is None:
|
||||
data_server_host = (
|
||||
socket.gethostname()
|
||||
) # TODO check if that works -> Wihtout DATA_SERVER_HOST
|
||||
socket.getfqdn()
|
||||
)
|
||||
if not data_server_host.endswith('.psi.ch'):
|
||||
logger.info(f"Found host without psi.ch domain {data_server_host}")
|
||||
|
||||
if data_server_port is None:
|
||||
data_server_port = 3015
|
||||
self._data_server_host = data_server_host
|
||||
@@ -161,7 +168,6 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
self._data_server_started = threading.Event()
|
||||
# Socket server
|
||||
self._socket_server = None
|
||||
self._socket_server_allowed_connections = 1 # How many ?
|
||||
self._socket_server_timeout = 0.1
|
||||
self._socket_server_buffer_size = 4096
|
||||
# Data buffers
|
||||
@@ -171,6 +177,8 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
self._decoder = json.JSONDecoder()
|
||||
# Wait timeout
|
||||
self._pv_timeout = 5.0 # Default timeout for PV operations
|
||||
# Register cleanup
|
||||
atexit.register(self.on_destroy)
|
||||
|
||||
### Beamline specifi methods for the TimePix Detector integration ###
|
||||
|
||||
@@ -235,6 +243,7 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
TRoiStep=1,
|
||||
TRoiN=5000,
|
||||
)
|
||||
logger.info(config)
|
||||
# Parse pixel map from scan info if needed, otherwise use some default pixel map.
|
||||
pixel_map = PixelMap(
|
||||
chips=[
|
||||
@@ -337,7 +346,7 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
def _stop_data_receiver(self):
|
||||
if self._data_server_thread is not None and self._data_server_thread.is_alive():
|
||||
self._data_server_thread_event.set()
|
||||
self._data_server_thread.join(timeout=5.0)
|
||||
self._data_server_thread.join(timeout=1.0)
|
||||
if self._data_server_thread is not None and self._data_server_thread.is_alive():
|
||||
logger.warning(
|
||||
f"Data server thread did not stop gracefully for device {self.name}."
|
||||
@@ -354,6 +363,7 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
while not self._data_server_thread_event.is_set():
|
||||
try:
|
||||
self._data_server_started.set()
|
||||
# logger.info(self._socket_server)
|
||||
conn, addr = self._socket_server.accept()
|
||||
logger.info(f"Accepted connection from {addr}")
|
||||
with conn:
|
||||
@@ -408,18 +418,13 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
with self._rlock:
|
||||
if self._socket_server:
|
||||
try:
|
||||
self._data_server_thread_event.set() # Signal the data server thread to stop
|
||||
self._stop_data_receiver()
|
||||
except Exception as e :
|
||||
logger.info(f"Failed to stop data receiver for device {self.name} with exception {e}.")
|
||||
try:
|
||||
self._socket_server.close()
|
||||
except Exception as e: # pylint: disable=broad-except
|
||||
logger.warning(f"Failed to shutdown socket server gracefully. Error: {e}")
|
||||
self._stop_data_receiver()
|
||||
self._socket_server = None
|
||||
self._data_server_thread.join(timeout=5.0)
|
||||
if self._data_server_thread.is_alive():
|
||||
logger.warning(
|
||||
f"Data server thread for {self.name} did not stop gracefully. Forcing shutdown."
|
||||
)
|
||||
self._data_server_thread = None
|
||||
logger.warning(f"Failed to shutdown socket server. Error: {e}")
|
||||
|
||||
def restart_data_receiver(self):
|
||||
"""Restart the data receiver thread."""
|
||||
@@ -440,24 +445,25 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
# AF_INET6 for IPv6, use AF_INET for IPv4; for localhost this may be different depending on the system
|
||||
# TODO add an os check if self._data_server_host is localhost
|
||||
# self._socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #BEAMLINE USAGE!
|
||||
addr_info = socket.getaddrinfo(
|
||||
self._data_server_host, self._data_server_port, socket.AF_UNSPEC, socket.SOCK_STREAM
|
||||
)
|
||||
# Use the first valid address returned by getaddrinfo
|
||||
af, socktype, proto, _, _ = addr_info[0]
|
||||
self._socket_server = socket.socket(af, socktype, proto)
|
||||
# addr_info = socket.getaddrinfo(
|
||||
# self._data_server_host, self._data_server_port, socket.AF_UNSPEC, socket.SOCK_STREAM
|
||||
# )
|
||||
# # Use the first valid address returned by getaddrinfo
|
||||
# af, socktype, proto, _, _ = addr_info[0]
|
||||
# self._socket_server = socket.socket(af, socktype, proto)
|
||||
info = socket.getaddrinfo(self._data_server_host, port=self._data_server_port, family=socket.AF_INET, type=socket.SOCK_STREAM)
|
||||
if len(info) == 0:
|
||||
raise RuntimeError(f"No socket info found")
|
||||
if len(info) > 1:
|
||||
logger.warning(f"Found multiple socket interfaces {info}, using the first one")
|
||||
af, socktype, proto, _, host_port_info = info[0]
|
||||
self._socket_server = socket.socket(af, socktype, proto)
|
||||
self._socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
if af == socket.AF_INET6:
|
||||
try:
|
||||
self._socket_server.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
||||
except (AttributeError, OSError):
|
||||
# This option might not exist on some systems, so we handle the exception
|
||||
pass
|
||||
self._socket_server.bind((self._data_server_host, self._data_server_port))
|
||||
self._socket_server.listen(self._socket_server_allowed_connections)
|
||||
self._socket_server.bind(host_port_info)
|
||||
self._socket_server.listen(1) # Only allow one connection
|
||||
self._socket_server.settimeout(self._socket_server_timeout)
|
||||
self._start_data_receiver()
|
||||
logger.info(f"Data server started on {self._data_server_host}:{self._data_server_port}")
|
||||
logger.info(f"Data server started on {host_port_info}")
|
||||
|
||||
|
||||
# pylint: disable=protected-access
|
||||
@@ -469,7 +475,7 @@ if __name__ == "__main__":
|
||||
mock_server = TimePixFlyMockServer()
|
||||
|
||||
# Create a Timepix object
|
||||
timepix = Timepix(name="TimePixDetector")
|
||||
timepix = Timepix(name="TimePixDetector", prefix='')
|
||||
timepix.on_connected()
|
||||
timepix.stage()
|
||||
timepix.pre_scan()
|
||||
|
||||
Reference in New Issue
Block a user