diff --git a/single_ursim_control/main.py b/single_ursim_control/main.py index 928e093..1d3de50 100644 --- a/single_ursim_control/main.py +++ b/single_ursim_control/main.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import sys from config import Config -from plugins import SleepPlugin, SyncPlugin, WaitPlugin, URRTDEPlugin +from plugins import SleepPlugin, SyncPlugin, WaitPlugin, URRTDEPlugin, LogPlugin from plugin_repository import PluginRepository from program_executor import ProgramExecutor, ProgramExecutorStates from http_server import ControllerHTTPServer @@ -39,6 +39,7 @@ def main() -> int: plugin_repo.register_plugin(SyncPlugin) plugin_repo.register_plugin(WaitPlugin) plugin_repo.register_plugin(URRTDEPlugin) + plugin_repo.register_plugin(LogPlugin) # Download the program logging.info("Downloading program...") diff --git a/single_ursim_control/plugins/__init__.py b/single_ursim_control/plugins/__init__.py index aa84740..6510626 100644 --- a/single_ursim_control/plugins/__init__.py +++ b/single_ursim_control/plugins/__init__.py @@ -2,4 +2,5 @@ from .abstract_plugin import AbstractCommand, AbstractCommandCompiler, AbstractP from .sleep_plugin import SleepPlugin from .sync_plugin import SyncPlugin from .wait_plugin import WaitPlugin -from .ur_rtde_plugin import URRTDEPlugin \ No newline at end of file +from .ur_rtde_plugin import URRTDEPlugin +from .log_plugin import LogPlugin diff --git a/single_ursim_control/plugins/log_plugin.py b/single_ursim_control/plugins/log_plugin.py new file mode 100644 index 0000000..4b77537 --- /dev/null +++ b/single_ursim_control/plugins/log_plugin.py @@ -0,0 +1,65 @@ +from typing import Dict + +from .abstract_plugin import AbstractCommand, AbstractPlugin, AbstractCommandCompiler +import logging + + +class LogCommand(AbstractCommand): + LEVELS = { # _nameToLevel would be nicer, but we are limiting options here + "DEBUG": logging.DEBUG, + "INFO": logging.INFO, + "WARNING": logging.WARNING + # Programs are not allowed to print error level + } + + def __init__(self, program_logger: logging.Logger, level: str, message: str): + + self._program_logger = program_logger + + try: + self._level = self.LEVELS[level] + except KeyError: + raise ValueError(f"Unknown or not allowed log level: {level}") + + self._message = message + + def execute(self): + self._program_logger.log(self._level, self._message) + + def abort(self): + # There is really nothing to abort here + pass + + def describe(self) -> dict: + return { + "command": "log", + "params": { + "level": logging.getLevelName(self._level), + "message": self._message + } + } + + +class LogCompiler(AbstractCommandCompiler): + + def __init__(self, program_logger: logging.Logger): + self._program_logger = program_logger + + def compile(self, level: str, message: str) -> AbstractCommand: + return LogCommand(self._program_logger, level, message) + + +class LogPlugin(AbstractPlugin): + plugin_name = "log" + + def __init__(self): + self._logger = logging.getLogger("plugin").getChild("log") + self._program_logger = self._logger.getChild("program") + + def load_compilers(self) -> Dict[str, AbstractCommandCompiler]: + return { + "log": LogCompiler(self._program_logger) + } + + def close(self): + pass