Source code for mxcubecore.HardwareObjects.LNLS.EPICS.EPICSNState

from enum import Enum

from mxcubecore.HardwareObjects.abstract.AbstractNState import (
    AbstractNState,
    BaseValueEnum,
)
from mxcubecore.HardwareObjects.LNLS.EPICS.EPICSActuator import EPICSActuator


[docs]class EPICSNState(EPICSActuator, AbstractNState): """ This class manages devices that exist in a discrete number of states and provides an interface between those states (configured in the yaml files) and the EPICS PVs. It ensures that hardware states are treated as Enums. YAML Example ------------ %YAML 1.2 --- class: LNLS.EPICS.EPICSNState.EPICSNState epics: "MNC:B:PB03:PV_ACTIVATE_BACKLIGHT": channels: rbv: suffix: ':RBV' polling_period: 200 val: suffix: ':SET' configuration: default_limits: (0, 1) values: {'LEVEL0': 1, 'LEVEL1': 0} """
[docs] def init(self): super().init() limits = self._nominal_limits EPICSActuator.set_limits(self, limits) self._initialise_values() current_value = self.get_value() self.update_value(current_value)
def _set_value(self, value): if isinstance(value, Enum): value = value.value super()._set_value(value)
[docs] def get_value(self): value = EPICSActuator.get_value(self) if not isinstance(value, Enum): value = self.value_to_enum(value) return value
def _initialise_values(self): values = self.get_property("values") self.VALUES = Enum( "ValueEnum", dict(values, **{item.name: item.value for item in BaseValueEnum}), )
[docs] def update_value(self, value=None) -> None: if value is None: return if not isinstance(value, Enum): value = self.value_to_enum(value) super().update_value(value)
def hasnt_arrived(self, setpoint): if not isinstance(setpoint, Enum): setpoint = self.value_to_enum(setpoint) readback = self.get_value() if not readback: return False return setpoint != readback
[docs]class EPICSNStateInterval(EPICSNState): """ This class is a workaround for devices that exist in a discrete number of states and do NOT have an on/off switch, but NEED to have a virtual on/off state in the GUI. Example: our frontlight device only allows for intensity setting (between 0 and 20000), but does not have an on/off switch. This class implements the following logic: if the state of the device is higher than LEVEL1, it will be shown as on in the GUI. Otherwise, it will be shown as off in the GUI. Clicking on the icon when it is off will bring it to the LEVEL0 intensity value. Clicking on the icon when it is on will bring it to the LEVEL1 intensity value. YAML Example ------------ %YAML 1.2 --- class: LNLS.EPICS.EPICSNState.EPICSNStateInterval epics: "MNC:B:LUCIOLE01:LIGHT_CH2": channels: rbv: suffix: '' polling_period: 200 val: suffix: '' configuration: default_limits: (0, 1) values: {'LEVEL0': 15000, 'LEVEL1': 0} """
[docs] def update_value(self, value=None) -> None: if value is None: return if isinstance(value, Enum): value = value.value if not isinstance(value, int): return values_list = list(self.VALUES) if not (len(values_list) > 1): return enum_value = values_list[0] if value > values_list[1].value else values_list[1] super().update_value(enum_value)
[docs]class EPICSToggle(EPICSNState): """ This class is a workaround for devices that exist in a discrete number of states but take always the same input when switching between these states. Example: a safety shutter with RBVs 0 for open and 1 for closed, but input value must always be 1 for either opening/closing. YAML Example ------------ %YAML 1.2 --- class: LNLS.EPICS.EPICSNState.EPICSToggle epics: "MNC:A:PPS01:": channels: rbv: suffix: 'PG_STATUS' polling_period: 200 val: suffix: 'OEAOPENCLOSE' configuration: default_limits: (0, 1) values: {'Open': 0, 'Closed': 1} input_value: 1 """
[docs] def init(self): super().init() self.input_value = self.get_property("input_value")
def _set_value(self, value): # noqa: ARG002 super()._set_value(self.input_value)