GUI/DAQ: fixed connection error handling for tell, daq, smargon. Added handling for aerotech. Fixed bug where connection messaged flashed when polling status, fixed bug where tell connected would quash other messages and appear as an error.
This commit is contained in:
@@ -1622,6 +1622,16 @@ class AareDAQ:
|
||||
# Keep status flowing even if Tell code throws something unexpected
|
||||
return self.__cfg.current_sample, False, f"TELL unavailable: {e}"
|
||||
|
||||
def _aerotech_status(self) -> tuple[bool, str | None]:
|
||||
aerotech_ok = True
|
||||
aerotech_err: str | None = None
|
||||
try:
|
||||
_ = self.__devs.aerotech.status()
|
||||
except Exception as e:
|
||||
aerotech_ok = False
|
||||
aerotech_err = str(e)
|
||||
return aerotech_ok, aerotech_err
|
||||
|
||||
def _safe_geom(self) -> tuple[SampleGeometryModel, bool, str | None]:
|
||||
"""
|
||||
Return (geom, smargon_connected, smargon_error) without raising.
|
||||
@@ -1704,6 +1714,7 @@ class AareDAQ:
|
||||
def status(self) -> DAQStatusModel:
|
||||
safe_sample, tell_ok, tell_err = self._safe_sample()
|
||||
safe_geom, smargon_ok, smargon_err = self._safe_geom()
|
||||
aerotech_ok, aerotech_err = self._aerotech_status()
|
||||
|
||||
return DAQStatusModel(
|
||||
state=self.state,
|
||||
@@ -1721,6 +1732,8 @@ class AareDAQ:
|
||||
tell_error=tell_err,
|
||||
smargon_connected=smargon_ok,
|
||||
smargon_error=smargon_err,
|
||||
aerotech_connected=aerotech_ok,
|
||||
aerotech_error=aerotech_err,
|
||||
)
|
||||
|
||||
def cancel(self):
|
||||
|
||||
@@ -78,6 +78,8 @@ class MainWindow(QMainWindow):
|
||||
self._controls_help_dialog = None
|
||||
self._cleanup_done = False
|
||||
self._default_window_state = None
|
||||
self._last_status_message: str | None = None
|
||||
self._last_status_is_error: bool | None = None
|
||||
|
||||
# Tutorial manager (define tutorials after widgets exist)
|
||||
self._tutorial_event_bus = TutorialEventBus(self)
|
||||
@@ -482,10 +484,26 @@ class MainWindow(QMainWindow):
|
||||
self.daq.fluorimeter_spectrum_update.connect(lambda: self.fluor_panel_dock.setVisible(True))
|
||||
|
||||
self.daq.status_message.connect(self.status_bar.show_connection_message)
|
||||
self.daq.status_message.connect(self.alert_banner.show_message)
|
||||
self.daq.status_message.connect(self._show_status_message_once)
|
||||
|
||||
register_tutorials(self, self.tutorial_manager)
|
||||
|
||||
@Slot(str, bool)
|
||||
def _show_status_message_once(self, message: str, is_error: bool = True) -> None:
|
||||
message = (message or "").strip()
|
||||
if not message:
|
||||
self.alert_banner.clear_message()
|
||||
self._last_status_message = None
|
||||
self._last_status_is_error = None
|
||||
return
|
||||
|
||||
if message == self._last_status_message and is_error == self._last_status_is_error:
|
||||
return
|
||||
|
||||
self._last_status_message = message
|
||||
self._last_status_is_error = is_error
|
||||
self.alert_banner.show_message(message, is_error=is_error)
|
||||
|
||||
@Slot(QPixmap)
|
||||
def _on_samcam_prediction_pixmap(self, pix: QPixmap) -> None:
|
||||
self._last_pred_image_ts = time.monotonic()
|
||||
|
||||
@@ -80,6 +80,9 @@ class DAQWorker(QObject):
|
||||
self._last_tell_connected: bool | None = None
|
||||
self._last_tell_error: str | None = None
|
||||
self._last_smargon_connected: bool | None = None
|
||||
self._last_smargon_error: str | None = None
|
||||
self._last_aerotech_connected: bool | None = None
|
||||
self._last_aerotech_error: str | None = None
|
||||
self._server_connected: bool | None = None
|
||||
self._last_server_error: str | None = None
|
||||
|
||||
@@ -196,8 +199,10 @@ class DAQWorker(QObject):
|
||||
*,
|
||||
tell_conn: bool,
|
||||
smargon_conn: bool,
|
||||
aerotech_conn: bool,
|
||||
tell_changed: bool,
|
||||
smargon_changed: bool,
|
||||
aerotech_changed: bool,
|
||||
) -> tuple[str | None, str | None, bool]:
|
||||
disconnected: list[str] = []
|
||||
restored: list[str] = []
|
||||
@@ -212,11 +217,22 @@ class DAQWorker(QObject):
|
||||
elif smargon_changed:
|
||||
restored.append("Smargon")
|
||||
|
||||
if not aerotech_conn:
|
||||
disconnected.append("Aerotech")
|
||||
elif aerotech_changed:
|
||||
restored.append("Aerotech")
|
||||
|
||||
if disconnected:
|
||||
if len(disconnected) == 3:
|
||||
return (
|
||||
"all-devices-down",
|
||||
"TELL, Smargon, and Aerotech connection errors, please inform your local contact.",
|
||||
True,
|
||||
)
|
||||
if len(disconnected) == 2:
|
||||
return (
|
||||
"tell+smargon-down",
|
||||
"TELL and Smargon connection errors, please inform your local contact.",
|
||||
"+".join(sorted(d.lower() for d in disconnected)) + "-down",
|
||||
f"{disconnected[0]} and {disconnected[1]} connection errors, please inform your local contact.",
|
||||
True,
|
||||
)
|
||||
device = disconnected[0]
|
||||
@@ -227,10 +243,11 @@ class DAQWorker(QObject):
|
||||
)
|
||||
|
||||
if restored:
|
||||
if len(restored) == 3:
|
||||
return (None, "TELL, Smargon, and Aerotech connections restored.", False)
|
||||
if len(restored) == 2:
|
||||
return (None, "TELL and Smargon connections restored.", False,)
|
||||
device = restored[0]
|
||||
return (None, f"{device} connection restored.",False)
|
||||
return (None, f"{restored[0]} and {restored[1]} connections restored.", False)
|
||||
return (None, f"{restored[0]} connection restored.", False)
|
||||
|
||||
return (None, None, False)
|
||||
|
||||
@@ -258,19 +275,31 @@ class DAQWorker(QObject):
|
||||
or self._last_tell_connected != tell_conn
|
||||
or self._last_tell_error != tell_err_text
|
||||
)
|
||||
|
||||
smargon_changed = (
|
||||
self._last_smargon_connected is not None and self._last_smargon_connected != smargon_conn
|
||||
self._last_smargon_connected is None
|
||||
or self._last_smargon_connected != smargon_conn
|
||||
or self._last_smargon_error != smargon_err_text
|
||||
)
|
||||
aerotech_changed = (
|
||||
self._last_aerotech_connected is None
|
||||
or self._last_aerotech_connected != aerotech_conn
|
||||
or self._last_aerotech_error != aerotech_err_text
|
||||
)
|
||||
|
||||
self._last_tell_connected = tell_conn
|
||||
self._last_smargon_connected = smargon_conn
|
||||
self._last_aerotech_connected = aerotech_conn
|
||||
self._last_tell_error = tell_err_text
|
||||
self._last_smargon_error = smargon_err_text
|
||||
self._last_aerotech_error = aerotech_err_text
|
||||
|
||||
status_key, status_msg, is_error = self._compose_device_status_message(
|
||||
tell_conn=tell_conn,
|
||||
smargon_conn=smargon_conn,
|
||||
aerotech_conn=aerotech_conn,
|
||||
tell_changed=tell_changed,
|
||||
smargon_changed=smargon_changed,
|
||||
aerotech_changed=aerotech_changed,
|
||||
)
|
||||
self._emit_status_if_changed(status_key, status_msg, is_error)
|
||||
|
||||
@@ -278,6 +307,8 @@ class DAQWorker(QObject):
|
||||
self._log_device_error_throttled(device="tell", message=tell_err)
|
||||
if not smargon_conn:
|
||||
self._log_device_error_throttled(device="smargon", message=smargon_err)
|
||||
if not aerotech_conn:
|
||||
self._log_device_error_throttled(device="aerotech", message=aerotech_err)
|
||||
|
||||
except Exception as e:
|
||||
err_msg = str(e)
|
||||
@@ -293,6 +324,7 @@ class DAQWorker(QObject):
|
||||
self._last_server_error = err_msg
|
||||
self._last_tell_connected = None
|
||||
self._last_smargon_connected = None
|
||||
self._last_aerotech_connected = None
|
||||
|
||||
logger.error(f"Exception from status response: {e}")
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ class AlertBanner(QFrame):
|
||||
super().__init__(parent)
|
||||
|
||||
self._current_message: str | None = None
|
||||
self._current_is_error: bool | None = None
|
||||
|
||||
self._clear_timer = QTimer(self)
|
||||
self._clear_timer.setSingleShot(True)
|
||||
@@ -42,7 +43,7 @@ class AlertBanner(QFrame):
|
||||
self.clear_message()
|
||||
return
|
||||
|
||||
if msg == self._current_message:
|
||||
if self._current_message == msg and self._current_is_error == is_error:
|
||||
return
|
||||
|
||||
if is_error:
|
||||
@@ -62,6 +63,8 @@ class AlertBanner(QFrame):
|
||||
"}"
|
||||
)
|
||||
else:
|
||||
if msg == self._current_message:
|
||||
return
|
||||
decorated = f"✅ {msg} ✅"
|
||||
self.setStyleSheet(
|
||||
"QFrame {"
|
||||
@@ -79,12 +82,15 @@ class AlertBanner(QFrame):
|
||||
)
|
||||
self._clear_timer.start(5000)
|
||||
|
||||
self._current_message = msg
|
||||
self._current_is_error = is_error
|
||||
self._label.setText(decorated)
|
||||
self.setVisible(True)
|
||||
|
||||
@Slot()
|
||||
def clear_message(self):
|
||||
self._current_message = None
|
||||
self._current_is_error = None
|
||||
self._clear_timer.stop()
|
||||
self._label.clear()
|
||||
self.setVisible(False)
|
||||
|
||||
Reference in New Issue
Block a user