Neu: Dns.kt (eigener DNS-Client auf UDP/53, Aufbau wie Snmp.kt) und das
Werkzeug "DNS-Pruefung". Unterschied zur Internet-Kette: dort antwortet, wen
das System fuer richtig haelt, und der Systemcache liegt dazwischen. Hier geht
je ein Paket an je einen Server aus der Netzkonfiguration - nur so laesst sich
sagen, WELCHER Server hakt, und genau das ist beim Kunden die
Reparaturanweisung ("die Fritzbox antwortet, der zweite DHCP-Eintrag zeigt
ins Leere").
Vier Ausgaenge, bewusst nicht zu "geht/geht nicht" verkuerzt:
ok, unbekannt (NXDOMAIN - ein FUNKTIONIERENDER Server!), ohneAdresse
(SERVFAIL/REFUSED - Stoerung), keineAntwort (Ausfall).
Beim Emulator-Test einen Fehlalarm gefunden und behoben: die erste Fassung
meldete "DNS-Server antworten unterschiedlich", sobald zwei Resolver
verschiedene IPs lieferten. Gegen www.google.de gemessen taten sie das sofort
(10.0.2.3 -> 192.178.24.195, 9.9.9.9 -> 192.178.183.94) - bei jedem CDN normal.
Die Warnung waere bei praktisch jeder Messung gekommen und haette im
Kundendokument eine gelbe Ampel ohne Befund erzeugt. Gewertet wird jetzt nur
noch der Sortenunterschied privat gegen oeffentlich - so sieht Split-Horizon
oder ein Fremd-DNS aus. Beide Antworten stehen ohnehin einzeln im Protokoll.
tools/pruefe-dns.mjs: 10 Bewertungsfaelle plus 10 Adressbereiche fuer
istPrivat() (172.16-31 macht eine naive Zeichenkettenpruefung falsch).
Im Emulator gemessen: 10.0.2.3 und 9.9.9.9 beide befragt und beantwortet;
der Cache-Effekt ist sichtbar (16 ms lokal, 500 ms zu Quad9).
Ausserdem: inputmode fuer die Eingabefelder im ToolDialog ('decimal' bei
Adress-/Netzfeldern, damit die Tastatur einen Punkt hat - mit 'numeric' laesst
sich keine IP eingeben), Autokorrektur und Grossschreibung aus (sonst wird aus
"fritz.box" beim Tippen "Fritz.Box").
Der Debug-Selbsttest uebernimmt jetzt die Vorgabewerte des Werkzeugs - vorher
mass er mit leeren Parametern etwas anderes als der Techniker vor Ort (die
DNS-Pruefung fragte "1 von 1 Servern", weil der Vergleichsserver fehlte).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"SNMP-Switch" stand an jeder IP-Kamera und erzeugte dort zuverlaessig eine
Messung "nicht messbar" im Kundenprotokoll - eine Zeile, die niemandem hilft
und den Abnahmebeleg verwaessert.
Bewusst KEIN hartes Filtern: Device.deviceType ist freier Text aus zwei
unabhaengigen Quellen (Kotlin guessDeviceType, TS typeFromMdns) und wird aus
MAC-Hersteller, mDNS-Diensten und offenen Ports geraten. Ein managed Switch,
der als "Linux-Geraet" durchgeht, verloere beim Filtern ausgerechnet SNMP -
schlimmer als die ueberfluessige Zeile, die wir loswerden wollen. Unpassende
Werkzeuge stehen deshalb nachrangig (kleiner, blasser, mit Titel-Hinweis)
hinter den passenden, statt zu verschwinden. Leerer oder unbekannter Typ:
alles gleichrangig, nie weniger.
Die SNMP-Liste ist absichtlich grosszuegig (Switch, Router, Gateway, NAS,
Drucker, Server, USV, Accesspoint, Firewall) - Drucker sind in der Praxis die
haeufigste SNMP-Quelle ueberhaupt.
tools/pruefe-geraeteaktionen.mjs rechnet 13 Faelle nach und prueft dabei zwei
Zusicherungen: die erwartete Einsortierung UND dass kein Werkzeug verschwindet.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Die haeufigste Aussage beim Kunden ist "Internet geht nicht". Bisher musste
der Techniker Ping, Traceroute und Browser einzeln bedienen und selbst
schlussfolgern, welches Glied hakt. Das Werkzeug misst alle vier Stufen in
einem Lauf und benennt das Fehlerglied.
Neue native Methoden: dnsResolve (System-Resolver; die Grenze - Server nicht
waehlbar, Cache dazwischen - steht im Code und im Ergebnis) und httpsCheck.
Bei httpsCheck ist instanceFollowRedirects=false keine Feinheit, sondern der
Kern: ein Gaeste-WLAN beantwortet jede Anfrage mit einer Umleitung auf sein
Portal. Wer ihr folgt, bekommt ein sauberes 200 und meldet "Internet in
Ordnung", obwohl ohne Anmeldung nichts geht. linkInfo liefert zusaetzlich
NET_CAPABILITY_VALIDATED und _CAPTIVE_PORTAL - Androids eigenes Urteil,
das uns keine einzige Messung kostet.
Drei Entscheidungen fuer die Ehrlichkeit der Aussage:
1. Die Kette bricht nicht ab. Sehr viele Router beantworten Ping
grundsaetzlich nicht - ein Abbruch dort meldete "Gateway tot" bei
voellig gesundem Internet.
2. Eine stille Stufe ist kein Fehler, wenn eine spaetere antwortet. Wer eine
Antwort aus dem Internet bekommt, hat sein Gateway benutzt. Ergebnis:
gruen mit Hinweis statt rot.
3. Anmeldeseite schlaegt Fehlerglied. Sonst stuende im Kundendokument "Kein
Internet - HTTPS antwortet nicht", obwohl der Techniker nur auf "Anmelden"
tippen muss. Beim Pruefen aufgefallen und korrigiert.
Die Bewertung liegt in kette-bewertung.ts ohne jeden Laufzeit-Import, damit
tools/pruefe-kette.mjs sie laden kann: elf konstruierte Faelle gegen von Hand
ermittelte Sollwerte, alle korrekt. Der Browser-Mock liefert fuer DNS und
HTTPS bewusst nur den Gutfall und beweist nichts - das steht dort auch so.
Dabei repariert: tools/pruefe-monitor.mjs importierte eine .mjs-Kopie aus
einem /tmp-Sitzungsverzeichnis und lief nach dessen Wegfall nicht mehr,
waehrend in der ROADMAP "alle Faelle korrekt" stand. Die Rechnung liegt jetzt
in monitor-auswertung.ts, beide Pruefer laden die TS-Datei direkt.
Neu in der Debug-Seite: "Internet-Kette pruefen (misst nur, speichert nichts)".
Beantwortet vor Ort die erste aller Fragen - kommt das Messgeraet selbst ins
Netz? - und ist der einzige Weg, die native Schicht im Emulator zu pruefen,
solange die Testinstanz nur HTTP spricht (der WebView blockiert aus der
Origin https://localhost jede HTTP-Anfrage, siehe ROADMAP).
Im Emulator geprueft: Gutfall (alle vier Stufen mit Messwerten, validated=ja)
und Flugmodus (Status "nicht messbar", Fehlerglied Anschluss, ausdruecklich
KEINE Aussage ueber das Kundennetz).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Port-Schnellprobe um 502 (Modbus) und 515 (LPD) erweitert. 502 ist in diesem
Betrieb der wichtigste Hinweis ueberhaupt - Wechselrichter, Batteriespeicher
und Wallboxen sprechen Modbus/TCP. Die Geraeteart-Heuristik wertet 502 laengst
aus ("IoT/SPS"), der Zweig war nur nachweislich unerreichbar, weil die Sonde
den Port gar nicht geprueft hat. Dasselbe bei 515 fuer Drucker.
Laufzeit vorher/nachher im Emulator gemessen (voller /24): 44,8 s -> 52,0 s,
also +16 % bei 20 % mehr Ports. Proportional und vertretbar.
88 und 8443 bewusst NICHT in die Schnellprobe: sie kommen im Handwerksnetz
praktisch nicht vor, und dieser Pfad laeuft je stiller Adresse in beiden
Runden plus in der Anreicherung. Im Port-Scan auf ein einzelnes Geraet sind
sie dagegen jetzt dabei, ebenso 554 (RTSP) und 9100.
Servicenamen ergaenzt, damit im Protokoll nicht die nackte Portnummer steht.
IP-Test bewertet jetzt die Dose statt nur "IP ja/nein". Das ist der
Elektro-Abnahmebeleg schlechthin: 100 Mbit auf einer Cat-7-Leitung heisst so
gut wie immer, dass zwei Aderpaare nicht aufgelegt sind oder die Dose falsch
geklemmt ist - ein Befund, den der Techniker sofort beheben kann, solange er
noch auf der Leiter steht. Vorher stand dort eine gruene Ampel, weil ja eine
IP da war. Unbekannte Geschwindigkeit ergibt Status 3 statt 0: bei manchen
Android-Versionen ist /sys/class/net/<iface>/speed gesperrt, und eine Abnahme
darf nicht auf einer Angabe beruhen, die es nicht gibt.
"Protokoll loeschen" ist ins Ueberlaufmenue der Kopfzeile gewandert. Es stand
als roter Link unmittelbar ueber dem gruenen "Abschliessen & synchronisieren" -
bei offener Tastatur liegen beide im selben Daumenbereich, und ein Fehlgriff
loescht ein noch nicht synchronisiertes Protokoll unwiederbringlich.
AppHeader hat dafuer ein optionales Snippet bekommen (die Komponente wird auf
zehn Seiten benutzt, das Zahnrad darf durch nichts verdraengt werden). Das
Menue meldet sich als Overlay an, sonst haette der Hardware-Zurueck das
Protokoll verlassen statt das Menue zu schliessen.
Im Emulator geprueft.
Werkzeuge waren zu umstaendlich, um sie beim Kunden wirklich zu benutzen: die
Produktivdaten zeigen 19 Protokolle, aber nur 26 Messungen, fast durchweg ein
einzelner IP-Scan. Der Standardfall "IP-Scan im aktuellen Netz" kostete drei
Tipper, obwohl das einzige Feld ausdruecklich leer bleiben darf.
- Kurzer Tap auf eine Werkzeugkarte startet sofort, langes Halten oeffnet die
Optionen. Auf den betroffenen Karten steht "Tippen startet · Halten fuer
Optionen" - sonst ist das Verhalten unsichtbar und der erste versehentliche
Scan ueberrascht.
- quickRun wird je Werkzeug AUSDRUECKLICH gesetzt, nicht hergeleitet:
ToolParamField kennt kein 'required', die Pflicht steht allein im run()-Rumpf.
portscan.ports hat keinen Vorgabewert und ist optional, iperf.host hat
ebenfalls keinen und ist Pflicht - eine Heuristik ueber "hat Default" wuerde
genau falsch herum raten. iperf bleibt deshalb bewusst ohne Schnellstart.
- Der Lauf bleibt zwingend im ToolDialog: dort sitzen Bildschirmsperre,
Fortschritt mit Abbrechen und die EINZIGE Fehlerbehandlung eines
Werkzeuglaufs (runTool selbst hat kein try/catch). Ein Schnellstart daran
vorbei wuerde Fehler verschlucken.
- Die Vorschau wird nicht uebersprungen, sondern nur ohne Warnung automatisch
durchgewunken. Der IP-Scan warnt ab ~1000 Adressen - genau der Fall, in dem
ein versehentlicher Tap sonst minutenlang das falsche Netz absucht.
- Langdruck bricht ab, sobald der Finger mehr als 10 px wandert: das
Werkzeug-Raster liegt in einem Scroll-Bereich, sonst oeffnet jeder Wisch nach
einer halben Sekunde den Dialog.
- Nach einer Messung wird zum Ergebnis gescrollt und es 2,5 s hervorgehoben.
Bei 46 Geraeten liegt die neue Karte sonst dutzende Bildschirme entfernt.
block:'center', weil die feste Aktionsleiste den unteren Rand verdeckt; bei
einer Geraete-Messung wird die Geraetekarte angesteuert, denn dort hinein
wird gerendert.
- Verwendete Parameter stehen in der Messkarte. Seit dem Schnellstart laeuft
eine Messung auch ohne Dialog - dann ist das der einzige Ort, an dem man
sieht, WOMIT gemessen wurde. Beschriftung aus tool.params, nicht aus der
Ergebnistabelle: 'count' heisst dort "Gefundene Geraete", als Ping-Parameter
aber "Anzahl Pakete".
- Zuletzt benutzte Parameter werden gemerkt (neues Modul toolparams.ts).
Ortsgebundene Schluessel wie 'subnet' ausdruecklich NICHT: ein aus dem
vorigen Kundennetz uebernommener Netzbereich waere schlimmer als gar keiner,
der Schnellstart wuerde stillschweigend das falsche Netz scannen.
Im Emulator geprueft, und dabei zwei Fehler gefunden, die im Code nicht
auffielen: die Parameterzeile wiederholte "Ziel: 8.8.8.8" direkt ueber dem
Ergebnis (jetzt werden Werte ausgelassen, die das Ergebnis ohnehin nennt), und
Traceroute schrieb "1 Hops" ins Kundendokument (jetzt "1 Station").
Bisher fand der IP-Scan Geräte nur per ICMP-Ping; ein Windows-PC mit aktiver
Firewall (Ping blockiert, Ports offen) fiel komplett durch. Kein Fortschritt
während des Laufs, kein Abbrechen, kein Hinweis was gescannt wird.
Nativ (NetDiagScannerPlugin.kt):
- Mehrgleisige Suche: gefunden bei Ping ODER Port-Probe ODER ARP-Tabellen-
Eintrag. Runde 1 über alle Adressen, ARP-Abgleich, Runde 2 NUR für die
weiterhin stillen Adressen, ARP erneut abgleichen.
- startIpScan()/cancelIpScan() statt eines einzigen langen ipScan()-Promise:
läuft als Lauf mit Live-Events (ipScanProgress/ipScanFinished), Abbruch
liefert das bis dahin gefundene Teilergebnis statt nichts.
- Eigener limitedParallelism(128)-Dispatcher, damit ein großer Sweep keinen
gleichzeitigen Ping/Monitor/Dauertest ausbremst.
- arpAvailable ehrlich über File.canRead() statt "Tabelle war halt leer".
- mDNS-Budget 4s -> 9s, Discovery/Auflösung entkoppelt (eigene Nachlaufzeit),
discoveryOk meldet einen echten Suchfehler statt stiller 0 Treffer.
App:
- scanner.ts: neue Events onIpScanProgress/onIpScanFinished.
- ipscan.ts: protocolPatch statt direktem Beschreiben von ctx.protocol;
fehlgeschlagener Scan erzeugt jetzt auch eine Messung (Status 2 statt
nichts); "neu"/"nicht mehr erreichbar" als Diagnosefelder.
- ToolDialog: generischer Vorschau-Schritt (tool.preview — Adapter, eigene
IP, Gateway, Adressenzahl; ab >1024 Adressen Bestätigung "Trotzdem
scannen") und Live-Fortschritt (tool.supportsProgress — Fortschrittsbalken,
laufende Trefferliste, Abbrechen). Beide Mechanismen sind generisch für
alle Tools nutzbar, nicht IP-Scan-spezifisch fest verdrahtet.
- DeviceCard zeigt den Fundweg ("via Ping/Port/ARP/mDNS") als Badge.
- Geräteliste numerisch nach IP sortiert (Favoriten weiter zuerst).
Im Emulator getestet (nicht nur Codereview): ICMP per iptables zu einem
Ziel geblockt, nur TCP/22 offen -> Gerät korrekt "via Port" gefunden.
/24 zweimal komplett gescannt: gleiche 4 Geräte, zweiter Lauf ohne "neu".
/20 (4094 Adressen) löst die Bestätigung korrekt aus. Abbrechen mitten im
Lauf liefert sauber ein Teilergebnis. Sync nach Dolibarr per DB-Query
verifiziert.
Dabei zwei echte Bugs gefunden, die reines Codereview nicht gefunden hätte:
Fortschritt zeigte "504 von 254" (Runde 2 zählte im Zähler von Runde 1
weiter), und das native Feld hieß "gefundenVia" statt "foundVia" wie von
der TS-Seite erwartet — der Fundweg kam nie an.
Details: ROADMAP_UMSETZUNG.md Phase 3
Kompletter Umbau (ROADMAP_UMSETZUNG.md Phase 2). Die alte Fassung hatte vier
Probleme, die den Test praktisch wertlos machten: kein festes Intervall (ein
"Messpunkt" dauerte so lange wie das Ziel zufaellig antwortete — Prod #126:
38 Punkte in 300 s statt der ueblichen ~250-300), keine Zeitreihe (nur
Summen), kein Foreground-Service trotz gegenteiliger Doku-Behauptung, kein
Abbruchpfad. Vor allem aber: waehrend der 1-60 Minuten sah man nichts ausser
"Messung laeuft ...".
Nativ (NetDiagScannerPlugin.kt, MonitorService.kt)
StressRun komplett neu: feste Taktung per naechstem Fixpunkt (nextTick +=
intervalSec*1000, kein Zeitverzug ueber eine Stunde), Rohzaehler
(sentTotal/receivedTotal/rttSum/Min/Max) + echte Zeitreihe (Liste aus
{ts,rtt}), Ausfallsegmente werden waehrend des Laufs erkannt und
geschlossen. Laeuft im MonitorService (Foreground, wie der Geraete-Monitor)
— dafuer wurde der Dienst auf eine Job-Registry umgestellt (jobId -> Text),
damit ein gleichzeitig laufender Geraete-Monitor und Dauertest sich beim
Beenden nicht gegenseitig die Benachrichtigung wegnehmen.
Events stressSample (live, pro Probe) und stressFinished (einmalig, Grund
completed/stopped) + getStressStatus zur Wiederaufnahme nach Seitenwechsel.
WICHTIG geloest: laeuft der Test natuerlich aus, waehrend niemand zuhoert
(App im Hintergrund, andere Seite offen), bleibt der Lauf-Eintrag in
stressRuns bestehen (wie monitorRuns) statt sofort geloescht zu werden —
sonst waere das Ergebnis unwiederbringlich weg. Neuer Aufraeum-Call
dismissStressRun.
Nebenbei: der geteilte io-Scope aller Plugin-Methoden lief bisher auf einem
gewoehnlichen Job — eine unbehandelte Exception in EINER Coroutine (z.B.
IP-Scan mit kaputtem Host) haette strukturell alle Geschwister-Coroutinen
mitgerissen, auch einen parallel laufenden Monitor/Dauertest. Jetzt
SupervisorJob + CoroutineExceptionHandler.
Kritischer Bug gefunden UND gefixt (im Emulator, echter Netzausfall-Test):
`.put("rtt", rtt as Any?)` mit Kotlin null wird von org.json.JSONObject
behandelt wie `remove(key)` — der Schluessel verschwindet komplett statt
als JSON null anzukommen. Die App bekam damit `undefined` statt `null` fuer
verlorene Proben; `!== null`-Filter hielten das faelschlich fuer "erhalten".
Ergebnis: ein per Flugmodus ausgeloester echter Ausfall zeigte live "0 %
Verlust" und "NaN ms" bei Min/Max/Oe. Betraf NUR die Live-Anzeige — die
gespeicherte Messung war unabhaengig davon korrekt, weil buildStressResult()
ausschliesslich aus dem nativen Kotlin-Zustand rechnet, nie ueber die
Pro-Probe-JSON-Bruecke. Fix: ueberall explizit JSONObject.NULL statt bloss
`null` (betraf auch die Traceroute-Korrektur aus Phase 1). Zusaetzlich
TS-seitig als zweite Verteidigungslinie `!= null` statt `!== null` (deckt
sowohl null als auch undefined ab).
Neu: gemeinsame Bewertung (tools/rating.ts)
ping.ts und der alte Dauertest bewerteten denselben Netzzustand
unterschiedlich (ping.ts: avgMs>100 -> Rot; Dauertest: nur lossPct/maxMs).
rateLatency() ist jetzt die einzige Stelle: Verlust, Jitter, Latenz nach
Zielklasse (LAN/WLAN/WAN) UND eine eigene Regel "jeder Ausfall > 5 s = Rot"
unabhaengig vom Gesamt-Verlustprozentsatz. ping.ts umgestellt, unveraendertes
Verhalten fuer die bisherigen Schwellen (inkl. Jitter>10ms, das beim
Portieren fast uebersehen wurde).
Neue Route statt Dialog (routes/protokoll/[id]/stresstest/)
Wie IP-Test/WLAN/Monitor eine eigene Seite statt des blockierenden
Werkzeug-Dialogs. Einrichtung (Ziel leer=Gateway, Dauer, Takt) mit
Vorlaufprobe wie zuvor in stresstest.ts. Laufend: grosse Live-Zahl mit
Ampelfarbe (rateLatency), Fortschrittsbalken mit Restzeit, Streifendiagramm
(StressChart.svelte, live rollierendes 120s-Fenster), Zaehler
gesendet/verloren/Ø/Min/Max, offener-Ausfall-Banner, Ereignisliste mit
Uhrzeit ("Ausfall — wieder da nach 16 s"), Abbrechen. Abgeschlossene Laeufe
darunter aufklappbar mit demselben Diagramm (kompletter Verlauf statt
Fenster). stresstest.ts (Tool-Registry-Eintrag) ist jetzt nur noch
Namens-Lookup fuer die Messungen-Liste, run() wirft bewusst einen Fehler,
falls doch noch etwas den alten Weg aufruft.
Sicherheitsnetz gegen verpasste Events (lib/stresstest.ts)
Ein natuerlich beendeter Test, waehrend niemand auf der Stresstest-Seite
ist, verpasst dort das stressFinished-Event. Die Hauptprotokollseite prueft
deshalb beim Oeffnen zusaetzlich per resumeFinishedStressSessions() nach
(praktisch immer besucht, bevor ein Protokoll abgeschlossen wird) und
traegt das Ergebnis nach. Bekannter Rest-Fall (dokumentiert): verlaesst der
Techniker das Protokoll komplett ohne eine der beiden Seiten noch einmal zu
oeffnen, bleibt der fertige Lauf bis zum naechsten Besuch liegen.
Ergebnis-Speicherung: Zeitreihe in 1-Minuten-Buckets + Ausfallsegmente +
laengster Ausfall als Measurement (tool=stresstest, sync-faehig) — Ausfaelle
werden beim Abschliessen mit dem nativen (autoritativen) Ergebnis abgeglichen,
nicht nur mit der lokal live mitgefuehrten Kopie.
Getestet im Emulator (Pixel 6 / Android 14):
- 1-Minuten-Lauf komplett bei ausgeschaltetem Display durchgelaufen
(Foreground-Service haelt den Prozess), automatischer Abschluss + Toast
- Echter Netzausfall per Flugmodus (15s) waehrend laufendem 5-Minuten-Test:
korrekt 23,2%/16,7% Verlust, Min/Max ohne NaN, Ereignisliste mit exakter
Uhrzeit und Dauer — nach dem NULL-Fix verifiziert
- Abbrechen-Pfad: sofortiger Stopp, korrektes Teil-Ergebnis
- Wiederaufnahme: laufender Test nach APK-Neuinstallation (Prozess-Kill)
korrekt als beendet erkannt
- gradle compileDebugKotlin ok, svelte-check 0 Fehler
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Vier Werkzeuge haben nachweislich Unsinn ins Kundenprotokoll geschrieben. Belege
sind echte Prod-Messungen; jeder Fix wurde im Emulator gegen den passenden
Fehlerfall nachgestellt.
SNMP (Snmp.kt, snmp.ts)
Snmp.get lieferte bei JEDEM Problem null -> "-" -> parseInt("-")||0 -> 0.
Ein Switch, der gar nicht antwortet, stand damit als "0 Fehler" in Gruen im
Kunden-PDF (Prod #95/#96). Neu: Ergebnistyp Value/Timeout/Failure statt
String?, Request-ID- und error-status-Pruefung, v2c-Ausnahmen (0x80/0x81/0x82)
erkannt, ein Wiederholversuch bei Timeout. Das Werkzeug meldet jetzt
"nicht messbar" statt Zahlen zu erfinden.
Test: SNMP gegen einen Host ohne Agent -> status 3 "keine SNMP-Antwort".
Traceroute (pingWithTtl, traceroute.ts)
Der Fallback-Regex \((\d+\.\d+\.\d+\.\d+)\) traf IMMER zuerst die ping-Kopfzeile
"PING 8.8.8.8 (8.8.8.8) ...". Ein stummer Hop wurde dadurch als Ziel ausgegeben
und der Trace beendet — daher "2 Hops bis 8.8.8.8, beide 0 ms" (Prod #13).
Zwischen-Hops liefern zudem nie ein time=, die Zeit war strukturell 0.
Neu: Kopfzeile verworfen, zeilenweise geparst, Reverse-DNS-Antworten erkannt,
RTT selbst per nanoTime gestoppt, 3 Proben je TTL, waitFor(3s)+destroyForcibly,
"keine Antwort" ist null und nicht 0, Bewertung haengt an "Ziel erreicht".
Test: 8.8.8.8 -> 1 Hop mit echten 13,3 ms (statt 0 ms);
192.0.2.1 -> status 3, alle Hops "* (keine Antwort)" statt gruen.
Ping (measurePing, ping.ts)
Kein WifiLock, keine Aufwaermproben: zwischen den Proben schlief das Funkmodul
ein, die Aufwachzeit landete in der Messung — 296 ms zum LAN-Gateway bei 0 %
Verlust und rotem Status (Prod #4). WAKE_LOCK fehlte im Manifest, weshalb
WifiLock.acquire() eine SecurityException warf, die ein leerer catch schluckte.
Neu: WAKE_LOCK im Manifest, WifiLock (LOW_LATENCY) + PARTIAL_WAKE_LOCK um jede
Messung, 2 verworfene Aufwaermproben, Median und Messaufschlag (avg-min)
zusaetzlich ausgewiesen, Verlust als Kommazahl statt Ganzzahl-Division,
Bewertung auf den Median statt den Mittelwert, "keine Antwort" != "0 ms".
Test: 20 Proben -> Median 0,3 ms, Messaufschlag 0,1 ms, Verfahren dokumentiert.
Durchsatz (measureThroughput, iperf.ts)
Kein soTimeout: nahm die Gegenstelle an, ohne zu senden, blockierte read()
unbegrenzt und das Werkzeug-Fenster hing dauerhaft auf "Messung laeuft ...".
Neu: soTimeout 4 s je Phase, harter withTimeout-Guard, Ist-Zeit statt
angenommener halber Dauer, measured-Flag — ohne uebertragene Bytes gibt es
kein rotes "0 Mbit/s" mehr, sondern "nicht messbar".
Test: Gegenstelle nimmt an und schweigt -> Ergebnis nach 30 s statt Dauerhaenger.
Netzerkennung (firstLocalIpv4, getLocalSubnet, hostsInSubnet)
firstLocalIpv4() gab bei fehlendem Netz hart "192.168.1.1" zurueck; zusammen mit
dem Praefix-Fallback /24 entstand das Phantom-Netz 192.168.1.0/24, das auch noch
ins Protokoll geschrieben wurde. Der Fehlerzweig in ipscan.ts konnte deshalb nie
greifen. Neu: "" statt Phantom-IP, Link-Local uebersprungen, getLocalSubnet
meldet einen Fehler, DHCP-Fallback nur bei WLAN-Transport (sonst wurde bei
gestecktem USB-RJ45 die Maske aus dem WLAN genommen), unlesbares CIDR-Praefix
wird abgelehnt statt still durch /24 ersetzt.
Test: Flugmodus -> "Kein Netzbereich — WLAN/LAN nicht aktiv?" statt Phantom-Netz.
Stresstest-Ziel (stresstest.ts)
Vorgabe 192.168.1.1 im Kundennetz 192.168.178.0/24 -> 5 Minuten ins Leere
gemessen, Ergebnis "100 % Verlust" rot im Protokoll (Prod #126). Neu: kein
fester Vorgabewert, leer = Gateway des aktiven Adapters, und eine Vorlaufprobe
bricht ab, bevor minutenlang gegen ein totes Ziel gemessen wird.
Test: Ziel 192.168.1.1 -> nach 7 s "antwortet nicht — Test nicht gestartet"
(vorher: 60 s Messung mit rotem 100-%-Ergebnis).
Neue Bewertung "nicht messbar" (MeasureStatus 3)
Bisher gab es nur ok/warn/fail. Ein Test, der gar nicht durchgefuehrt werden
konnte, musste sich als eines davon ausgeben — meist als Gruen. Status 3 wird
neutral grau dargestellt (Messkarte und Geraetekarte) und ist keine Aussage
ueber das Kundennetz.
Geprueft: gradle compileDebugKotlin ok, svelte-check 0 Fehler (2 vorbestehende
Warnungen), alle sieben Faelle im Emulator (Pixel 6 / Android 14) durchgespielt
und die Ergebnisse in der Datenbank gegengelesen statt am Bildschirm geraten.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Aufraeumen vor den eigentlichen Korrekturen — ohne Verhaltensaenderung am Code.
Doppelte Plugin-Quelle:
Die drei Kotlin-Dateien lagen byte-identisch in native-plugin/ UND in
android/app/src/main/java/de/data_it_solution/netdiag/. Gebaut wurde immer nur die
Kopie unter android/ — eine Aenderung an der falschen Datei sah deshalb aus wie
"der Fix wirkt nicht". native-plugin/ enthaelt jetzt nur noch die Anleitung, die
auf den echten Ort verweist.
Doku sagte drei Dinge, die nicht stimmen:
- stresstest.ts behauptete "laeuft nativ als Foreground-Service". Tut es nicht —
im Plugin steht an der Stelle nur ein Kommentar, dass man einen ergaenzen
sollte. Bei ausgeschaltetem Display friert Android den Lauf ein.
- iperf.ts/scanner.ts/README nannten den Durchsatztest "iperf-kompatibel". Er
spricht kein iperf3-Protokoll (kein Cookie, kein Parameterblock) und scheitert
gegen einen echten iperf3-Server.
- ipscan.ts beschrieb sich als "ARP + Ping + Namen". Gefunden wird nur, wer auf
Ping antwortet oder sich per mDNS meldet; die ARP-Tabelle wird lediglich
nachgeschlagen und ist ab Android 10 meist gar nicht lesbar.
Statt der falschen Zusagen stehen dort jetzt die tatsaechlichen Grenzen plus
Verweis auf die Phase, die sie behebt.
README: DHCP-Check und WLAN-Scan als Werkzeuge entfernt (sind nicht mehr in
tools/index.ts registriert, tauchen aber in alten Protokollen noch auf).
Geprueft: vite build ok, svelte-check 0 Fehler (2 vorbestehende Warnungen).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
IP-Test: USB-RJ45-Adapter in Netzwerkdose stecken und sofort IP-Adresse,
DHCP-Server, Gateway und Link-Geschwindigkeit (10/100/1000 Mbit) ablesen.
Auto-Refresh alle 2 s, Speichern mit optionalem Raum/Dose-Name ins Protokoll.
WLAN-Empfangstracker: Netz auswählen und beim Durchgehen live RSSI verfolgen.
Hybrid-Modus: 500 ms Polling bei verbundenem Netz (kein Scan-Throttling),
~30 s Scan-Sweep bei Fremd-BSSID. Sessions mit Samples, Min/Max/Avg und
Sparkline-Verlauf werden im Protokoll gespeichert.
Ersetzt DHCP-Info-Tool und WLAN-Scan-Tool (eigene Routen /iptest/ + /wifi/).
Kotlin-Plugin: linkInfo(), startWifiScan(), startWifiTrack/stop/status().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- arpConflictScan (Plugin): pingt das Subnetz über mehrere Runden und liest
je Runde die ARP-Tabelle; mehrere MACs pro IP = Konflikt. Kein Root nötig
- Erkennt den Fall, dass /proc/net/arp nicht lesbar ist (Android-Limit) und
meldet das ehrlich, statt fälschlich Entwarnung zu geben
- ipconflict.ts: neues Protokoll-Tool, in der Tool-Registry eingetragen —
listet betroffene IPs samt der konkurrierenden MAC-Adressen
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- NetBIOS-Namensabfrage (UDP 137) je Host integriert
- mdnsScan: neue Plugin-Methode, mDNS/Bonjour via NsdManager — findet
Drucker, Kameras, Chromecast, AirPlay; liefert Namen + Diensttypen
- Quick-Port-Probe (22/80/443/554/9100 …) speist eine deviceType-Heuristik
(Kamera, Drucker, Router, Switch, NAS, Wallbox, Server …)
- OUI-Vendor-Tabelle von 6 auf ~150 kuratierte Einträge erweitert
- ipscan.ts führt IP-Scan + mDNS pro IP zusammen, mDNS-only-Geräte ergänzt
- neue DeviceCard-Komponente: zeigt Geräteart-Badge, offene Ports,
mDNS-Dienste, mac, NetBIOS-Name; ersetzt die Inline-Geräteliste
- upsertDevice überschreibt vorhandene Daten nicht mehr mit undefined
(Favorit/eigener Name bleiben bei magerem Re-Scan erhalten)
- Manifest: CHANGE_WIFI_MULTICAST_STATE für die mDNS-Suche
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Auftragsliste: Kundenname + Adresse sind jetzt die Überschrift, die
Auftragsnummer nur noch Kleingedrucktes — Aufträge sind so ohne
Nummer-im-Kopf wiederzufinden. Auftragsnotiz wird mit angezeigt.
IP-Scanner: ist kein Netzbereich angegeben, nutzt das Tool den im
Protokoll hinterlegten; ist auch der leer, fragt es den aktiven
WLAN-/LAN-Adapter ab und scannt dessen Subnetz. Der ermittelte
Netzbereich wird ins Protokoll übernommen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>