Commit graph

5 commits

Author SHA1 Message Date
39a0507f99 Phase 4: WLAN-Kanalanalyse — Kanalgraph, Kanalempfehlung, Momentaufnahmen
Bisher zeigte die App nur eine Liste sichtbarer Netze ohne Kanalgraph, ohne
Empfehlung und ohne Möglichkeit, einen Kanalwechsel vorher/nachher zu
vergleichen. Fester 800-ms-Sleep statt auf den echten Scan zu warten, keine
Reaktion auf ausgeschaltete Ortung, Standortberechtigung auch dort nötig, wo
Android 13+ das gar nicht mehr verlangt.

Nativ (NetDiagScannerPlugin.kt):
- wifiScan liefert jetzt frequency, widthMhz, centerFreq0/1, standard
  (Wi-Fi 4/5/6/7), security (offen/WEP/WPA/WPA2/WPA3), ageMs, band
  (inkl. 6 GHz) je Netz. freqToChannel() um das 6-GHz-Band erweitert
  (inkl. Sonderfall Kanal 2/PSC).
- wifiScan({trigger:true}) löst einen frischen Scan aus und wartet auf
  SCAN_RESULTS_AVAILABLE_ACTION (5s Zeitgrenze) statt blind zu schlafen.
- isLocationEnabled()-Prüfung + openLocationSettings(): ausgeschaltete
  Ortung (< Android 13) ergibt jetzt einen Klartextfehler mit direktem
  Weg zu den Einstellungen statt einer stillen leeren Liste.
- NEARBY_WIFI_DEVICES (API 33+, neverForLocation) statt Standortrecht —
  eigenes Berechtigungs-Alias, wifiScanPermissionAlias() wählt je nach
  SDK-Version; gilt für wifiScan/startWifiScan/startWifiTrack gemeinsam.

App:
- WifiChannelChart.svelte: Kanalgraph 2,4/5/6 GHz als Inline-SVG — Bögen
  mit Kanalbreite als Bogenbreite, Signalstärke als Bogenhöhe, Überlapp
  (Co-/Adjacent-Channel) direkt als sichtbare Farbverdichtung.
- wifi/recommend.ts: beste der drei nicht überlappenden 2,4-GHz-Kanäle
  nach Störlast + zwei feste Warnregeln (40 MHz im 2,4-GHz-Band,
  160 MHz/DFS im 5-GHz-Band).
- wifi/rating.ts: rssiRating() vereinheitlicht — ersetzt drei Kopien mit
  unterschiedlichen Schwellen (iptest/+page.svelte, wifi/+page.svelte
  zweimal).
- Neue Route /protokoll/{id}/wifikanal/ + Werkzeug-Kachel "WLAN-Kanäle":
  Netzliste nach SSID gruppiert (Mesh), Momentaufnahmen speichern
  (protocol.wifiSurveys, nur lokal), automatischer Kanaländerungs-Hinweis
  seit der letzten Aufnahme, Zeitverlauf mehrerer Netze aus den
  gespeicherten Momentaufnahmen (echte Zeitstempel, feste Y-Skala
  -100..-20 dBm, Messlücken reißen die Linie statt sie zu überbrücken).

Im Emulator getestet (API 33+): NEARBY_WIFI_DEVICES-Berechtigungsdialog
erscheint und wird korrekt verarbeitet — echte Bestätigung, kein
Codereview-only. Leerer Netz-Zustand rendert sauber. Der AVD hat keine
echte WLAN-Hardware (liefert grundsätzlich 0 Scan-Ergebnisse) — Kanalgraph
mit echten Netzen und der Ortung-aus-Zweig (<Android 13, auf diesem API-33-
AVD unerreichbar) konnten deshalb nicht live geprüft werden, nur die
Chart-Mathematik gegen die Mock-Werte durchgerechnet (keine NaN/Werte
außerhalb des Zeichenbereichs). Sollte auf einem echten Handy mit echtem
WLAN-Empfang gegengeprüft werden.

Details: ROADMAP_UMSETZUNG.md Phase 4
2026-08-15 16:16:15 +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
d2df3ee929 Neues Werkzeug: Geräte-Monitor (Dauerüberwachung) [apk]
All checks were successful
Build APK / build-apk (push) Successful in 1m47s
Für das Kamera-Problem: mehrere Geräte auswählen und ihre Erreichbarkeit
über längere Zeit überwachen — jeder Ausfall wird mit Uhrzeit protokolliert.

- MonitorService: schlanker Vordergrund-Dienst, hält den Prozess am Leben,
  damit die Überwachung bei Display aus / App-Wechsel weiterläuft
- Plugin startMonitor/stopMonitor/getMonitorStatus: pingt die Geräte im
  gewählten Intervall, Wechsel erreichbar↔weg erzeugt ein monitorEvent;
  WifiLock gegen WLAN-Schlaf, Heads-up-Benachrichtigung bei Ausfall
- Monitor-Seite (protokoll/[id]/monitor): Geräte-Mehrfachauswahl,
  Intervallwahl, Live-Ereignisliste, frühere Überwachungen mit Ausfallzahl
- Überwachung läuft beim Verlassen der Seite weiter; Rückkehr nimmt den
  Stand wieder auf (getMonitorStatus)
- Manifest: MonitorService + FOREGROUND_SERVICE_DATA_SYNC, POST_NOTIFICATIONS
- Kachel "Geräte-Monitor" im Werkzeuge-Raster

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 23:12:26 +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
27581cd080 android/ fest ins Repo aufgenommen — Build wie beim Adressmanager [apk]
All checks were successful
Build APK / build-apk (push) Successful in 5m25s
Der android-Ordner wurde bisher bei JEDEM CI-Lauf neu erzeugt (cap add android)
und Kotlin/MainActivity/Plugin jedes Mal frisch reingepatcht — genau das war die
Ursache der ganzen Kotlin-Build-Fehler.

Jetzt liegt android/ einmal sauber eingerichtet im Repo:
- kotlin-android-Plugin aktiviert (1.9.24, jvmTarget 17)
- NetDiagScannerPlugin.kt + Snmp.kt + MainActivity.kt (registriert das Plugin)
- AndroidManifest mit allen noetigen Permissions
- Signing-Config in app/build.gradle (Werte aus gradle.properties)

build.yml entschlackt: nur noch npm install, vite build, cap sync, gradle.
Build-Artefakte bleiben per .gitignore aussen vor.

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