Source code for tbot.machine.board.board

# tbot, Embedded Automation Tool
# Copyright (C) 2019  Harald Seiler
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <>.

import abc
import contextlib
import typing
import tbot
import tbot.error
from .. import machine, shell, connector, channel

[docs]class PowerControl(machine.Initializer): """ Machine-initializer for controlling power for a hardware. When initializing, :py:meth:`~tbot.machine.board.PowerControl.poweron` is called and when deinitializing, :py:meth:`~tbot.machine.board.PowerControl.poweroff` is called. """
[docs] @abc.abstractmethod def poweron(self) -> None: """ Power-on the hardware. If the machine is using the :py:class:`~tbot.machine.connector.ConsoleConnector`, you can use ```` to run commands on the lab-host. **Example**: .. code-block:: def poweron(self):"", "on") """ pass
[docs] @abc.abstractmethod def poweroff(self) -> None: """ Power-off the hardware. """ pass
[docs] def power_check(self) -> bool: """ Check if the board is already on and someone else might be using it. Implementations of this function should raise an exception in case they detect the board to be on or return ``False``. If the board is off and ready to be used, an implementation should return ``True``. """ return True
@contextlib.contextmanager def _init_machine(self) -> typing.Iterator: if not self.power_check(): raise Exception("Board is already on, someone else might be using it!") try: tbot.log.EventIO( ["board", "on",], tbot.log.c("POWERON").bold + f" ({})", verbosity=tbot.log.Verbosity.QUIET, ) self.poweron() yield None finally: tbot.log.EventIO( ["board", "off",], tbot.log.c("POWEROFF").bold + f" ({})", verbosity=tbot.log.Verbosity.QUIET, ) self.poweroff()
[docs]class Board(shell.RawShell): """ Base class for board-machines. This class does nothing special except providing the ``.interactive()`` method for directly interacting with the serial-console. """ pass
M = typing.TypeVar("M", bound=machine.Machine) class Connector(connector.Connector): def __init__(self, board: typing.Union[Board, channel.Channel]) -> None: if not (isinstance(board, Board) or isinstance(board, channel.Channel)): raise TypeError( f"{self.__class__!r} can only be instantiated from a `Board` (got {board!r})." ) self._board = board = getattr(board, "host", None) @classmethod @contextlib.contextmanager def from_context(cls: typing.Type[M], ctx: "tbot.Context") -> typing.Iterator[M]: with contextlib.ExitStack() as cx: b = cx.enter_context(ctx.request(tbot.role.Board, exclusive=True)) m = cx.enter_context(cls(b)) # type: ignore yield m @contextlib.contextmanager def _connect(self) -> typing.Iterator[channel.Channel]: if isinstance(self._board, channel.Channel): yield self._board else: with as ch: yield ch def clone(self) -> typing.NoReturn: raise tbot.error.AbstractMethodError()