dolibarr.netdiag/core/modules/modNetDiag.class.php
Eduard Wisch 90cbee6e81 Geraete-Monitor: eigener PDF-Zweig statt einer Sammelzelle
Die Dauerueberwachung lief im generischen else-Zweig und wurde von
netdiagPdfFlattenResult() zu EINER |-getrennten Zeile zusammengeschoben.
Bei zehn ueberwachten Geraeten standen damit die zehn Geraete-Zeilen und
saemtliche Einzelausfaelle in einer einzigen Tabellenzelle - vollstaendig,
aber beim Kunden nicht lesbar. Dauertest und WLAN-Kanal hatten laengst je
einen Tabellen-Renderer, der Monitor nicht.

netdiagPdfMonitor() gibt jetzt aus: Kennzahlenzeile, Tabelle "Ueberwachte
Geraete", Tabelle "Einzelne Ausfaelle" mit Uhrzeiten, Hinweis zum
Messverfahren am Schluss. Tabellenkoepfe wiederholen sich nach einem
Seitenumbruch.

Die Falle dabei, gegen die im Code ein Kommentar steht: beim Dauertest
fuehrt ein gesetztes 'hinweis' zum sofortigen Abbruch der Ausgabe. Der
Monitor legt aber IMMER einen Hinweis an (das Messverfahren gehoert zur
Aussage dazu) - derselbe Aufbau haette hier bei jedem Lauf alle Zahlen
verschluckt. Nur 'fehler' bricht ab.

Obergrenze 200 Ausfallzeilen gegen ein im Sekundentakt flappendes Geraet.
Gekuerzt wird sichtbar ("... und N weitere Ausfaelle") - stilles Kuerzen
waere bei einem Abnahmebeleg eine Falschaussage.

Ausserdem: 'ausfallzeitSek' heisst jetzt "Ausfallzeit (schlechtestes
Geraet)". Der Wert ist der des schlechtesten Geraets, nicht die Summe -
bei zehn Geraeten las sich "Ausfallzeit: 8 min" wie eine Gesamtaussage.

Geprueft gegen die lokale Testinstanz mit vier konstruierten Faellen
(10 Geraete mit Aussetzern, ein durchgehend totes Geraet, 250 Ausfaelle
ueber sechs Seiten, abgerissener Lauf) und gegen die echte Monitor-
Messung aus ND2026-0016. PDF gerendert und angesehen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 22:22:02 +02:00

