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>
170 lines
8.5 KiB
Bash
Executable File
170 lines
8.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# TP25 — Gehweg-Messung: was kostet eine WLAN-Uebergabe wirklich?
|
|
#
|
|
# Beantwortet die Frage, die die Sampler-Daten offen lassen: bei jedem AP-/Bandwechsel steht in
|
|
# der Registration-Table ~4 s lang kein Durchsatz — aber die Zaehler starten nach einer
|
|
# Neuanmeldung ohnehin bei null. Ein Ping AUF das Telefon trennt beides:
|
|
# Paketverlust = echte Funkstille · kein Verlust = die 4 s waren Buchhaltung.
|
|
#
|
|
# Gepingt wird VOM CORE aus (Kabel bis zum AP), damit der Verlust eindeutig dem Telefon
|
|
# gehoert und nicht der Funkstrecke des messenden Laptops.
|
|
#
|
|
# Braucht KEINEN Call. Misst nur, aendert nichts.
|
|
#
|
|
# bash docs/tp25-walk-messung.sh # laeuft bis Ctrl-C bzw. bis "Stoppen" geklickt wird
|
|
#
|
|
# Waehrend des Gehens auf der Konsole: 🚶 beim Losgehen, 📍 beim Stehenbleiben.
|
|
|
|
set -uo pipefail
|
|
|
|
RUN_DIR="${TP6_RUN_DIR:-/private/tmp/claude-501/-Users-christophemsenhuber-dev-bf-network-r6/0d86ebd1-035f-4513-a231-5cca8111ecfd/scratchpad/tp6-run2}"
|
|
PHONE="${TP25_PHONE_IP:-10.40.10.178}" # S22 -- wird gepingt und gesampelt
|
|
PHONE_MAC="${TP25_PHONE_MAC:-2A:0D:B0:5D:AD:A7}"
|
|
# 🔴 Seit dem Lauf vom 2026-08-22 wird das ZWEITE Telefon mitgepingt. Vorher lief der Ping
|
|
# nur auf das gepinnte Geraet -- und weil das per Automatik immer auf dem GEGEN-AP sitzt,
|
|
# fehlte ausgerechnet die Strecke, die die Alltagsabdeckung zeigt. Der Terrassen-Vergleich
|
|
# liess sich deshalb nicht fuehren, obwohl beide Telefone dabei waren.
|
|
PHONE2="${TP25_PHONE2_IP:-10.40.10.196}" # iPhone -- roamt frei
|
|
PHONE2_NAME="${TP25_PHONE2_NAME:-iphone}"
|
|
STATE="$RUN_DIR/phase.json"
|
|
MARKERS="$RUN_DIR/markers.csv"
|
|
HERE="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
|
mkdir -p "$RUN_DIR"
|
|
[[ -f "$MARKERS" ]] || echo "ts_epoch,ts_local,marker" > "$MARKERS"
|
|
|
|
# Zeiger fuer die Klick-Konsole (docs/tp6-marker/server.py). Die laeuft als Dauer-Preview
|
|
# auf Port 3031 und kennt dieses Verzeichnis sonst nicht -- ihre Marker landeten dann im
|
|
# Lauf von gestern, waehrend der Sampler hierher schreibt. Beides fiel erst bei der
|
|
# Auswertung auf, wenn die Raummarken fehlten.
|
|
printf '%s\n' "$RUN_DIR" > "$HERE/docs/tp6-marker/.current-run"
|
|
|
|
# 🔴 Die AP-Zuordnung JETZT einfrieren, im Messlauf. Die cap-wifiN-Nummern vergibt der
|
|
# Manager dynamisch beim Anmelden der CAPs -- sie aendern sich, sobald ein AP neu
|
|
# bootet oder umgesteckt wird. Wer sie erst bei der Auswertung nachschlaegt, beschriftet
|
|
# alte Daten mit einer neuen Wahrheit. Genau das waere am 2026-08-22 beinahe passiert:
|
|
# die Raumkarte vom 08-21 haette Technik OG dann ap1 zugeschrieben -- dem AP, der nicht
|
|
# in diesem Raum steht.
|
|
bash "$HERE/docs/tp25-pin-s22.sh" map > "$RUN_DIR/ap-map.txt" 2>/dev/null \
|
|
&& echo "AP-Zuordnung eingefroren -> $RUN_DIR/ap-map.txt" \
|
|
|| echo "⚠️ AP-Zuordnung konnte nicht gelesen werden -- Auswertung bleibt bei cap-wifiN"
|
|
|
|
# Frueheren Lauf beiseitelegen, statt ihn zu ueberschreiben.
|
|
if [[ -f "$RUN_DIR/sampler.csv" ]]; then
|
|
ARCHIV="$RUN_DIR/archiv-$(date +%H%M%S)"; mkdir -p "$ARCHIV"
|
|
for f in sampler.csv markers.csv walk-ping.csv walk-ping.log ping-dauerlauf.log; do
|
|
[[ -f "$RUN_DIR/$f" ]] && mv "$RUN_DIR/$f" "$ARCHIV/"
|
|
done
|
|
echo "ts_epoch,ts_local,marker" > "$MARKERS"
|
|
echo "Vorheriger Lauf -> $ARCHIV"
|
|
fi
|
|
|
|
state() {
|
|
python3 - "$STATE" "$1" <<'PY'
|
|
import json, os, sys
|
|
p, inst = sys.argv[1], sys.argv[2]
|
|
tmp = p + ".tmp"
|
|
with open(tmp, "w") as fh:
|
|
json.dump({"mode": "langzeit", "phase": "GEHWEG", "title": "Roaming-Messung läuft",
|
|
"instruction": inst, "step": 0, "steps": 0, "ends": 0}, fh)
|
|
os.replace(tmp, p)
|
|
PY
|
|
}
|
|
|
|
state "Kein Call nötig. <b>🚶</b> drücken, wenn du losgehst, <b>📍</b> wenn du stehen bleibst — und bitte den Weg gehen, den du beim Telefonieren wirklich gehst.<br><br>Ich pinge dein Telefon fünfmal pro Sekunde. Jeder AP- oder Bandwechsel zeigt sich dann als echter Paketverlust: <b>so lange ist der Call wirklich tot.</b><br><br>Am Ende: <b>⏹ Aufzeichnung stoppen</b>."
|
|
|
|
# Sampler am Manager (1-s-Takt, feiner als bei der TP6-Messung)
|
|
bash "$HERE/docs/tp6-monitor-core.sh" --out "$RUN_DIR/sampler.csv" --mac "$PHONE_MAC" --interval 1 \
|
|
> "$RUN_DIR/sampler.out" 2>&1 & SAMPLER=$!
|
|
|
|
# 5 Pings/s auf JEDES Telefon — GEPINGT WIRD VOM CORE, nicht von diesem Rechner.
|
|
# 🔴 Der Grund: pingt der Laptop, laeuft der Weg ueber ZWEI Funkstrecken (Laptop -> AP ->
|
|
# Core -> AP -> Telefon). Fehlt dann ein Paket, ist nicht entscheidbar, welches der
|
|
# beiden Geraete weg war. Vom Core aus ist die Strecke bis zum AP durchgehend Kabel,
|
|
# also misst der Verlust genau das, was er messen soll: den Funk zum Telefon.
|
|
# (Aufgefallen am 2026-08-21, als das MacBook waehrend einer Messung vom Dock ans
|
|
# WLAN wechselte und dabei auch noch die IP wechselte.)
|
|
PW="$(grep -m1 '^CRS326_CORE_PASS=' ~/.secrets/credentials.env | cut -d= -f2- | sed 's/^["'"'"'"'"'"']//; s/["'"'"'"'"'"']$//')"
|
|
|
|
# $1 = Ziel-IP, $2 = Ausgabedatei. Schreibt "ts_local,seq,ms"; leeres ms = Verlust.
|
|
# 🔴 sshpass -e statt -p: mit -p steht das Router-Passwort in der Kommandozeile und damit
|
|
# in `ps` und in jedem Prozess-Trace. Am 2026-08-22 ist es genau so im Klartext in einem
|
|
# Sitzungsmitschnitt gelandet.
|
|
ping_lauf() {
|
|
local ziel="$1" datei="$2"
|
|
echo "ts_local,seq,ms" > "$datei"
|
|
(
|
|
while true; do
|
|
SSHPASS="$PW" sshpass -e ssh -o StrictHostKeyChecking=no -o ConnectTimeout=8 \
|
|
-o ServerAliveInterval=15 admin@10.40.99.1 \
|
|
"/ping $ziel interval=200ms count=100000" 2>/dev/null \
|
|
| while IFS= read -r l; do
|
|
l="${l%$'\r'}"
|
|
case "$l" in
|
|
*SEQ*HOST*) continue ;;
|
|
esac
|
|
seq="$(printf '%s' "$l" | awk '{print $1}')"
|
|
case "$seq" in
|
|
''|*[!0-9]*) continue ;;
|
|
esac
|
|
case "$l" in
|
|
*timeout*) printf '%s,%s,\n' "$(date +%H:%M:%S)" "$seq" ;;
|
|
*) printf '%s,%s,%s\n' "$(date +%H:%M:%S)" "$seq" \
|
|
"$(printf '%s' "$l" | awk '{print $NF}')" ;;
|
|
esac
|
|
done >> "$datei"
|
|
printf '%s,,RECONNECT\n' "$(date +%H:%M:%S)" >> "$datei"
|
|
sleep 2
|
|
done
|
|
) &
|
|
}
|
|
|
|
# 🔴 Die PID NICHT ueber $(ping_lauf ...) holen: die Kommandosubstitution wartet, bis die
|
|
# stdout-Pipe schliesst, und der Hintergrundjob darin haelt sie offen -- das Skript blieb
|
|
# dort stehen, der zweite Ping wurde nie gestartet (2026-08-22). Die Funktion laeuft in
|
|
# der aktuellen Shell, also liefert $! danach die richtige PID.
|
|
ping_lauf "$PHONE" "$RUN_DIR/walk-ping.csv"; PINGER=$!
|
|
ping_lauf "$PHONE2" "$RUN_DIR/walk-ping-$PHONE2_NAME.csv"; PINGER2=$!
|
|
|
|
# 🔴 Kinder ZUERST. `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 (2026-08-22, beim Test des Stopp-Knopfs gefunden). Wer den Vater
|
|
# zuerst killt, verliert den Zugriff auf die Kinder.
|
|
killbaum() {
|
|
local pid="$1" kind
|
|
for kind in $(pgrep -P "$pid" 2>/dev/null); do killbaum "$kind"; done
|
|
kill "$pid" 2>/dev/null
|
|
}
|
|
|
|
beenden() {
|
|
for pid in $SAMPLER $PINGER $PINGER2; do killbaum "$pid"; done
|
|
pkill -f "ping $PHONE interval=200ms" 2>/dev/null
|
|
pkill -f "ping $PHONE2 interval=200ms" 2>/dev/null
|
|
# Der /ping am Router endet mit der SSH-Sitzung (am 2026-08-22 nachgeprueft: nach dem
|
|
# Kill der Sitzungen lief am Core nichts weiter). Bewusst KEIN "job remove" am Geraet --
|
|
# ein pauschales Aufraeumen fremder Jobs waere ein zu grobes Werkzeug fuer ein Messskript.
|
|
state "Aufzeichnung gestoppt."
|
|
echo; echo "Gestoppt. Auswertung:"
|
|
echo " python3 docs/tp25-gehweg-auswertung.py --dir $RUN_DIR"
|
|
}
|
|
trap beenden EXIT
|
|
|
|
echo "Gehweg-Messung laeuft."
|
|
echo " Funk -> $RUN_DIR/sampler.csv"
|
|
echo " Ping -> $RUN_DIR/walk-ping.csv ($PHONE, gepinnt)"
|
|
echo " Ping -> $RUN_DIR/walk-ping-$PHONE2_NAME.csv ($PHONE2, frei roamend)"
|
|
echo " Stoppen: '⏹ Aufzeichnung stoppen' auf der Konsole -- oder Ctrl-C hier."
|
|
|
|
# 🔴 Bis 2026-08-22 lief hier nur `while true; do touch; sleep 5; done`, und das Skript war
|
|
# ausschliesslich per Ctrl-C zu beenden -- obwohl der Anleitungstext auf der Konsole einen
|
|
# Stopp-Knopf versprach. Christoph drueckte "Call beendet" und den Not-Aus, beides schrieb
|
|
# nur Marken, und die Messung lief weiter. Jetzt gibt es den Knopf wirklich: die Konsole
|
|
# legt stop.flag ab, und diese Schleife bricht darauf ab.
|
|
rm -f "$RUN_DIR/stop.flag"
|
|
while [[ ! -f "$RUN_DIR/stop.flag" ]]; do
|
|
touch "$STATE" 2>/dev/null
|
|
sleep 2
|
|
done
|
|
echo "Stopp von der Konsole empfangen."
|