Esempio n. 1
0
class ExporterMotor(AbstractMotor):
    """Motor using the Exporter protocol, based on AbstractMotor"""
    def __init__(self, name):
        AbstractMotor.__init__(self, name)
        self.username = None
        self._motor_pos_suffix = None
        self._motor_state_suffix = None
        self._exporter = None
        self._exporter_address = None
        self.motor_position = None
        self.motor_state = None

    def init(self):
        """Initialise the motor"""
        AbstractMotor.init(self)

        self._motor_pos_suffix = self.getProperty("position_suffix",
                                                  "Position")
        self._motor_state_suffix = self.getProperty("state_suffix", "State")

        self._exporter_address = self.getProperty("exporter_address")
        _host, _port = self._exporter_address.split(":")
        self._exporter = Exporter(_host, int(_port))

        self.motor_position = self.add_channel(
            {
                "type": "exporter",
                "exporter_address": self._exporter_address,
                "name": "position",
            },
            self.actuator_name + self._motor_pos_suffix,
        )
        if self.motor_position:
            self.get_value()
            self.motor_position.connectSignal("update", self.update_value)

        self.motor_state = self.add_channel(
            {
                "type": "exporter",
                "exporter_address": self._exporter_address,
                "name": "motor_state",
            },
            self.actuator_name + self._motor_state_suffix,
        )

        if self.motor_state:
            self.motor_state.connectSignal("update", self._update_state)

        self.update_state()

    def get_state(self):
        """Get the motor state.
        Returns:
            (enum 'HardwareObjectState'): Motor state.
        """
        try:
            _state = self.motor_state.get_value().upper()
            self.specific_state = _state
            return ExporterStates.__members__[_state].value
        except (KeyError, AttributeError):
            return self.STATES.UNKNOWN

    def _update_state(self, state):
        try:
            state = state.upper()
            state = ExporterStates.__members__[state].value
        except (AttributeError, KeyError):
            state = self.STATES.UNKNOWN
        return self.update_state(state)

    def _get_hwstate(self):
        """Get the hardware state, reported by the MD2 application.
        Returns:
            (string): The state.
        """
        try:
            return self._exporter.read_property("HardwareState")
        except Exception:
            return "Ready"

    def _get_swstate(self):
        """Get the software state, reported by the MD2 application.
        Returns:
            (string): The state.
        """
        return self._exporter.read_property("State")

    def _ready(self):
        """Get the "Ready" state - software and hardware.
        Returns:
            (bool): True if both "Ready", False otherwise.
        """
        if (self._get_swstate() == "Ready" and self._get_hwstate() == "Ready"
                and self.motor_state.get_value() == "Ready"):
            return True
        return False

    def _wait_ready(self, timeout=3):
        """Wait for the state to be "Ready".
        Args:
            timeout (float): waiting time [s].
        Raises:
            RuntimeError: Execution timeout.
        """
        with Timeout(timeout, RuntimeError("Execution timeout")):
            while not self._ready():
                sleep(0.01)

    def wait_move(self, timeout=20):
        """Wait until the end of move ended, using the application state.
        Args:
            timeout(float): Timeout [s]. Default value is 20 s
        """
        self._wait_ready(timeout)

    def wait_motor_move(self, timeout=20):
        """Wait until the end of move ended using the motor state.
        Args:
            timeout(float): Timeout [s]. Default value is 20 s
        Raises:
            RuntimeError: Execution timeout.
        """
        with Timeout(timeout, RuntimeError("Execution timeout")):
            while self.get_state() != self.STATES.READY:
                sleep(0.01)

    def get_value(self):
        """Get the motor position.
        Returns:
            (float): Motor position.
        """
        _v = self.motor_position.get_value()

        if math.isnan(_v) or None:
            logging.getLogger("HWR").debug("Value of %s is NaN" %
                                           self.actuator_name)
            _v = self._nominal_value

        self._nominal_value = _v

        return self._nominal_value

    def __get_limits(self, cmd):
        """Returns motor low and high limits.
        Args:
            cmd (str): command name
        Returns:
            (tuple): two floats tuple (low limit, high limit).
        """
        try:
            _low, _high = self._exporter.execute(cmd, (self.actuator_name, ))
            # inf is a problematic value, convert to sys.float_info.max
            if _low == float("-inf"):
                _low = -sys.float_info.max

            if _high == float("inf"):
                _high = sys.float_info.max

            return _low, _high
        except ValueError:
            return -1e4, 1e4

    def get_limits(self):
        """Returns motor low and high limits.
        Args:
            cmd (str): command name
        Returns:
            (tuple): two floats tuple (low limit, high limit).
        """
        self._nominal_limits = self.__get_limits("getMotorLimits")
        return self._nominal_limits

    def get_dynamic_limits(self):
        """Returns motor low and high dynamic limits.
        Returns:
            (tuple): two floats tuple (low limit, high limit).
        """
        return self.__get_limits("getMotorDynamicLimits")

    def _set_value(self, value):
        """Move motor to absolute value.
        Args:
            value (float): target value
        """
        self.update_state(self.STATES.BUSY)
        self.motor_position.set_value(value)

    def abort(self):
        """Stop the motor movement immediately."""
        if self.get_state() != self.STATES.UNKNOWN:
            self._exporter.execute("abort")

    def home(self, timeout=None):
        """Homing procedure.
        Args:
            timeout (float): optional - timeout [s].
        """
        self._exporter.execute("startHomingMotor", (self.actuator_name, ))
        self.wait_ready(timeout)

    def get_max_speed(self):
        """Get the motor maximum speed.
        Returns:
            (float): the maximim speed [unit/s].
        """
        return self._exporter.execute("getMotorMaxSpeed",
                                      (self.actuator_name, ))

    def name(self):
        """Get the motor name. Should be removed when GUI ready"""
        return self.actuator_name
