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."
|