wip local

This commit is contained in:
2025-08-08 10:45:49 +02:00
parent 19565e9bae
commit 6de114f2a6
3 changed files with 69 additions and 42 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ if __name__ == """__main__""":
# data_server_host = "x10da-bec-001.psi.ch"
# port = 3030
timepix = Timepix(
name="TimePixDetector", prefix='X10DA-ES-TPX1:', rest_url=rest_url, ws_url=ws_url
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)
@@ -1,5 +1,10 @@
if __name__ == """__main__""":
import threading
import time
from unittest import mock
import ophyd
from ophyd_devices.tests.utils import MockPV, patch_dual_pvs
from superxas_bec.devices.timepix.timepix import Timepix
from superxas_bec.devices.timepix.timepix_fly_client.timepix_fly_mock_server import (
@@ -7,24 +12,34 @@ if __name__ == """__main__""":
)
mock_server = TimePixFlyMockServer()
timepix = Timepix(name="timepix", data_server_host="localhost")
timepix.on_connected()
with mock.patch.object(ophyd, "cl") as mock_cl:
mock_cl.get_pv = MockPV
mock_cl.thread_class = threading.Thread
timepix = Timepix(name="timepix", prefix="")
patch_dual_pvs(timepix)
timepix.timepix_fly_client.on_connected()
timepix._reset_buffers()
timepix.start_data_server()
# timepix.on_connected()
## LOOP for a scan
timepix.stage()
status = timepix.pre_scan()
status.wait(timeout=10)
print(f"Pre-scan status: {status}")
mock_server.start_acquisition()
print("Acquisition started on mock server.")
# time.sleep(5)
status = timepix.complete()
status.wait(timeout=10)
for ii, msg in enumerate(timepix._data_buffer):
print(f"Message {ii}: {msg.keys()}")
print(f"Received data {ii} with message type {msg['type']}")
if msg["type"] == "EndFrame":
print(f"Received error message: {msg}")
# print(f"Data: {msg}") # Print first 50 characters of data
timepix.unstage()
timepix.destroy()
## LOOP for a scan
timepix.stage()
status = timepix.pre_scan()
timepix.cam.acquire_busy._read_pv.mock_data = 1
status.wait(timeout=10)
print(f"Pre-scan status: {status}")
mock_server.start_acquisition()
print("Acquisition started on mock server.")
# time.sleep(5)
status = timepix.complete()
time.sleep(8)
timepix.cam.acquire_busy._read_pv.mock_data = 0
status.wait(timeout=10)
for ii, msg in enumerate(timepix._data_buffer):
print(f"Message {ii}: {msg.keys()}")
print(f"Received data {ii} with message type {msg['type']}")
if msg["type"] == "EndFrame":
print(f"Received error message: {msg}")
# print(f"Data: {msg}") # Print first 50 characters of data
timepix.unstage()
timepix.destroy()
+33 -21
View File
@@ -3,6 +3,7 @@ TimePix Detector class for interfacing with the TimePix detector. The timepix_si
implements the HTTP communication to the REST API for the tpx3app app.
"""
import atexit
import enum
import json
import signal
@@ -10,7 +11,6 @@ import socket
import threading
import time
from typing import Literal
import atexit
from bec_lib.logger import bec_logger
from ophyd import ADBase
@@ -123,13 +123,13 @@ class Timepix(PSIDeviceBase, TimePixControl):
self,
*,
name,
prefix:str,
prefix: str,
rest_url: str = "localhost:8452",
ws_url: str = "localhost:8452/ws",
scan_info=None,
device_manager=None,
data_server_host: str | None = None,
data_server_port: int | None = None,
hostname: str | None = None,
host_port: int | None = None,
**kwargs,
):
"""
@@ -146,21 +146,22 @@ 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, prefix=prefix, 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:
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 hostname is None:
hostname = socket.getfqdn()
if not hostname.endswith(".psi.ch"):
logger.info(f"Found host without psi.ch domain {hostname}")
if data_server_port is None:
data_server_port = 3015
self._data_server_host = data_server_host
self._data_server_port = data_server_port
if host_port is None:
host_port = 3015
self._hostname = hostname
self._data_server_host: str | None = None
self._data_server_port = host_port
self._rlock = threading.RLock()
# Data server
self._data_server_thread = None
@@ -237,6 +238,8 @@ class Timepix(PSIDeviceBase, TimePixControl):
success=[TimePixFlyStatus.CONFIG],
error=[TimePixFlyStatus.EXCEPT, TimePixFlyStatus.SHUTDOWN],
)
if self._data_server_host is None:
raise RuntimeError(f"Data server host is not set for device {self.name}.")
# Parse scan info for OtherConfig
config = OtherConfigModel(
output_uri=f"tcp:{self._data_server_host}:{self._data_server_port}",
@@ -419,8 +422,10 @@ class Timepix(PSIDeviceBase, TimePixControl):
if self._socket_server:
try:
self._stop_data_receiver()
except Exception as e :
logger.info(f"Failed to stop data receiver for device {self.name} with exception {e}.")
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
@@ -451,16 +456,23 @@ class Timepix(PSIDeviceBase, TimePixControl):
# # 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)
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._data_server_host = host_port_info[0] # Hostname or IP address
self._data_server_port = host_port_info[1] # Port number, should be the same as before
self._socket_server = socket.socket(af, socktype, proto)
self._socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._socket_server.bind(host_port_info)
self._socket_server.listen(1) # Only allow one connection
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 {host_port_info}")
@@ -475,7 +487,7 @@ if __name__ == "__main__":
mock_server = TimePixFlyMockServer()
# Create a Timepix object
timepix = Timepix(name="TimePixDetector", prefix='')
timepix = Timepix(name="TimePixDetector", prefix="")
timepix.on_connected()
timepix.stage()
timepix.pre_scan()