Esempio n. 1
0
    async def test_ignore_feature(self):
        async with self.make_script():

            ignore = ["mtdome", "mtdometrajectory"]

            await self.configure_script(ignore=ignore)

            await self.run_script()

            for comp in self.script.group.components_attr:

                if getattr(self.script.group.check, comp):

                    current_state = salobj.State(
                        getattr(self.mtcs_mock.controllers,
                                comp).evt_summaryState.data.summaryState)

                    with self.subTest(f"{comp} summary state", comp=comp):
                        assert current_state == salobj.State.ENABLED

            for comp in ignore:
                current_state = salobj.State(
                    getattr(self.mtcs_mock.controllers,
                            comp).evt_summaryState.data.summaryState)

                with self.subTest(f"{comp} summary state", comp=comp):
                    assert current_state == salobj.State.STANDBY
Esempio n. 2
0
    async def test_no_queue(self):
        """Test the simple target production loop.

        This test makes sure the scheduler will go to a fault state if it is
        enabled and the queue is not enabled.
        """
        data = await self.scheduler_remote.evt_errorCode.next(
            flush=False, timeout=STD_TIMEOUT)
        assert data.errorCode == 0

        # Test 1 - Enable scheduler, Queue is not enable. Scheduler should go
        # to ENABLE and then to FAULT It may take some time for the scheduler
        # to go to FAULT state.

        # Make sure Queue is in STANDBY
        await salobj.set_summary_state(self.queue_remote, salobj.State.STANDBY)

        # Enable Scheduler
        await salobj.set_summary_state(
            self.scheduler_remote,
            salobj.State.ENABLED,
            override="simple_target_loop_sequential.yaml",
        )

        # Resume scheduler operation
        await self.scheduler_remote.cmd_resume.start(timeout=STD_TIMEOUT)

        # Wait until summary state is FAULT or Timeout
        state = None
        while True:
            try:
                evt_state = await self.scheduler_remote.evt_summaryState.next(
                    flush=False, timeout=STD_TIMEOUT)
                state = salobj.State(evt_state.summaryState)
                if state == salobj.State.FAULT:
                    break
            except asyncio.TimeoutError:
                break

        self.assertEqual(state, salobj.State.FAULT,
                         f"Scheduler in {state}, expected FAULT. ")
        self.assertEqual(
            self.scheduler.summary_state,
            salobj.State.FAULT,
            f"Scheduler in {state}, expected FAULT. ",
        )
        # Check error code
        data = await self.scheduler_remote.evt_errorCode.next(
            flush=False, timeout=STD_TIMEOUT)
        assert data.errorCode == NO_QUEUE

        # recover from fault state sending it to STANDBY
        await self.scheduler_remote.cmd_standby.start(timeout=STD_TIMEOUT)

        self.assertEqual(
            self.scheduler.summary_state,
            salobj.State.STANDBY,
            "Scheduler in %s, expected STANDBY. " %
            salobj.State(self.scheduler.summary_state),
        )
Esempio n. 3
0
    async def get_state(self,
                        component: str,
                        ignore_timeout: bool = False) -> salobj.State:
        """Get summary state for component.

        Parameters
        ----------
        component : `str`
            Name of the component.
        ignore_timeout : `bool`
            If `True` will return None in case it times out getting the state.
            Default is `False`, which means raise `TimeoutError`.

        Returns
        -------
        state : `salobj.State` or `None`
            Current state of component.

        Raises
        ------
        `asyncio.TimeoutError`
            If can not get state in `self.fast_timeout` seconds.

        """
        try:
            ss = await getattr(
                self.rem,
                component).evt_summaryState.aget(timeout=self.fast_timeout)
            return salobj.State(ss.summaryState)
        except asyncio.TimeoutError as e:
            if ignore_timeout:
                return None
            else:
                raise e
Esempio n. 4
0
    def assert_summary_state(self, state, isbefore=None):
        """Assert that the current summary state is as specified.

        First check that CSC can command the low-level controller.

        Used in do_xxx methods to check that a command is allowed.

        Parameters
        ----------
        state : `lsst.ts.salobj.State`
            Expected summary state.
        isbefore : `bool`, optional
            Deprecated. The only allowed values are False
            (which raises a deprecation warning) and None.
        """
        if isbefore:
            raise ValueError(
                f"isbefore={isbefore}; this deprecated argument must be None or False"
            )
        elif isbefore is False:
            warnings.warn(f"isbefore={isbefore} is deprecated",
                          DeprecationWarning)
        state = salobj.State(state)
        self.assert_connected()
        if self.summary_state != state:
            raise salobj.ExpectedError(
                f"Rejected: initial state is {self.summary_state!r} instead of {state!r}"
            )
Esempio n. 5
0
 def assert_enable(data):
     """Callback function to make sure scheduler is enabled"""
     self.assertEqual(
         data.summaryState,
         salobj.State.ENABLED,
         "Scheduler unexpectedly transitioned from "
         "ENABLE to %s" % salobj.State(data.summaryState),
     )
