Files
Smart-Dashboard/ajax/speicher.php
T
adminandClaude Opus 5 ba5622f9b2 Solar: Speicher-Ansicht mit Modulen und Zellen der BYD-Batterie
Dritte Ansicht der Realtime-Karte (auch per Klick auf die Batterie):
Kennzahlen (Ladestand mit kWh und voll/leer um, Leistung, SOH,
Zellspreizung, Temperaturen, Spannung, Durchsatz, Zustand), der Turm aus
BMU und acht Modulen mit je 16 Zellbalken, das gewaehlte Modul mit
Zellspannungen und Temperaturfuehlern, dazu Verlaeufe fuer Ladestand und
Leistung (EnergyFlow) sowie Spreizung und Temperatur (byd) mit Zeitraum-
wahl und Anzeige beim Ueberfahren. Neu: ajax/speicher.php.

Nebenbei: Icon-Zeichen in energiefluss.js und im Katalog stehen als
Escape (\uF...) statt als unsichtbare Zeichen im Quelltext.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 18:11:22 +02:00

83 lines
3.2 KiB
PHP

<?php
/*
* Verlauf für die Speicher-Ansicht der Solar-Seite (js/solar/speicher.js).
*
* ?was=verlauf&stunden=24 Ladestand und Leistung aus EnergyFlow (reicht
* Jahre zurück) und die BMU-Werte aus byd
* (Spreizung, Temperaturen, SOH - seit 15.09.2026)
* ?was=gesundheit SOH, größte Spreizung und Zähler je Tag aus byd
*
* Die Live-Werte kommen nicht von hier, sondern über MQTT
* (solarManager/byd/#, geschrieben von gatherBYDData.py).
*
* Zeiten gehen als Unix-Sekunden hinaus; ab sieben Tagen wird auf Stunden
* gemittelt, damit ein Monat nicht als 8.600 Punkte über die Leitung geht.
*/
require_once("../helper.php");
require_once("../restricted/costs.php"); // solarDb()
header("Content-Type: application/json; charset=utf-8");
if (!checkLogin()) {
http_response_code(403);
echo json_encode(["error" => "Nicht angemeldet."]);
exit;
}
$was = $_GET["was"] ?? "verlauf";
try {
$db = solarDb();
if ($was === "verlauf") {
$stunden = max(1, min(24 * 90, intval($_GET["stunden"] ?? 24)));
$stuendlich = $stunden > 24 * 3;
$gruppe = $stuendlich ? "FLOOR(UNIX_TIMESTAMP(datetime) / 3600) * 3600" : "UNIX_TIMESTAMP(datetime)";
$soc = [];
$res = $db->query("SELECT $gruppe AS t, AVG(soc) AS soc, AVG(battP) AS p
FROM EnergyFlow
WHERE datetime >= NOW() - INTERVAL $stunden HOUR
GROUP BY t ORDER BY t");
while ($res && $z = $res->fetch_assoc()) {
// battP > 0 heißt entladen; hinaus geht "positiv = laden", wie bei der BMU.
$soc[] = [(int)$z["t"], round((float)$z["soc"], 1), round(-(float)$z["p"])];
}
$bmu = [];
$res = $db->query("SELECT $gruppe AS t, AVG(spreizung) AS spr, MIN(t_min) AS tmin, MAX(t_max) AS tmax, AVG(soh) AS soh
FROM byd
WHERE datetime >= NOW() - INTERVAL $stunden HOUR
GROUP BY t ORDER BY t");
while ($res && $z = $res->fetch_assoc()) {
$bmu[] = [(int)$z["t"], round((float)$z["spr"], 1), (int)$z["tmin"], (int)$z["tmax"], round((float)$z["soh"], 1)];
}
echo json_encode([
"von" => time() - $stunden * 3600, "bis" => time(),
"soc" => $soc, "bmu" => $bmu,
]);
exit;
}
if ($was === "gesundheit") {
$tage = [];
$res = $db->query("SELECT DATE(datetime) AS tag, AVG(soh) AS soh, MAX(spreizung) AS spr,
MAX(geladen_kwh) AS geladen, MAX(entladen_kwh) AS entladen
FROM byd GROUP BY tag ORDER BY tag");
while ($res && $z = $res->fetch_assoc()) {
$tage[] = [$z["tag"], round((float)$z["soh"], 1), (int)$z["spr"],
(float)$z["geladen"], (float)$z["entladen"]];
}
echo json_encode(["tage" => $tage]);
exit;
}
http_response_code(400);
echo json_encode(["error" => "Unbekannter Abschnitt."]);
} catch (Throwable $e) {
http_response_code(500);
echo json_encode(["error" => "Verlauf nicht abrufbar: " . $e->getMessage()]);
}