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>