diff --git a/haos-addon/config.yaml b/haos-addon/config.yaml index 602160e..ae477da 100644 --- a/haos-addon/config.yaml +++ b/haos-addon/config.yaml @@ -1,5 +1,5 @@ name: ShineBridge -version: "1.8.1" +version: "1.8.2" slug: shinebridge description: Growatt Wechselrichter lokal in Home Assistant — Modbus TCP via ShineLAN-X, MQTT Discovery, Web UI url: https://gitea.bitfire.work/retr0/shinebridge diff --git a/haos-addon/src/main.py b/haos-addon/src/main.py index 6b5b9d2..4e870f2 100644 --- a/haos-addon/src/main.py +++ b/haos-addon/src/main.py @@ -407,7 +407,8 @@ def api_period_energy(): entry["label"] = f"{pd.strftime('%d.%m.%Y')} – {(end_d - datetime.timedelta(days=1)).strftime('%d.%m.%Y')}" pd_start_ts = datetime.datetime.combine(pd, datetime.time.min).timestamp() - for agg_id in ("grid_import_kwh", "grid_export_kwh"): + for agg_id in ("grid_import_kwh", "grid_export_kwh", + "bat_discharge_total", "bat_charge_total"): cur = agg.get(agg_id) if cur is None: continue @@ -416,23 +417,27 @@ def api_period_energy(): if val is not None: entry[agg_id] = round(val, 2) - # Kostenberechnung: Festpreis oder Börsenpreis + # Effektiver Importpreis (Festpreis oder Börsenpreis) + eff_price = price_import + if tariff_type == "spot": + avg_ct = _get_avg_spot_price(pd_start_ts, now_ts, spot_country) + if avg_ct is not None: + eff_price = (avg_ct + spot_markup) / 100 + entry["spot_avg_ct"] = avg_ct + entry["spot_markup_ct"] = spot_markup + entry["effective_price"]= round(eff_price, 4) + if "grid_import_kwh" in entry: - if tariff_type == "spot": - avg_ct = _get_avg_spot_price(pd_start_ts, now_ts, spot_country) - if avg_ct is not None: - eff_price = (avg_ct + spot_markup) / 100 # ct/kWh → €/kWh - entry["import_cost"] = round(entry["grid_import_kwh"] * eff_price, 2) - entry["spot_avg_ct"] = avg_ct - entry["spot_markup_ct"] = spot_markup - entry["effective_price"]= round(eff_price, 4) - else: - entry["import_cost"] = round(entry["grid_import_kwh"] * price_import, 2) - else: - entry["import_cost"] = round(entry["grid_import_kwh"] * price_import, 2) + entry["import_cost"] = round(entry["grid_import_kwh"] * eff_price, 2) if "grid_export_kwh" in entry: entry["export_revenue"] = round(entry["grid_export_kwh"] * price_export, 2) + # Eigenverbrauch-Ersparnis: Batterie-Entladung (→ Haus + Auto) zu Importpreis + bat_dch = entry.get("bat_discharge_total") + if bat_dch is not None: + entry["savings_kwh"] = bat_dch + entry["savings_eur"] = round(bat_dch * eff_price, 2) + result[period_type] = entry return jsonify(result) diff --git a/haos-addon/src/web/index.html b/haos-addon/src/web/index.html index 2e237b7..361b0c3 100644 --- a/haos-addon/src/web/index.html +++ b/haos-addon/src/web/index.html @@ -604,19 +604,26 @@ function renderEnergy(inverters, aggregates, period, spotData) { `; } - function sectionCards(title, data, col) { + function sectionCards(title, data) { const impSub = data.spot_avg_ct != null ? `Ø ${data.spot_avg_ct.toFixed(1)} + ${(data.spot_markup_ct||0).toFixed(1)} ct/kWh` : ''; const imp = periodCard('Netzbezug', data.grid_import_kwh, data.import_cost, C.imp, impSub); const exp = periodCard('Einspeisung', data.grid_export_kwh, data.export_revenue, C.exp, ''); - if (!imp && !exp) return ''; + const sav = data.savings_kwh != null + ? `
+
${fKwh(data.savings_kwh)}
+ ${data.savings_eur != null ? `
${fEur(data.savings_eur)} gespart
` : ''} +
Eigenversorgung
Batterie → Haus & Auto
+
` + : ''; + if (!imp && !exp && !sav) return ''; return `
${title}
-
${imp}${exp}
`; +
${imp}${exp}${sav}
`; } - const cards = sectionCards(mon.label || 'Diesen Monat', mon, C.imp) + - sectionCards(yr.label || 'Dieses Jahr', yr, C.imp); + const cards = sectionCards(mon.label || 'Diesen Monat', mon) + + sectionCards(yr.label || 'Dieses Jahr', yr); const spotHtml = (period.spot_chart !== false) ? renderSpotChart(spotData) : '';