From ff772ef487dc7fe06ee8f661ec4bcf4984f13c53 Mon Sep 17 00:00:00 2001 From: appleb_m Date: Tue, 28 Apr 2026 15:07:15 +0200 Subject: [PATCH] DAQ: added back mount_handler logic - to be tested. --- src/aare/daq/daq.py | 34 +++++++++++++---- src/aare/devices/tell_client.py | 66 ++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 29 deletions(-) diff --git a/src/aare/daq/daq.py b/src/aare/daq/daq.py index 06e658f9..c9532182 100644 --- a/src/aare/daq/daq.py +++ b/src/aare/daq/daq.py @@ -68,8 +68,9 @@ from aare.common.exception_handler import ( SmargonCommunicationError, TellCommunicationError, JFJochCommunicationError, AerotechCommunicationError, MagnetPositionSensorErorr, UnmountingFailed, - DataCollectionException, RasterScanException + DataCollectionException, RasterScanException, TellMountFailedException ) +from aare.devices.tell_client import TellEventValueEnum logger = setup_logger("aareDAQ") #TODO tidy up DAQ - migrate functions itno different scripts, to reduce size? @@ -921,9 +922,26 @@ class AareDAQ: raise Exception("Goniometer is not in position based on magnet position sensor readout") - def __mount_failure_handler(self, value): - logger.debug(f"Mount response: {value}") - pass + def __mount_handler(self, target : SampleShortInfo, mount_attempted: bool = False): + + value = self.__devs.tell.mount(address=target.tell_address(), force=True, auto_unmount=True, read_dm=False, + wait=True, timeout=360.0) + logger.debug(f"Mount response: {value.value}") + if value == TellEventValueEnum.NO_PIN_IN_GRIPPER: + if mount_attempted: + raise MountingFailed("No Pin in Gripper") + else: + logger.warning("No Pin in Gripper - retrying mounting") + self.__mount_handler(target, mount_attempted=True) + elif value == TellEventValueEnum.PIN_IS_LOST_GRIPPER: + logger.error("Pin is lost") + raise MountingFailed("Pin is lost") + elif value == TellEventValueEnum.ROBOT_CLEAR_AFTER_MOUNT or value == TellEventValueEnum.DRY or value == TellEventValueEnum.COLD: + logger.info(f"Robot is {value.value} - freeing beamline for user") + else: + logger.info(f"Mount response: {value.value} is not currently handled") + return + def __mount(self, target: SampleShortInfo | None): self.__devs.smargon_move_home() @@ -951,11 +969,11 @@ class AareDAQ: log_msg = (f"Unmounting sample: {previous_sample} \n " f"and {log_msg}") logger.debug(log_msg) - value = self.__devs.tell.mount(address=target.tell_address(), force=True, auto_unmount=True, read_dm=False, - wait=True, timeout=360.0) - self.__mount_failure_handler(value) - logger.info(f"Mount result: {value}") + self.__mount_handler(target) self.__cfg.current_sample = target + except TellMountFailedException as e: + logger.error(f"Failed to mount: {target} due to exception: {e}") + raise except Exception as e: logger.error(f"Mount failed: {e}") diff --git a/src/aare/devices/tell_client.py b/src/aare/devices/tell_client.py index 24290801..3ca25354 100755 --- a/src/aare/devices/tell_client.py +++ b/src/aare/devices/tell_client.py @@ -1,6 +1,7 @@ import ast import json import re +from enum import Enum from typing import List from aare.common.beamline import MXBeamline @@ -29,6 +30,30 @@ from aare.common.logger_config import setup_logger logger = setup_logger("aareDAQ") + +class TellEventTypeEnum(Enum): + STATE = "state" + MOTION_TASK = "Motion Task" + MOTION_SYNC = "Motion Sync" + GIPPER_DETECTION = "Gripper detection" + UNKNOWN = "Unknown event type" + + +class TellEventValueEnum(Enum): + SUCCESS = "success" + NO_PIN_IN_GRIPPER = "No Pin in Gripper" + PIN_STILL_IN_GRIPPER = "Pin still in Gripper" + PIN_IS_LOST_GRIPPER = "Pin is lost" + UNKNOWN = "Unknown value" + ROBOT_CLEAR_AFTER_MOUNT = "Robot Clear after mount" + DRY = "dry" + COLD = "cold" + PARK = "park" + UNMOUNT = "unmount" + MOUNT = "mount" + MANUAL = "manual" + + class TellClient: """High-level Tell robot API using a pluggable backend""" def __init__(self, bl: MXBeamline, backend: TellBackend | None = None): @@ -159,7 +184,7 @@ class TellClient: auto_unmount: bool = False, wait: bool = False, timeout: float = 600.0, - ): + ) -> TellEventTypeEnum | TellEventValueEnum | None: SampleDewarAddress.model_validate(address) segment = address.puck.segment @@ -194,38 +219,37 @@ class TellClient: timeout=wait_timeout, msg=f"Mount {segment}{puck}-{sample}: " ) return value - elif event == "Gripper detection" and value == "No Pin in Gripper": - logger.info(f"gripper detection: {event} occurred with value: {value}") - return value - elif event == "Gripper detection" and value == "Pin still in Gripper": - logger.info(f"gripper detection: {event} occurred with value: {value}") - return value - elif event == "Gripper detection" and value == "Pin is lost": - logger.info(f"gripper detection: {event} occurred with value: {value}") - return value - elif event == "Gripper detection": - logger.info(f"gripper detection: {event} occurred with value: {value}") - elif event == "Motion Task" and value == "dry": - logger.info(f"event: {event} occurred with value: {value}") - logger.info(" Drying occurring, releasing interface to user") - return value - elif event == "Motion Sync" and value == "Robot Clear after mount": - logger.info(f"event: {event} occurred with value: {value}") - logger.info(" Mounting complete, releasing interface to user") - return value + elif event == TellEventTypeEnum.GIPPER_DETECTION.value and value == TellEventValueEnum.NO_PIN_IN_GRIPPER.value: + logger.info(f"{TellEventValueEnum.NO_PIN_IN_GRIPPER.value}") + return TellEventValueEnum.NO_PIN_IN_GRIPPER + elif event == TellEventTypeEnum.GIPPER_DETECTION.value and value == TellEventValueEnum.PIN_STILL_IN_GRIPPER.value: + logger.info(f"{TellEventValueEnum.PIN_STILL_IN_GRIPPER.value}") + return TellEventValueEnum.PIN_STILL_IN_GRIPPER + elif event == TellEventTypeEnum.GIPPER_DETECTION.value and value == TellEventValueEnum.PIN_IS_LOST_GRIPPER.value: + logger.info(f"{TellEventValueEnum.PIN_IS_LOST_GRIPPER.value}") + return TellEventValueEnum.PIN_IS_LOST_GRIPPER + elif event == TellEventTypeEnum.GIPPER_DETECTION.value: + return TellEventTypeEnum.GIPPER_DETECTION + elif event == TellEventTypeEnum.MOTION_TASK.value and value == TellEventValueEnum.DRY.value: + logger.info(f"{TellEventValueEnum.DRY.value}") + return TellEventValueEnum.DRY + elif event == TellEventTypeEnum.MOTION_SYNC.value and value == TellEventValueEnum.ROBOT_CLEAR_AFTER_MOUNT.value: + logger.info(f"{TellEventValueEnum.ROBOT_CLEAR_AFTER_MOUNT.value}") + return TellEventValueEnum.ROBOT_CLEAR_AFTER_MOUNT else: logger.info(f"Unexpected event: {event} occurred with value: {value}") logger.info("Checking command completed okay anyway") self.check_command_ok( timeout=wait_timeout, msg=f"Mount {segment}{puck}-{sample}: " ) + return TellEventValueEnum.UNKNOWN elif wait and segment == "X": logger.info("Loading an auxiliary puck") self.check_command_ok( timeout=wait_timeout, msg=f"Mount {segment}{puck}-{sample}: " ) logger.info("post waiting") - return None + return TellEventValueEnum.SUCCESS def unmount(self, force=False, wait=False, timeout=360.0): if self.is_busy():