Die Auswertung liest jetzt beide Geraete und stellt sie je Raum untereinander:
REFERENZ (iPhone, frei) was du an dieser Stelle wirklich hast
SONDE (S22, Gegen-AP) was die Rueckfallebene noch leisten koennte
Damit faellt der Terrassen-Vergleich beim naechsten Lauf von selbst raus, und
die Lesart wird eindeutig: gute Referenz + schlechte Sonde = alles haengt an
EINEM AP; beide schlecht = echtes Loch ohne Rueckfallebene (der Kuechenfall).
Rueckwaertskompatibel: Laeufe ohne walk-ping-iphone.csv/beide-telefone.csv
laufen einspaltig weiter und liefern fuer den Lauf vom 22.8. Ziffer fuer Ziffer
dieselben Zahlen wie vorher. Das Geraet heisst dort "Geraet" -- welches es war,
steht in den Dateien nicht, also wird es auch nicht behauptet.
Drei Fehler, die der Abnahmetest zutage foerderte und die alle den naechsten
Rundgang gekostet haetten:
1. Die Gegen-AP-Automatik war nach dem Start AUS. Wer den Klick vergisst, geht
die ganze Runde mit beiden Telefonen auf DEMSELBEN AP -- im Test genau so
passiert. tp25-runde.sh schaltet sie jetzt scharf; /auto nimmt dafuer ?an=1
(ein Toggle waere falsch: bei schon laufender Konsole haette der Start sie
ausgeschaltet).
2. "Funk da, aber keine einzige Ping-Antwort" erschien als "—", also wie eine
Datenluecke. Beim Test lag das iPhone gesperrt auf dem Tisch: angemeldet mit
-47 dBm und trotzdem stumm. Wer das als Luecke liest, sucht danach ein
Funkloch, das es nicht gibt. Jetzt: "keine Antwort" + "⚠️ Display gesperrt?".
3. Der Aufraeumer meldete "AP-Pin geloest", und danach standen die Regeln
trotzdem am Core. Wettlauf: er loeste den Pin, waehrend die Konsole noch
lief, und deren Automatik setzte ihn binnen zwei Sekunden wieder. Das
Telefon waere nach JEDER Runde gepinnt geblieben. Jetzt erst Konsole toeten,
dann Pin loesen.
Zuletzt: tp25-pin-s22.sh laeuft auf sshpass -e. Damit steht das Router-Passwort
in keiner Kommandozeile mehr -- `grep -rn "sshpass -p" docs/ nautobot/` findet
nur noch die Erwaehnung in teilprojekte.md. Die Rotation kann jetzt kommen.
Abnahme (mehrere echte Laeufe): Automatik meldet EIN, beide Telefone stehen auf
verschiedenen APs, beide werden gepingt, ein Klick auf Stopp beendet alles,
Pin danach "off", kein Prozess uebrig.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
docs/tp25-runde.sh startet Konsole und Messung zusammen, friert die AP-Karte
ein, sagt die vom Interface GELESENE Adresse fuers Telefon an und loest beim
Beenden den Pin. Grund: beide Einzelteile hatten als Standard-Laufverzeichnis
einen Pfad in ein Sitzungs-Scratchpad -- wer sie ohne die passende
Umgebungsvariable startete, mass in ein totes Verzeichnis und merkte es erst
bei der Auswertung.
Der Probelauf hat dabei sofort einen Fehler in der eigenen Anzeige aufgedeckt:
die Seite meldete "✅ beide angemeldet, auf verschiedenen APs", waehrend beide
Telefone auf ap2 hingen. Das Kriterium prueft "beide angemeldet" -- nicht, ob
sie auf VERSCHIEDENEN APs sitzen. Das ist ein gruenes Licht fuer einen
Messpunkt, den es nicht gibt: Piep, weitergehen, kein Gegen-AP gemessen.
Wieder dieselbe Klasse wie der 14-h-Ausfall -- Anzeige geprueft statt Wirkung.
Jetzt vier Zustaende, gegen sechs Faelle geprueft (inkl. "gleicher AP, anderes
Band" -> zaehlt NICHT):
bereit verschiedene APs -> Piep, weitergehen
wird nachgezogen gleicher AP, Automatik -> warten
kein Gegen-AP gleicher AP, ohne Auto -> Warnung statt gruen
S22 sucht S22 nicht angemeldet -> stehenbleiben
teilprojekte.md: Passwort-Rotation als offener Follow-up eingetragen (User:
"machen wir, aber erst spaeter") -- inkl. der noch offenen sshpass -p in
tp6-monitor-core.sh und tp25-pin-s22.sh, die vorher nachgezogen gehoeren.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mit dem Gating der Call-Buttons wurde der Hinweis "Erst den Treiber starten
lassen" zur Sackgasse: ohne Treiber gibt es keinen Start-Button mehr. Er sagt
jetzt, was ohne Treiber SEHR WOHL geht (Raeume, AP-Pin) und wie man die
Ping-Aufzeichnung dazuholt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Christophs Einwand, und er hat recht: wer in ap2-Zone losgeht und das S22
auf ap2 pinnt, misst dort dasselbe, was das frei roamende iPhone ohnehin
liefert. Der Erkenntnisgewinn liegt beim ANDEREN AP.
Die Konsole liest deshalb beide Telefone mit und zwingt das S22 automatisch
auf den Gegen-AP des iPhones. Pro Standort gibt es damit zwei Messpunkte
statt einem, ohne den Weg zweimal zu gehen. Ein kurzer Doppelton meldet
"beide angemeldet, verschiedene APs" -- das ist das Signal zum Weitergehen.
Drei Zustaende statt zwei, weil zwei hier luegen wuerden:
bereit beide haengen -> Piep, weiter
sucht S22 versucht den Gegen-AP -> stehenbleiben
unerreichbar nach 45 s: der Gegen-AP traegt hier NICHT. Das ist das
Messergebnis, kein Defekt -- Marker UNERREICHBAR=apX, kein
Dauer-Alarm, weitergehen.
Ausserdem:
- Raumkacheln sind zurueck. Sie hingen am TP6-Treiber-Zustand und waren ohne
laufenden Call-Treiber unsichtbar -- ausgerechnet beim Kartieren.
- Die Call-Buttons (Start / Not-Aus fuer die Saettigungs-Flows) erscheinen nur
noch MIT Treiber. Ohne einen haette der Start-Klick nichts gemessen; der
Not-Aus haette nichts zu stoppen gehabt. 🚶/📍 brauchen keinen Treiber und
bleiben immer da.
Zwei Fehler beim Bauen, beide mit Merkwert:
1. `(:while (true) do={...})` -- die Klammern beenden die RouterOS-Sitzung
wortlos. Mit stderr auf DEVNULL sah man nur, dass alle 3 s ein neuer ssh
startet, und sonst nichts. stderr geht jetzt in beobachter.log.
2. `for zeile in proc.stdout` liest blockweise vor: bei einer Zeile alle 2 s
waeren die ersten Daten nach etwa einer Stunde gekommen. iter(readline, "").
Und eine Sicherheitskorrektur: `sshpass -p` schreibt das Router-Passwort in
die Kommandozeile -- sichtbar in ps und in jedem argv-Trace. Beim Debuggen ist
es am 2026-08-22 genau so im Klartext gelandet. Der Beobachter nutzt jetzt
`sshpass -e` (Passwort nur in der Umgebung des Kindprozesses). tp6-monitor-core.sh
und tp25-pin-s22.sh haben dieselbe Schwaeche und sind noch NICHT umgestellt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP25: das S22 laesst sich jetzt per access-list am Manager auf EINEN AP
festnageln (docs/tp25-pin-s22.sh, Umschalter in der Klick-Konsole). Damit
werden Einzel-AP-Abdeckungskarten messbar, statt dass der Client mitten im
Weg wechselt. Gepinnt wird der Standort, nicht das Band -- Band-Ping-Pong
(Fund C) bleibt damit ein echter Befund und wird nicht wegkonfiguriert.
Beim Bauen fielen drei Fehler auf, die alle dieselbe Form haben: eine
Konstante, die einmal richtig war.
1. Die AP-Zuordnung war VERTAUSCHT. server.py und tp25-gehweg-auswertung.py
fuehren cap-wifi1/2 als ap1 -- live ist es ap2 (belegt ueber cap=,
configuration= und Kanal). Baender stimmten, Identitaet nicht. Die
cap-wifiN-Nummern vergibt der Manager dynamisch in der Anmeldereihenfolge
der CAPs, jede feste Tabelle dazu wartet auf den naechsten AP-Reboot.
server.py liest sie jetzt vom Geraet; die Auswertung ist NOCH NICHT
angefasst -- offen ist, ob die Funde vom 08-21 mit vertauschten AP-Namen
notiert sind.
2. Das Laufverzeichnis war beim Serverstart eingefroren. Die Konsole laeuft
als Dauer-Preview, der Messlauf legt spaeter ein neues Verzeichnis an --
Marker waeren in den Lauf von gestern gewandert, waehrend der Sampler ins
neue schreibt. tp25-walk-messung.sh hinterlaesst jetzt einen Zeiger.
3. Das Startbanner nannte eine hartkodierte IP (10.40.10.183 = MacBook Air).
Auf dem Mac mini ist es 10.40.10.82, und genau die falsche Adresse ging
ans Telefon: "geht nicht" bei einem Server, der sauber auf 0.0.0.0 lauschte.
Es werden jetzt die real gefundenen Interface-Adressen gedruckt.
Ausserdem, aus dem Test heraus:
- Ein vom Pin ABGEWIESENER Verbindungsversuch ist in den Ping-Daten nicht von
einem Funkloch zu unterscheiden, und der Manager protokolliert ihn auf
info-Ebene nicht. Android quittiert ihn mit "Verbindung fehlgeschlagen" und
waehlt das Netz ab -- danach misst der Rest des Rundgangs Stille. Die Konsole
schlaegt deshalb mit Vollbanner, Ton und Vibration Alarm, sobald das gepinnte
Geraet nirgends haengt.
- Die Konsole laeuft diesmal auf dem S22 selbst, also auf genau dem Geraet, das
der Pin gleich vom WLAN wirft. Die Anweisung zum Wiederverbinden erscheint
deshalb clientseitig VOR dem Abbruch.
- ThreadingHTTPServer: der Pin braucht ~8 s ueber SSH und haette sonst die
ganze Seite blockiert, Not-Aus inklusive.
Governance: /interface wifi access-list steht unter KEINER ComplianceRule --
der Change erzeugt keinen Drift und laesst sich nicht als Transaktion fuehren.
Fuer eine Messung vertretbar; relevant wird es, wenn Fund E (signal-range)
dauerhaft dort landet.
teilprojekte.md: die beiden Hinweise auf die offene Transaktion
TEST-ether3-trunk-ap1-sideboard nachgezogen -- sie ist seit 08-22
zurueckgerollt, crs326-core ist transaktionsfrei.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zweiter Gehweg-Durchgang, diesmal methodisch sauber: Ping vom Core statt vom
Laptop, Konsole auf dem iPhone (Wake Lock haelt es wach, sonst misst man
Ruhezustand), Raumwechsel per Klick markiert.
Das Ergebnis ist eindeutig und macht die Roaming-Geschichte klein. Im ganzen Haus
null Paketverlust -- Technik UG und OG, Diele, Kinder-, Schlaf- und
Arbeitszimmer, Treppe, alle 0 %, und die Uebergaben ap1<->ap2 auf der Treppe
kosten 0,2 s. Auf der Terrasse dagegen 43 % Verlust ueber 162 Sekunden, am Stueck
fehlen 20,4 Sekunden, bei -72 dBm. Dort ist ein Call nicht gestoert, sondern weg.
Die Topologie erklaert es vollstaendig: ap2 steht in Technik OG, das nur ueber
das Arbeitszimmer zugaenglich ist -- zur Terrasse liegen Technik OG,
Arbeitszimmer, Diele OG und die Aussenwand dazwischen.
Das dreht die Massnahmen um. Ein signal-range-Boden (Fund E) wuerde die Terrasse
VERSCHLECHTERN, weil es dort keinen besseren AP gibt, auf den er steuern koennte
-- er wuerde nur rauswerfen. Stattdessen: 5 GHz auf 20 MHz (+3 dB, ein Wort im
Template), dann ap2 von Technik OG in die Diele OG umhaengen, die an Terrasse,
Arbeitszimmer und Treppe grenzt. Kein neuer AP noetig, damit ist auch die
User-Randbedingung erfuellt.
Konsole nachgezogen: Marker werden URL-dekodiert und behalten ihre Gross- und
Kleinschreibung (aus "RAUM=Diele OG" wurde "RAUM%3DDIELE%20OG"), Diele OG ist
ergaenzt, und das Raumraster steht jetzt oben -- ohne JavaScript laedt die Seite
nach jedem Klick neu, und dann muss der naechste Raum ohne Scrollen erreichbar
sein.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Gehweg-Messung erzeugte bisher eine Zeitachse, aus der niemand ablesen
konnte, WO es schlecht war -- der teure Abschnitt von gestern liegt bei
"15:07 bis 15:09", und das ist kein Satz, aus dem eine Massnahme folgt.
Die Konsole bekommt deshalb ein Raster mit einem Button je Raum; der aktive Raum
wird hervorgehoben und die Verweildauer mitgezaehlt. Die Liste steht per
TP25_ROOMS in der Umgebung, damit ein fehlender Raum kein Codeeingriff ist.
tp25-gehweg-auswertung.py verbindet die drei Mitschnitte -- Ping aufs Telefon,
Funkwerte vom Manager, Raum-Marken -- zu einer Tabelle mit Signal, Paketverlust
und laengster Luecke je Raum, samt AP, auf dem der Client dort haengt.
Dazu die Lehre aus dem ersten Durchgang, diesmal als Anleitung statt als Fussnote:
die Konsole gehoert waehrend der Messung auf DAS TELEFON. Der Wake Lock haelt das
Display an und das Polling das Geraet wach -- ohne das beantwortet ein iPhone die
Pings verzoegert oder gar nicht, und 44 % Verlust sind Ruhezustand statt Funk.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Durchlauf 1 ist gemessen (Ergebnis folgt separat im Runbook). Fuer den Durchlauf
mit laufendem Videocall brauchte es Werkzeug, das es noch nicht gab:
- tp6-monitor-core.sh haengt EINE persistente SSH-Sitzung an den Core und laesst
dort eine Console-Schleife laufen, die im 2-s-Takt CPU, WAN-Rate und die
Registration-Table-Werte eines WLAN-Clients als CSV ausgibt. Nur Lesezugriffe.
Unter CAPsMAN fuehrt der Manager die Tabelle, deshalb wird der Core abgefragt
und nicht ap1/ap2. Zwei RouterOS-Fallen sind im Code kommentiert: die Console
parst eine per SSH uebergebene Mehrzeilen-Eingabe zeilenweise, und in der
Einzeiler-Form braucht jeder do={}-Block ein abschliessendes Semikolon.
- tp6-marker/server.py ist die Konsole fuer die Person am Telefon: Phasenkarte
mit Klartext-Anweisung, Countdown, Fortschritt, Marker-Buttons und Not-Aus,
bedienbar vom iPad. Die Buttons sind server-seitig gerenderte Formulare und
die Anleitung aktualisiert sich notfalls per meta-refresh -- auf dem iPad ist
das JavaScript ausgefallen, uebrig blieb nur der eine statische Button.
- tp6-call-run.sh fuehrt Durchlauf 2 mit denselben Messparametern wie Durchlauf 1
(3 Flows x 430 KB/s, 24 Pings, 30 s Settle) und ergaenzt Ruhephasen davor und
danach, Phasenmarken, eine PID-Datei fuer den Not-Aus und einen Heartbeat.
Der Heartbeat ist kein Detail: ohne ihn geht der Start-Klick still ins Leere,
der Call laeuft ohne Last, und "keine Probleme" liest sich wie ein Ergebnis,
obwohl es eine Nicht-Messung ist -- genau so passiert, 5,5 Minuten lang.
- tp6-auswertung.py schneidet die Sampler-CSV an den Phasenmarken auf und meldet
neben min/avg/max auch die Ereignisse, die im Mittelwert untergehen: Roaming,
Re-Assoc und Verschwinden des Clients.
- tp6-bufferbloat-messung.sh schickt jetzt User-Agent und Referer mit. Ohne die
beantwortet speed.cloudflare.com /__down mit 403 und einem Byte: die Flows
sind sofort tot, die Ping-Reihe sieht sauber aus, und die Download-Seite gilt
faelschlich als bufferbloat-frei. Aufgefallen ist es nur, weil der Sampler am
Core 164 kbit statt 50 Mbit zeigte.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>