class ExporterNState(AbstractNState):
    """Microdiff with Exporter implementation of AbstartNState"""

    SPECIFIC_STATES = ExporterStates

    def __init__(self, name):
        AbstractNState.__init__(self, name)
        self._exporter = None
        self.value_channel = None
        self.state_channel = None

    def init(self):
        """Initialise the device"""
        AbstractNState.init(self)
        value_channel = self.get_property("value_channel_name")
        state_channel = self.get_property("state_channel_name", "State")

        _exporter_address = self.get_property("exporter_address")
        _host, _port = _exporter_address.split(":")
        self._exporter = Exporter(_host, int(_port))

        self.value_channel = self.add_channel(
            {
                "type": "exporter",
                "exporter_address": _exporter_address,
                "name": value_channel.lower(),
            },
            value_channel,
        )
        self.value_channel.connect_signal("update", self.update_value)

        self.state_channel = self.add_channel(
            {
                "type": "exporter",
                "exporter_address": _exporter_address,
                "name": "state",
            },
            state_channel,
        )

        self.state_channel.connect_signal("update", self._update_state)
        self.update_state()

    def _update_state(self, state=None):
        """To be used to update the state when emiting the "update" signal.
        Args:
            state (str): optional state value
        Returns:
            (enum 'HardwareObjectState'): state.
        """
        if not state:
            state = self.get_state()
        else:
            state = self._value2state(state)
        return self.update_state(state)

    def _value2state(self, state):
        """Convert string state to HardwareObjectState enum value
        Args:
            state (str): the state
        Returns:
            (enum 'HardwareObjectState'): state
        """
        try:
            return self.SPECIFIC_STATES.__members__[state.upper()].value
        except (AttributeError, KeyError):
            return self.STATES.UNKNOWN

    def get_state(self):
        """Get the device state.
        Returns:
            (enum 'HardwareObjectState'): Device state.
        """
        state = self.state_channel.get_value()
        return self._value2state(state)

    def abort(self):
        """Stop the action."""
        if self.get_state() != self.STATES.UNKNOWN:
            self._exporter.execute("abort")

    def _set_value(self, value):
        """Set device to value
        Args:
            value (str, int, float or enum): Value to be set.
        """
        # NB Workaround beacuse diffractomer does not send event on
        # change of light position
        self.update_state(self.STATES.BUSY)

        if isinstance(value, Enum):
            if isinstance(value.value, tuple) or isinstance(value.value, list):
                value = value.value[0]
            else:
                value = value.value

        self.value_channel.set_value(value)
        self.update_state(self.STATES.READY)

    def get_value(self):
        """Get the device value
        Returns:
            (Enum): Enum member, corresponding to the value or UNKNOWN.
        """
        _val = self.value_channel.get_value()
        return self.value_to_enum(_val)
Esempio n. 3
0
class ExporterNState(AbstractNState):
    """Microdiff with Exporter implementation of AbstartNState"""

    SPECIFIC_STATES = ExporterStates

    def __init__(self, name):
        AbstractNState.__init__(self, name)
        self._exporter = None
        self.value_channel = None
        self.state_channel = None
        self.use_value_as_state = None

    def init(self):
        """Initialise the device"""
        AbstractNState.init(self)
        value_channel = self.get_property("value_channel_name")
        # use the value to check if action finished.
        self.use_value_as_state = self.get_property("value_state")
        state_channel = self.get_property("state_channel_name", "State")

        _exporter_address = self.get_property("exporter_address")
        _host, _port = _exporter_address.split(":")
        self._exporter = Exporter(_host, int(_port))

        self.value_channel = self.add_channel(
            {
                "type": "exporter",
                "exporter_address": _exporter_address,
                "name": value_channel.lower(),
            },
            value_channel,
        )
        self.value_channel.connect_signal("update", self.update_value)

        self.state_channel = self.add_channel(
            {
                "type": "exporter",
                "exporter_address": _exporter_address,
                "name": "state",
            },
            state_channel,
        )

        self.state_channel.connect_signal("update", self._update_state)
        self.update_state()

    def _wait_hardware(self, value, timeout=None):
        """Wait timeout seconds till hardware in place.
        Args:
            value (str, int): value to be tested.
            timeout(float): Timeout [s]. None means infinite timeout.
        """
        with Timeout(timeout, RuntimeError("Timeout waiting for hardware")):
            while self.value_channel.get_value() != value:
                sleep(0.5)

    def _wait_ready(self, timeout=None):
        """Wait timeout seconds till status is ready.
        Args:
            timeout(float): Timeout [s]. None means infinite timeout.
        """
        with Timeout(timeout, RuntimeError("Timeout waiting for status ready")):
            while not self.get_state() == self.STATES.READY:
                sleep(0.5)

    def _update_state(self, state=None):
        """To be used to update the state when emiting the "update" signal.
        Args:
            state (str): optional state value
        Returns:
            (enum 'HardwareObjectState'): state.
        """
        if not state:
            state = self.get_state()
        else:
            state = self._value2state(state)
        return self.update_state(state)

    def _value2state(self, state):
        """Convert string state to HardwareObjectState enum value
        Args:
            state (str): the state
        Returns:
            (enum 'HardwareObjectState'): state
        """
        try:
            return self.SPECIFIC_STATES.__members__[state.upper()].value
        except (AttributeError, KeyError):
            return self.STATES.UNKNOWN

    def get_state(self):
        """Get the device state.
        Returns:
            (enum 'HardwareObjectState'): Device state.
        """
        state = self.state_channel.get_value()
        return self._value2state(state)

    def abort(self):
        """Stop the action."""
        if self.get_state() != self.STATES.UNKNOWN:
            self._exporter.execute("abort")

    def _set_value(self, value):
        """Set device to value
        Args:
            value (str, int, float or enum): Value to be set.
        """
        # NB Workaround beacuse diffractomer does not send event on
        # change of actuators (light, scintillator, cryostream...)
        self.update_state(self.STATES.BUSY)

        if isinstance(value, Enum):
            if isinstance(value.value, (tuple, list)):
                value = value.value[0]
            else:
                value = value.value
        self.value_channel.set_value(value)
        # wait until the hardware returns value set
        if self.use_value_as_state:
            self._wait_hardware(value, 120)
        self._wait_ready(120)
        self.update_state(self.STATES.READY)

    def get_value(self):
        """Get the device value
        Returns:
            (Enum): Enum member, corresponding to the value or UNKNOWN.
        """
        _val = self.value_channel.get_value()
        return self.value_to_enum(_val)