Dashboard: Doppelungen zusammengelegt, Lade- und Renderlast gesenkt
Zusammenlegung
- Die sechs Endpunkte getConsData_/getProdData_{month,year,decade}.php sind
ajax/energyHistory.php?series=&range= gewichen, der gemeinsame Aufbau der
Chart-Daten steht in ajax/chartData.php. Die erzeugte SQL wurde gegen alle
sechs Originale abgeglichen.
- Die 13 Raeume der Home-Ansicht stehen nur noch in restricted/rooms.php.
home.php rendert die SVG-Kacheln daraus, homeMQTT.js bekommt dieselbe
Tabelle als JSON (346 -> 222 bzw. 428 -> 197 Zeilen).
- Gemeinsame JS-Helfer in js/solar/common.js; geteilte Bausteine fuer
Wetterkacheln, Chart-Skripte und das Formular der Ladesteuerung.
- Seitenvorlagen sind jetzt .php und werden eingebunden, statt per
file_get_contents zusammengesetzt zu werden.
Fehlerbehebungen
- ?action=weather fuehrte auf eine leere Seite, es gibt jetzt weather.php.
- homeMQTT.js griff auf ein #meteogram zu, das home.php nie hatte, und brach
damit den readystatechange-Handler ab.
- Die Heizungsseite abonnierte weatherStation/#, zeigte die Werte aber nie an.
Ladelast
- Chart.js, MQTT und Meteogramm werden nur noch auf den Seiten geladen, die
sie brauchen; die Seitentabelle dafuer steht in index.php.
- mqtt.js durch die minifizierte Fassung ersetzt (859 -> 359 KB). MQTT.js
5.14.1, byte-identisch mit dem signierten npm-Tarball.
- Rund 3,1 MB ungenutzte Vendor-Reste und AdminLTE-Demobilder entfernt.
- Solar 1796 -> 1240 KB, Home 1796 -> 873 KB, Historie 1796 -> 843 KB.
Speicher im Browser
- Chart.defaults.devicePixelRatio auf 1.5 gedeckelt. Die Zeichenpuffer der
Diagramme waren mit 20-45 MB der groesste Posten der Seite.
- Das Meteogramm-iframe laedt erst beim Hinscrollen.
Realtime-SVG
- Filterbereiche auf das noetige Mass verkleinert und den wirkungslosen
feOffset-Durchgang entfernt: 60 % weniger gerasterte Filterflaeche bei
pixelgleichem Ergebnis.
- Die Fluss-Animation laeuft ueber transform statt stroke-dashoffset, mit
Punkten statt Strichmuster; sie ruht, wo kein Fluss anliegt.
- Der Wertupdate schreibt nur noch bei echter Aenderung und benutzt
textContent statt innerHTML: 9 statt 86 Elemente pro Update, davon keines
mit Filter. describeArc rundet auf volle Grad.
- waterInfo auf scale(0.90) wie die uebrigen Info-Gruppen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/*
|
||||
* Gemeinsame Bausteine für die Chart-Endpunkte in ajax/.
|
||||
*
|
||||
* Alle Endpunkte liefern Chart.js-Daten im gleichen Format: eine Abfrage mit
|
||||
* einer Spalte "time" (Beschriftung) und je einer Spalte pro Datenreihe.
|
||||
* chartDataset() legt das Styling einer Reihe fest, buildChartData() baut
|
||||
* daraus das fertige {labels, datasets}-Objekt.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Styling für eine Datenreihe. $filled merkt sich über die Reihen hinweg,
|
||||
* ob die unterste Fläche des Stapels schon gegen die Nulllinie gefüllt wurde.
|
||||
*/
|
||||
function chartDataset($name, $linecolors, &$filled)
|
||||
{
|
||||
$color = isset($linecolors[$name]) ? $linecolors[$name] : "#888888";
|
||||
|
||||
$dataset = (object)[];
|
||||
$dataset->label = $name;
|
||||
$dataset->data = [];
|
||||
$dataset->borderColor = $color;
|
||||
$dataset->backgroundColor = $color . "55";
|
||||
$dataset->borderWidth = 1;
|
||||
$dataset->pointRadius = 0;
|
||||
$dataset->pointHoverRadius = 5;
|
||||
$dataset->tension = 0.2;
|
||||
|
||||
if ($name == "Solarleistung") {
|
||||
$dataset->stack = "SolarPwr";
|
||||
$dataset->fill = "none";
|
||||
$dataset->yAxisID = 'y';
|
||||
} else if ($name == "Ladestand") {
|
||||
$dataset->stack = "Charge";
|
||||
$dataset->fill = "none";
|
||||
$dataset->yAxisID = 'y1';
|
||||
} else {
|
||||
$dataset->stack = "Consumers";
|
||||
if (!$filled) {
|
||||
$filled = true;
|
||||
$dataset->fill = "origin";
|
||||
} else {
|
||||
$dataset->fill = "-1";
|
||||
}
|
||||
$dataset->yAxisID = 'y';
|
||||
}
|
||||
|
||||
return $dataset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Führt $query aus und baut daraus das Chart.js-Objekt.
|
||||
* $labelFactor multipliziert die Zeitspalte (1 für Textbeschriftungen,
|
||||
* 1000 für Unix-Zeitstempel, die Chart.js in Millisekunden erwartet).
|
||||
*/
|
||||
function buildChartData($mysql, $query, $linecolors, $labelFactor = 1)
|
||||
{
|
||||
$obj = (object)[];
|
||||
$obj->labels = [];
|
||||
$obj->datasets = [];
|
||||
|
||||
$result = mysqli_query($mysql, $query);
|
||||
if (!$result) {
|
||||
// Nicht ins Ergebnis schreiben - der Aufrufer liefert JSON aus.
|
||||
error_log("chartData: " . mysqli_error($mysql));
|
||||
return $obj;
|
||||
}
|
||||
if ($result->num_rows < 2) {
|
||||
return $obj;
|
||||
}
|
||||
|
||||
$column = []; // Spaltenname -> Position in $obj->datasets
|
||||
$filled = false;
|
||||
foreach ($result->fetch_fields() as $field) {
|
||||
if ($field->name == "time") {
|
||||
continue;
|
||||
}
|
||||
$column[$field->name] = count($obj->datasets);
|
||||
$obj->datasets[] = chartDataset($field->name, $linecolors, $filled);
|
||||
}
|
||||
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
foreach ($row as $name => $value) {
|
||||
if ($name == "time") {
|
||||
$obj->labels[] = $labelFactor == 1 ? $value : $value * $labelFactor;
|
||||
} else {
|
||||
$obj->datasets[$column[$name]]->data[] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
Reference in New Issue
Block a user