#!/usr/bin/env python3
"""
TP6 — Klick-Konsole fuer den Call-Durchlauf.
Zwei Aufgaben:
1. FUEHREN: die Seite sagt jederzeit, was gerade laeuft, wie lange es noch dauert und
was der Mensch am Telefon jetzt tun (und lassen) soll. Am Ende sagt sie unmissver-
staendlich, dass die Messung abgeschlossen ist.
2. MITSCHREIBEN: jeder Klick landet mit Zeitstempel in derselben Zeitachse wie der
Core-Sampler. Der Not-Aus killt zusaetzlich sofort die Saettigungs-Flows.
🔴 Zwei Dinge, die hier absichtlich so gebaut sind:
- Die Buttons sind server-seitig gerenderte
' % (n, n, c, l)
for n, l, c, modes in BUTTONS if mode in modes
)
return PAGE.format(
banner=banner, title=st.get("title", "—"), phase=st.get("phase", "—"),
instruction=st.get("instruction", ""), prog=prog, countdown=countdown,
wlan=wlan, wan="rx %s / tx %s · CPU %s%%" % (fmt_bps(w.get("wan_rx")),
fmt_bps(w.get("wan_tx")), w.get("cpu", "?")),
last=last_marker(), buttons=btns,
)
PAGE = """
TP6 — Call-Konsole
{banner}
{phase}
{title}
{instruction}
{countdown}
{prog}
WLAN {wlan}
WAN {wan}
Marker {last}
{buttons}
"""
class Handler(BaseHTTPRequestHandler):
def _send(self, code, body, ctype="application/json"):
raw = body.encode("utf-8")
self.send_response(code)
self.send_header("Content-Type", ctype + "; charset=utf-8")
self.send_header("Content-Length", str(len(raw)))
self.send_header("Cache-Control", "no-store")
self.end_headers()
self.wfile.write(raw)
def _back(self):
self.send_response(303)
self.send_header("Location", "/")
self.send_header("Content-Length", "0")
self.end_headers()
def do_GET(self):
if self.path.startswith("/status"):
st = read_state()
st["sampler"] = sampler_tail()
st["last"] = last_marker()
self._send(200, json.dumps(st))
elif self.path in ("/", "/index.html"):
self._send(200, render(read_state()), "text/html")
else:
self._send(404, "{}")
def do_POST(self):
if self.path.startswith("/jserr"):
with open(os.path.join(RUN_DIR, "jserrors.log"), "a") as fh:
fh.write("%s %s\n" % (time.strftime("%H:%M:%S"), self.path.split("msg=", 1)[-1]))
self._send(200, "{}")
return
if self.path.startswith("/m?"):
name = self.path.split("type=", 1)[1].split("&")[0].upper()
if name == "ABORT":
write_marker("ABORT_killed=%d" % kill_flows())
else:
if name == "CALL_START":
open(GO_FLAG, "w").close()
write_marker(name)
if "text/html" in (self.headers.get("Accept") or ""):
self._back()
else:
self._send(200, json.dumps({"ok": True}))
else:
self._send(404, "{}")
def log_message(self, *_a):
pass
if __name__ == "__main__":
print("Konsole: http://localhost:%d/ · vom iPad: http://10.40.10.183:%d/" % (PORT, PORT))
print("Marker -> %s" % MARKERS)
HTTPServer(("0.0.0.0", PORT), Handler).serve_forever()