Compare commits
4 commits
36dd18f53a
...
8f23d417a3
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f23d417a3 | |||
| 2c5f7cf11b | |||
| 0f37cae9e5 | |||
| b2ab430ae7 |
5 changed files with 300 additions and 14 deletions
68
ChangeLog.md
68
ChangeLog.md
|
|
@ -1,5 +1,73 @@
|
||||||
# Changelog NetDiag
|
# Changelog NetDiag
|
||||||
|
|
||||||
|
## 1.1.5 — 2026-08-16
|
||||||
|
|
||||||
|
### Feldtabelle für das neue Werkzeug „DNS-Prüfung"
|
||||||
|
|
||||||
|
Die App fragt jeden DNS-Server des Netzes einzeln und namentlich (eigener
|
||||||
|
UDP-Client auf Port 53). Damit die Aussage im Kundendokument ankommt, sind
|
||||||
|
`gefragteServer` und `antworten` in der Whitelist ergänzt und `dnscheck` in
|
||||||
|
der Werkzeugliste eingetragen — ohne diese drei Zeilen stünde dort nur die
|
||||||
|
Ampel. Die einzelnen Serverzeilen („192.168.1.1: antwortet, kennt den Namen
|
||||||
|
nicht") sind das eigentliche Ergebnis.
|
||||||
|
|
||||||
|
## 1.1.4 — 2026-08-16
|
||||||
|
|
||||||
|
### Drei Falschaussagen im Kundendokument, alle aus Altdaten
|
||||||
|
|
||||||
|
- **„0 DHCP-Server (!)" in Rot.** In der Produktionsdatenbank stehen drei
|
||||||
|
ausgelieferte Messungen des entfernten Werkzeugs `dhcpcheck` mit Ergebnis
|
||||||
|
`{"count":0,"server":[],"hinweis":""}` und Status 2. Bei einer Kabelverbindung
|
||||||
|
gibt Android die DHCP-Angaben aber grundsätzlich nicht heraus (nur `DhcpInfo`,
|
||||||
|
nur WLAN, deprecated) — gemessen wurde also nichts, „0 gefunden" war der
|
||||||
|
Rückgabewert für „nicht ermittelbar". `netdiagAltlastKorrektur()` zeigt diese
|
||||||
|
Messungen jetzt als „nicht messbar" mit Erklärung, in PDF **und**
|
||||||
|
Technikeransicht. Die gespeicherten Rohdaten bleiben unangetastet (Beleg);
|
||||||
|
korrigiert wird nur die Darstellung, und die wird bei jedem Abruf neu erzeugt.
|
||||||
|
Die Ergebniszahlen werden bei so korrigierten Messungen unterdrückt —
|
||||||
|
„Gefundene Geräte: 0" widerspräche der Aussage direkt darüber.
|
||||||
|
- **„Lease-Dauer: 864000 s s".** Ältere App-Fassungen haben die Einheit in den
|
||||||
|
Wert geschrieben, die Feldtabelle hängt sie erneut an. Nachgewiesen an
|
||||||
|
Prod-Messung #42. Die Einheit wird jetzt nur noch angehängt, wenn sie nicht
|
||||||
|
schon am Wert steht.
|
||||||
|
- **Adress- und Lease-Felder mit dem Wert 0** (`server`, `dhcpServer`,
|
||||||
|
`gateway`, `ipv4`, `lease` …) sind keine Messung, sondern das „nichts
|
||||||
|
ermittelt" der alten Android-API. Sie erscheinen jetzt als „nicht ermittelbar"
|
||||||
|
statt als „0".
|
||||||
|
|
||||||
|
Neues Feld in der Whitelist: `dhcpQuelle` — `system` (LinkProperties, ab
|
||||||
|
Android 11, gilt für jeden Anschlusstyp) oder `wlan` (alter Weg, nur WLAN, dafür
|
||||||
|
mit Lease-Dauer). Damit ist im Nachhinein klärbar, ob eine fehlende DHCP-Angabe
|
||||||
|
an der Leitung lag oder an der Android-Version.
|
||||||
|
|
||||||
|
## 1.1.3 — 2026-08-16
|
||||||
|
|
||||||
|
### Internet-Kette im PDF + ein Zeichenfehler, der jedes Protokoll betraf
|
||||||
|
|
||||||
|
- **`netdiagPdfKette()`** für das neue App-Werkzeug „Internet-Kette": Fehlerglied
|
||||||
|
als eigene hervorgehobene Zeile, darunter die vier geprüften Stufen einzeln,
|
||||||
|
dann Systemurteil und Hinweis. Ohne eigenen Zweig stünden die Stufen als
|
||||||
|
`|`-Kette in einer Zelle und das Fehlerglied — die eigentliche Aussage —
|
||||||
|
mittendrin.
|
||||||
|
- **`netdiagPdfText()`: Pfeile wurden als „?" gedruckt.** `pdf_getPDFFont()`
|
||||||
|
liefert hier Helvetica, einen Core-Font mit WinAnsi-Kodierung; alles außerhalb
|
||||||
|
dieses Zeichenvorrats setzt TCPDF wortlos als „?" (bekannt aus KB #1025).
|
||||||
|
Aufgefallen an „www.google.de → 142.250.185.67", das im Kundendokument als
|
||||||
|
„www.google.de ? 142.250.185.67" ankam — der Pfeil ist dort kein Schmuck,
|
||||||
|
er trennt Frage und Antwort. Die Ersetzung greift jetzt in **allen**
|
||||||
|
PDF-Zweigen, also auch für Altdaten und künftige Werkzeuge.
|
||||||
|
Bewusst keine Unicode-Schrift: `dejavusans` würde Schriftbild und Dateigröße
|
||||||
|
aller Protokolle ändern. Gedankenstrich, Mittelpunkt, Auslassungspunkte und
|
||||||
|
Anführungszeichen sind in WinAnsi enthalten und bleiben unangetastet
|
||||||
|
(im erzeugten Dokument nachgeprüft).
|
||||||
|
- Feld-Whitelist um `fehlerglied`, `stufen`, `systemUrteil`, `validated` und
|
||||||
|
`captivePortal` erweitert, Werkzeugname `internetkette` → „Internet-Kette".
|
||||||
|
`validated`/`captivePortal` kommen aus dem LinkInfo-Objekt und erscheinen
|
||||||
|
damit auch beim IP-Test an der Dose.
|
||||||
|
|
||||||
|
Geprüft an vier Fällen gegen die lokale Testinstanz, zwei davon sind die echten
|
||||||
|
Emulator-Messungen dieser Nacht (Gutfall und Flugmodus).
|
||||||
|
|
||||||
## 1.1.2 — 2026-08-16
|
## 1.1.2 — 2026-08-16
|
||||||
|
|
||||||
### Geräte-Monitor bekommt einen eigenen PDF-Zweig
|
### Geräte-Monitor bekommt einen eigenen PDF-Zweig
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ class modNetDiag extends DolibarrModules
|
||||||
$this->editor_url = '';
|
$this->editor_url = '';
|
||||||
$this->editor_squarred_logo = '';
|
$this->editor_squarred_logo = '';
|
||||||
|
|
||||||
$this->version = '1.1.2';
|
$this->version = '1.1.5';
|
||||||
|
|
||||||
// Konstanten-Name in llx_const für Modul-Status
|
// Konstanten-Name in llx_const für Modul-Status
|
||||||
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
|
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
|
||||||
|
|
|
||||||
|
|
@ -345,6 +345,19 @@ function netdiagKundenfelder()
|
||||||
'aussetzer' => array('Aussetzer', ''),
|
'aussetzer' => array('Aussetzer', ''),
|
||||||
'geraete' => array('Je Gerät', ''),
|
'geraete' => array('Je Gerät', ''),
|
||||||
'ausfaelle' => array('Einzelne Ausfälle', ''),
|
'ausfaelle' => array('Einzelne Ausfälle', ''),
|
||||||
|
// Internet-Kette (Anschluss → Gateway → Namensauflösung → HTTPS).
|
||||||
|
// 'fehlerglied' ist die eigentliche Aussage des Werkzeugs — ohne diesen
|
||||||
|
// Eintrag stünde im Kundendokument nur die Ampel.
|
||||||
|
'fehlerglied' => array('Fehlerglied', ''),
|
||||||
|
'stufen' => array('Geprüfte Stufen', ''),
|
||||||
|
'systemUrteil' => array('Urteil des Betriebssystems', ''),
|
||||||
|
// Kommen aus dem LinkInfo-Objekt und damit auch im IP-Test (Dose) vor
|
||||||
|
'validated' => array('Internetverbindung bestätigt', ''),
|
||||||
|
'captivePortal' => array('Anmeldeseite erkannt', ''),
|
||||||
|
// DNS-Prüfung: je ein Paket an je einen Server. `antworten` ist die
|
||||||
|
// eigentliche Aussage — welcher Server antwortet und welcher nicht.
|
||||||
|
'gefragteServer' => array('Befragte DNS-Server', ''),
|
||||||
|
'antworten' => array('Antworten der Server', ''),
|
||||||
// Netz/DHCP
|
// Netz/DHCP
|
||||||
'server' => array('DHCP-Server', ''),
|
'server' => array('DHCP-Server', ''),
|
||||||
'lease' => array('Lease-Dauer', 's'),
|
'lease' => array('Lease-Dauer', 's'),
|
||||||
|
|
@ -385,6 +398,9 @@ function netdiagKundenfelder()
|
||||||
'ipv4' => array('IP-Adresse', ''),
|
'ipv4' => array('IP-Adresse', ''),
|
||||||
'prefixLength' => array('Präfixlänge', ''),
|
'prefixLength' => array('Präfixlänge', ''),
|
||||||
'dhcpServer' => array('DHCP-Server', ''),
|
'dhcpServer' => array('DHCP-Server', ''),
|
||||||
|
// 'system' = vom Betriebssystem gemeldet (gilt für jeden Anschlusstyp),
|
||||||
|
// 'wlan' = alter WLAN-Weg. Macht einen fehlenden Wert einordenbar.
|
||||||
|
'dhcpQuelle' => array('Quelle der DHCP-Angabe', ''),
|
||||||
'leaseSec' => array('Lease-Dauer', 's'),
|
'leaseSec' => array('Lease-Dauer', 's'),
|
||||||
'linkSpeedMbps' => array('Verbindungsgeschwindigkeit', 'Mbit/s'),
|
'linkSpeedMbps' => array('Verbindungsgeschwindigkeit', 'Mbit/s'),
|
||||||
'rxLinkSpeedMbps' => array('Empfangsgeschwindigkeit', 'Mbit/s'),
|
'rxLinkSpeedMbps' => array('Empfangsgeschwindigkeit', 'Mbit/s'),
|
||||||
|
|
@ -422,6 +438,51 @@ function netdiagKundenfelder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bekannte Falschaussagen aus Altmessungen bei der Anzeige geraderücken.
|
||||||
|
*
|
||||||
|
* Betrifft das entfernte Werkzeug `dhcpcheck`. In der Produktionsdatenbank
|
||||||
|
* stehen drei ausgelieferte Messungen mit dem Label „0 DHCP-Server (!)",
|
||||||
|
* Ergebnis `{"count":0,"server":[],"hinweis":""}` und **Status 2 (rot)** — eine
|
||||||
|
* Aussage über das Kundennetz, welche die Messung nie hergab: bei einer
|
||||||
|
* Kabelverbindung gibt Android die DHCP-Lease grundsätzlich nicht heraus (sie
|
||||||
|
* steckt nur im deprecated `DhcpInfo` und nur für WLAN). Gemessen wurde also
|
||||||
|
* nichts; „0 gefunden" ist der Rückgabewert für „nicht ermittelbar".
|
||||||
|
*
|
||||||
|
* Korrigiert wird bei der **Anzeige**, nicht in der Datenbank: die gespeicherte
|
||||||
|
* Messung bleibt unangetastet (Rohdaten sind Beleg), aber jedes neu erzeugte
|
||||||
|
* Kundendokument zeigt statt der roten Ampel ein ehrliches „nicht messbar".
|
||||||
|
*
|
||||||
|
* @param string $tool Werkzeug-ID der Messung
|
||||||
|
* @param int $status gespeicherter Status
|
||||||
|
* @param string $label gespeichertes Label
|
||||||
|
* @param string $json gespeichertes Ergebnis-JSON
|
||||||
|
* @return array{status:int,label:string,hinweis:string} korrigierte Anzeige
|
||||||
|
*/
|
||||||
|
function netdiagAltlastKorrektur($tool, $status, $label, $json)
|
||||||
|
{
|
||||||
|
$out = array('status' => (int) $status, 'label' => (string) $label, 'hinweis' => '');
|
||||||
|
if ($tool !== 'dhcpcheck') {
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
$data = json_decode((string) $json, true);
|
||||||
|
if (!is_array($data)) {
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
$leer = (isset($data['count']) && (int) $data['count'] === 0)
|
||||||
|
&& (!isset($data['server']) || $data['server'] === array() || $data['server'] === '');
|
||||||
|
if (!$leer) {
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
$out['status'] = 3; // nicht messbar
|
||||||
|
$out['label'] = 'DHCP-Server nicht ermittelbar';
|
||||||
|
$out['hinweis'] = 'Diese Messung stammt aus einer früheren App-Fassung. Bei einer '
|
||||||
|
.'Kabelverbindung gibt Android die DHCP-Angaben nicht heraus — es wurde also nichts '
|
||||||
|
.'gemessen. Die frühere Darstellung („0 DHCP-Server") las sich wie ein Befund über '
|
||||||
|
.'das Kundennetz und war keiner.';
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sekundenwert lesbar machen (aus „8123456" wird „94 Tage 0 Std").
|
* Sekundenwert lesbar machen (aus „8123456" wird „94 Tage 0 Std").
|
||||||
*
|
*
|
||||||
|
|
@ -490,11 +551,36 @@ function netdiagFeldFuerKunde($key, $val)
|
||||||
return null; // nicht ermittelt — lieber weglassen als „: " drucken
|
return null; // nicht ermittelt — lieber weglassen als „: " drucken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adressfelder mit dem Wert 0 bzw. 0.0.0.0 sind KEINE Messung, sondern der
|
||||||
|
* Rückgabewert „nichts ermittelt" der alten Android-API. In ausgelieferten
|
||||||
|
* Protokollen steht deshalb „DHCP-Server: 0" — eine Angabe, die es so im
|
||||||
|
* Kundennetz nie gab, und bei einer Kabelverbindung schlicht der Umstand,
|
||||||
|
* dass Android die Lease dort gar nicht herausgibt (nur WLAN, deprecated).
|
||||||
|
* Rückwirkend wirksam: Protokoll-PDFs werden bei jedem Abruf neu erzeugt.
|
||||||
|
* Lease-Dauer 0 fällt in dieselbe Kategorie.
|
||||||
|
*/
|
||||||
|
$adressfelder = array('server', 'dhcpServer', 'gateway', 'dns', 'ipv4', 'ip');
|
||||||
|
if (in_array($key, $adressfelder, true) && ($val === 0 || $val === '0' || $val === '0.0.0.0')) {
|
||||||
|
return $label.': nicht ermittelbar';
|
||||||
|
}
|
||||||
|
if (in_array($key, array('lease', 'leaseSec'), true) && ($val === 0 || $val === '0')) {
|
||||||
|
return $label.': nicht ermittelbar';
|
||||||
|
}
|
||||||
|
|
||||||
// Sekundenwerte lesbar machen statt sechsstellige Zahlen zu drucken
|
// Sekundenwerte lesbar machen statt sechsstellige Zahlen zu drucken
|
||||||
if ($einheit === 's' && is_numeric($val) && $val >= 3600) {
|
if ($einheit === 's' && is_numeric($val) && $val >= 3600) {
|
||||||
return $label.': '.netdiagDauerLesbar($val);
|
return $label.': '.netdiagDauerLesbar($val);
|
||||||
}
|
}
|
||||||
$text = netdiagKundentext((string) $val);
|
$text = netdiagKundentext((string) $val);
|
||||||
|
/*
|
||||||
|
* Einheit nicht doppelt anhängen. Ältere App-Fassungen haben sie in den
|
||||||
|
* Wert geschrieben („864000 s"); im Kundendokument stand dadurch
|
||||||
|
* „Lease-Dauer: 864000 s s". Nachgewiesen an der Prod-Messung #42.
|
||||||
|
*/
|
||||||
|
if ($einheit !== '' && preg_match('/\s'.preg_quote($einheit, '/').'$/u', $text)) {
|
||||||
|
return $label.': '.$text;
|
||||||
|
}
|
||||||
return $label.': '.$text.($einheit !== '' ? ' '.$einheit : '');
|
return $label.': '.$text.($einheit !== '' ? ' '.$einheit : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,10 +646,12 @@ function netdiagToolName($tool)
|
||||||
'traceroute' => 'Traceroute',
|
'traceroute' => 'Traceroute',
|
||||||
'stresstest' => 'Dauer-/Stresstest',
|
'stresstest' => 'Dauer-/Stresstest',
|
||||||
'iperf' => 'Durchsatz-Test',
|
'iperf' => 'Durchsatz-Test',
|
||||||
|
'internetkette' => 'Internet-Kette',
|
||||||
'wifikanal' => 'WLAN-Kanalanalyse',
|
'wifikanal' => 'WLAN-Kanalanalyse',
|
||||||
'monitor' => 'Geräte-Monitor',
|
'monitor' => 'Geräte-Monitor',
|
||||||
'iptest' => 'IP-Test (Dose)',
|
'iptest' => 'IP-Test (Dose)',
|
||||||
'wifitrack' => 'WLAN-Empfang',
|
'wifitrack' => 'WLAN-Empfang',
|
||||||
|
'dnscheck' => 'DNS-Prüfung',
|
||||||
// nicht mehr vorhandene Werkzeuge, aber in Altprotokollen enthalten
|
// nicht mehr vorhandene Werkzeuge, aber in Altprotokollen enthalten
|
||||||
'dhcpcheck' => 'DHCP-Prüfung',
|
'dhcpcheck' => 'DHCP-Prüfung',
|
||||||
'wifiscan' => 'WLAN-Scan',
|
'wifiscan' => 'WLAN-Scan',
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,11 @@ function netdiagGeneratePdf($db, $protocol, $outputlangs)
|
||||||
// stünde im PDF doppelt "OK OK".
|
// stünde im PDF doppelt "OK OK".
|
||||||
$statusmarks = array(0 => '', 1 => '! ', 2 => 'X ', 3 => '? ');
|
$statusmarks = array(0 => '', 1 => '! ', 2 => 'X ', 3 => '? ');
|
||||||
foreach ($measurements as $m) {
|
foreach ($measurements as $m) {
|
||||||
$st = (int) $m->measure_status;
|
// Bekannte Falschaussagen aus Altmessungen geraderücken (siehe
|
||||||
|
// netdiagAltlastKorrektur() — betrifft das entfernte Werkzeug dhcpcheck,
|
||||||
|
// dessen „0 DHCP-Server (!)" in Rot in ausgelieferten Protokollen steht).
|
||||||
|
$korr = netdiagAltlastKorrektur($m->tool, $m->measure_status, $m->label, $m->result);
|
||||||
|
$st = (int) $korr['status'];
|
||||||
if ($st < 0 || $st > 3) {
|
if ($st < 0 || $st > 3) {
|
||||||
$st = 1; // unbekannter Wert -> als Warnung behandeln, nie als OK
|
$st = 1; // unbekannter Wert -> als Warnung behandeln, nie als OK
|
||||||
}
|
}
|
||||||
|
|
@ -182,24 +186,40 @@ function netdiagGeneratePdf($db, $protocol, $outputlangs)
|
||||||
netdiagPdfEnsureSpace($pdf, 11);
|
netdiagPdfEnsureSpace($pdf, 11);
|
||||||
$pdf->SetFont('', 'B', 9);
|
$pdf->SetFont('', 'B', 9);
|
||||||
// Klarname statt interner ID — „ipscan" sagt dem Kunden nichts
|
// Klarname statt interner ID — „ipscan" sagt dem Kunden nichts
|
||||||
$title = netdiagToolName($m->tool).($m->label ? ' — '.$m->label : '');
|
$title = netdiagToolName($m->tool).($korr['label'] ? ' — '.$korr['label'] : '');
|
||||||
$pdf->Cell(150, 6, dol_trunc($title, 80), 1, 0, 'L');
|
$pdf->Cell(150, 6, dol_trunc($title, 80), 1, 0, 'L');
|
||||||
$pdf->Cell(30, 6, $statusmarks[$st].$statuslabels[$st], 1, 1, 'C', true);
|
$pdf->Cell(30, 6, $statusmarks[$st].$statuslabels[$st], 1, 1, 'C', true);
|
||||||
$pdf->SetFont('', '', 8);
|
$pdf->SetFont('', '', 8);
|
||||||
// Messparameter: ohne sie steht das Ergebnis ohne Bezug da — man sieht
|
// Messparameter: ohne sie steht das Ergebnis ohne Bezug da — man sieht
|
||||||
// nicht, gegen welches Ziel gemessen wurde (Prod-Messung #126).
|
// nicht, gegen welches Ziel gemessen wurde (Prod-Messung #126).
|
||||||
|
if ($korr['hinweis'] !== '') {
|
||||||
|
$pdf->SetFont('', 'I', 7);
|
||||||
|
$pdf->MultiCell(180, 4, netdiagPdfText($korr['hinweis']), 1, 'L');
|
||||||
|
$pdf->SetFont('', '', 8);
|
||||||
|
}
|
||||||
$params = netdiagFormatParams($m->params);
|
$params = netdiagFormatParams($m->params);
|
||||||
if ($params !== '') {
|
if ($params !== '') {
|
||||||
$pdf->SetFont('', 'I', 7);
|
$pdf->SetFont('', 'I', 7);
|
||||||
$pdf->MultiCell(180, 4, $params, 1, 'L');
|
$pdf->MultiCell(180, 4, netdiagPdfText($params), 1, 'L');
|
||||||
$pdf->SetFont('', '', 8);
|
$pdf->SetFont('', '', 8);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Bei einer als Altlast korrigierten Messung KEINE Zahlen mehr drucken:
|
||||||
|
* „Gefundene Geräte: 0 | DHCP-Server: keine" widerspricht der Aussage
|
||||||
|
* „nicht messbar" direkt darüber und liest sich wieder wie ein Befund.
|
||||||
|
* Der Erklärtext steht bereits hinter der Titelzeile.
|
||||||
|
*/
|
||||||
|
if ($korr['hinweis'] !== '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ($m->tool === 'stresstest') {
|
if ($m->tool === 'stresstest') {
|
||||||
netdiagPdfStressTest($pdf, $m->result);
|
netdiagPdfStressTest($pdf, $m->result);
|
||||||
} elseif ($m->tool === 'wifikanal') {
|
} elseif ($m->tool === 'wifikanal') {
|
||||||
netdiagPdfWifiKanal($pdf, $m->result);
|
netdiagPdfWifiKanal($pdf, $m->result);
|
||||||
} elseif ($m->tool === 'monitor') {
|
} elseif ($m->tool === 'monitor') {
|
||||||
netdiagPdfMonitor($pdf, $m->result);
|
netdiagPdfMonitor($pdf, $m->result);
|
||||||
|
} elseif ($m->tool === 'internetkette') {
|
||||||
|
netdiagPdfKette($pdf, $m->result);
|
||||||
} else {
|
} else {
|
||||||
$pdf->MultiCell(180, 5, netdiagPdfFlattenResult($m->result), 1, 'L');
|
$pdf->MultiCell(180, 5, netdiagPdfFlattenResult($m->result), 1, 'L');
|
||||||
}
|
}
|
||||||
|
|
@ -222,6 +242,48 @@ function netdiagGeneratePdf($db, $protocol, $outputlangs)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zeichen ersetzen, die der PDF-Standardzeichensatz nicht darstellen kann.
|
||||||
|
*
|
||||||
|
* `pdf_getPDFFont()` liefert in dieser Dolibarr-Installation Helvetica — einen
|
||||||
|
* Core-Font mit WinAnsi-Kodierung, kein Unicode. Alles außerhalb dieses Vorrats
|
||||||
|
* druckt TCPDF als „?", ohne zu warnen (bekannt aus KB #1025, dort mit dem
|
||||||
|
* Ankreuzkästchen ☐).
|
||||||
|
*
|
||||||
|
* Aufgefallen am Pfeil in der Internet-Kette: aus
|
||||||
|
* „Namensauflösung: www.google.de → 142.250.185.67" wurde im Kundendokument
|
||||||
|
* „www.google.de ? 142.250.185.67" — der Pfeil ist dort kein Schmuck, er
|
||||||
|
* trennt Frage und Antwort.
|
||||||
|
*
|
||||||
|
* Bewusst eine Ersetzung statt einer Unicode-Schrift: `dejavusans` würde jedes
|
||||||
|
* Zeichen können, aber Schriftbild und Dateigröße aller Protokolle ändern.
|
||||||
|
* Gedankenstrich, Mittelpunkt, Auslassungspunkte und Anführungszeichen sind in
|
||||||
|
* WinAnsi enthalten und bleiben unangetastet (im Dokument nachgeprüft).
|
||||||
|
*
|
||||||
|
* @param string $s Text aus der App oder aus Altdaten
|
||||||
|
* @return string druckbarer Text
|
||||||
|
*/
|
||||||
|
function netdiagPdfText($s)
|
||||||
|
{
|
||||||
|
return strtr((string) $s, array(
|
||||||
|
'→' => '->',
|
||||||
|
'←' => '<-',
|
||||||
|
'↔' => '<->',
|
||||||
|
'⇒' => '=>',
|
||||||
|
'✓' => 'ja',
|
||||||
|
'✔' => 'ja',
|
||||||
|
'✗' => 'nein',
|
||||||
|
'✘' => 'nein',
|
||||||
|
'≤' => '<=',
|
||||||
|
'≥' => '>=',
|
||||||
|
'≠' => '!=',
|
||||||
|
'☐' => '[ ]',
|
||||||
|
'☑' => '[x]',
|
||||||
|
'⚠' => '!',
|
||||||
|
'≈' => 'ca. ',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mess-Ergebnis (JSON) als einzeiligen Text für PDF-Ausgabe.
|
* Mess-Ergebnis (JSON) als einzeiligen Text für PDF-Ausgabe.
|
||||||
*
|
*
|
||||||
|
|
@ -235,7 +297,7 @@ function netdiagPdfFlattenResult($json)
|
||||||
}
|
}
|
||||||
$data = json_decode($json, true);
|
$data = json_decode($json, true);
|
||||||
if (!is_array($data)) {
|
if (!is_array($data)) {
|
||||||
return netdiagKundentext((string) $json);
|
return netdiagPdfText(netdiagKundentext((string) $json));
|
||||||
}
|
}
|
||||||
$parts = array();
|
$parts = array();
|
||||||
foreach ($data as $key => $val) {
|
foreach ($data as $key => $val) {
|
||||||
|
|
@ -244,7 +306,7 @@ function netdiagPdfFlattenResult($json)
|
||||||
$parts[] = $feld;
|
$parts[] = $feld;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return empty($parts) ? '-' : implode(' | ', $parts);
|
return empty($parts) ? '-' : netdiagPdfText(implode(' | ', $parts));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -369,7 +431,69 @@ function netdiagPdfStressTest($pdf, $json)
|
||||||
$pdf->Cell(180, 5, 'Ausfälle ('.count($ausfaelle).')', 1, 1, 'L');
|
$pdf->Cell(180, 5, 'Ausfälle ('.count($ausfaelle).')', 1, 1, 'L');
|
||||||
$pdf->SetFont('', '', 8);
|
$pdf->SetFont('', '', 8);
|
||||||
foreach ($ausfaelle as $line) {
|
foreach ($ausfaelle as $line) {
|
||||||
$pdf->Cell(180, 5, dol_trunc((string) $line, 120), 1, 1, 'L');
|
$pdf->Cell(180, 5, dol_trunc(netdiagPdfText($line), 120), 1, 1, 'L');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internet-Kette ins PDF schreiben: Fehlerglied zuerst, dann die Stufen.
|
||||||
|
*
|
||||||
|
* Ohne eigenen Zweig stünden die vier Stufen als `|`-Kette in einer Zelle und
|
||||||
|
* das Fehlerglied — die eigentliche Aussage — mittendrin. Beim Kunden wird
|
||||||
|
* genau diese eine Zeile gelesen: „woran liegt es".
|
||||||
|
*
|
||||||
|
* @param TCPDF $pdf PDF-Objekt (Cursor steht direkt hinter der Titelzeile)
|
||||||
|
* @param string $json result-JSON der Messung
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function netdiagPdfKette($pdf, $json)
|
||||||
|
{
|
||||||
|
$data = json_decode((string) $json, true);
|
||||||
|
if (!is_array($data)) {
|
||||||
|
$pdf->MultiCell(180, 5, netdiagPdfFlattenResult($json), 1, 'L');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fehlerglied als eigene, hervorgehobene Zeile
|
||||||
|
$glied = isset($data['fehlerglied']) ? trim((string) $data['fehlerglied']) : '';
|
||||||
|
if ($glied !== '') {
|
||||||
|
$pdf->SetFont('', 'B', 8);
|
||||||
|
$pdf->Cell(180, 5, $glied === 'keines'
|
||||||
|
? 'Kein Glied der Kette hat versagt.'
|
||||||
|
: 'Fehlerglied: '.$glied, 1, 1, 'L');
|
||||||
|
$pdf->SetFont('', '', 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stufen = (isset($data['stufen']) && is_array($data['stufen'])) ? $data['stufen'] : array();
|
||||||
|
if (!empty($stufen)) {
|
||||||
|
netdiagPdfEnsureSpace($pdf, 10);
|
||||||
|
$pdf->SetFont('', 'B', 8);
|
||||||
|
$pdf->Cell(180, 5, 'Geprüfte Stufen', 1, 1, 'L');
|
||||||
|
$pdf->SetFont('', '', 8);
|
||||||
|
foreach ($stufen as $line) {
|
||||||
|
netdiagPdfEnsureSpace($pdf, 5, function ($p) {
|
||||||
|
$p->SetFont('', 'B', 8);
|
||||||
|
$p->Cell(180, 5, 'Geprüfte Stufen — Fortsetzung', 1, 1, 'L');
|
||||||
|
$p->SetFont('', '', 8);
|
||||||
|
});
|
||||||
|
// MultiCell statt Cell: die Stufenzeilen enthalten Fehlertexte des
|
||||||
|
// Systems („Unable to resolve host …"), die auch mal lang werden.
|
||||||
|
// Abschneiden würde ausgerechnet die Begründung kappen.
|
||||||
|
$pdf->MultiCell(180, 5, netdiagPdfText(netdiagKundentext((string) $line)), 1, 'L');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($data['systemUrteil'])) {
|
||||||
|
netdiagPdfEnsureSpace($pdf, 8);
|
||||||
|
$pdf->SetFont('', 'I', 7);
|
||||||
|
$pdf->MultiCell(180, 4, netdiagPdfText(netdiagKundentext((string) $data['systemUrteil'])), 1, 'L');
|
||||||
|
$pdf->SetFont('', '', 8);
|
||||||
|
}
|
||||||
|
if (!empty($data['hinweis'])) {
|
||||||
|
netdiagPdfEnsureSpace($pdf, 8);
|
||||||
|
$pdf->SetFont('', 'I', 7);
|
||||||
|
$pdf->MultiCell(180, 4, netdiagPdfText(netdiagKundentext((string) $data['hinweis'])), 1, 'L');
|
||||||
|
$pdf->SetFont('', '', 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,7 +525,7 @@ function netdiagPdfMonitor($pdf, $json)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!empty($data['fehler']) || !empty($data['error'])) {
|
if (!empty($data['fehler']) || !empty($data['error'])) {
|
||||||
$pdf->MultiCell(180, 5, netdiagKundentext((string) ($data['fehler'] ?? $data['error'])), 1, 'L');
|
$pdf->MultiCell(180, 5, netdiagPdfText(netdiagKundentext((string) ($data['fehler'] ?? $data['error']))), 1, 'L');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -448,7 +572,7 @@ function netdiagPdfMonitor($pdf, $json)
|
||||||
$p->Cell(180, 5, 'Überwachte Geräte ('.count($geraete).') — Fortsetzung', 1, 1, 'L');
|
$p->Cell(180, 5, 'Überwachte Geräte ('.count($geraete).') — Fortsetzung', 1, 1, 'L');
|
||||||
$p->SetFont('', '', 8);
|
$p->SetFont('', '', 8);
|
||||||
});
|
});
|
||||||
$pdf->Cell(180, 5, dol_trunc((string) $line, 120), 1, 1, 'L');
|
$pdf->Cell(180, 5, dol_trunc(netdiagPdfText($line), 120), 1, 1, 'L');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -483,7 +607,7 @@ function netdiagPdfMonitor($pdf, $json)
|
||||||
$p->Cell(180, 5, 'Einzelne Ausfälle ('.count($ausfaelle).') — Fortsetzung', 1, 1, 'L');
|
$p->Cell(180, 5, 'Einzelne Ausfälle ('.count($ausfaelle).') — Fortsetzung', 1, 1, 'L');
|
||||||
$p->SetFont('', '', 8);
|
$p->SetFont('', '', 8);
|
||||||
});
|
});
|
||||||
$pdf->Cell(180, 5, dol_trunc((string) $line, 120), 1, 1, 'L');
|
$pdf->Cell(180, 5, dol_trunc(netdiagPdfText($line), 120), 1, 1, 'L');
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
$rest = count($ausfaelle) - $max;
|
$rest = count($ausfaelle) - $max;
|
||||||
|
|
@ -499,7 +623,7 @@ function netdiagPdfMonitor($pdf, $json)
|
||||||
if (!empty($data['hinweis'])) {
|
if (!empty($data['hinweis'])) {
|
||||||
netdiagPdfEnsureSpace($pdf, 10);
|
netdiagPdfEnsureSpace($pdf, 10);
|
||||||
$pdf->SetFont('', 'I', 7);
|
$pdf->SetFont('', 'I', 7);
|
||||||
$pdf->MultiCell(180, 4, netdiagKundentext((string) $data['hinweis']), 1, 'L');
|
$pdf->MultiCell(180, 4, netdiagPdfText(netdiagKundentext((string) $data['hinweis'])), 1, 'L');
|
||||||
$pdf->SetFont('', '', 8);
|
$pdf->SetFont('', '', 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -558,7 +682,7 @@ function netdiagPdfWifiKanal($pdf, $json)
|
||||||
|
|
||||||
if (!empty($data['warnungen']) && is_array($data['warnungen'])) {
|
if (!empty($data['warnungen']) && is_array($data['warnungen'])) {
|
||||||
foreach ($data['warnungen'] as $w) {
|
foreach ($data['warnungen'] as $w) {
|
||||||
$pdf->MultiCell(180, 5, '! '.dol_trunc((string) $w, 160), 1, 'L');
|
$pdf->MultiCell(180, 5, '! '.dol_trunc(netdiagPdfText($w), 160), 1, 'L');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,10 @@ print '<th>'.$langs->trans("Tool").'</th><th>'.$langs->trans("Label").'</th>';
|
||||||
print '<th>'.$langs->trans("Result").'</th><th class="center">'.$langs->trans("MeasureStatus").'</th>';
|
print '<th>'.$langs->trans("Result").'</th><th class="center">'.$langs->trans("MeasureStatus").'</th>';
|
||||||
print '</tr>';
|
print '</tr>';
|
||||||
foreach ($measurements as $m) {
|
foreach ($measurements as $m) {
|
||||||
$st = (int) $m->measure_status;
|
// Dieselbe Korrektur wie im PDF, damit Technikeransicht und Kundendokument
|
||||||
|
// nicht auseinanderlaufen (netdiagAltlastKorrektur(), Werkzeug dhcpcheck).
|
||||||
|
$korr = netdiagAltlastKorrektur($m->tool, $m->measure_status, $m->label, $m->result);
|
||||||
|
$st = (int) $korr['status'];
|
||||||
// Unbekannte Werte nie als OK durchgehen lassen (Array-Zugriff waere sonst leer)
|
// Unbekannte Werte nie als OK durchgehen lassen (Array-Zugriff waere sonst leer)
|
||||||
if ($st < 0 || $st > 3) {
|
if ($st < 0 || $st > 3) {
|
||||||
$st = 1;
|
$st = 1;
|
||||||
|
|
@ -261,7 +264,10 @@ foreach ($measurements as $m) {
|
||||||
print '<td class="nowraponall">'.dol_print_date($m->date_measure, 'dayhour').'</td>';
|
print '<td class="nowraponall">'.dol_print_date($m->date_measure, 'dayhour').'</td>';
|
||||||
print '<td>'.dol_escape_htmltag($m->category).'</td>';
|
print '<td>'.dol_escape_htmltag($m->category).'</td>';
|
||||||
print '<td>'.dol_escape_htmltag(netdiagToolName($m->tool)).'</td>';
|
print '<td>'.dol_escape_htmltag(netdiagToolName($m->tool)).'</td>';
|
||||||
print '<td>'.dol_escape_htmltag($m->label);
|
print '<td>'.dol_escape_htmltag($korr['label']);
|
||||||
|
if ($korr['hinweis'] !== '') {
|
||||||
|
print '<br><span class="opacitymedium small">'.dol_escape_htmltag($korr['hinweis']).'</span>';
|
||||||
|
}
|
||||||
// Messparameter darunter: sonst ist nicht erkennbar, wogegen gemessen wurde
|
// Messparameter darunter: sonst ist nicht erkennbar, wogegen gemessen wurde
|
||||||
$params = netdiagFormatParams($m->params);
|
$params = netdiagFormatParams($m->params);
|
||||||
if ($params !== '') {
|
if ($params !== '') {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue