Commit graph

16 commits

Author SHA1 Message Date
2f7b1c91a4 DNS-Pruefung: eigener UDP-Client fragt jeden Server namentlich
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>
2026-08-16 23:24:32 +02:00
7d79358c02 Geraete-Aktionen nach Geraetetyp sortieren statt sie zu verstecken
"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>
2026-08-16 23:14:06 +02:00
460b85d708 Internet-Kette: Anschluss, Gateway, Namensaufloesung und HTTPS in einem Lauf
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>
2026-08-16 22:56:20 +02:00
0fe938a764 Modbus/LPD in der Schnellprobe, Dosen-Bewertung, Loeschen ins Ueberlaufmenue
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.
2026-08-16 19:27:33 +02:00
85e68ca528 Schnellstart, Sprung zum Ergebnis und Parametergedaechtnis
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").
2026-08-16 19:09:19 +02:00
8b369fc3bc Phase 3: IP-Scanner komplett überarbeitet — mehrgleisige Suche, Live-Fortschritt
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
2026-08-15 12:47:28 +02:00
34589f12d1 Phase 2: Dauertest komplett neu — Live-Ansicht, fester Takt, Foreground-Service
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>
2026-08-15 00:39:36 +02:00
240d65d534 Phase 1: Messverfahren liefern keine falschen Aussagen mehr
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>
2026-08-14 19:16:17 +02:00
881ca7956f Phase 0: doppelte Plugin-Quelle aufgeloest, falsche Doku-Zusagen korrigiert
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>
2026-08-14 18:39:40 +02:00
3c95ff6b07 Phase 6: IP-Test (Dose prüfen) und WLAN-Empfangstracker [apk]
All checks were successful
Build APK / build-apk (push) Successful in 1m49s
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>
2026-05-20 10:03:25 +02:00
9ee9c954b2 Neues Werkzeug: IP-Konflikt-Prüfung
- 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>
2026-05-19 23:00:32 +02:00
1a0f1dc5ca IP-Scan: Geräte deutlich umfassender erkennen
- 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>
2026-05-19 22:42:25 +02:00
53d91d1526 Bugfixes: IP-Scanner, DHCP, Aufträge, Messergebnisse [apk]
All checks were successful
Build APK / build-apk (push) Successful in 1m41s
- IP-Scanner: ConnectivityManager.getLinkProperties statt hartcodiertem /24 –
  erkennt jetzt das echte Subnetz inkl. Prefix-Länge und Gateway
- DHCP: dhcpDiscover durch dhcpInfo ersetzt (liest WifiManager.dhcpInfo,
  kein Root nötig) – zeigt Server, Gateway, Lease-Zeit, DNS
- Aufträge: tms-Feld ergänzt, Order by tms DESC – "zuletzt bearbeitet" zuerst;
  Checkbox-Logik invertiert (Standard: alle Aufträge, Haken = nur aktive)
- MeasurementResult-Komponente: Arrays (WLAN-Netze, Traceroute-Hops) als
  echte Liste statt Komma-String; Skalare kompakt in einer Zeile
- Traceroute: 5 aufeinanderfolgende Timeouts → Abbruch statt endlos warten
- tools/types.ts: MeasureStatus exportiert (behebt 5 Svelte-Check-Fehler)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 22:02:46 +02:00
c81871f010 IP-Scan instrumentiert: loggt Eingabe-Subnetz vs. gescanntes Subnetz
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 19:49:49 +02:00
Eduard Wisch
27dae2ce50 Auftragsliste nach Kunde+Ort, IP-Scanner mit Adapter-Erkennung
All checks were successful
Build APK / build-apk (push) Has been skipped
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>
2026-05-19 12:57:19 +02:00
Eduard Wisch
bf01b4cd21 Initiales Commit — NetDiag App vollständig implementiert [apk]
Some checks failed
Build APK / build-apk (push) Failing after 11m29s
SvelteKit + Capacitor 6 Netzwerk-Diagnose-App:
- Tool-Plattform (IP-Scan, Port, Ping, WLAN, DHCP, SNMP, Traceroute, Stresstest, iperf)
- Offline-First SQLite-Cache + idempotenter Dolibarr-Sync
- Natives Kotlin-Plugin NetDiagScanner (ARP, Ping, Ports, WLAN, DHCP, SNMP, Traceroute)
- Backbutton-Single-Instance-Modul, Auto-Updater, Toast-System
- Auftrags-/Kunden-Übersicht nach Baustellen-App-Muster
- CI: [apk]-Tag → Forgejo Runner → Package Registry netdiag-apk

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:01:56 +02:00