Der Stopp-Knopf, den der Anleitungstext seit jeher versprach
Zwei Maengel aus dem Rundgang vom 22.8. behoben. 1. STOPP-KNOPF. Die Konsole nannte "⏹ Aufzeichnung stoppen", es gab ihn nicht. Christoph drueckte "Call beendet" und den Not-Aus -- beide schreiben nur Marken -- und die Messung lief weiter, waehrend der Core sein Telefon mit 5 Pings/s bearbeitete. Jetzt legt der Knopf stop.flag ab, und die Warteschleife des Messskripts bricht darauf ab. 2. ZWEITES TELEFON. Der Beobachter las immer schon beide Geraete, hielt die Zahlen aber nur im Speicher fuer die Anzeige. Da das S22 per Automatik immer auf dem GEGEN-AP sitzt, fehlte damit ausgerechnet die Strecke, die die Alltagsabdeckung zeigt -- der Terrassen-Vergleich war nicht zu fuehren. Jetzt: zweiter Ping (walk-ping-iphone.csv) und beide-telefone.csv im 2-s-Takt mit iface + Signal je Geraet. Beim Testen kamen zwei Fehler ans Licht, die den naechsten Lauf gekostet haetten: - `PINGER=$(ping_lauf ...)` blockiert. Die Kommandosubstitution wartet, bis die stdout-Pipe schliesst, und der Hintergrundjob darin haelt sie offen. Das Skript stand in dieser Zeile, der zweite Ping wurde nie gestartet -- und es sah von aussen aus wie ein normal laufender Lauf. Die Funktion laeuft in der aktuellen Shell, also liefert $! danach die richtige PID. - `kill $SAMPLER` traf nur den Wrapper. Dessen Subshell samt SSH-Sitzung wurde dabei verwaist und lief weiter: nach dem Stopp hielt der Core stumm eine Sampler-Sitzung offen. Wer den Vater zuerst killt, verliert den Zugriff auf die Kinder -- jetzt killbaum(), Kinder zuerst. Mitgenommen von der Rotationsliste: tp6-monitor-core.sh und der Ping in tp25-walk-messung.sh laufen jetzt ueber `sshpass -e` statt `-p`. Damit steht das Router-Passwort in keiner Kommandozeile mehr. `pgrep -fl "sshpass -p"` ist leer. Offen bleibt tp25-pin-s22.sh. Abnahme: Lauf gestartet, beide Ziele gepingt (10.40.10.178 + .196), ein Klick auf den Stopp-Knopf, danach kein Prozess und keine SSH-Sitzung mehr uebrig, Pin geloest. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -283,6 +283,12 @@ def beobachter():
|
||||
continue
|
||||
_live.update(iphone=teile[0], iphone_sig=teile[1],
|
||||
s22=teile[2], s22_sig=teile[3], stand=time.time())
|
||||
# 🔴 Bis 2026-08-22 blieben diese Zahlen NUR im Speicher, fuer die Anzeige.
|
||||
# Nach dem Rundgang fehlte deshalb die halbe Messung: das S22 sitzt per
|
||||
# Automatik immer auf dem Gegen-AP, die Alltagsabdeckung zeigt das iPhone
|
||||
# -- und genau dessen Zeitreihe war weg. Nachtraeglich liess sich nur das
|
||||
# Roaming-Log am Manager retten: Ereignisse, keine Kurve.
|
||||
mitschreiben(teile)
|
||||
entscheide()
|
||||
except Exception as e:
|
||||
# Ein Beobachter, der still stirbt, ist schlimmer als keiner (Lehre aus dem
|
||||
@@ -295,6 +301,19 @@ def beobachter():
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
def mitschreiben(teile):
|
||||
"""Beide Telefone im 2-s-Takt in den Lauf schreiben: iface + Signal je Geraet."""
|
||||
try:
|
||||
pfad = _p("beide-telefone.csv")
|
||||
frisch = not os.path.exists(pfad) or os.path.getsize(pfad) == 0
|
||||
with open(pfad, "a") as fh:
|
||||
if frisch:
|
||||
fh.write("ts_epoch,ts_local,iphone_iface,iphone_sig,s22_iface,s22_sig\n")
|
||||
fh.write("%d,%s,%s\n" % (time.time(), time.strftime("%H:%M:%S"), ",".join(teile)))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def entscheide():
|
||||
"""Gegen-AP setzen, sobald das iPhone den AP wechselt."""
|
||||
if not _auto["an"] or _pin["busy"]:
|
||||
@@ -510,6 +529,14 @@ def render(st):
|
||||
notaus = ('<form method="post" action="/m?type=ABORT" onsubmit="return send(event,\'ABORT\')">'
|
||||
'<button class="abort" type="submit">⛔ LAST SOFORT STOPPEN</button></form>'
|
||||
) if st.get("driver") else ""
|
||||
# 🔴 Der Stopp-Knopf. Er beendet die AUFZEICHNUNG (stop.flag -> tp25-walk-messung.sh),
|
||||
# nicht nur eine Marke. Vorher gab es ihn nicht, obwohl der Anleitungstext ihn nannte:
|
||||
# am 2026-08-22 drueckte Christoph "Call beendet" und den Not-Aus, beide schrieben nur
|
||||
# Marken, und der Core pingte danach noch minutenlang weiter.
|
||||
if st.get("driver"):
|
||||
notaus = ('<form method="post" action="/stop" onsubmit="return sendstop(event)">'
|
||||
'<button class="end" type="submit">⏹ Aufzeichnung stoppen</button></form>'
|
||||
) + notaus
|
||||
|
||||
# 🚶 Gehen/Stehen braucht keinen Treiber -- das sind reine Zeitmarken fuer die Auswertung.
|
||||
btns = ('<form method="post" action="/m?type=WALK" onsubmit="return send(event,\'WALK\')">'
|
||||
@@ -634,6 +661,17 @@ function signale(){{
|
||||
letzterAlarm = alarm ? 1 : 0; letzterBusy = busy ? 1 : 0;
|
||||
}}
|
||||
|
||||
function sendstop(ev){{
|
||||
try{{
|
||||
ev.preventDefault(); unlock(); okton();
|
||||
var inst = document.getElementById('pininst');
|
||||
fetch('/stop', {{method:'POST'}}).catch(function(){{}});
|
||||
var b = ev.target.querySelector('button');
|
||||
if(b){{ b.textContent = '⏹ gestoppt — Aufzeichnung endet'; b.disabled = true; }}
|
||||
setTimeout(refresh, 1500);
|
||||
return false;
|
||||
}}catch(e){{ return true; }}
|
||||
}}
|
||||
function sendauto(ev){{
|
||||
try{{
|
||||
ev.preventDefault(); unlock(); okton();
|
||||
@@ -722,6 +760,13 @@ class Handler(BaseHTTPRequestHandler):
|
||||
fh.write("%s %s\n" % (time.strftime("%H:%M:%S"), self.path.split("msg=", 1)[-1]))
|
||||
self._send(200, "{}")
|
||||
return
|
||||
if self.path.startswith("/stop"):
|
||||
# Der Knopf, den der Anleitungstext seit jeher versprach und den es nie gab.
|
||||
open(_p("stop.flag"), "w").close()
|
||||
write_marker("STOP")
|
||||
self._send(200, json.dumps({"ok": True})) if "text/html" not in (
|
||||
self.headers.get("Accept") or "") else self._back()
|
||||
return
|
||||
if self.path.startswith("/auto"):
|
||||
_auto["an"] = not _auto["an"]
|
||||
_auto["aufgegeben"] = ""
|
||||
|
||||
Reference in New Issue
Block a user