From 54db11559794d1de05769e4288ba9fefae8063d8 Mon Sep 17 00:00:00 2001 From: sldesnoo-Delft <s.l.desnoo@tudelft.nl> Date: Thu, 6 Mar 2025 16:07:53 +0100 Subject: [PATCH] Examples dataset webserver and remote command server --- core_tools/GUI/script_runner/web_server.py | 5 +- examples/demo_station/dataset_webclient.py | 16 ++++ examples/demo_station/dataset_webserver.py | 105 +++++++++++++++++++++ examples/demo_station/remote_script.py | 32 +++++++ 4 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 examples/demo_station/dataset_webclient.py create mode 100644 examples/demo_station/dataset_webserver.py create mode 100644 examples/demo_station/remote_script.py diff --git a/core_tools/GUI/script_runner/web_server.py b/core_tools/GUI/script_runner/web_server.py index bfa70d4c..9fb95570 100644 --- a/core_tools/GUI/script_runner/web_server.py +++ b/core_tools/GUI/script_runner/web_server.py @@ -108,8 +108,9 @@ class WebRequestHandler(BaseHTTPRequestHandler): ) -def run_web_server(command_list: list[Command]): - server_address = ('127.0.0.1', 8001) +def run_web_server(command_list: list[Command], server_address: tuple[str, int] | None = None): + if server_address is None: + server_address = ('0.0.0.0', 8001) httpd = HTTPServer(server_address, WebRequestHandler) httpd.commands = command_list try: diff --git a/examples/demo_station/dataset_webclient.py b/examples/demo_station/dataset_webclient.py new file mode 100644 index 00000000..e23c0c53 --- /dev/null +++ b/examples/demo_station/dataset_webclient.py @@ -0,0 +1,16 @@ +import json +import requests +from pprint import pprint + + +base = "http://127.0.0.1:8002" + + +# %% + +r = requests.get(base + "/latest", + params={ + "start_time": "2025-03-06 15:30", + }) +print(r.status_code) +pprint(json.loads(r.content)) diff --git a/examples/demo_station/dataset_webserver.py b/examples/demo_station/dataset_webserver.py new file mode 100644 index 00000000..ee2b8e45 --- /dev/null +++ b/examples/demo_station/dataset_webserver.py @@ -0,0 +1,105 @@ +import json +from functools import cached_property +from http.cookies import SimpleCookie +from http.server import HTTPServer, BaseHTTPRequestHandler, HTTPStatus +from urllib.parse import parse_qsl, urlparse + +import core_tools as ct +from core_tools.data.ds.reader import load_by_uuid +from core_tools.data.SQL.queries.dataset_gui_queries import query_for_measurement_results + +from core_tools.data.ds.ds2xarray import ds2xarray + + +""" +TIP: + Switch project name to 'Game', so all data is for Game +""" + + +class DatasetRequestHandler(BaseHTTPRequestHandler): + + @cached_property + def url(self): + return urlparse(self.path) + + @cached_property + def query_data(self): + return dict(parse_qsl(self.url.query)) + + @cached_property + def post_data(self): + content_length = int(self.headers.get("Content-Length", 0)) + return self.rfile.read(content_length) + + @cached_property + def form_data(self): + return dict(parse_qsl(self.post_data.decode("utf-8"))) + + @cached_property + def cookies(self): + return SimpleCookie(self.headers.get("Cookie")) + + def log_request(self, code='-', size='-'): + pass + + def do_GET(self): + if self.url.path != "/latest": + self.send_error(HTTPStatus.NOT_FOUND) + else: + start_time = self.query_data.get("start_time") + ds = self.get_last_ds(start_time) + if ds is None: + self.send_error(HTTPStatus.NO_CONTENT) + else: + response = self.get_ds_json(ds).encode("utf-8") + self.send_response(HTTPStatus.OK) + self.send_header("Content-Type", "application/json") + self.end_headers() + self.wfile.write(response) + + def get_last_ds(self, start_time: str | None): + res = query_for_measurement_results.search_query( + start_time=start_time, # optional + name=None, # part of name optional + project=self.server.project_name, # optional + keywords=None, # optional + ) + if len(res) == 0: + return None + uuid = res[-1].uuid + ds = load_by_uuid(uuid) + return ds + + def get_ds_json(self, ds, variables: list[str] | None = None): + xds = ds2xarray(ds, snapshot=False) + for m_param in ds: + for name, descr in m_param: + var_name = descr.param_name + xds[var_name].attrs["written"] = descr.written() + + if variables is not None: + xds = xds[variables] + + d = xds.to_dict() + return json.dumps(d, indent=1) + + +def run_web_server(project_name: str | None, server_address: tuple[str, int] | None = None): + if server_address is None: + server_address = ('0.0.0.0', 8002) + httpd = HTTPServer(server_address, DatasetRequestHandler) + httpd.project_name = project_name + try: + print(f"Server running at http://{server_address[0]}:{server_address[1]}") + print("Interrupt kernel to stop server") + httpd.serve_forever() + except KeyboardInterrupt: + httpd.shutdown() + + + # %% + +ct.configure('./setup_config/ct_config_laptop.yaml') + +run_web_server(None) diff --git a/examples/demo_station/remote_script.py b/examples/demo_station/remote_script.py new file mode 100644 index 00000000..3397caa9 --- /dev/null +++ b/examples/demo_station/remote_script.py @@ -0,0 +1,32 @@ +import json +import requests +from pprint import pprint + + +base = "http://127.0.0.1:8001" + +# %% +r = requests.get(base + "/functions") +print(r.status_code) +pprint(json.loads(r.content)) + + +# %% + +r = requests.post(base + "/run", + data={ + "__name__": "sayHi", + "name": "Oriol", + "times": 2, + }) +print(r.status_code) +pprint(json.loads(r.content)) + +r = requests.post(base + "/run", + data={ + "__name__": "Fit it", + "x": 13.0, + "mode": "RIGHT", + }) +print(r.status_code) +pprint(json.loads(r.content)) -- GitLab