fix: fix occasional crash of mo1_bragg for scan; closes #11
This commit is contained in:
@@ -14,7 +14,8 @@ from typing import Any, Literal
|
||||
from bec_lib.devicemanager import ScanInfo
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import DeviceStatus, StatusBase
|
||||
from ophyd import DeviceStatus, StatusBase, Signal
|
||||
from ophyd.status import SubscriptionStatus
|
||||
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
||||
from ophyd_devices.utils.errors import DeviceStopError
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -200,39 +201,39 @@ class Mo1Bragg(PSIDeviceBase, Mo1BraggPositioner):
|
||||
# Load the scan parameters to the controller
|
||||
self.scan_control.scan_load.put(1)
|
||||
# Wait for params to be checked from controller
|
||||
status = self.task_handler.submit_task(
|
||||
task=self.wait_for_signal,
|
||||
task_args=(self.scan_control.scan_msg, ScanControlLoadMessage.SUCCESS),
|
||||
)
|
||||
return status
|
||||
self.wait_for_signal(self.scan_control.scan_msg, ScanControlLoadMessage.SUCCESS, timeout=self.timeout_for_pvwait)
|
||||
return None
|
||||
|
||||
def on_unstage(self) -> DeviceStatus | StatusBase | None:
|
||||
"""Called while unstaging the device."""
|
||||
|
||||
def unstage_procedure():
|
||||
if self.stopped is True:
|
||||
logger.warning(f"Resetting stopped in unstage for device {self.name}.")
|
||||
self._stopped = False
|
||||
current_state = self.scan_control.scan_msg.get()
|
||||
# Case 1, message is already ScanControlLoadMessage.PENDING
|
||||
if current_state == ScanControlLoadMessage.PENDING:
|
||||
return None
|
||||
# Case 2, probably called after scan, backend should resolve on its own. Timeout to wait
|
||||
if current_state in [ScanControlLoadMessage.STARTED, ScanControlLoadMessage.SUCCESS]:
|
||||
try:
|
||||
self.wait_for_signal(
|
||||
self.scan_control.scan_msg,
|
||||
ScanControlLoadMessage.PENDING,
|
||||
timeout=self.timeout_for_pvwait / 2,
|
||||
timeout=self.timeout_for_pvwait,
|
||||
)
|
||||
return
|
||||
except TimeoutError:
|
||||
logger.warning(
|
||||
f"Timeout after {self.timeout_for_pvwait} while waiting for scan validation"
|
||||
f"Timeout in on_unstage of {self.name} after {self.timeout_for_pvwait}s, current scan_control_message : {self.scan_control.scan_msg.get()}"
|
||||
)
|
||||
time.sleep(0.25)
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < self.timeout_for_pvwait / 2:
|
||||
if not self.scan_control.scan_msg.get() == ScanControlLoadMessage.PENDING:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
raise TimeoutError(
|
||||
f"Device {self.name} run into timeout after {self.timeout_for_pvwait} while waiting for scan validation"
|
||||
)
|
||||
|
||||
status = self.task_handler.submit_task(unstage_procedure)
|
||||
status.wait()
|
||||
def callback(*, old_value, value, **kwargs):
|
||||
if value == ScanControlLoadMessage.PENDING:
|
||||
return True
|
||||
return False
|
||||
status = SubscriptionStatus(self.scan_control.scan_msg, callback=callback)
|
||||
self.scan_control.scan_val_reset.put(1)
|
||||
status.wait(timeout=self.timeout_for_pvwait)
|
||||
return None
|
||||
|
||||
def on_pre_scan(self) -> DeviceStatus | StatusBase | None:
|
||||
@@ -268,11 +269,13 @@ class Mo1Bragg(PSIDeviceBase, Mo1BraggPositioner):
|
||||
if scan_duration < 0.1
|
||||
else self.scan_control.scan_start_timer.put
|
||||
)
|
||||
def callback(*, old_value, value, **kwargs):
|
||||
if old_value == ScanControlScanStatus.READY and value == ScanControlScanStatus.RUNNING:
|
||||
return True
|
||||
return False
|
||||
|
||||
status = SubscriptionStatus(self.scan_control.scan_status, callback=callback)
|
||||
start_func(1)
|
||||
status = self.task_handler.submit_task(
|
||||
task=self.wait_for_signal,
|
||||
task_args=(self.scan_control.scan_status, ScanControlScanStatus.RUNNING),
|
||||
)
|
||||
return status
|
||||
|
||||
def on_stop(self) -> None:
|
||||
@@ -328,7 +331,7 @@ class Mo1Bragg(PSIDeviceBase, Mo1BraggPositioner):
|
||||
time.sleep(0.1)
|
||||
# If we end up here, the status did not resolve
|
||||
raise TimeoutError(
|
||||
f"Device {self.name} run into timeout after {timeout}s while waiting for scan to start"
|
||||
f"Device {self.name} run into timeout after {timeout}s for signal {signal.name} with value {signal.get()}, expected {value}"
|
||||
)
|
||||
|
||||
@typechecked
|
||||
@@ -462,12 +465,23 @@ class Mo1Bragg(PSIDeviceBase, Mo1BraggPositioner):
|
||||
f"Resetting scan validation in stage for state: {ScanControlLoadMessage(self.scan_control.scan_msg.get())}, "
|
||||
f"retry .get() on scan_control: {ScanControlLoadMessage(self.scan_control.scan_msg.get())} and sleeping 1s"
|
||||
)
|
||||
self.scan_control.scan_val_reset.put(1)
|
||||
current_scan_msg = self.scan_control.scan_msg.get()
|
||||
|
||||
def callback(*, old_value, value, **kwargs):
|
||||
if old_value == current_scan_msg and value == target_state:
|
||||
return True
|
||||
return False
|
||||
|
||||
status = SubscriptionStatus(self.scan_control.scan_msg, callback=callback)
|
||||
self.scan_control.scan_val_reset.put(1)
|
||||
|
||||
status.wait(timeout=self.timeout_for_pvwait)
|
||||
|
||||
# try:
|
||||
# self.wait_for_signal(self.scan_control.scan_msg, target_state, timeout=4)
|
||||
# except TimeoutError as exc:
|
||||
# raise TimeoutError(
|
||||
# f"Timeout after {self.timeout_for_pvwait} while waiting for scan status,"
|
||||
# f" current state: {ScanControlScanStatus(self.scan_control.scan_msg.get())}"
|
||||
# ) from exc
|
||||
|
||||
try:
|
||||
self.wait_for_signal(self.scan_control.scan_msg, target_state, timeout=4)
|
||||
except TimeoutError as exc:
|
||||
raise TimeoutError(
|
||||
f"Timeout after {self.timeout_for_pvwait} while waiting for scan status,"
|
||||
f" current state: {ScanControlScanStatus(self.scan_control.scan_msg.get())}"
|
||||
) from exc
|
||||
|
||||
@@ -135,6 +135,7 @@ class Nidaq(PSIDeviceBase, NidaqControl):
|
||||
def __init__(self, prefix: str = "", *, name: str, scan_info: ScanInfo = None, **kwargs):
|
||||
super().__init__(name=name, prefix=prefix, scan_info=scan_info, **kwargs)
|
||||
self.timeout_wait_for_signal = 5 # put 5s firsts
|
||||
self._timeout_wait_for_pv = 3 # 3s timeout for pv calls
|
||||
self.valid_scan_names = [
|
||||
"xas_simple_scan",
|
||||
"xas_simple_scan_with_xrd",
|
||||
@@ -278,7 +279,7 @@ class Nidaq(PSIDeviceBase, NidaqControl):
|
||||
timeout = self.timeout_wait_for_signal,
|
||||
check_stopped=True):
|
||||
raise NidaqError(f"Device {self.name} has not been reached in state STANDBY, current state {NidaqState(self.state.get())}")
|
||||
self.scan_duration.set(0).wait()
|
||||
self.scan_duration.set(0).wait(timeout=self._timeout_wait_for_pv)
|
||||
|
||||
def on_stage(self) -> DeviceStatus | StatusBase | None:
|
||||
"""
|
||||
@@ -296,9 +297,9 @@ class Nidaq(PSIDeviceBase, NidaqControl):
|
||||
raise NidaqError(
|
||||
f"Device {self.name} has not been reached in state STANDBY, current state {NidaqState(self.state.get())}"
|
||||
)
|
||||
self.scan_type.set(ScanType.TRIGGERED).wait()
|
||||
self.scan_duration.set(0).wait()
|
||||
self.stage_call.set(1).wait()
|
||||
self.scan_type.set(ScanType.TRIGGERED).wait(timeout = self._timeout_wait_for_pv)
|
||||
self.scan_duration.set(0).wait(timeout=self._timeout_wait_for_pv)
|
||||
self.stage_call.set(1).wait(timeout = self._timeout_wait_for_pv)
|
||||
|
||||
if not self.wait_for_condition(
|
||||
condition=lambda: self.state.get() == NidaqState.STAGE, timeout=self.timeout_wait_for_signal, check_stopped=True
|
||||
@@ -306,7 +307,7 @@ class Nidaq(PSIDeviceBase, NidaqControl):
|
||||
raise NidaqError(
|
||||
f"Device {self.name} has not been reached in state STAGE, current state {NidaqState(self.state.get())}"
|
||||
)
|
||||
self.kickoff_call.set(1).wait()
|
||||
self.kickoff_call.set(1).wait(timeout = self._timeout_wait_for_pv)
|
||||
logger.info(f"Device {self.name} was staged: {NidaqState(self.state.get())}")
|
||||
|
||||
def on_unstage(self) -> DeviceStatus | StatusBase | None:
|
||||
@@ -374,4 +375,4 @@ class Nidaq(PSIDeviceBase, NidaqControl):
|
||||
|
||||
def on_stop(self) -> None:
|
||||
"""Called when the device is stopped."""
|
||||
self.stop_call.set(1).wait()
|
||||
self.stop_call.put(1)
|
||||
|
||||
Reference in New Issue
Block a user