Esempio n. 6
0
    async def check_component_state(
            self,
            component: str,
            desired_state: salobj.State = salobj.State.ENABLED) -> None:
        """Monitor the summary state of a component and raises an exception if
        it is or goes to a state different than the desired state.

        This method will run forever as long as the summary state remains
        unchanged. The intention is that this can run alongside an operation
        that require the component to be in a certain state, when the
        operation is completed, the task can be canceled.

        Parameters
        ----------
        component : `str`
            Name of the component to follow. Must be one of:
            atmcs, atptg, ataos, atpneumatics, athexapod, atdome,
            atdometrajectory
        desired_state : `salobj.State`
            Desired state of the CSC.

        Raises
        ------
        RuntimeError
            If state is not `desired_state`.
        KeyError
            If component is not found.
        """
        desired_state = salobj.State(desired_state)
        state_topic = getattr(self.rem, component).evt_summaryState
        state_topic.flush()
        data = await state_topic.aget()
        while True:
            state = salobj.State(data.summaryState)
            if state != desired_state:
                self.log.warning(
                    f"{component} not in {desired_state!r}: {state!r}")
                raise RuntimeError(
                    f"{component} state is {state!r}, expected {desired_state!r}"
                )
            else:
                self.log.debug(f"{component}: {state!r}")
            data = await state_topic.next(flush=False)
Esempio n. 7
0
 def __call__(self, topic_callback):
     state = topic_callback.get().summaryState
     if state == salobj.State.ENABLED:
         return base.NoneNoReason
     elif state == salobj.State.FAULT:
         return AlarmSeverity.SERIOUS, "FAULT state"
     else:
         try:
             state_name = salobj.State(state).name
         except Exception:
             state_name = str(state)
         return AlarmSeverity.WARNING, f"{state_name} state"
Esempio n. 8
0
    async def next_state(self, component: str) -> salobj.State:
        """Get summary state for component.

        Parameters
        ----------
        component : `str`
            Name of the component.

        Returns
        -------
        state : `salobj.State`
            Current state of component.
        """
        ss = await getattr(self.rem, component).evt_summaryState.next(
            flush=False, timeout=self.fast_timeout)
        return salobj.State(ss.summaryState)
Esempio n. 9
0
    async def test_run(self):
        async with self.make_script():
            await self.configure_script()

            await self.run_script()

            for comp in self.script.group.components_attr:

                if getattr(self.script.group.check, comp):

                    current_state = salobj.State(
                        getattr(self.mtcs_mock.controllers,
                                comp).evt_summaryState.data.summaryState)

                    with self.subTest(f"{comp} summary state", comp=comp):
                        assert current_state == salobj.State.STANDBY
Esempio n. 10
0
    async def wait_summary_state(self,
                                 state,
                                 max_telem=MAX_STATE_CHANGE_TELEMETRY_MESSAGES
                                 ):
        """Wait for the summary state to be as specified.

        Parameters
        ----------
        state : `lsst.ts.salobj.State`
            Allowed summary states.
        max_telem : `int`
            Maximum number of low-level telemetry messages to wait for.
        """
        state = salobj.State(state)
        for i in range(max_telem):
            self.assert_connected()
            await self.client.next_telemetry()
            if self.summary_state == state:
                return
        raise salobj.ExpectedError(
            f"Failed: final state is {self.summary_state!r} instead of {state!r}"
        )
Esempio n. 11
0
    async def set_state(
        self,
        state: salobj.State,
        overrides: typing.Optional[typing.Dict[str, str]] = None,
        components: typing.Optional[typing.List[str]] = None,
    ) -> None:
        """Set summary state for all components.

        Parameters
        ----------
        state : `salobj.State`
            Desired state.

        overrides : `dict` or None
            Settings to apply for each component.

        components : `list[`str`]`
            List of components to set state, as they appear in
            `self.components_attr`.

        Raises
        ------
        RuntimeError

            * If a component in `components` is not part of the group.

            * If it fails to transition one or more components.

        """
        work_components = self.get_work_components(components)

        if overrides is None:
            overrides = dict()

        set_ss_tasks = []

        for comp in work_components:
            if getattr(self.check, comp):
                set_ss_tasks.append(
                    salobj.set_summary_state(
                        remote=getattr(self.rem, comp),
                        state=salobj.State(state),
                        override=overrides.get(comp, ""),
                        timeout=self.long_long_timeout,
                    ))
            else:
                set_ss_tasks.append(self.get_state(comp, ignore_timeout=True))

        ret_val = (await asyncio.gather(*set_ss_tasks, return_exceptions=True)
                   if self._concurrent_operation else
                   [(await asyncio.gather(task, return_exceptions=True))[0]
                    for task in set_ss_tasks])

        error_flag = False
        failed_components = []

        for i, comp in enumerate(work_components):
            if isinstance(ret_val[i], Exception):
                error_flag = True
                failed_components.append(comp)
                err_message = (
                    f"Unable to transition {comp} to "
                    f"{salobj.State(state)!r} {traceback.format_exc()}.\n")
                etype: typing.Type[BaseException] = type(ret_val[i])
                value: BaseException = ret_val[i]
                tb: types.TracebackType = ret_val[i].__traceback__
                err_traceback = traceback.format_exception(
                    etype,
                    value,
                    tb,
                )
                for trace in err_traceback:
                    err_message += trace
                self.log.error(err_message)
            else:
                self.log.debug(f"[{comp}]::{ret_val[i]!r}")

        if error_flag:
            raise RuntimeError(f"Failed to transition {failed_components} to "
                               f"{salobj.State(state)!r}.")
        else:
            self.log.info(f"All components in {salobj.State(state)!r}.")
    def get_summary_state(self) -> typing.Optional[salobj.State]:
        """Get Scheduler summary state."""
        current_summary_state = self.scheduler_remote.evt_summaryState.get()

        return (None if current_summary_state is None else salobj.State(
            current_summary_state.summaryState))