From fa2e5c1fd0f8e675a24cb01ecdc14fcd846c9293 Mon Sep 17 00:00:00 2001 From: gac-x05la Date: Wed, 21 Aug 2024 17:54:54 +0200 Subject: [PATCH] Changes before redeployment --- .../devices/gigafrost/gigafrostclient.py | 6 +-- .../devices/gigafrost/stddaq_preview.py | 4 +- tomcat_bec/devices/gigafrost/stddaq_rest.py | 22 +++++--- tomcat_bec/devices/gigafrost/stddaq_ws.py | 51 +++++++++++-------- 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/tomcat_bec/devices/gigafrost/gigafrostclient.py b/tomcat_bec/devices/gigafrost/gigafrostclient.py index 4d5d93a..a53f6d2 100644 --- a/tomcat_bec/devices/gigafrost/gigafrostclient.py +++ b/tomcat_bec/devices/gigafrost/gigafrostclient.py @@ -139,7 +139,7 @@ class GigaFrostClient(PSIDetectorBase): self.__class__.__dict__["cam"].kwargs['auto_soft_enable'] = auto_soft_enable self.__class__.__dict__["daq"].kwargs['ws_url'] = daq_ws_url self.__class__.__dict__["daq"].kwargs['rest_url'] = daq_rest_url - #self.__class__.__dict__["daq"].__class__.__dict__["cfg"].kwargs['rest_url'] = daq_rest_url + #self.__class__.__dict__["daq"].__class__.__dict__["config"].kwargs['rest_url'] = daq_rest_url super().__init__( prefix=prefix, @@ -198,8 +198,8 @@ class GigaFrostClient(PSIDetectorBase): return old, new def stage(self): - px_daq_h = self.daq.cfg.cfg_image_pixel_height.get() - px_daq_w = self.daq.cfg.cfg_image_pixel_width.get() + px_daq_h = self.daq.config.cfg_image_pixel_height.get() + px_daq_w = self.daq.config.cfg_image_pixel_width.get() px_gf_w = self.cam.cfgRoiX.get() px_gf_h = self.cam.cfgRoiY.get() diff --git a/tomcat_bec/devices/gigafrost/stddaq_preview.py b/tomcat_bec/devices/gigafrost/stddaq_preview.py index 0f27705..832a6a3 100644 --- a/tomcat_bec/devices/gigafrost/stddaq_preview.py +++ b/tomcat_bec/devices/gigafrost/stddaq_preview.py @@ -53,7 +53,7 @@ class StdDaqPreview(Device): frame = Component(Signal, kind=Kind.normal) image_shape = Component(Signal, kind=Kind.omitted) value = Component(Signal, kind=Kind.hinted) - _throttle = 0.2 + throttle = Component(Signal, value=0.2, kind=Kind.omitted) def __init__( self, *args, url: str = "tcp://129.129.95.38:20000", parent: Device = None, **kwargs @@ -122,7 +122,7 @@ class StdDaqPreview(Device): meta, data = self._socket.recv_multipart(flags=zmq.NOBLOCK) t_curr = time() t_elapsed = t_curr - t_last - if t_elapsed > self._throttle: + if t_elapsed > self.throttle.get(): header = json.loads(meta) if header["type"]=="uint16": image = np.frombuffer(data, dtype=np.uint16) diff --git a/tomcat_bec/devices/gigafrost/stddaq_rest.py b/tomcat_bec/devices/gigafrost/stddaq_rest.py index e4ff21d..b00b9ae 100644 --- a/tomcat_bec/devices/gigafrost/stddaq_rest.py +++ b/tomcat_bec/devices/gigafrost/stddaq_rest.py @@ -6,6 +6,7 @@ Created on Thu Jun 27 17:28:43 2024 @author: mohacsi_i """ +from time import sleep from ophyd import Device, Signal, Component, Kind import requests @@ -30,6 +31,7 @@ class StdDaqRestClient(Device): # pylint: disable=too-many-instance-attributes # Status attributes + rest_url = Component(Signal, kind=Kind.config) cfg_detector_name = Component(Signal, kind=Kind.config) cfg_detector_type = Component(Signal, kind=Kind.config) cfg_n_modules = Component(Signal, kind=Kind.config) @@ -50,7 +52,8 @@ class StdDaqRestClient(Device): self, *args, rest_url: str = "http://localhost:5000", parent: Device = None, **kwargs ) -> None: super().__init__(*args, parent=parent, **kwargs) - self._url_base = rest_url + self.rest_url._metadata["write_access"] = False + self.rest_url.put(rest_url, force=True) # Connect ro the DAQ and initialize values self.read_daq_config() @@ -59,7 +62,7 @@ class StdDaqRestClient(Device): """Read the current configuration from the JSON file """ r = requests.get( - self._url_base + '/api/config/get', + self.rest_url.get() + '/api/config/get', params={'config_file': "/etc/std_daq/configs/gf1.json", 'user':"ioc"}, timeout=2 ) @@ -95,6 +98,7 @@ class StdDaqRestClient(Device): 'image_pixel_width': int(self.cfg_image_pixel_width.get()), 'start_udp_port': int(self.cfg_start_udp_port.get()), 'writer_user_id': int(self.cfg_writer_user_id.get()), + 'log_level': "debug", 'submodule_info': {}, 'max_number_of_forwarders_spawned': int(self.cfg_max_number_of_forwarders_spawned.get()), 'use_all_forwarders': bool(self.cfg_use_all_forwarders.get()), @@ -112,10 +116,10 @@ class StdDaqRestClient(Device): config = self._build_config() - params = {"user": "ioc", "config_file": "/etc/std_daq/configs/gf1.json"} - + #params = {"user": "ioc", "config_file": "/etc/std_daq/configs/gf1.json"} + params = {"user": "ioc"} r = requests.post( - self._url_base +'/api/config/set', + self.rest_url.get() +'/api/config/set', params=params, json=config, timeout=2, @@ -146,12 +150,14 @@ class StdDaqRestClient(Device): pixel_width = d.get('image_width', pixel_width) pixel_height = d.get('image_height', pixel_height) - self.cfg_image_pixel_height.set(pixel_height).wait() self.cfg_image_pixel_width.set(pixel_width).wait() self.write_daq_config() logger.info(f"[{self.name}] Reconfigured the StdDAQ") + # No feedback on restart, we just sleep + sleep(3) + new = self.read_configuration() return old, new @@ -159,6 +165,10 @@ class StdDaqRestClient(Device): self.read_daq_config() return super().read() + def read_configuration(self): + self.read_daq_config() + return super().read_configuration() + def stage(self) -> list: """Stage op: Read the current configuration from the DAQ """ diff --git a/tomcat_bec/devices/gigafrost/stddaq_ws.py b/tomcat_bec/devices/gigafrost/stddaq_ws.py index d5806dd..78ea0e7 100644 --- a/tomcat_bec/devices/gigafrost/stddaq_ws.py +++ b/tomcat_bec/devices/gigafrost/stddaq_ws.py @@ -21,7 +21,7 @@ except ModuleNotFoundError: -class StdDaqWsClient(Device): +class StdDaqClient(Device): """StdDaq API This class combines the new websocket and REST interfaces that were meant @@ -46,17 +46,17 @@ class StdDaqWsClient(Device): n_total = Component(Signal, value=10000, kind=Kind.config) file_path = Component(Signal, value="/gpfs/test/test-beamline", kind=Kind.config) - cfg = Component(StdDaqRestClient, kind=Kind.config) + config = Component(StdDaqRestClient, kind=Kind.config) def __init__( self, *args, ws_url: str = "ws://localhost:8080", - rest_url="http://localhost:5000", + rest_url: str="http://localhost:5000", parent: Device = None, **kwargs ) -> None: - self.__class__.__dict__['cfg'].kwargs['rest_url'] = rest_url + self.__class__.__dict__['config'].kwargs['rest_url'] = rest_url super().__init__(*args, parent=parent, **kwargs) self.status._metadata["write_access"] = False @@ -73,11 +73,16 @@ class StdDaqWsClient(Device): StdDAQ may reject connection for a few seconds, so if it fails, wait a bit and try to connect again. """ - try: - self._client = connect(self._ws_url) - except ConnectionRefusedError: - sleep(5) - self._client = connect(self._ws_url) + num_retry = 0 + while num_retry < 5: + try: + self._client = connect(self._ws_url) + break + except ConnectionRefusedError: + num_retry += 1 + sleep(3) + if num_retry==5: + raise ConnectionRefusedError("The standard DAQ websocket interface refused connection 5 times.") def __del__(self): """Try to close the socket""" @@ -116,11 +121,15 @@ class StdDaqWsClient(Device): # Set acquisition parameters if 'n_total' in d: self.n_total.set(int(d['n_total'])) + if 'ntotal' in d: + self.n_total.set(int(d['ntotal'])) if 'file_path' in d: self.output_file.set(str(d['file_path'])) # Configure DAQ if 'pixel_width' in d or 'pixel_height' in d: - self.cfg.configure(d) + self.stop() + sleep(1) + self.config.configure(d) new_config = self.read_configuration() return (old_config, new_config) @@ -148,6 +157,7 @@ class StdDaqWsClient(Device): self._mon = Thread(target=self.poll, daemon=True) self._mon.start() + sleep(3) return super().stage() def unstage(self): @@ -155,8 +165,12 @@ class StdDaqWsClient(Device): WARN: This will also close the connection!!! """ - message = {"command": "stop"} - _ = self.message(message, wait_reply=False) + # The poller thread locks recv raising a RuntimeError + try: + message = {"command": "stop"} + self.message(message, wait_reply=False) + except RuntimeError: + pass return super().unstage() def stop(self, success=False): @@ -164,9 +178,7 @@ class StdDaqWsClient(Device): WARN: This will also close the connection!!! """ - message = {"command": "stop"} - # The poller thread locks recv raising a RuntimeError - self.message(message, wait_reply=False) + self.unstage() def message(self, message: dict, timeout=1, wait_reply=True): """Send a message to the StdDAQ and receive a reply @@ -198,6 +210,7 @@ class StdDaqWsClient(Device): def poll(self): """Monitor status messages until connection is open""" try: + sleep(0.1) for msg in self._client: try: message = json.loads(msg) @@ -211,11 +224,7 @@ class StdDaqWsClient(Device): self._mon = None -class StdDaqClient(StdDaqWsClient): - """Just an alias""" - - -# Automatically connect to MicroSAXS testbench if directly invoked +# Automatically connect to microXAS testbench if directly invoked if __name__ == "__main__": - daq = StdDaqWsClient(name="daq", ws_url="ws://xbl-daq-29:8080", rest_url="http://xbl-daq-29:5000") + daq = StdDaqClient(name="daq", ws_url="ws://xbl-daq-29:8080", rest_url="http://xbl-daq-29:5000") daq.wait_for_connection()