Einstellungsseite, Skoda-Seite und Karte
Sammelstand der offenen Arbeit im Dashboard. Einstellungen: eine Eingabemaske fuer die Energiepreise unter restricted/settings.php, dazu costs.php als Modell und ajax/settings.php als Endpunkt. Die Preise stehen jetzt in gridCosts, gasCosts und fuelCosts statt fest im Quelltext von getStats.php; die Jahresstatistik rechnet ueber LEAD() den jeweils gueltigen Zeitraum aus und schlaegt den anteiligen Grundpreis auf. Eingegeben wird in gewohnten Einheiten - l/100 km, kWh/100 km, Euro je Liter -, umgerechnet wird beim Speichern. solarLog_costs.sql beschreibt die Umstellung der Tabellen. Skoda: eigene Seite mit Live-Werten ueber MQTT und Historie ueber ajax/skoda.php, Kommandos ueber ajax/skodaCmd.php. Karte: Leaflet mit einem eigenen Kachel-Zwischenspeicher (ajax/tile.php), dessen Ablage unter tiles/ nicht ins Repository gehoert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+97
-41
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once("../helper.php");
|
||||
require_once("../restricted/costs.php");
|
||||
if(!isset($_GET["year"])){
|
||||
$_GET["year"] = date("Y");
|
||||
}else{
|
||||
@@ -17,47 +18,98 @@ if(isset($_GET["type"])){
|
||||
}
|
||||
}
|
||||
|
||||
$Query = "SELECT
|
||||
SUM(gridPcons/12000) as 'Stromverbrauch',
|
||||
SUM((gridPcons*cost)/12000)+140 as 'Stromkosten (140€ fix)',
|
||||
SUM(pvP - IF(gridP < 0, -gridP,0) - IF(battP < 0, -battP,0)- heaterPwr + IF(battP > 0, battP,0))*cost/12000 as 'Verbrauchsersparnis',
|
||||
SUM((gridPfeed*gain)/12000) as 'Einspeisevergütung',
|
||||
SUM(IF(gridP < 500, heaterPwr, 0)*0.063/12000) as 'Ersparnis Heizung',
|
||||
SUM(IF(battP > 0, battP, 0)*cost/12000) as 'Ersparnis Batterie',
|
||||
AVG(autonomy) AS 'Ø Autarkie',
|
||||
(SUM(PL1_EV+PL2_EV+PL3_EV))/12 AS 'Autoladung ges. EG',
|
||||
(((SUM(IF(gridP>100,0,PL1_EV+PL2_EV+PL3_EV)))/(SUM(PL1_EV+PL2_EV+PL3_EV))))*100 AS 'Autoladung Solar EG',
|
||||
(SUM(IF(gridP>100,0,(PL1_EV+PL2_EV+PL3_EV)*cost))/12) AS 'Ersparnis Solarladung EG',
|
||||
(SUM(PL1_EV+PL2_EV+PL3_EV))/24.5 AS 'Benzin gespart EG',
|
||||
(SUM(PL1_EVog+PL2_EVog+PL3_EVog))/12 AS 'Autoladung ges. OG',
|
||||
(((SUM(IF(gridP>100,0,PL1_EVog+PL2_EVog+PL3_EVog)))/(SUM(PL1_EVog+PL2_EVog+PL3_EVog))))*100 AS 'Autoladung Solar OG',
|
||||
(SUM(IF(gridP>100,0,(PL1_EVog+PL2_EVog+PL3_EVog)*cost))/12) AS 'Ersparnis Solarladung OG',
|
||||
(SUM(PL1_EVog+PL2_EVog+PL3_EVog))/24.5 AS 'Benzin gespart OG'
|
||||
FROM EnergyFlow JOIN gridCosts ON DATE(datetime) >= DATE(gridCosts.active_date) AND DATE(datetime) <= DATE(gridCosts.end_date)
|
||||
WHERE year(datetime) = ".$_GET["year"].";";
|
||||
/**
|
||||
* Die Jahresstatistik als eine Abfrage - jetzt auf stats_daily.
|
||||
*
|
||||
* Gerechnet wird nicht mehr ueber die Rohdaten aus EnergyFlow, sondern ueber
|
||||
* die Tageswerte. Zwei Gruende:
|
||||
*
|
||||
* 1. Die Rohdaten werden nach zwoelf Monaten ausgeduennt bzw. ins
|
||||
* Stundenarchiv verschoben (solarlog-rollup.sh). Eine Kachel, die auf
|
||||
* EnergyFlow rechnet, zeigt fuer alte Jahre danach zu wenig an.
|
||||
* 2. Ein Jahr sind 365 Zeilen statt rund 105.000.
|
||||
*
|
||||
* Die Tarife bleiben unveraendert: je Zeile ein Stichtag, das Ende holt
|
||||
* LEAD() beim naechsten. Weil ein Stichtag ein DATUM ist, kann ein Tag nie
|
||||
* zwei Tarife haben - die Verdichtung auf Tage verliert hier also nichts.
|
||||
*
|
||||
* Was in stats_daily vorberechnet sein MUSS, weil es eine Bedingung je
|
||||
* Messwert auswertet und sich aus Tagessummen nicht rekonstruieren laesst:
|
||||
*
|
||||
* eigenverbrauch_kwh pv - Einspeisung - Batterieladung
|
||||
* - Heizstab + Batterieentladung. Dazu addiert
|
||||
* wird pv_fehlbetrag_kwh: bei Ausfall einzelner
|
||||
* Wechselrichter fehlt deren Beitrag in pv, alle
|
||||
* Senken sind dagegen gemessen - die Differenz
|
||||
* faellt sonst zu klein oder negativ aus.
|
||||
* heizstab_solar_kwh Heizstab, anteilig nach autonomy
|
||||
* auto_*_solar_kwh Wallbox, anteilig nach autonomy - dem vom
|
||||
* Geraet in feiner Aufloesung gerechneten
|
||||
* Nicht-Netz-Anteil der Zufuhr
|
||||
*
|
||||
* Einheiten sind in stats_daily bereits bereinigt: PL*_EV und PL*_EVog
|
||||
* liefern Kilowatt, alle uebrigen Leistungsspalten Watt. In der alten
|
||||
* Abfrage stand das als /12 gegen /12000 nebeneinander.
|
||||
*
|
||||
* Die Solaranteile teilen jetzt durch NULLIF(...): ohne Ladung im Jahr kam
|
||||
* vorher 0/0 heraus.
|
||||
*
|
||||
* "Ersparnis Batterie" rechnet den Nutzen netto: was die entladene Energie
|
||||
* aus dem Netz gekostet haette, abzueglich der Verguetung, die fuer den zum
|
||||
* Laden verwendeten Strom entgangen ist. Brutto waere die Kachel zu
|
||||
* freundlich - der Speicher ist nicht umsonst zu fuellen.
|
||||
*
|
||||
* Achtung beim Lesen: "Verbrauchsersparnis" ist der GESAMTE Eigenverbrauch
|
||||
* zum Strompreis. "Ersparnis Batterie" und "Ersparnis Solarladung" sind
|
||||
* Teilmengen davon, nach Herkunft bzw. Verwendung herausgegriffen. Sie
|
||||
* duerfen nicht addiert werden.
|
||||
*
|
||||
* Der Grundpreis fehlt weiterhin bewusst - er haengt an den Tagen des
|
||||
* Jahres, nicht an einem Messwert, und kommt aus grundpreisImJahr() dazu.
|
||||
*/
|
||||
function statistikAbfrage($jahr)
|
||||
{
|
||||
return "WITH
|
||||
preis AS (SELECT active_date, cost, gain,
|
||||
LEAD(active_date) OVER (ORDER BY active_date) AS folgt FROM gridCosts),
|
||||
gas AS (SELECT active_date, cost, kwhPerLitre,
|
||||
LEAD(active_date) OVER (ORDER BY active_date) AS folgt FROM gasCosts),
|
||||
sprit AS (SELECT active_date, cost, lPer100km, kwhPer100km,
|
||||
LEAD(active_date) OVER (ORDER BY active_date) AS folgt FROM fuelCosts)
|
||||
SELECT
|
||||
SUM(d.netz_bezug_kwh) AS 'Stromverbrauch',
|
||||
SUM(d.netz_bezug_kwh * preis.cost) AS 'Stromkosten',
|
||||
SUM((d.eigenverbrauch_kwh + IFNULL(d.pv_fehlbetrag_kwh,0)) * preis.cost) AS 'Verbrauchsersparnis',
|
||||
SUM(d.netz_einsp_kwh * preis.gain) AS 'Einspeisevergütung',
|
||||
SUM(d.heizstab_solar_kwh * gas.cost / NULLIF(gas.kwhPerLitre,0)) AS 'Ersparnis Heizung',
|
||||
SUM(d.batt_entladen_kwh * preis.cost - d.batt_laden_kwh * preis.gain) AS 'Ersparnis Batterie',
|
||||
SUM(d.autarkie_avg * d.stunden_erfasst) / NULLIF(SUM(d.stunden_erfasst),0) AS 'Ø Autarkie',
|
||||
SUM(d.auto_eg_kwh) AS 'Autoladung ges. EG',
|
||||
SUM(d.auto_eg_solar_kwh) / NULLIF(SUM(d.auto_eg_kwh),0) * 100 AS 'Autoladung Solar EG',
|
||||
SUM(d.auto_eg_solar_kwh * preis.cost) AS 'Ersparnis Solarladung EG',
|
||||
SUM(d.auto_eg_kwh * sprit.lPer100km / NULLIF(sprit.kwhPer100km,0)) AS 'Benzin gespart EG',
|
||||
SUM(d.auto_eg_kwh * sprit.lPer100km / NULLIF(sprit.kwhPer100km,0) * sprit.cost) AS 'Ersparnis Benzin EG',
|
||||
SUM(d.auto_og_kwh) AS 'Autoladung ges. OG',
|
||||
SUM(d.auto_og_solar_kwh) / NULLIF(SUM(d.auto_og_kwh),0) * 100 AS 'Autoladung Solar OG',
|
||||
SUM(d.auto_og_solar_kwh * preis.cost) AS 'Ersparnis Solarladung OG',
|
||||
SUM(d.auto_og_kwh * sprit.lPer100km / NULLIF(sprit.kwhPer100km,0)) AS 'Benzin gespart OG',
|
||||
SUM(d.auto_og_kwh * sprit.lPer100km / NULLIF(sprit.kwhPer100km,0) * sprit.cost) AS 'Ersparnis Benzin OG'
|
||||
FROM stats_daily d
|
||||
JOIN preis ON d.tag >= preis.active_date AND (preis.folgt IS NULL OR d.tag < preis.folgt)
|
||||
LEFT JOIN gas ON d.tag >= gas.active_date AND (gas.folgt IS NULL OR d.tag < gas.folgt)
|
||||
LEFT JOIN sprit ON d.tag >= sprit.active_date AND (sprit.folgt IS NULL OR d.tag < sprit.folgt)
|
||||
WHERE YEAR(d.tag) = " . intval($jahr) . ";";
|
||||
}
|
||||
|
||||
$PrevQuery = "SELECT
|
||||
SUM(gridPcons/12000) as 'Stromverbrauch',
|
||||
SUM((gridPcons*cost)/12000)+140 as 'Stromkosten (140€ fix)',
|
||||
SUM(pvP - IF(gridP < 0, -gridP,0) - IF(battP < 0, -battP,0)- heaterPwr + IF(battP > 0, battP,0))*cost/12000 as 'Verbrauchsersparnis',
|
||||
SUM((gridPfeed*gain)/12000) as 'Einspeisevergütung',
|
||||
SUM(IF(gridP < 500, heaterPwr, 0)*0.063/12000) as 'Ersparnis Heizung',
|
||||
SUM(IF(battP > 0, battP, 0)*cost/12000) as 'Ersparnis Batterie',
|
||||
AVG(autonomy) AS 'Ø Autarkie',
|
||||
(SUM(PL1_EV+PL2_EV+PL3_EV))/12 AS 'Autoladung ges. EG',
|
||||
(((SUM(IF(gridP>100,0,PL1_EV+PL2_EV+PL3_EV)))/(SUM(PL1_EV+PL2_EV+PL3_EV))))*100 AS 'Autoladung Solar EG',
|
||||
(SUM(IF(gridP>100,0,(PL1_EV+PL2_EV+PL3_EV)*cost))/12) AS 'Ersparnis Solarladung EG',
|
||||
(SUM(PL1_EV+PL2_EV+PL3_EV))/24.5 AS 'Benzin gespart EG',
|
||||
(SUM(PL1_EVog+PL2_EVog+PL3_EVog))/12 AS 'Autoladung ges. OG',
|
||||
(((SUM(IF(gridP>100,0,PL1_EVog+PL2_EVog+PL3_EVog)))/(SUM(PL1_EVog+PL2_EVog+PL3_EVog))))*100 AS 'Autoladung Solar OG',
|
||||
(SUM(IF(gridP>100,0,(PL1_EVog+PL2_EVog+PL3_EVog)*cost))/12) AS 'Ersparnis Solarladung OG',
|
||||
(SUM(PL1_EVog+PL2_EVog+PL3_EVog))/24.5 AS 'Benzin gespart OG'
|
||||
FROM EnergyFlow JOIN gridCosts ON DATE(datetime) >= DATE(gridCosts.active_date) AND DATE(datetime) <= DATE(gridCosts.end_date)
|
||||
WHERE year(datetime) = ".($_GET["year"]-1).";";
|
||||
$Query = statistikAbfrage($_GET["year"]);
|
||||
$PrevQuery = statistikAbfrage($_GET["year"] - 1);
|
||||
|
||||
|
||||
$units = Array("kWh","€","€","€","€","€","€","%","kWh","%","€","L","kWh","%","€","L");
|
||||
$LessIsBetter = Array(true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false);
|
||||
// Reihenfolge wie in der Abfrage, mit "Verg.+Einsp. Strom" an Stelle 4.
|
||||
$units = Array("kWh","€","€","€","€","€","€","%",
|
||||
"kWh","%","€","L","€",
|
||||
"kWh","%","€","L","€");
|
||||
// Nur bei Verbrauch und Kosten ist weniger besser.
|
||||
$LessIsBetter = array_merge([true, true], array_fill(0, count($units) - 2, false));
|
||||
|
||||
function array_insert($array,$values,$offset) {
|
||||
return array_slice($array, 0, $offset, true) + $values + array_slice($array, $offset, NULL, true);
|
||||
@@ -67,7 +119,7 @@ function array_insert($array,$values,$offset) {
|
||||
if (checkLogin()) {
|
||||
|
||||
$html = "<div class='row row-cols-2 row-cols-md-4 g-2 row-info'>";
|
||||
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
|
||||
$mysql = solarDb();
|
||||
$Res = mysqli_query($mysql,$Query);
|
||||
$ResPrev = mysqli_query($mysql,$PrevQuery);
|
||||
if(!$Res || !$ResPrev){
|
||||
@@ -77,13 +129,17 @@ if (checkLogin()) {
|
||||
$i = 0;
|
||||
$row = $Res->fetch_assoc();
|
||||
$rowPrev = $ResPrev->fetch_assoc();
|
||||
// Der Grundpreis faellt unabhaengig vom Verbrauch an und laesst sich
|
||||
// deshalb nicht aus den Messwerten summieren.
|
||||
$row["Stromkosten"] += grundpreisImJahr($_GET["year"]);
|
||||
$rowPrev["Stromkosten"] += grundpreisImJahr($_GET["year"] - 1);
|
||||
//$row["Vergütung+Einsparung Strom"] = $row["Einspeisevergütung"]+$row["Verbrauchsersparnis"];
|
||||
$row = array_insert($row,["Verg.+Einsp. Strom" => $row["Einspeisevergütung"]+$row["Verbrauchsersparnis"]],4);
|
||||
$rowPrev = array_insert($rowPrev,["Verg.+Einsp. Strom" => $rowPrev["Einspeisevergütung"]+$rowPrev["Verbrauchsersparnis"]],4);
|
||||
$i = 0;
|
||||
foreach ($row as $name => $value) {
|
||||
if(str_starts_with($name,"Autoladung ges.")){
|
||||
$html .= "</div><hr class='mt-2 mb-3 border-light' />";
|
||||
$html .= "</div><hr class='mt-3 mb-3 border-light' />";
|
||||
$html .= "<div class='row row-cols-2 row-cols-md-4 g-2 row-info'>";
|
||||
}
|
||||
/*$html .= "<div class='col-12 col-sm-4 col-md-2 col-xl-1'>
|
||||
|
||||
Reference in New Issue
Block a user