#
# Project name: MXCuBE
# https://github.com/mxcube
#
# This file is part of MXCuBE software.
#
# MXCuBE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# MXCuBE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with MXCuBE. If not, see <http://www.gnu.org/licenses/>.
import logging
import gevent
from mxcubecore import HardwareRepository as HWR
from mxcubecore.BaseHardwareObjects import HardwareObject
__credits__ = ["EMBL Hamburg"]
__license__ = "LGPLv3+"
__category__ = "General"
[docs]class EMBLDoorInterlock(HardwareObject):
DoorInterlockState = {
3: "unlocked",
1: "closed",
0: "locked_active",
46: "locked_inactive",
-1: "error",
}
def __init__(self, name):
super().__init__(name)
self.use_door_interlock = None
self.door_interlock_state = None
self.door_interlock_final_state = None
self.door_interlock_breakabled = None
self.chan_ics_error = None
self.chan_state_locked = None
self.chan_state_breakable = None
self.chan_cmd_break_error = None
self.cmd_break_interlock = None
self.ics_enabled = True
[docs] def init(self):
self.door_interlock_state = "unknown"
self.use_door_interlock = self.get_property("useDoorInterlock", True)
self.chan_state_locked = self.get_channel_object("chanStateLocked")
self.chan_state_locked.connect_signal("update", self.state_locked_changed)
self.chan_state_breakable = self.get_channel_object("chanStateBreakable")
self.chan_state_breakable.connect_signal("update", self.state_breakable_changed)
self.chan_ics_error = self.get_channel_object("chanIcsErrorOne")
self.chan_ics_error.connect_signal("update", self.ics_error_msg_changed)
self.chan_cmd_break_error = self.get_channel_object("chanCmdBreakError")
if self.chan_cmd_break_error is not None:
self.chan_cmd_break_error.connect_signal(
"update", self.cmd_break_error_msg_changed
)
self.cmd_break_interlock = self.get_command_object("cmdBreak")
[docs] def cmd_break_error_msg_changed(self, error_msg):
"""Displays error log message if door interlock break do not work
:param error_msg: error message
:type error_msg: str
:return: None
"""
if len(error_msg) > 0:
logging.getLogger("GUI").error(
"Break ICS door interlock: Error %s" % error_msg
)
[docs] def ics_error_msg_changed(self, error_msg):
"""Updates ICS error message
:param error_msg: error message
:type error_msg: str
:return: None
"""
if len(error_msg) > 0:
self.ics_enabled = False
else:
self.ics_enabled = True
self.get_state()
[docs] def connected(self):
"""Sets is ready"""
self.set_is_ready(True)
[docs] def disconnected(self):
"""Sets not ready"""
self.set_is_ready(False)
[docs] def state_breakable_changed(self, state):
"""Updates door interlock state"""
self.door_interlock_breakabled = state
self.get_state()
[docs] def state_locked_changed(self, state):
"""Updates door interlock state"""
self.door_interlock_state = state
self.get_state()
[docs] def get_state(self):
"""Returns current state"""
if self.door_interlock_state:
if self.door_interlock_breakabled:
self.door_interlock_final_state = "locked_active"
msg = "Locked (unlock enabled)"
else:
self.door_interlock_final_state = "locked_inactive"
msg = "Locked (unlock disabled)"
else:
self.door_interlock_final_state = "unlocked"
msg = "Unlocked"
if not self.ics_enabled:
self.door_interlock_final_state = "error"
msg = "Desy ICS error"
if not self.use_door_interlock:
self.door_interlock_final_state = "locked_active"
msg = "Locked (unlock enabled)"
self.emit("doorInterlockStateChanged", self.door_interlock_final_state, msg)
return self.door_interlock_final_state, msg
[docs] def unlock_door_interlock(self):
"""Break Interlock (only if it is allowed by doorInterlockCanUnlock)
It doesn't matter what we are sending in the command
as long as it is a one char
"""
if HWR.beamline.diffractometer is not None:
detector_distance = HWR.beamline.detector.distance
if HWR.beamline.diffractometer.in_plate_mode:
if detector_distance is not None:
if detector_distance.get_value() < 780:
detector_distance.set_value(800, timeout=None)
while detector_distance.get_value() < 360:
gevent.sleep(0.01)
gevent.sleep(2)
else:
if detector_distance is not None:
if detector_distance.get_value() < 1099:
detector_distance.set_value(1100)
gevent.sleep(1)
try:
HWR.beamline.diffractometer.set_phase(
HWR.beamline.diffractometer.PHASE_TRANSFER, timeout=None
)
except Exception:
logging.getLogger("GUI").error(
"Unable to set diffractometer to transfer phase"
)
if not self.use_door_interlock:
logging.getLogger().info("Door interlock is disabled")
return
if self.door_interlock_state:
if self.door_interlock_breakabled:
if self.cmd_break_interlock is None:
self.cmd_break_interlock = self.get_command_object(
"cmdBreakInterlock"
)
self.cmd_break_interlock()
else:
msg = (
"Door Interlock cannot be broken at the moment "
+ "please check its status and try again."
)
logging.getLogger("GUI").error(msg)
else:
self.log.info("Door is Interlocked")
[docs] def re_emit_values(self):
"""Updates state"""
self.get_state()