diff --git a/src/aare/daq/server.py b/src/aare/daq/server.py index e0f5f3e7..6a473545 100644 --- a/src/aare/daq/server.py +++ b/src/aare/daq/server.py @@ -1483,8 +1483,10 @@ async def take_over_beamline( return "OK" -@app.post("/state/free_beamline") -async def free_beamline(payload: RecoveryActionRequest, token: str = Depends(oauth2_scheme)) -> str: +@app.post("/state/force_clear_busy") +async def force_clear_busy( + payload: RecoveryActionRequest, token: str = Depends(oauth2_scheme) +) -> str: """ Clear the beamline busy flag. Staff only. @@ -1506,8 +1508,8 @@ async def free_beamline(payload: RecoveryActionRequest, token: str = Depends(oau return "OK" -@app.post("/recovery/recover_beamline") -async def recover_beamline( +@app.post("/recovery/force_maintenance_state") +async def force_maintenance_state( payload: RecoveryActionRequest, token: str = Depends(oauth2_scheme) ) -> dict: """ @@ -1533,7 +1535,7 @@ async def recover_beamline( cfg.state = BeamlineStateEnum.Maintenance logger.warning( - "Beamline recovery action executed.", + "Beamline recovery action executed - forced maintenance state.", extra={ "session": getattr(data, "session", None), "previous_state": getattr(prev_state, "name", str(prev_state)), diff --git a/src/aare/devices/bec_worker.py b/src/aare/devices/bec_worker.py index d6a5c1f8..c0ca889e 100644 --- a/src/aare/devices/bec_worker.py +++ b/src/aare/devices/bec_worker.py @@ -270,12 +270,6 @@ class BECClientWorker: return True return self.planner.is_state(state) - def current_state(self): - if self.simulated: - logger.debug("Simulating check_beamline_state") - return BeamlineState.MAINTENANCE - return self.planner.current_state() - def list_position_devices(self): """List the position devices available for the BEC worker""" if self.simulated or self.position_devices is None: diff --git a/src/aare/gui/panels/beamline_recovery_panel.py b/src/aare/gui/panels/beamline_recovery_panel.py index aa5c5a85..7e4a5822 100644 --- a/src/aare/gui/panels/beamline_recovery_panel.py +++ b/src/aare/gui/panels/beamline_recovery_panel.py @@ -106,8 +106,8 @@ class RecoveryPanel(QWidget): self._take_over_btn.clicked.connect(self._take_over_beamline) layout.addWidget(self._take_over_btn) - self._free_beamline_btn = QPushButton("Free beamline", self) - self._free_beamline_btn.setStyleSheet( + self._force_clear_busy_btn = QPushButton("Clear busy flag", self) + self._force_clear_busy_btn.setStyleSheet( card_style( PENDING_CARD_BG, PENDING_CARD_BORDER, @@ -116,11 +116,11 @@ class RecoveryPanel(QWidget): extra="padding: 10px; font-weight: 600;", ) ) - self._free_beamline_btn.clicked.connect(self._free_beamline) - layout.addWidget(self._free_beamline_btn) + self._force_clear_busy_btn.clicked.connect(self._force_clear_busy) + layout.addWidget(self._force_clear_busy_btn) - self._recover_beamline_btn = QPushButton("Recover beamline", self) - self._recover_beamline_btn.setStyleSheet( + self._force_maintenance_state_btn = QPushButton("Force to maintenance state", self) + self._force_maintenance_state_btn.setStyleSheet( card_style( CHIP_BAD_BG, BAD_CARD_BORDER, @@ -130,8 +130,8 @@ class RecoveryPanel(QWidget): extra="padding: 10px; font-weight: 700;", ) ) - self._recover_beamline_btn.clicked.connect(self._recover_beamline) - layout.addWidget(self._recover_beamline_btn) + self._force_maintenance_state_btn.clicked.connect(self._force_maintenance_state) + layout.addWidget(self._force_maintenance_state_btn) self._recovery_unmount_btn = QPushButton("Unmount sample (recovery)", self) self._recovery_unmount_btn.setStyleSheet( @@ -201,8 +201,8 @@ class RecoveryPanel(QWidget): else "Disabled because no mounted sample is visible in current status." ) - self._free_beamline_btn.setEnabled(beamline_busy) - self._free_beamline_btn.setToolTip( + self._force_clear_busy_btn.setEnabled(beamline_busy) + self._force_clear_busy_btn.setToolTip( "" if beamline_busy else "Disabled because beamline does not currently appear busy." ) @@ -238,22 +238,23 @@ class RecoveryPanel(QWidget): self._daq.take_over_beamline(code) @Slot() - def _free_beamline(self) -> None: + def _force_clear_busy(self) -> None: if not self._confirm( - "Free beamline", "This will clear the beamline busy flag.\n\nDo you want to continue?" + "Clear busy flag", + "This will clear the beamline busy flag.\nAfter this, the server may still report that it is 'moving' if it is not in a defined state. You may then force the server into maintenance mode to recover.\nDo you want to continue?", ): return - code = self._prompt_recovery_code("Free beamline") + code = self._prompt_recovery_code("Clear busy flag") if not code: return self._last_action.setText("Last action: Clearing beamline busy flag...") - self._daq.free_beamline(code) + self._daq.force_clear_busy(code) @Slot() - def _recover_beamline(self) -> None: + def _force_maintenance_state(self) -> None: if self._sample_appears_mounted(): if not self._confirm( - "Recover beamline", + "Force maintenance mode", "A sample appears to be mounted.\n\n" "Recovering the beamline may damage the sample or leave hardware in an unsafe state.\n\n" "Only continue if you are sure this is the correct recovery action.", @@ -261,17 +262,17 @@ class RecoveryPanel(QWidget): return else: if not self._confirm( - "Recover beamline", + "Force maintenance mode", "This will take over the beamline, clear the busy flag, and set the state to Maintenance.\n\n" "Do you want to continue?", ): return - code = self._prompt_recovery_code("Recover beamline") + code = self._prompt_recovery_code("Force maintenance mode") if not code: return self._last_action.setText("Last action: Recovering beamline to Maintenance...") - self._daq.recover_beamline(code) + self._daq.force_maintenance_state(code) @Slot() def _recovery_unmount_sample(self) -> None: diff --git a/src/aare/gui/threads/daq_worker.py b/src/aare/gui/threads/daq_worker.py index bd8ef669..2973063a 100644 --- a/src/aare/gui/threads/daq_worker.py +++ b/src/aare/gui/threads/daq_worker.py @@ -872,12 +872,12 @@ class DAQWorker(QObject): self.generic_post("state/xtal_snapshot") @Slot(str) - def free_beamline(self, confirmation_code: str): + def force_clear_busy(self, confirmation_code: str): if self._base_url is None: - logger.info("POST /state/free_beamline") + logger.info("POST /state/force_clear_busy") return - request = QNetworkRequest(QUrl(f"{self._base_url}/state/free_beamline")) + request = QNetworkRequest(QUrl(f"{self._base_url}/state/force_clear_busy")) request.setRawHeader(b"Authorization", f"Bearer {self._token}".encode()) request.setRawHeader(b"Content-Type", b"application/json") body = json.dumps({"confirmation_code": confirmation_code}) @@ -902,12 +902,12 @@ class DAQWorker(QObject): ) @Slot(str) - def recover_beamline(self, confirmation_code: str): + def force_maintenance_state(self, confirmation_code: str): if self._base_url is None: - logger.info("POST /recovery/recover_beamline") + logger.info("POST /recovery/force_maintenance_state") return - request = QNetworkRequest(QUrl(f"{self._base_url}/recovery/recover_beamline")) + request = QNetworkRequest(QUrl(f"{self._base_url}/recovery/force_maintenance_state")) request.setRawHeader(b"Authorization", f"Bearer {self._token}".encode()) request.setRawHeader(b"Content-Type", b"application/json") body = json.dumps({"confirmation_code": confirmation_code}) diff --git a/src/aare/gui/widgets/busy_overlay.py b/src/aare/gui/widgets/busy_overlay.py index 6013a7b2..e41604f6 100644 --- a/src/aare/gui/widgets/busy_overlay.py +++ b/src/aare/gui/widgets/busy_overlay.py @@ -15,9 +15,6 @@ from aare.gui.styles import ( BUSY_PSI_RED, BUSY_PSI_RED_BORDER, BUSY_PSI_RED_DOT, - BUSY_PURPLE, - BUSY_PURPLE_BORDER, - BUSY_PURPLE_DOT, BUSY_RED_BADGE, BUSY_RED_BORDER, BUSY_RED_DOT, @@ -108,7 +105,11 @@ def build_busy_overlay_style( tell_state: TellStateModel | None, session_state: SessionsStateEnum | None = None, ) -> BusyOverlayStyle | None: - if session_state == SessionsStateEnum.Vacant: + if session_state in { + SessionsStateEnum.OwnedByElse, + SessionsStateEnum.PendingYouToElse, + SessionsStateEnum.Vacant, + }: return BusyOverlayStyle( text="In viewing mode", badge_bg=BUSY_YELLOW, @@ -117,20 +118,8 @@ def build_busy_overlay_style( overlay_border=qcolor(BUSY_YELLOW_BORDER, 235), overlay_text=qcolor(WHITE), accent_dot=BUSY_YELLOW_DOT, - subtext="Click here to grab baton if need to interact with GUI", + subtext="Click here to grab the baton if you need to interact with GUI", ) - - if session_state in {SessionsStateEnum.OwnedByElse, SessionsStateEnum.PendingYouToElse}: - return BusyOverlayStyle( - text="GUEST MODE", - badge_bg=BUSY_PURPLE, - badge_fg=WHITE, - overlay_fill=qcolor(BUSY_PURPLE, 190), - overlay_border=qcolor(BUSY_PURPLE_BORDER, 230), - overlay_text=qcolor(WHITE), - accent_dot=BUSY_PURPLE_DOT, - ) - if not is_busy: return None