single_ursim_control/single_ursim_control/main.py

111 lines
3.3 KiB
Python

#!/usr/bin/env python3
import sys
from config import Config
from plugins import SleepPlugin, SyncPlugin, WaitPlugin, URRTDEPlugin
from plugin_repository import PluginRepository
from program_executor import ProgramExecutor, ProgramExecutorStates
from http_server import ControllerHTTPServer
import logging
import signal
from compiler import compile_program
from program_loader import load_program
class HTTPControl:
def GET_status(self, path, data):
return 200, "Very good!"
def POST_terminate(self, path, data):
return 200, "Will do sir!"
def POST_continue(self, path, data):
return 201, "Will do sir!"
def main() -> int:
# init instance
logging.basicConfig(
stream=sys.stdout,
format="%(asctime)s [%(levelname)s]: %(name)s: %(message)s",
level=logging.DEBUG if Config.DEBUG else logging.INFO
)
logging.info("Registering available plugins...")
# Register all available plugins
plugin_repo = PluginRepository()
plugin_repo.register_plugin(SleepPlugin)
plugin_repo.register_plugin(SyncPlugin)
plugin_repo.register_plugin(WaitPlugin)
plugin_repo.register_plugin(URRTDEPlugin)
# Download the program
logging.info("Downloading program...")
try:
program_source = load_program(Config.PROGRAM_URL)
except Exception as e:
logging.error(f"Failed to download program: {e}! Exiting...")
logging.exception(e)
return 1
# Load required plugins
logging.info("Loading required plugins...")
try:
plugin_repo.load_plugins(program_source['load_plugins'])
except Exception as e:
logging.error(f"Error during plugin loading: {e}! Exiting...")
logging.exception(e)
return 2
# Compile the program
logging.info("Compiling program...")
try:
program = compile_program(plugin_repo, program_source['program'])
except Exception as e:
logging.error(f"Error during compilation: {e}! Exiting...")
logging.exception(e)
return 3
# prepare the executor
logging.info("Preparing for execution...")
executor = ProgramExecutor(program, loop=False)
# Setup signal handler
def handle_stop_signal(signum, frame):
logging.warning(f"Signal {signum} received. Aborting execution!")
executor.abort()
# Should be possible to call only once
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
signal.signal(signal.SIGINT, handle_stop_signal)
signal.signal(signal.SIGTERM, handle_stop_signal)
# Actually execute
execution_success = True
if Config.DRY_RUN:
logging.info("DRY_RUN enabled. Dumping command descriptions and exiting!")
for i, command in enumerate(program):
logging.info(f"{i:04d}: {command.describe()}")
else:
logging.info("Starting execution...")
executor.start()
executor.join()
if executor.state == ProgramExecutorStates.DONE:
logging.info("Program executed successfully!")
else:
logging.error(f"Could not finish execution! Executor state: {executor.state.name}")
execution_success = False
# Close all resources
logging.info("Cleaning up...")
plugin_repo.close()
return 0 if execution_success else 5
if __name__ == '__main__':
sys.exit(main())