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:
2026-08-26 22:54:28 +02:00
co-authored by Claude Opus 5
parent 29f752eafe
commit 6b8556567b
68 changed files with 1555 additions and 60085 deletions
-16
View File
@@ -2,15 +2,6 @@
require_once("../helper.php");
$close = 0;
function getSSLPage($url) {
$curlSession = curl_init();
curl_setopt($curlSession, CURLOPT_URL, $url);
curl_setopt($curlSession, CURLOPT_BINARYTRANSFER, true);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, true);
$jsonData = json_decode(curl_exec($curlSession),true);
curl_close($curlSession);
return $jsonData;
}
if (checkLogin()) {
if (isset($_POST["sensorSelect1"])) { //if form war sent add an action
@@ -127,13 +118,6 @@ if (checkLogin()) {
}
if (!$close) {
echo <<<ENDE
<style>
input[type='range']::-webkit-slider-runnable-track {
background: linear-gradient(to right, #00788F, #00788F), #D7D7D7;
background-size: var(--background-size, 0%) 100%;
background-repeat: no-repeat;
}
</style>
<!--begin::Form-->
<form id="heater_form">
<div class="accordion" id="actionAccordion">
+2 -83
View File
@@ -55,87 +55,6 @@ if (checkLogin()) {
$close = 1;
}
if (!$close) {
echo <<<ENDE
<style>
input[type='range']::-webkit-slider-runnable-track {
background: linear-gradient(to right, #00788F, #00788F), #D7D7D7;
background-size: var(--background-size, 0%) 100%;
background-repeat: no-repeat;
$formId = "carEG_form";
include __DIR__ . "/carForm.php";
}
</style>
<div class="d-grid gap-2 col-6 mx-auto my-4">
<button class="btn btn-primary" id="evStart/Stop">Laden starten</button>
</div>
<!--begin::Form-->
<form id="carEG_form">
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Modus</div>
</div>
<!--begin::Body-->
<div class="card-body">
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="evMode" id="EV_Default" value="default">
<label class="form-check-label" for="EV_Default"> Immer Laden </label></input>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="evMode" id="EV_Eco" value="eco">
<label class="form-check-label" for="EV_Eco"> Überschuss </label></input>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="evMode" id="EV_NextTrip" value="NextTrip">
<label class="form-check-label" for="EV_NextTrip"> Ladeplanung </label></input>
</div>
</div>
</div>
</div>
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Max. Ladestrom</div>
</div>
<div class="card-body">
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="evAmp" id="EV_6A" value="6">
<label class="form-check-label" for="EV_6A"> 6A </label></input>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="evAmp" id="EV_10A" value="10">
<label class="form-check-label" for="EV_10A"> 10A </label></input>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="evAmp" id="EV_16A" value="16">
<label class="form-check-label" for="EV_16A"> 16A </label></input>
</div>
</div>
</div>
</div>
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Ladeplanung</div>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="form-check">
<label class="form-label" for="addedCharge">Zusätzlich benötigte Ladung (%): </label>
<div style="font-size: 15px;color: #297195;display: inline-block;" id="modal-slider-label">sdf</div>
<input type="range" id="modal-slider" name="fte" class="form-range range-color-track" min="1" max="100" />
<div class="d-flex justify-content-between">
<span class="max-amount f-16 font-weight-normal darkGray-color text-right mt-1">1%</span>
<span class="max-amount f-16 font-weight-normal darkGray-color text-right mt-1">100%</span>
</div>
<!--<input name="fte" class="form-control" type="number" max="100" min="1" value="" />-->
</div>
</div>
<div class="row mb-3">
<div class="form-check">
<label class="form-label" for="planedTime">Zeitpunkt zudem geladen sein soll: </label>
<input id="EV_NextTripTime" name="ftt" class="form-control" size="2" type="time" value=""/>
</div>
</div>
</div>
</div>
</form>
ENDE;
}
+81
View File
@@ -0,0 +1,81 @@
<?php
/*
* Formular des Auto-Lademodals. carEG.php und carOG.php zeigen dasselbe
* Formular; nur die Ansteuerung der Wallbox dahinter unterscheidet sich.
* $formId trennt die beiden Formulare fuer das JavaScript.
*/
?>
<div class="d-grid gap-2 col-6 mx-auto my-4">
<button class="btn btn-primary" id="evStart/Stop">Laden starten</button>
</div>
<!--begin::Form-->
<form id="<?= $formId ?>">
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Modus</div>
</div>
<!--begin::Body-->
<div class="card-body">
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="evMode" id="EV_Default" value="default">
<label class="form-check-label" for="EV_Default"> Immer Laden </label></input>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="evMode" id="EV_Eco" value="eco">
<label class="form-check-label" for="EV_Eco"> Überschuss </label></input>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="evMode" id="EV_NextTrip" value="NextTrip">
<label class="form-check-label" for="EV_NextTrip"> Ladeplanung </label></input>
</div>
</div>
</div>
</div>
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Max. Ladestrom</div>
</div>
<div class="card-body">
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="evAmp" id="EV_6A" value="6">
<label class="form-check-label" for="EV_6A"> 6A </label></input>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="evAmp" id="EV_10A" value="10">
<label class="form-check-label" for="EV_10A"> 10A </label></input>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="evAmp" id="EV_16A" value="16">
<label class="form-check-label" for="EV_16A"> 16A </label></input>
</div>
</div>
</div>
</div>
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Ladeplanung</div>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="form-check">
<label class="form-label" for="addedCharge">Zusätzlich benötigte Ladung (%): </label>
<div style="font-size: 15px;color: #297195;display: inline-block;" id="modal-slider-label">sdf</div>
<input type="range" id="modal-slider" name="fte" class="form-range range-color-track" min="1" max="100" />
<div class="d-flex justify-content-between">
<span class="max-amount f-16 font-weight-normal darkGray-color text-right mt-1">1%</span>
<span class="max-amount f-16 font-weight-normal darkGray-color text-right mt-1">100%</span>
</div>
<!--<input name="fte" class="form-control" type="number" max="100" min="1" value="" />-->
</div>
</div>
<div class="row mb-3">
<div class="form-check">
<label class="form-label" for="planedTime">Zeitpunkt zudem geladen sein soll: </label>
<input id="EV_NextTripTime" name="ftt" class="form-control" size="2" type="time" value=""/>
</div>
</div>
</div>
</div>
</form>
+10 -100
View File
@@ -2,25 +2,16 @@
require_once("../helper.php");
function getSSLPage($url) {
$curlSession = curl_init();
curl_setopt($curlSession, CURLOPT_URL, $url);
curl_setopt($curlSession, CURLOPT_BINARYTRANSFER, true);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, true);
$jsonData = json_decode(curl_exec($curlSession),true);
curl_close($curlSession);
return $jsonData;
}
if (checkLogin()) {
$close = 0;
if (isset($_POST["evStart/Stop"])) {
if ($_POST["evStart/Stop"] == "Laden starten") {
$close = 1;
getSSLPage("http://192.168.179.122/api/set?frc=2");
httpGetJson("http://192.168.179.122/api/set?frc=2");
} else if ($_POST["evStart/Stop"] == "Laden stoppen") {
$close = 1;
getSSLPage("http://192.168.179.122/api/set?frc=1");
httpGetJson("http://192.168.179.122/api/set?frc=1");
}
$close = 1;
} else if (isset($_POST["evMode"])) {
@@ -37,23 +28,23 @@ if (checkLogin()) {
if ($_POST["evMode"] == "eco") {
$close = 1;
if ($_POST["ftt"] && $_POST["fte"] > 0) {
getSSLPage("http://192.168.179.122/api/set?ate=" . $_POST["fte"] . "&att=" . $seconds . "&amp=" . $_POST["evAmp"] . "&fup=true&lmo=4");
httpGetJson("http://192.168.179.122/api/set?ate=" . $_POST["fte"] . "&att=" . $seconds . "&amp=" . $_POST["evAmp"] . "&fup=true&lmo=4");
} else {
getSSLPage("http://192.168.179.122/api/set?amp=" . $_POST["evAmp"] . "&fup=true&lmo=4");
httpGetJson("http://192.168.179.122/api/set?amp=" . $_POST["evAmp"] . "&fup=true&lmo=4");
}
} else if ($_POST["evMode"] == "default") {
$close = 1;
if ($_POST["ftt"] && $_POST["fte"] > 0) {
getSSLPage("http://192.168.179.122/api/set?ate=" . $_POST["fte"] . "&att=" . $seconds . "&amp=" . $_POST["evAmp"] . "&fup=true&lmo=3");
httpGetJson("http://192.168.179.122/api/set?ate=" . $_POST["fte"] . "&att=" . $seconds . "&amp=" . $_POST["evAmp"] . "&fup=true&lmo=3");
} else {
getSSLPage("http://192.168.179.122/api/set?amp=" . $_POST["evAmp"] . "&fup=true&lmo=3");
httpGetJson("http://192.168.179.122/api/set?amp=" . $_POST["evAmp"] . "&fup=true&lmo=3");
}
} else if ($_POST["evMode"] == "NextTrip") {
$close = 1;
if ($_POST["ftt"] && $_POST["fte"] > 0) {
getSSLPage("http://192.168.179.122/api/set?ate=" . $_POST["fte"] . "&att=" . $seconds . "&amp=" . $_POST["evAmp"] . "&fup=true&lmo=5");
httpGetJson("http://192.168.179.122/api/set?ate=" . $_POST["fte"] . "&att=" . $seconds . "&amp=" . $_POST["evAmp"] . "&fup=true&lmo=5");
} else {
getSSLPage("http://192.168.179.122/api/set?amp=" . $_POST["evAmp"] . "&fup=true&lmo=5");
httpGetJson("http://192.168.179.122/api/set?amp=" . $_POST["evAmp"] . "&fup=true&lmo=5");
}
}
$close = 1;
@@ -62,87 +53,6 @@ if (checkLogin()) {
$close = 1;
}
if (!$close) {
echo <<<ENDE
<style>
input[type='range']::-webkit-slider-runnable-track {
background: linear-gradient(to right, #00788F, #00788F), #D7D7D7;
background-size: var(--background-size, 0%) 100%;
background-repeat: no-repeat;
}
</style>
<div class="d-grid gap-2 col-6 mx-auto my-4">
<button class="btn btn-primary" id="evStart/Stop">Laden starten</button>
</div>
<!--begin::Form-->
<form id="carOG_form">
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Modus</div>
</div>
<!--begin::Body-->
<div class="card-body">
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="evMode" id="EV_Default" value="default">
<label class="form-check-label" for="EV_Default"> Immer Laden </label></input>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="evMode" id="EV_Eco" value="eco">
<label class="form-check-label" for="EV_Eco"> Überschuss </label></input>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="evMode" id="EV_NextTrip" value="NextTrip">
<label class="form-check-label" for="EV_NextTrip"> Ladeplanung </label></input>
</div>
</div>
</div>
</div>
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Max. Ladestrom</div>
</div>
<div class="card-body">
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="evAmp" id="EV_6A" value="6">
<label class="form-check-label" for="EV_6A"> 6A </label></input>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="evAmp" id="EV_10A" value="10">
<label class="form-check-label" for="EV_10A"> 10A </label></input>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="evAmp" id="EV_16A" value="16">
<label class="form-check-label" for="EV_16A"> 16A </label></input>
</div>
</div>
</div>
</div>
<div class="card m-3">
<div class="card-header py-1 px-3">
<div class="card-title">Ladeplanung</div>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="form-check">
<label class="form-label" for="addedCharge">Zusätzlich benötigte Ladung (%): </label>
<div style="font-size: 15px;color: #297195;display: inline-block;" id="modal-slider-label">sdf</div>
<input type="range" id="modal-slider" name="fte" class="form-range range-color-track" min="1" max="100" />
<div class="d-flex justify-content-between">
<span class="max-amount f-16 font-weight-normal darkGray-color text-right mt-1">1%</span>
<span class="max-amount f-16 font-weight-normal darkGray-color text-right mt-1">100%</span>
</div>
<!--<input name="fte" class="form-control" type="number" max="100" min="1" value="" />-->
</div>
</div>
<div class="row mb-3">
<div class="form-check">
<label class="form-label" for="planedTime">Zeitpunkt zudem geladen sein soll: </label>
<input id="EV_NextTripTime" name="ftt" class="form-control" size="2" type="time" value=""/>
</div>
</div>
</div>
</div>
</form>
ENDE;
$formId = "carOG_form";
include __DIR__ . "/carForm.php";
}
+93
View File
@@ -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;
}
+74
View File
@@ -0,0 +1,74 @@
<?php
/*
* Aggregierte Energiedaten für die Historie-Seite.
* Ersetzt getConsData_{month,year,decade}.php und getProdData_{month,year,decade}.php.
*
* Aufruf: energyHistory.php?series=prod|cons&range=month|year|decade
*/
require_once("../helper.php");
require_once("./chartData.php");
// Zeitraum -> [Format der Beschriftung, Filter auf datetime]
$ranges = [
"month" => ["'%d.%b.'", "DATE_FORMAT(datetime,'%Y%m%d') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 1 MONTH),'%Y%m%d')"],
"year" => ["'%b. %y'", "DATE_FORMAT(datetime,'%Y%m') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 13 MONTH),'%Y%m')"],
"decade" => ["'%Y'", "DATE_FORMAT(datetime,'%Y') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 10 YEAR),'%Y')"],
];
// Datenreihen je Diagramm. Beide teilen sich Solarertrag und Heizstab und
// unterscheiden sich nur darin, wohin die Energie fließt (prod) bzw. woher
// sie kommt (cons).
$series = [
"prod" => "SUM(pvP/12 - IF(gridP < 0, -gridP/12,0) - IF(battP < 0, -battP/12,0) - heaterPwr/12) AS Direktverbrauch,
SUM(heaterPwr/12) AS Heizstab,
SUM(IF(battP < 0, -battP/12,0)) AS Batterieladung,
SUM(gridPfeed/12) AS Einspeisung",
"cons" => "SUM(pvP/12 - IF(gridP < 0, -gridP/12,0) - IF(battP < 0, -battP/12,0) - heaterPwr/12) AS Solarverbrauch,
SUM(heaterPwr/12) AS Heizstab,
SUM(IF(battP > 0, battP/12,0)) AS Batteriebezug,
SUM(gridPcons/12) AS Netzbezug",
];
$linecolors["Direktverbrauch"] = "#FFFF00";
$linecolors["Solarverbrauch"] = "#FFFF00";
$linecolors["UG"] = "#FFaa00";
$linecolors["OG"] = "#FF4400";
$linecolors["Auto UG"] = "#00aaFF";
$linecolors["Auto OG"] = "#0044FF";
$linecolors["Heizstab"] = "#FF6600";
$linecolors["Batterieladung"] = "#00aa00";
$linecolors["Batteriebezug"] = "#00aa00";
$linecolors["Einspeisung"] = "#FF0000";
$linecolors["Netzbezug"] = "#FF0000";
$linecolors["Ladestand"] = "#00aa00";
$linecolors["Vorhersage"] = "#2222FF";
header('Content-Type: application/json; charset=utf-8');
$rangeKey = isset($_GET["range"]) ? $_GET["range"] : "";
$seriesKey = isset($_GET["series"]) ? $_GET["series"] : "";
if (!isset($ranges[$rangeKey]) || !isset($series[$seriesKey])) {
http_response_code(400);
echo json_encode(["error" => "Unbekannter Zeitraum oder Datenreihe."]);
exit;
}
list($labelFormat, $filter) = $ranges[$rangeKey];
$obj = (object)[];
$obj->labels = [];
$obj->datasets = [];
if (checkLogin()) {
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
$query = "SELECT
DATE_FORMAT(datetime, $labelFormat) AS 'time',
" . $series[$seriesKey] . "
FROM EnergyFlow
WHERE $filter
GROUP BY DATE_FORMAT(datetime, $labelFormat)
ORDER BY datetime ; ";
$obj = buildChartData($mysql, $query, $linecolors);
}
echo json_encode($obj);
-98
View File
@@ -1,98 +0,0 @@
<?php
require_once("../helper.php");
$consQuery = "SELECT
DATE_FORMAT(datetime,'%Y') AS 'time',
SUM(pvP/12 - IF(gridP < 0, -gridP/12,0) - IF(battP < 0, -battP/12,0)- heaterPwr/12) Solarverbrauch,
SUM(heaterPwr/12) AS Heizstab,
SUM(IF(battP > 0, battP/12,0)) AS Batteriebezug,
SUM(gridPcons/12) AS Netzbezug
FROM EnergyFlow
WHERE DATE_FORMAT(datetime,'%Y') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 10 YEAR),'%Y')
GROUP BY time
ORDER BY datetime ; ";
$linecolors["Solarverbrauch"] = "#FFFF00";
$linecolors["UG"] = "#FFaa00";
$linecolors["OG"] = "#FF4400";
$linecolors["Auto UG"] = "#00aaFF";
$linecolors["Auto OG"] = "#0044FF";
$linecolors["Heizstab"] = "#FF6600";
$linecolors["Batteriebezug"] = "#00aa00";
$linecolors["Netzbezug"] = "#FF0000";
$linecolors["Ladestand"] = "#00aa00";
$linecolors["Vorhersage"] = "#2222FF";
if (checkLogin()) {
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
$result = mysqli_query($mysql, $consQuery);
if(!$result){
echo "Error:<br>".mysqli_error($mysql)."<br />";
}
$obj = (object)[]; // Cast empty array to object
$obj->labels = [];
$obj->datasets = [];
$i = 0;
$filled = 0;
if ($result->num_rows > 1) {
$ii = 0;
$row = $result->fetch_assoc();
foreach ($row as $name => $value) {
$dataset = (object)[];
if ($name != "time") {
$dataset->borderColor = $linecolors[$name];
$dataset->backgroundColor = $linecolors[$name]."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 == 0) {
$filled = 1;
$dataset->fill = "origin";
} else {
$dataset->fill = "-1";
}
$dataset->yAxisID = 'y';
}
$dataset->label = $name;
$dataset->data[] = $value;
$obj->datasets[] = clone $dataset;
$ii++;
} else {
$obj->labels[] = $value;
}
}
while ($row = $result->fetch_assoc()) {
$ii = 0;
foreach ($row as $name => $value) {
if ($name != "time") {
$obj->datasets[$ii]->data[] = $value;
$ii++;
} else {
$obj->labels[] = $value;
}
}
}
}
}
//header('Content-Type: application/json');
echo json_encode($obj);
//echo '{"labels":[1761322682000,1761322782000,1761322882000,1761322982000,1761323082000,1761323182000,1761323282000],"datasets":[{"stack": "Stack 0","cubicInterpolationMode":"monotone","fill":"origin","label":"Acquisitions by year","data":[10,20,50,20,10,5,70]},{"fill": "false","stack": "Stack 1","cubicInterpolationMode": "monotone","label": "Acquisitions by year","data": [10,20,50,20,10,5,70]}]}';
-98
View File
@@ -1,98 +0,0 @@
<?php
require_once("../helper.php");
$consQuery = "SELECT
DATE_FORMAT(datetime, '%d.%b.') AS 'time',
SUM(pvP/12 - IF(gridP < 0, -gridP/12,0) - IF(battP < 0, -battP/12,0)- heaterPwr/12) Solarverbrauch,
SUM(heaterPwr/12) AS Heizstab,
SUM(IF(battP > 0, battP/12,0)) AS Batteriebezug,
SUM(gridPcons/12) AS Netzbezug
FROM EnergyFlow
WHERE DATE_FORMAT(datetime,'%Y%m%d') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 1 MONTH),'%Y%m%d')
GROUP BY DATE_FORMAT(datetime, '%d.%b.')
ORDER BY datetime ; ";
$linecolors["Solarverbrauch"] = "#FFFF00";
$linecolors["UG"] = "#FFaa00";
$linecolors["OG"] = "#FF4400";
$linecolors["Auto UG"] = "#00aaFF";
$linecolors["Auto OG"] = "#0044FF";
$linecolors["Heizstab"] = "#FF6600";
$linecolors["Batteriebezug"] = "#00aa00";
$linecolors["Netzbezug"] = "#FF0000";
$linecolors["Ladestand"] = "#00aa00";
$linecolors["Vorhersage"] = "#2222FF";
if (checkLogin()) {
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
$result = mysqli_query($mysql, $consQuery);
if(!$result){
echo "Error:<br>".mysqli_error($mysql)."<br />";
}
$obj = (object)[]; // Cast empty array to object
$obj->labels = [];
$obj->datasets = [];
$i = 0;
$filled = 0;
if ($result->num_rows > 1) {
$ii = 0;
$row = $result->fetch_assoc();
foreach ($row as $name => $value) {
$dataset = (object)[];
if ($name != "time") {
$dataset->borderColor = $linecolors[$name];
$dataset->backgroundColor = $linecolors[$name]."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 == 0) {
$filled = 1;
$dataset->fill = "origin";
} else {
$dataset->fill = "-1";
}
$dataset->yAxisID = 'y';
}
$dataset->label = $name;
$dataset->data[] = $value;
$obj->datasets[] = clone $dataset;
$ii++;
} else {
$obj->labels[] = $value;
}
}
while ($row = $result->fetch_assoc()) {
$ii = 0;
foreach ($row as $name => $value) {
if ($name != "time") {
$obj->datasets[$ii]->data[] = $value;
$ii++;
} else {
$obj->labels[] = $value;
}
}
}
}
}
//header('Content-Type: application/json');
echo json_encode($obj);
//echo '{"labels":[1761322682000,1761322782000,1761322882000,1761322982000,1761323082000,1761323182000,1761323282000],"datasets":[{"stack": "Stack 0","cubicInterpolationMode":"monotone","fill":"origin","label":"Acquisitions by year","data":[10,20,50,20,10,5,70]},{"fill": "false","stack": "Stack 1","cubicInterpolationMode": "monotone","label": "Acquisitions by year","data": [10,20,50,20,10,5,70]}]}';
-98
View File
@@ -1,98 +0,0 @@
<?php
require_once("../helper.php");
$consQuery = "SELECT
DATE_FORMAT(datetime, '%b. %y') AS 'time',
SUM(pvP/12 - IF(gridP < 0, -gridP/12,0) - IF(battP < 0, -battP/12,0)- heaterPwr/12) Solarverbrauch,
SUM(heaterPwr/12) AS Heizstab,
SUM(IF(battP > 0, battP/12,0)) AS Batteriebezug,
SUM(gridPcons/12) AS Netzbezug
FROM EnergyFlow
WHERE DATE_FORMAT(datetime,'%Y%m') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 13 MONTH),'%Y%m')
GROUP BY DATE_FORMAT(datetime, '%b. %y')
ORDER BY datetime ; ";
$linecolors["Solarverbrauch"] = "#FFFF00";
$linecolors["UG"] = "#FFaa00";
$linecolors["OG"] = "#FF4400";
$linecolors["Auto UG"] = "#00aaFF";
$linecolors["Auto OG"] = "#0044FF";
$linecolors["Heizstab"] = "#FF6600";
$linecolors["Batteriebezug"] = "#00aa00";
$linecolors["Netzbezug"] = "#FF0000";
$linecolors["Ladestand"] = "#00aa00";
$linecolors["Vorhersage"] = "#2222FF";
if (checkLogin()) {
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
$result = mysqli_query($mysql, $consQuery);
if(!$result){
echo "Error:<br>".mysqli_error($mysql)."<br />";
}
$obj = (object)[]; // Cast empty array to object
$obj->labels = [];
$obj->datasets = [];
$i = 0;
$filled = 0;
if ($result->num_rows > 1) {
$ii = 0;
$row = $result->fetch_assoc();
foreach ($row as $name => $value) {
$dataset = (object)[];
if ($name != "time") {
$dataset->borderColor = $linecolors[$name];
$dataset->backgroundColor = $linecolors[$name]."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 == 0) {
$filled = 1;
$dataset->fill = "origin";
} else {
$dataset->fill = "-1";
}
$dataset->yAxisID = 'y';
}
$dataset->label = $name;
$dataset->data[] = $value;
$obj->datasets[] = clone $dataset;
$ii++;
} else {
$obj->labels[] = $value;
}
}
while ($row = $result->fetch_assoc()) {
$ii = 0;
foreach ($row as $name => $value) {
if ($name != "time") {
$obj->datasets[$ii]->data[] = $value;
$ii++;
} else {
$obj->labels[] = $value;
}
}
}
}
}
//header('Content-Type: application/json');
echo json_encode($obj);
//echo '{"labels":[1761322682000,1761322782000,1761322882000,1761322982000,1761323082000,1761323182000,1761323282000],"datasets":[{"stack": "Stack 0","cubicInterpolationMode":"monotone","fill":"origin","label":"Acquisitions by year","data":[10,20,50,20,10,5,70]},{"fill": "false","stack": "Stack 1","cubicInterpolationMode": "monotone","label": "Acquisitions by year","data": [10,20,50,20,10,5,70]}]}';
-98
View File
@@ -1,98 +0,0 @@
<?php
require_once("../helper.php");
$consQuery = "SELECT
DATE_FORMAT(datetime,'%Y') AS 'time',
SUM(pvP/12 - IF(gridP < 0, -gridP/12,0) - IF(battP < 0, -battP/12,0) - heaterPwr/12) Direktverbrauch,
SUM(heaterPwr/12) AS Heizstab,
SUM(IF(battP < 0, -battP/12,0)) AS Batterieladung,
SUM(gridPfeed/12) AS Einspeisung
FROM EnergyFlow
WHERE DATE_FORMAT(datetime,'%Y') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 10 YEAR),'%Y')
GROUP BY DATE_FORMAT(datetime, '%Y')
ORDER BY datetime ; ";
$linecolors["Direktverbrauch"] = "#FFFF00";
$linecolors["UG"] = "#FFaa00";
$linecolors["OG"] = "#FF4400";
$linecolors["Auto UG"] = "#00aaFF";
$linecolors["Auto OG"] = "#0044FF";
$linecolors["Heizstab"] = "#FF6600";
$linecolors["Batterieladung"] = "#00aa00";
$linecolors["Einspeisung"] = "#FF0000";
$linecolors["Ladestand"] = "#00aa00";
$linecolors["Vorhersage"] = "#2222FF";
if (checkLogin()) {
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
$result = mysqli_query($mysql, $consQuery);
if(!$result){
echo "Error:<br>".mysqli_error($mysql)."<br />";
}
$obj = (object)[]; // Cast empty array to object
$obj->labels = [];
$obj->datasets = [];
$i = 0;
$filled = 0;
if ($result->num_rows > 1) {
$ii = 0;
$row = $result->fetch_assoc();
foreach ($row as $name => $value) {
$dataset = (object)[];
if ($name != "time") {
$dataset->borderColor = $linecolors[$name];
$dataset->backgroundColor = $linecolors[$name]."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 == 0) {
$filled = 1;
$dataset->fill = "origin";
} else {
$dataset->fill = "-1";
}
$dataset->yAxisID = 'y';
}
$dataset->label = $name;
$dataset->data[] = $value;
$obj->datasets[] = clone $dataset;
$ii++;
} else {
$obj->labels[] = $value;
}
}
while ($row = $result->fetch_assoc()) {
$ii = 0;
foreach ($row as $name => $value) {
if ($name != "time") {
$obj->datasets[$ii]->data[] = $value;
$ii++;
} else {
$obj->labels[] = $value;
}
}
}
}
}
//header('Content-Type: application/json');
echo json_encode($obj);
//echo '{"labels":[1761322682000,1761322782000,1761322882000,1761322982000,1761323082000,1761323182000,1761323282000],"datasets":[{"stack": "Stack 0","cubicInterpolationMode":"monotone","fill":"origin","label":"Acquisitions by year","data":[10,20,50,20,10,5,70]},{"fill": "false","stack": "Stack 1","cubicInterpolationMode": "monotone","label": "Acquisitions by year","data": [10,20,50,20,10,5,70]}]}';
-98
View File
@@ -1,98 +0,0 @@
<?php
require_once("../helper.php");
$consQuery = "SELECT
DATE_FORMAT(datetime, '%d.%b.') AS 'time',
SUM(pvP/12 - IF(gridP < 0, -gridP/12,0) - IF(battP < 0, -battP/12,0) - heaterPwr/12) Direktverbrauch,
SUM(heaterPwr/12) AS Heizstab,
SUM(IF(battP < 0, -battP/12,0)) AS Batterieladung,
SUM(gridPfeed/12) AS Einspeisung
FROM EnergyFlow
WHERE DATE_FORMAT(datetime,'%Y%m%d') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 1 MONTH),'%Y%m%d')
GROUP BY DATE_FORMAT(datetime, '%d.%b.')
ORDER BY datetime ; ";
$linecolors["Direktverbrauch"] = "#FFFF00";
$linecolors["UG"] = "#FFaa00";
$linecolors["OG"] = "#FF4400";
$linecolors["Auto UG"] = "#00aaFF";
$linecolors["Auto OG"] = "#0044FF";
$linecolors["Heizstab"] = "#FF6600";
$linecolors["Batterieladung"] = "#00aa00";
$linecolors["Einspeisung"] = "#FF0000";
$linecolors["Ladestand"] = "#00aa00";
$linecolors["Vorhersage"] = "#2222FF";
if (checkLogin()) {
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
$result = mysqli_query($mysql, $consQuery);
if(!$result){
echo "Error:<br>".mysqli_error($mysql)."<br />";
}
$obj = (object)[]; // Cast empty array to object
$obj->labels = [];
$obj->datasets = [];
$i = 0;
$filled = 0;
if ($result->num_rows > 1) {
$ii = 0;
$row = $result->fetch_assoc();
foreach ($row as $name => $value) {
$dataset = (object)[];
if ($name != "time") {
$dataset->borderColor = $linecolors[$name];
$dataset->backgroundColor = $linecolors[$name]."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 == 0) {
$filled = 1;
$dataset->fill = "origin";
} else {
$dataset->fill = "-1";
}
$dataset->yAxisID = 'y';
}
$dataset->label = $name;
$dataset->data[] = $value;
$obj->datasets[] = clone $dataset;
$ii++;
} else {
$obj->labels[] = $value;
}
}
while ($row = $result->fetch_assoc()) {
$ii = 0;
foreach ($row as $name => $value) {
if ($name != "time") {
$obj->datasets[$ii]->data[] = $value;
$ii++;
} else {
$obj->labels[] = $value;
}
}
}
}
}
//header('Content-Type: application/json');
echo json_encode($obj);
//echo '{"labels":[1761322682000,1761322782000,1761322882000,1761322982000,1761323082000,1761323182000,1761323282000],"datasets":[{"stack": "Stack 0","cubicInterpolationMode":"monotone","fill":"origin","label":"Acquisitions by year","data":[10,20,50,20,10,5,70]},{"fill": "false","stack": "Stack 1","cubicInterpolationMode": "monotone","label": "Acquisitions by year","data": [10,20,50,20,10,5,70]}]}';
-98
View File
@@ -1,98 +0,0 @@
<?php
require_once("../helper.php");
$consQuery = "SELECT
DATE_FORMAT(datetime,'%b. %y') AS 'time',
SUM(pvP/12 - IF(gridP < 0, -gridP/12,0) - IF(battP < 0, -battP/12,0) - heaterPwr/12) Direktverbrauch,
SUM(heaterPwr/12) AS Heizstab,
SUM(IF(battP < 0, -battP/12,0)) AS Batterieladung,
SUM(gridPfeed/12) AS Einspeisung
FROM EnergyFlow
WHERE DATE_FORMAT(datetime,'%Y%m') >= DATE_FORMAT(DATE_SUB(now(),INTERVAL 13 MONTH),'%Y%m')
GROUP BY DATE_FORMAT(datetime, '%b. %y')
ORDER BY datetime ; ";
$linecolors["Direktverbrauch"] = "#FFFF00";
$linecolors["UG"] = "#FFaa00";
$linecolors["OG"] = "#FF4400";
$linecolors["Auto UG"] = "#00aaFF";
$linecolors["Auto OG"] = "#0044FF";
$linecolors["Heizstab"] = "#FF6600";
$linecolors["Batterieladung"] = "#00aa00";
$linecolors["Einspeisung"] = "#FF0000";
$linecolors["Ladestand"] = "#00aa00";
$linecolors["Vorhersage"] = "#2222FF";
if (checkLogin()) {
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
$result = mysqli_query($mysql, $consQuery);
if(!$result){
echo "Error:<br>".mysqli_error($mysql)."<br />";
}
$obj = (object)[]; // Cast empty array to object
$obj->labels = [];
$obj->datasets = [];
$i = 0;
$filled = 0;
if ($result->num_rows > 1) {
$ii = 0;
$row = $result->fetch_assoc();
foreach ($row as $name => $value) {
$dataset = (object)[];
if ($name != "time") {
$dataset->borderColor = $linecolors[$name];
$dataset->backgroundColor = $linecolors[$name]."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 == 0) {
$filled = 1;
$dataset->fill = "origin";
} else {
$dataset->fill = "-1";
}
$dataset->yAxisID = 'y';
}
$dataset->label = $name;
$dataset->data[] = $value;
$obj->datasets[] = clone $dataset;
$ii++;
} else {
$obj->labels[] = $value;
}
}
while ($row = $result->fetch_assoc()) {
$ii = 0;
foreach ($row as $name => $value) {
if ($name != "time") {
$obj->datasets[$ii]->data[] = $value;
$ii++;
} else {
$obj->labels[] = $value;
}
}
}
}
}
//header('Content-Type: application/json');
echo json_encode($obj);
//echo '{"labels":[1761322682000,1761322782000,1761322882000,1761322982000,1761323082000,1761323182000,1761323282000],"datasets":[{"stack": "Stack 0","cubicInterpolationMode":"monotone","fill":"origin","label":"Acquisitions by year","data":[10,20,50,20,10,5,70]},{"fill": "false","stack": "Stack 1","cubicInterpolationMode": "monotone","label": "Acquisitions by year","data": [10,20,50,20,10,5,70]}]}';
-16
View File
@@ -2,15 +2,6 @@
require_once("../helper.php");
function getSSLPage($url) {
$curlSession = curl_init();
curl_setopt($curlSession, CURLOPT_URL, $url);
curl_setopt($curlSession, CURLOPT_BINARYTRANSFER, true);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, true);
$jsonData = json_decode(curl_exec($curlSession),true);
curl_close($curlSession);
return $jsonData;
}
if (checkLogin()) {
$close = 0;
@@ -48,13 +39,6 @@ if (checkLogin()) {
}
if (!$close) {
echo <<<ENDE
<style>
input[type='range']::-webkit-slider-runnable-track {
background: linear-gradient(to right, #00788F, #00788F), #D7D7D7;
background-size: var(--background-size, 0%) 100%;
background-repeat: no-repeat;
}
</style>
<!--begin::Form-->
<form id="heater_form">
<div class="col-sm-11">
-7
View File
@@ -30,13 +30,6 @@ if (checkLogin()) {
}
if (!$close) {
echo <<<ENDE
<style>
input[type='range']::-webkit-slider-runnable-track {
background: linear-gradient(to right, #00788F, #00788F), #D7D7D7;
background-size: var(--background-size, 0%) 100%;
background-repeat: no-repeat;
}
</style>
<!--begin::Form-->
<form id="heater_form">
<div class="col-sm-11">