diff --git a/mxcubecore/HardwareObjects/BlissShutter.py b/mxcubecore/HardwareObjects/BlissShutter.py index ea12db60b5..95237adcff 100644 --- a/mxcubecore/HardwareObjects/BlissShutter.py +++ b/mxcubecore/HardwareObjects/BlissShutter.py @@ -31,17 +31,15 @@ actuator_name: safshut type: tango username: Safety shutter - objects: - controller: bliss.yaml """ +import logging from enum import ( Enum, unique, ) -import gevent - +from mxcubecore import HardwareRepository as HWR from mxcubecore.BaseHardwareObjects import HardwareObjectState from mxcubecore.HardwareObjects.abstract.AbstractShutter import AbstractShutter @@ -75,9 +73,14 @@ def __init__(self, name): def init(self): """Initialise the predefined values""" - self.controller = self.get_object_by_role("controller") super().init() - self._bliss_obj = getattr(self.controller, self.actuator_name) + try: + bliss_proxy = HWR.beamline.bliss_proxy + bliss_proxy.hardware.register(self.actuator_name) + self._bliss_obj = bliss_proxy.get_object(self.actuator_name) + except Exception as exc: + msg = f"BlissShutter: BLISS object {self.actuator_name} not available {exc}" + logging.getLogger("MX3.HWR").warning(msg) # for now we only treat tango type shutter self.shutter_type = self.get_property("type", "tango") try: @@ -88,14 +91,25 @@ def init(self): pass if self.shutter_type == "tango": self._initialise_values() - self._poll_task = gevent.spawn(self._poll_state) + + self._bliss_obj.subscribe("property", self._on_property_changed) + self._bliss_obj.subscribe("online", self._on_online_changed) self.update_state() + self.update_value() - def _poll_state(self): - while True: - self.update_value(self.get_value()) - gevent.sleep(0.5) + def _on_online_changed(self, online: bool) -> None: + """Callback for shutter online/offline events received via blissclient.""" + if not online: + self.update_state(HardwareObjectState.UNKNOWN) + else: + self._update_state() + + def _on_property_changed(self, data: dict) -> None: + """Callback for property changes received via blissclient.""" + if "state" in data: + self.update_state() + self.update_value() def _initialise_values(self): """Add the tango states to VALUES""" @@ -116,21 +130,30 @@ def get_state(self): (enum 'HardwareObjectState'): Device state. """ try: - _state = self._bliss_obj.state.name + _state = self._bliss_obj.state or "UNKNOWN" + return self.SPECIFIC_STATES[_state].value[0] except (AttributeError, KeyError): return self.STATES.UNKNOWN - return self.SPECIFIC_STATES[_state].value[0] + except Exception: + return self.STATES.UNKNOWN def get_value(self): """Get the device value Returns: (Enum): Enum member, corresponding to the value or UNKNOWN. """ - # the return from BLISS value is an Enum - _val = self._bliss_obj.state.name + try: + _val = self._bliss_obj.state or "UNKNOWN" + except Exception: + _val = "UNKNOWN" return self.value_to_enum(_val) def _set_value(self, value): + if self._bliss_obj is None: + raise RuntimeError( + f"BlissShutter '{self.actuator_name}' is offline — " + "BLISS object not available" + ) if value.name == "OPEN": self._bliss_obj.open() elif value.name == "CLOSED":