diff --git a/single_ursim_control/http_server.py b/single_ursim_control/http_server.py new file mode 100644 index 0000000..43a1ee5 --- /dev/null +++ b/single_ursim_control/http_server.py @@ -0,0 +1,71 @@ +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +import json +import logging +from threading import Thread + +# +# This section might be a little fragile, but thankfully crashing this won't take the whole process down +# Since it's running in it's own thread +# Although the process might become unresponsive +# + +class ControlRequestHandler(BaseHTTPRequestHandler): + + def log_message(self, format, *args): + self.server._logger.debug(format % args) + + def _handle_request(self, method: str, data: bytes = None): + _, name, *path = str(self.path).split("/") + method_name = f"{method}_{name}" + + if hasattr(self.server._methods_instance, method_name): + status, result = getattr(self.server._methods_instance, method_name)(path, data) + + self.send_response(status) + + try: + stringified_result = json.dumps(result) + content_type = 'application/json' + except TypeError: + stringified_result = str(result) + content_type = 'text/plain; charset=UTF-8' + + self.send_header('Content-type', content_type) + self.end_headers() + self.wfile.write(stringified_result.encode('utf-8')) + + else: + self.send_response(404) + self.send_header('Content-type', 'text/plain') + self.end_headers() + self.wfile.write(b"NOT FOUND") + + def do_GET(self): + self._handle_request('GET', None) + + def do_POST(self): + if self.headers['Content-Length']: + content_length = int(self.headers['Content-Length']) + post_data = self.rfile.read(content_length) + else: + post_data = None + + self._handle_request('POST', post_data) + + +class ControllerHTTPServer(Thread): + + def __init__(self, methods_instance, port: int = 8000): + super().__init__() + self._logger = logging.getLogger("http") + self._http_server = ThreadingHTTPServer(('', port), ControlRequestHandler) + self._http_server._methods_instance = methods_instance + self._http_server._logger = self._logger + + def run(self): + self._logger.info("Starting HTTP Server...") + self._http_server.serve_forever() + self._logger.info("Stopped HTTP Server...") + + def shutdown(self): + self._http_server.shutdown() diff --git a/single_ursim_control/main.py b/single_ursim_control/main.py index e6ab3a4..5860ab8 100644 --- a/single_ursim_control/main.py +++ b/single_ursim_control/main.py @@ -1,12 +1,26 @@ +#!/usr/bin/env python3 import os import sys from config import Config from plugins import WaitPlugin from plugin_repository import PluginRepository from program_executor import ProgramExecutor +from http_server import ControllerHTTPServer import logging +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(): # init logging.basicConfig( @@ -14,6 +28,8 @@ def main(): format="%(asctime)s [%(levelname)s]: %(name)s: %(message)s", level=logging.DEBUG ) + http_server = ControllerHTTPServer(HTTPControl()) + http_server.start() compiler_repo = PluginRepository() compiler_repo.register_plugin(WaitPlugin) @@ -21,6 +37,9 @@ def main(): compiler_repo.load_plugin("wait") program = [] program.append(compiler_repo.get_compiler("wait").compile(secs=2)) + program.append(compiler_repo.get_compiler("wait").compile(secs=3)) + program.append(compiler_repo.get_compiler("wait").compile(secs=10)) + program.append(compiler_repo.get_compiler("wait").compile(secs=10)) # execute: executor = ProgramExecutor(program) @@ -29,6 +48,7 @@ def main(): # End of execution executor.join() compiler_repo.close() + http_server.shutdown() if __name__ == '__main__':