77 lines
2.9 KiB
Python
Executable File
77 lines
2.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""fleet_test_server — stand-in for the YS Lootah fleet server, for deploy tests.
|
|
|
|
Runs on the workstation ("assume my workstation is a server"). Accepts the two
|
|
ingest endpoints the agents POST to, logs each request (JSON line -> REQLOG) and
|
|
prints a live summary. GET /ping returns 200 for reachability checks.
|
|
|
|
PORT=8799 REQLOG=/tmp/fleet_reqs.jsonl python3 fleet_test_server.py
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
|
|
PORT = int(os.environ.get("PORT", "8799"))
|
|
REQLOG = os.environ.get("REQLOG", "/tmp/fleet_reqs.jsonl")
|
|
open(REQLOG, "w").close()
|
|
|
|
|
|
class H(BaseHTTPRequestHandler):
|
|
def _emit(self, rec):
|
|
with open(REQLOG, "a") as f:
|
|
f.write(json.dumps(rec) + "\n")
|
|
|
|
def do_GET(self):
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
self.wfile.write(b'{"ok":true,"server":"fleet_test_server"}')
|
|
|
|
def do_POST(self):
|
|
n = int(self.headers.get("Content-Length", 0))
|
|
body = self.rfile.read(n)
|
|
ctype = (self.headers.get("Content-Type", "") or "").split(";")[0]
|
|
rec = {"path": self.path, "ctype": ctype,
|
|
"auth": self.headers.get("Authorization", ""), "len": n}
|
|
summary = ""
|
|
if ctype == "application/json":
|
|
try:
|
|
d = json.loads(body)
|
|
if "db_base64" in d:
|
|
d["db_base64"] = f"[{len(d['db_base64'])} chars]"
|
|
rec["json"] = d
|
|
if self.path.endswith("/telemetry"):
|
|
summary = (f"battery={d.get('battery')} charging={d.get('charging')} "
|
|
f"status={d.get('status')} pos={d.get('position')} "
|
|
f"faults={len(d.get('faults',[]))} sn={d.get('sn')} mac={d.get('mac')}")
|
|
except Exception as e:
|
|
rec["json_err"] = str(e)
|
|
else:
|
|
txt = body.decode("latin-1")
|
|
i = txt.find('name="meta"')
|
|
if i != -1:
|
|
meta = txt[i:].split("\r\n\r\n", 1)[-1].split("\r\n", 1)[0]
|
|
rec["meta"] = meta
|
|
try:
|
|
m = json.loads(meta)
|
|
summary = (f"map={m.get('name')} format={m.get('format')} "
|
|
f"size={m.get('size_bytes')}B points={len(m.get('points',[]))} sn={m.get('sn')}")
|
|
except Exception:
|
|
pass
|
|
self._emit(rec)
|
|
print(f"[RECV] POST {self.path} {summary}", flush=True)
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
self.wfile.write(b'{"ok":true}')
|
|
|
|
def log_message(self, *a):
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print(f"fleet_test_server listening on 0.0.0.0:{PORT} (log -> {REQLOG})", flush=True)
|
|
try:
|
|
ThreadingHTTPServer(("0.0.0.0", PORT), H).serve_forever()
|
|
except KeyboardInterrupt:
|
|
sys.exit(0)
|