Gehweg-Messung: gepingt wird vom Core, nicht vom Laptop
Pingt der messende Laptop das Telefon an, laeuft der Weg ueber zwei Funkstrecken -- Laptop -> AP -> Core -> AP -> Telefon. Fehlt dann ein Paket, ist nicht entscheidbar, welches der beiden Geraete weg war, und genau diese Trennschaerfe ist der ganze Zweck der Messung. Vom Core aus ist die Strecke bis zum AP durchgehend Kabel. Ausloeser war unfreiwillig: das MacBook ist mitten in einem Lauf vom Dock ans WLAN gewechselt und hat dabei die IP gewechselt -- die Konsole war ploetzlich nicht mehr erreichbar, und der Ping haette ab da zwei Funkstrecken gemessen. Das Ping-Protokoll ist jetzt eine CSV (ts_local,seq,ms; leeres ms = Verlust), die Auswertung liest beide Formate, damit die Laeufe von gestern lesbar bleiben. RouterOS-Dauern kommen als "3ms441us" oder "529us" und werden entsprechend geparst. Eine Falle steckt im Skript-Kommentar: tr puffert blockweise, sobald die Ausgabe in eine Pipe geht -- die ersten ~130 Zeilen haengen im Puffer und die Datei bleibt scheinbar leer. Das \r kommt deshalb im Shell-Loop weg, nicht per tr. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,16 +26,37 @@ AP = {"cap-wifi1": "ap1/5GHz", "cap-wifi2": "ap1/2,4GHz",
|
||||
"cap-wifi3": "ap2/5GHz", "cap-wifi4": "ap2/2,4GHz"}
|
||||
|
||||
|
||||
def ros_ms(v):
|
||||
"""RouterOS-Dauer in Millisekunden. Schreibweisen: "12ms", "3ms441us", "529us", "1s200ms"."""
|
||||
total = 0.0
|
||||
for zahl, einheit in re.findall(r"(\d+)(us|ms|s)", v):
|
||||
total += int(zahl) * {"us": 0.001, "ms": 1.0, "s": 1000.0}[einheit]
|
||||
return total
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--dir", required=True)
|
||||
a = ap.parse_args()
|
||||
|
||||
pings = []
|
||||
for line in open(os.path.join(a.dir, "walk-ping.log")):
|
||||
m = re.match(r"(\d\d:\d\d:\d\d) 64 bytes.*icmp_seq=(\d+).*time=([\d.]+)", line)
|
||||
if m:
|
||||
pings.append((sec(m.group(1)), int(m.group(2)), float(m.group(3))))
|
||||
csv_path = os.path.join(a.dir, "walk-ping.csv")
|
||||
if os.path.exists(csv_path):
|
||||
# Neues Format: Ping vom Core, "ts_local,seq,ms" — leeres ms = Verlust.
|
||||
for r in csv.DictReader(open(csv_path)):
|
||||
if not (r.get("seq") or "").isdigit():
|
||||
continue # RECONNECT-Zeilen
|
||||
ms = (r.get("ms") or "").strip()
|
||||
if ms:
|
||||
pings.append((sec(r["ts_local"]), int(r["seq"]), ros_ms(ms)))
|
||||
else:
|
||||
# Altes Format: BSD-ping vom Laptop.
|
||||
for line in open(os.path.join(a.dir, "walk-ping.log")):
|
||||
m = re.match(r"(\d\d:\d\d:\d\d) 64 bytes.*icmp_seq=(\d+).*time=([\d.]+)", line)
|
||||
if m:
|
||||
pings.append((sec(m.group(1)), int(m.group(2)), float(m.group(3))))
|
||||
if not pings:
|
||||
raise SystemExit("Keine Ping-Antworten gefunden.")
|
||||
|
||||
rows = [r for r in csv.DictReader(open(os.path.join(a.dir, "sampler.csv")))
|
||||
if r.get("sta_signal")]
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# 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
|
||||
@@ -28,7 +31,7 @@ mkdir -p "$RUN_DIR"
|
||||
# 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.log ping-dauerlauf.log; do
|
||||
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"
|
||||
@@ -53,14 +56,43 @@ state "Kein Call nötig. <b>🚶</b> drücken, wenn du losgehst, <b>📍</b> wen
|
||||
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 das Telefon, mit lokalem Zeitstempel je Zeile
|
||||
ping -i 0.2 "$PHONE" | while IFS= read -r l; do
|
||||
printf '%s %s\n' "$(date +%H:%M:%S)" "$l"
|
||||
done > "$RUN_DIR/walk-ping.log" 2>&1 & PINGER=$!
|
||||
# 5 Pings/s auf das 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/["'"'"'"'"'"']$//')"
|
||||
echo "ts_local,seq,ms" > "$RUN_DIR/walk-ping.csv"
|
||||
(
|
||||
while true; do
|
||||
sshpass -p "$PW" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=8 \
|
||||
-o ServerAliveInterval=15 admin@10.40.99.1 \
|
||||
"/ping $PHONE 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 >> "$RUN_DIR/walk-ping.csv"
|
||||
printf '%s,,RECONNECT\n' "$(date +%H:%M:%S)" >> "$RUN_DIR/walk-ping.csv"
|
||||
sleep 2
|
||||
done
|
||||
) & PINGER=$!
|
||||
|
||||
trap 'kill $SAMPLER $PINGER 2>/dev/null; pkill -f "ping -i 0.2 $PHONE" 2>/dev/null; state "Aufzeichnung gestoppt."; echo; echo "Gestoppt."' EXIT
|
||||
trap 'kill $SAMPLER $PINGER 2>/dev/null; pkill -f "ping $PHONE interval=200ms" 2>/dev/null; state "Aufzeichnung gestoppt."; echo; echo "Gestoppt."' EXIT
|
||||
|
||||
echo "Gehweg-Messung laeuft."
|
||||
echo " Funk -> $RUN_DIR/sampler.csv"
|
||||
echo " Ping -> $RUN_DIR/walk-ping.log"
|
||||
echo " Ping -> $RUN_DIR/walk-ping.csv (Quelle: crs326-core)"
|
||||
while true; do touch "$STATE" 2>/dev/null; sleep 5; done
|
||||
|
||||
Reference in New Issue
Block a user