240 lines
7.7 KiB
PHP

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \defgroup netdiag Modul NetDiag
* \brief NetDiag Modul-Descriptor — Netzwerk-Diagnose-Protokolle.
* \file htdocs/custom/netdiag/core/modules/modNetDiag.class.php
* \ingroup netdiag
* \brief Beschreibungs- und Aktivierungsdatei für das Modul NetDiag
*/
include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php';
/**
* Beschreibungs- und Aktivierungsklasse für das Modul NetDiag
*
* NetDiag speichert Netzwerk-Diagnose-Protokolle (IP-Scan, Port-Scan, Ping,
* WLAN, DHCP, SNMP, Durchsatz, Stresstest) und hängt sie an Kunde und Auftrag.
* Die JSON-API unter /custom/netdiag/api/ versorgt die mobile Diagnose-App.
*/
class modNetDiag extends DolibarrModules
{
/**
* Konstruktor. Definiert Namen, Konstanten, Verzeichnisse, Rechte, Menüs.
*
* @param DoliDB $db Datenbank-Handler
*/
public function __construct($db)
{
global $conf, $langs;
$this->db = $db;
// Eindeutige Modul-ID — 500300 frei (500100 belegt globalnotify, 500200 stundenzettel)
$this->numero = 500300;
// Schlüsseltext zur Identifikation (Rechte, Menüs, ...)
$this->rights_class = 'netdiag';
// Familie: 'technic' = transversales/technisches Modul
$this->family = "technic";
$this->module_position = '90';
// Modul-Label (ohne Leerzeichen), Fallback wenn Übersetzung 'ModuleNetDiagName' fehlt
$this->name = preg_replace('/^mod/i', '', get_class($this));
// Modulbeschreibung, Fallback wenn Übersetzung 'ModuleNetDiagDesc' fehlt
$this->description = "ModuleNetDiagDesc";
$this->descriptionlong = "Netzwerk-Diagnose-Protokolle: erfasst per mobiler App Geräte, Ports, Messungen und hängt sie an Kunde und Auftrag.";
// Autor
$this->editor_name = 'Alles Watt läuft';
$this->editor_url = '';
$this->editor_squarred_logo = '';
$this->version = '1.1.2';
// Konstanten-Name in llx_const für Modul-Status
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
// Icon (Font-Awesome)
$this->picto = 'fa-network-wired';
// Vom Modul unterstützte Funktionen
$this->module_parts = array(
'triggers' => 0,
'login' => 0,
'substitutions' => 0,
'menus' => 0,
'tpl' => 0,
'barcode' => 0,
'models' => 1,
'printing' => 0,
'theme' => 0,
'css' => array(),
'js' => array(),
'hooks' => array(),
'moduleforexternal' => 0,
'websitetemplates' => 0,
'captcha' => 0,
);
// Datenverzeichnisse, die beim Aktivieren angelegt werden
$this->dirs = array("/netdiag/temp");
// Konfigurationsseiten (in netdiag/admin)
$this->config_page_url = array("setup.php@netdiag");
// Abhängigkeiten
$this->hidden = false;
$this->depends = array();
$this->requiredby = array();
$this->conflictwith = array();
// Sprachdatei des Moduls
$this->langfiles = array("netdiag@netdiag");
// Voraussetzungen
$this->phpmin = array(7, 4);
$this->need_dolibarr_version = array(19, -3);
$this->need_javascript_ajax = 0;
$this->warnings_activation = array();
$this->warnings_activation_ext = array();
// Konstanten beim Aktivieren anlegen
// (Key, Typ, Wert, Beschreibung, sichtbar, current/allentities, deleteonunactive)
$this->const = array(
1 => array('NETDIAG_API_JWT_SECRET', 'chaine', dol_hash(dol_print_date(dol_now(), 'dayhourrfc').mt_rand(), 'md5'), 'Geheimer Schlüssel zum Signieren der API-JWT', 0, 'current', 1),
2 => array('NETDIAG_API_TOKEN_TTL', 'chaine', '604800', 'Gültigkeit des API-Tokens in Sekunden (Standard 7 Tage)', 1, 'current', 0),
3 => array('NETDIAG_APK_URL', 'chaine', 'https://git.data-it-solution.de/api/packages/data-it/generic/netdiag-apk/latest/NetDiag.apk', 'Download-URL der Android-App (für QR-Code im Admin)', 1, 'current', 0),
);
if (!isModEnabled("netdiag")) {
$conf->netdiag = new stdClass();
$conf->netdiag->enabled = 0;
}
// Neue Tabs an bestehenden Objekten
// Tab "Netzwerk-Diagnose" an Kunde (thirdparty) und Auftrag (order)
$this->tabs = array(
'thirdparty:+netdiag:NetDiagTab:netdiag@netdiag:$user->hasRight(\'netdiag\', \'protocol\', \'read\'):/custom/netdiag/netdiag_object_tab.php?socid=__ID__&objecttype=thirdparty',
'order:+netdiag:NetDiagTab:netdiag@netdiag:$user->hasRight(\'netdiag\', \'protocol\', \'read\'):/custom/netdiag/netdiag_object_tab.php?id=__ID__&objecttype=order',
);
$this->dictionaries = array();
$this->boxes = array();
$this->cronjobs = array();
// Rechte
$this->rights = array();
$r = 0;
$o = 1;
$this->rights[$r][0] = $this->numero.sprintf("%02d", ($o * 10) + 1);
$this->rights[$r][1] = 'Diagnose-Protokolle lesen';
$this->rights[$r][4] = 'protocol';
$this->rights[$r][5] = 'read';
$r++;
$this->rights[$r][0] = $this->numero.sprintf("%02d", ($o * 10) + 2);
$this->rights[$r][1] = 'Diagnose-Protokolle anlegen/ändern';
$this->rights[$r][4] = 'protocol';
$this->rights[$r][5] = 'write';
$r++;
$this->rights[$r][0] = $this->numero.sprintf("%02d", ($o * 10) + 3);
$this->rights[$r][1] = 'Diagnose-Protokolle löschen';
$this->rights[$r][4] = 'protocol';
$this->rights[$r][5] = 'delete';
$r++;
// Top-Menü
$this->menu = array();
$r = 0;
$this->menu[$r++] = array(
'fk_menu' => '',
'type' => 'top',
'titre' => 'ModuleNetDiagName',
'prefix' => img_picto('', $this->picto, 'class="pictofixedwidth valignmiddle"'),
'mainmenu' => 'netdiag',
'leftmenu' => '',
'url' => '/custom/netdiag/netdiagindex.php',
'langs' => 'netdiag@netdiag',
'position' => 1000 + $r,
'enabled' => '0', // Top-Menü deaktiviert — Zugriff nur über Tab an Kunde/Auftrag
'perms' => '$user->hasRight("netdiag", "protocol", "read")',
'target' => '',
'user' => 2,
);
$this->menu[$r++] = array(
'fk_menu' => 'fk_mainmenu=netdiag',
'type' => 'left',
'titre' => 'NetDiagProtocolList',
'prefix' => img_picto('', $this->picto, 'class="pictofixedwidth valignmiddle paddingright"'),
'mainmenu' => 'netdiag',
'leftmenu' => 'netdiag_protocol_list',
'url' => '/custom/netdiag/netdiagindex.php',
'langs' => 'netdiag@netdiag',
'position' => 1000 + $r,
'enabled' => 'isModEnabled("netdiag")',
'perms' => '$user->hasRight("netdiag", "protocol", "read")',
'target' => '',
'user' => 2,
);
}
/**
* Wird beim Aktivieren des Moduls aufgerufen.
* Legt Konstanten, Rechte, Menüs und Datenbanktabellen an.
*
* @param string $options Optionen ('', 'noboxes')
* @return int<-1,1> 1 wenn OK, <=0 bei Fehler
*/
public function init($options = '')
{
global $conf, $langs;
// SQL-Tabellen beim Aktivieren laden
$result = $this->_load_tables('/netdiag/sql/');
if ($result < 0) {
return -1;
}
// Rechte entfernen/neu setzen
$this->remove($options);
$sql = array();
return $this->_init($sql, $options);
}
/**
* Wird beim Deaktivieren des Moduls aufgerufen.
*
* @param string $options Optionen ('', 'noboxes')
* @return int<-1,1> 1 wenn OK, <=0 bei Fehler
*/
public function remove($options = '')
{
$sql = array();
return $this->_remove($sql, $options);
}
}