Source code for pyobs.mixins.waitformotion

from __future__ import annotations

import logging
import time
from asyncio import Event
from typing import Any

from pyobs.interfaces import IMotion
from pyobs.modules import Module
from pyobs.utils.enums import MotionStatus
from pyobs.utils.parallel import event_wait

log = logging.getLogger(__name__)


class WaitForMotionMixin:
    """Mixin for a device that should wait for the motion status of another device."""

    __module__ = "pyobs.mixins"

    def __init__(
        self,
        wait_for_modules: list[str] | None = None,
        wait_for_states: list[MotionStatus | str] | None = None,
        wait_for_timeout: float = 0,
        **kwargs: Any,
    ):
        """Initializes the mixin.

        Args:
            wait_for_modules: One or more modules to wait for.
            wait_for_states: List of states to wait for.
            wait_for_timeout: Wait timeout in seconds.
        """

        # store
        self.__wait_for_modules = wait_for_modules if wait_for_modules is not None else []
        self.__wait_for_states = (
            [s if isinstance(s, MotionStatus) else MotionStatus(s) for s in wait_for_states]
            if wait_for_states is not None
            else []
        )
        self.__wait_for_timeout = wait_for_timeout

[docs] async def _wait_for_motion(self, abort: Event) -> None: """Wait until all devices are in one of the given motion states. Args: abort: Abort event. Raises: TimeoutError: If wait timed out. """ # no device? if len(self.__wait_for_modules) == 0: return # check type this = self if not isinstance(self, Module): raise ValueError("This is not a module.") # all need to be derived from IMotion if not all([self.has_proxy(device, IMotion) for device in this.__wait_for_modules]): raise ValueError("Not all given devices are derived from IMotion!") # run until timeout start = time.time() log.info("Waiting for motion of other modules...") while not abort.is_set(): # timeout? if time.time() > start + this.__wait_for_timeout: raise TimeoutError # loop all modules all_done = True for module in this.__wait_for_modules: async with self.proxy(module, IMotion) as proxy: motion_state = await proxy.wait_for_state(IMotion, timeout=1.0) status = motion_state.status if motion_state is not None else MotionStatus.UNKNOWN if status not in this.__wait_for_states: all_done = False break if all_done: # if all good, we're finished waiting log.info("All other modules have finished moving.") break # sleep a little await event_wait(abort, 1)
__all__ = ["WaitForMotionMixin"]