# -*- coding: utf-8 -*-
"""Tango Shutter Hardware Object
Example XML:
<object class = "TangoShutter">
<username>label for users</username>
<command type="tango" tangoname="my device" name="Open">Open</command>
<command type="tango" tangoname="my device" name="Close">Close</command>
<channel type="tango" name="State" tangoname="my device" polling="1000">State</channel>
</object>
"""
import logging
import time
from mxcubecore import BaseHardwareObjects
from mxcubecore import HardwareRepository as HWR
[docs]class SOLEILGuillotine(BaseHardwareObjects.HardwareObject):
shutterState = {
# 0: 'ON',
# 1: 'OFF',
"False": "CLOSED",
"True": "OPENED",
"0": "CLOSED",
"1": "OPENED",
"4": "INSERT",
"5": "EXTRACT",
"6": "MOVING",
"7": "STANDBY",
"8": "FAULT",
"9": "INIT",
"10": "RUNNING",
"11": "ALARM",
"12": "DISABLED",
"13": "UNKNOWN",
"-1": "FAULT",
"None": "UNKNOWN",
"UNKNOWN": "UNKNOWN",
"CLOSE": "CLOSED",
"OPEN": "OPENED",
"INSERT": "CLOSED",
"EXTRACT": "OPENED",
"MOVING": "MOVING",
"RUNNING": "MOVING",
"_": "AUTOMATIC",
"FAULT": "FAULT",
"DISABLE": "DISABLED",
"OFF": "FAULT",
"STANDBY": "STANDBY",
"ON": "UNKNOWN",
"ALARM": "ALARM",
}
# shutterState = {
# None: 'unknown',
# 'UNKNOWN': 'unknown',
# 'CLOSE': 'closed',
# 'OPEN': 'opened',
# 'INSERT': 'closed',
# 'EXTRACT': 'opened',
# 'MOVING': 'moving',
# 'RUNNING':'moving',
# '_': 'automatic',
# 'FAULT': 'fault',
# 'DISABLE': 'disabled',
# 'OFF': 'fault',
# 'STANDBY': 'standby',
# 'ON': 'unknown'
# }
shutterStateString = {
"ON": "white",
"OFF": "#012345",
"CLOSED": "#C03000",
"CLOSE": "#FF00FF",
"OPEN": "#00FF00",
"OPENED": "#00FF00",
"INSERT": "#EC3CDD",
"EXTRACT": "#512345",
"MOVING": "#663300",
"STANDBY": "#009900",
"FAULT": "#990000",
"INIT": "#990000",
"RUNNING": "#990000",
"ALARM": "#990000",
"DISABLED": "#EC3CDD",
"UNKNOWN": "GRAY",
"FAULT": "#FF0000",
}
def __init__(self, name):
super().__init__(name)
logging.info("Guillotine init ")
[docs] def init(self):
self._shutterStateValue = "UNKNOWN"
self._currentDistance = "None"
self._d_security = self.get_property("security_distance")
self._d_home = self.get_property("safe_distance")
try:
self.shutChannel = self.get_channel_object("State")
self.shutChannel.connect_signal("update", self.shutterStateChanged)
self.pss = self.get_object_by_role("pss")
self.connect(
HWR.beamline.detector.distance,
"valueChanged",
self.shutterStateChanged,
)
self.connect(
HWR.beamline.detector.distance,
"valueChanged",
self.updateDetectorDistance,
)
for command_name in ("_Insert", "_Extract"):
setattr(self, command_name, self.get_command_object(command_name))
except KeyError:
logging.getLogger().warning("%s: cannot report State", self.name())
try:
self.pss_door = self.get_property(
"tangoname_pss"
) # PyTango.DeviceProxy('I11-MA-CE/PSS/DB_DATA')
except Exception:
self.log.error(
"Guillotine I11-MA-CE/PSS/DB_DATA: tangopssDevice is not defined "
)
if self.pss_door is not None:
self.memIntChan = self.get_channel_object("memInt")
self.connect(self.memIntChan, "update", self.updateGuillotine)
else:
self.log.error("Guillotine: tangopssDevice is not defined ")
def shutterStateChanged(self, value):
#
# emit signal
#
if isinstance(value, float):
value = self.shutChannel.value
self.shutterStateValue = str(value)
self.emit("shutterStateChanged", (self.getShutterState(),))
def getShutterState(self):
# A tester dans les conditio
# if self._currentDistance < self._d_security:
# if self.pss.getWagoState() != "ready":
# return "disabled"
if not self.checkDistance():
return "disabled"
return SOLEILGuillotine.shutterState.get(
self.shutterStateValue, "UNKNOWN"
).lower()
def updateDetectorDistance(self, value):
logging.info("UpdateDetectorDistance")
self._currentDistance = value # self.detector.res2dist(value)
def moveGuillotine(self, state):
if state == "Transfer":
self.goToSecurityDistance()
if state == "Collect":
HWR.beamline.detector.distance.set_value(180)
def updateGuillotine(self, value):
# if open door close guillotine but test distance
# if distance security ok else move detector to security distance
# wait until distance is reached
# if self.pss.getWagoState() != "ready":
if not value:
if self.checkDistance():
self._Insert()
else:
self.goToSecurityDistance()
# self.detector.set_value(self._d_home)
# time.sleep(1.0)# wait distance minimum to insert guillotine
# self._Insert()
def modeCollect(self):
currentDistance = self._currentDistance
logging.info(
"SOLEILGuillotine - setting gonio currentPosition is %s" % currentDistance
)
if self.isInsert():
if not self.checkDistance():
# self.detector.set_value(180)
HWR.beamline.detector.distance.set_value(self._d_security)
time.sleep(2.0)
while HWR.beamline.detector.distance.motorIsMoving():
time.sleep(0.5)
self._Extract()
time.sleep(0.2)
# self.detector.set_value(150)
HWR.beamline.detector.distance.set_value(currentDistance)
time.sleep(2.0)
while HWR.beamline.detector.distance.motorIsMoving():
time.sleep(0.5)
else:
self._Extract()
time.sleep(0.2)
def checkDistance(self):
# logging.info('Current distance is %s' % self._currentDistance)
if self._currentDistance < self._d_security:
return False
else:
return True
def isInsert(self):
if str(self.shutChannel.value) == "INSERT":
return True
else:
return False
def goToSecurityDistance(self):
if self._currentDistance < self._d_home:
HWR.beamline.detector.distance.set_value(self._d_home)
if str(self.shutChannel.value) == "EXTRACT":
self._Insert()
while HWR.beamline.detector.distance.motorIsMoving():
time.sleep(0.5)
def isShutterOk(self):
return not self.getShutterState() in (
"OFF",
"UNKNOWN",
"MOVING",
"FAULT",
"INSERT",
"EXTRACT",
"INIT",
"DISABLED",
"ERROR",
"ALARM",
"STANDBY",
)
def openShutter(self):
logging.info("Guillotine extract")
if self.checkDistance():
self._Extract()
return
logging.getLogger("user_level_log").error(
" Detector is too closed to the gonio Guillotine couldn't be moved"
)
def closeShutter(self):
logging.info("Guillotine insert")
if self.checkDistance():
self._Insert()
return
logging.getLogger("user_level_log").error(
" Detector is too closed to the gonio Guillotine couldn't be moved"
)
def setIn(self):
self._Insert()
def setOut(self):
self._Extract()