.md Report erzeugung in eigene Routinen
This commit is contained in:
+154
-112
@@ -24,6 +24,8 @@ import math
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from report_md import report_md
|
||||
|
||||
KJ_PER_KWH = 3600.0
|
||||
TAGE_PRO_JAHR = 365.0
|
||||
|
||||
@@ -241,6 +243,115 @@ def brennstoffkosten(e: dict, cfg: dict) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def container_invest_total(sp: dict, cfg: dict) -> dict:
|
||||
"""Investitionssumme aller Container-Module aus der container_invest-Config."""
|
||||
ci = cfg["container_invest"]
|
||||
masse = sp["masse_kg"]
|
||||
energie = sp["energie_pro_zyklus_kWh"]
|
||||
anzahl = ci["anzahl_module_dauerbetrieb"]
|
||||
|
||||
pcm_eur = masse * ci["pcm_natriumacetat"]["preis_eur_pro_kg"] * ci["pcm_natriumacetat"]["reserve_faktor"]
|
||||
behaelter_eur = max(ci["behaelter"]["mindestpreis_eur"],
|
||||
masse * ci["behaelter"]["preis_eur_pro_kg_pcm"])
|
||||
wt_eur = (ci["waermetauscher_ladung"]["preis_eur"]
|
||||
+ ci["waermetauscher_entladung"]["preis_eur"])
|
||||
hydraulik_eur = ci["hydraulik"]["preis_eur"]
|
||||
el = ci["elektronik"]
|
||||
elektronik_eur = (el["steuerung_eur"]
|
||||
+ el["sensoren_pt100_anzahl"] * el["sensor_preis_eur"]
|
||||
+ el["ventile_schaltschrank_eur"]
|
||||
+ el["fernueberwachung_4g_eur"]
|
||||
+ el["montage_verdrahtung_eur"])
|
||||
montage_eur = ci["montage_inbetriebnahme_eur"]
|
||||
|
||||
pro_modul = pcm_eur + behaelter_eur + wt_eur + hydraulik_eur + elektronik_eur + montage_eur
|
||||
gesamt = pro_modul * anzahl
|
||||
eur_pro_kwh = gesamt / (energie * anzahl) if energie > 0 else 0.0
|
||||
|
||||
return {
|
||||
"anzahl_module": anzahl,
|
||||
"pcm_eur": pcm_eur * anzahl,
|
||||
"behaelter_eur": behaelter_eur * anzahl,
|
||||
"wt_hydraulik_eur": (wt_eur + hydraulik_eur) * anzahl,
|
||||
"elektronik_eur": elektronik_eur * anzahl,
|
||||
"montage_eur": montage_eur * anzahl,
|
||||
"gesamt_eur": gesamt,
|
||||
"eur_pro_kwh_kapazitaet": eur_pro_kwh,
|
||||
}
|
||||
|
||||
|
||||
def anbieterkosten(e: dict, cfg: dict) -> dict:
|
||||
"""Jaehrliche Betriebskosten des Anbieters -> Gestehungskosten und Marge.
|
||||
|
||||
Abschreibung: linear ohne Kapitalzins (konservativ).
|
||||
Strombedarf: Netzbezug zum Netzpreis, PV-Eigenanteil zu LCOE-Gestehungskosten.
|
||||
"""
|
||||
a = cfg["anbieter"]
|
||||
inv = a["invest"]
|
||||
wp = e["waermepumpe"]
|
||||
sp = e["speicher"]
|
||||
pv_data = e["pv"]
|
||||
netz = e["netzbezug"]
|
||||
bat = e["batterie"]
|
||||
|
||||
energie_jahr = wp["speicher_kWh_tag"] * TAGE_PRO_JAHR
|
||||
fuhren_jahr = TAGE_PRO_JAHR / cfg["abholung"]["zyklus_tage"]
|
||||
|
||||
kosten_transport = fuhren_jahr * a["transport_eur_pro_fuhre"]
|
||||
|
||||
netz_eur = netz["netzbezug_kWh"] * a["netzstrompreis_ct_kWh"] / 100.0
|
||||
pv_kwh = netz["jahresbedarf_kWh"] - netz["netzbezug_kWh"]
|
||||
pv_eur = pv_kwh * a["pv_gestehung_ct_kWh"] / 100.0
|
||||
kosten_strom = netz_eur + pv_eur
|
||||
|
||||
kosten_wartung = a["wartung_eur_pro_jahr"]
|
||||
|
||||
kapital_pv = pv_data["kWp"] * inv["pv_eur_pro_kWp"] / inv["pv_nutzungsdauer_jahre"]
|
||||
kapital_bat = bat["nominal_kWh"] * inv["batterie_eur_pro_kWh"] / inv["batterie_nutzungsdauer_jahre"]
|
||||
kapital_wp = inv["waermepumpe_eur"] / inv["waermepumpe_nutzungsdauer_jahre"]
|
||||
ci = container_invest_total(sp, cfg)
|
||||
kapital_speicher = ci["gesamt_eur"] / inv["speicher_nutzungsdauer_jahre"]
|
||||
kosten_kapital = kapital_pv + kapital_bat + kapital_wp + kapital_speicher
|
||||
|
||||
jahreskosten = kosten_transport + kosten_strom + kosten_wartung + kosten_kapital
|
||||
gestehung_ct = jahreskosten / energie_jahr * 100.0 if energie_jahr > 0 else 0.0
|
||||
|
||||
marge = []
|
||||
for v in e.get("brennstoffkosten", {}).get("vergleich", []):
|
||||
m_ct = v["nutzwaerme_ct_kWh"] - gestehung_ct
|
||||
marge.append({
|
||||
"name": v["name"],
|
||||
"nutzwaerme_ct_kWh": v["nutzwaerme_ct_kWh"],
|
||||
"marge_ct_kWh": m_ct,
|
||||
"marge_eur_jahr": m_ct / 100.0 * energie_jahr,
|
||||
})
|
||||
|
||||
return {
|
||||
"fuhren_jahr": fuhren_jahr,
|
||||
"energie_jahr_kWh": energie_jahr,
|
||||
"kosten_transport_eur": kosten_transport,
|
||||
"kosten_strom_eur": kosten_strom,
|
||||
"kosten_strom_detail": {
|
||||
"netz_kWh": netz["netzbezug_kWh"],
|
||||
"netz_ct_kWh": a["netzstrompreis_ct_kWh"],
|
||||
"netz_eur": netz_eur,
|
||||
"pv_kWh": pv_kwh,
|
||||
"pv_ct_kWh": a["pv_gestehung_ct_kWh"],
|
||||
"pv_eur": pv_eur,
|
||||
},
|
||||
"kosten_wartung_eur": kosten_wartung,
|
||||
"kapital_pv_eur": kapital_pv,
|
||||
"kapital_batterie_eur": kapital_bat,
|
||||
"kapital_waermepumpe_eur": kapital_wp,
|
||||
"kapital_speicher_eur": kapital_speicher,
|
||||
"kosten_kapital_eur": kosten_kapital,
|
||||
"jahreskosten_eur": jahreskosten,
|
||||
"gestehungskosten_ct_kWh": gestehung_ct,
|
||||
"container_invest": ci,
|
||||
"marge": marge,
|
||||
}
|
||||
|
||||
|
||||
def rechne(milch_l_tag: float, cfg: dict) -> dict:
|
||||
q_milch = milch_kuehllast(milch_l_tag, cfg)
|
||||
wp = waermepumpe(q_milch, cfg)
|
||||
@@ -261,6 +372,8 @@ def rechne(milch_l_tag: float, cfg: dict) -> dict:
|
||||
}
|
||||
if "brennstoffe" in cfg:
|
||||
e["brennstoffkosten"] = brennstoffkosten(e, cfg)
|
||||
if "anbieter" in cfg and "container_invest" in cfg:
|
||||
e["anbieter"] = anbieterkosten(e, cfg)
|
||||
return e
|
||||
|
||||
|
||||
@@ -416,122 +529,51 @@ def report(e: dict, cfg: dict) -> str:
|
||||
f"{v['eur_pro_lkw']:>9.0f} | {v['eur_pro_jahr']:>9.0f}")
|
||||
L.append(f" Bewertet: voller LKW ~{bk['energie_lkw_kWh']:.0f} kWh, "
|
||||
f"Jahreserzeugung ~{bk['energie_jahr_kWh']:.0f} kWh")
|
||||
ak = e.get("anbieter")
|
||||
if ak:
|
||||
inv = cfg["anbieter"]["invest"]
|
||||
ci = ak["container_invest"]
|
||||
sd = ak["kosten_strom_detail"]
|
||||
L.append("")
|
||||
L.append("WAERME-GESTEHUNGSKOSTEN ANBIETER (linear, kein Kapitalzins)")
|
||||
L.append(f" Transport ({ak['fuhren_jahr']:.0f} Fuhren/a) ........"
|
||||
f" {ak['kosten_transport_eur']:>8.0f} EUR/a")
|
||||
L.append(f" WP-Strom ({sd['netz_kWh']:.0f} kWh Netz"
|
||||
f" @ {sd['netz_ct_kWh']:.0f} ct + {sd['pv_kWh']:.0f} kWh PV"
|
||||
f" @ {sd['pv_ct_kWh']:.0f} ct) .. {ak['kosten_strom_eur']:>6.0f} EUR/a")
|
||||
L.append(f" Wartung .......................... {ak['kosten_wartung_eur']:>8.0f} EUR/a")
|
||||
L.append(f" Kapital PV ({pv['kWp']:.1f} kWp, {inv['pv_nutzungsdauer_jahre']} J) ......"
|
||||
f" {ak['kapital_pv_eur']:>8.0f} EUR/a")
|
||||
L.append(f" Kapital Batterie ({bat['nominal_kWh']:.0f} kWh, {inv['batterie_nutzungsdauer_jahre']} J) ."
|
||||
f" {ak['kapital_batterie_eur']:>8.0f} EUR/a")
|
||||
L.append(f" Kapital WP ({inv['waermepumpe_nutzungsdauer_jahre']} J) ............."
|
||||
f" {ak['kapital_waermepumpe_eur']:>8.0f} EUR/a")
|
||||
L.append(f" Kapital Speicher ({ci['anzahl_module']} Module, {inv['speicher_nutzungsdauer_jahre']} J)"
|
||||
f" {ak['kapital_speicher_eur']:>8.0f} EUR/a")
|
||||
L.append(f" {'-'*46}")
|
||||
L.append(f" Jahreskosten gesamt .............. {ak['jahreskosten_eur']:>8.0f} EUR/a")
|
||||
L.append(f" Jahreserzeugung .................. {ak['energie_jahr_kWh']:>8.0f} kWh/a")
|
||||
L.append(f" -> Mindestverkaufspreis .......... {ak['gestehungskosten_ct_kWh']:>8.1f} ct/kWh")
|
||||
L.append(f" Speicher-Invest ({ci['anzahl_module']} Module): {ci['gesamt_eur']:,.0f} EUR"
|
||||
f" = {ci['eur_pro_kwh_kapazitaet']:.0f} EUR/kWh Kapazitaet")
|
||||
L.append(f" PCM {ci['pcm_eur']:,.0f} | Behaelter {ci['behaelter_eur']:,.0f}"
|
||||
f" | WT+Hydr. {ci['wt_hydraulik_eur']:,.0f}"
|
||||
f" | Elektr. {ci['elektronik_eur']:,.0f} | Montage {ci['montage_eur']:,.0f}")
|
||||
if ak["marge"]:
|
||||
L.append("")
|
||||
L.append("MARGE GEGEN ERSATZBRENNSTOFF")
|
||||
L.append(f" {'Brennstoff':<10} | {'ct/kWh':>7} | {'Marge ct/kWh':>12} | {'Marge EUR/Jahr':>14}")
|
||||
L.append(f" {'-'*10}-+-{'-'*7}-+-{'-'*12}-+-{'-'*14}")
|
||||
for m in ak["marge"]:
|
||||
haertester = " <== haertester Massstab" if m == ak["marge"][-1] else ""
|
||||
L.append(f" {m['name']:<10} | {m['nutzwaerme_ct_kWh']:>7.1f} |"
|
||||
f" {m['marge_ct_kWh']:>+12.1f} |"
|
||||
f" {m['marge_eur_jahr']:>+14.0f}{haertester}")
|
||||
L.append("=" * 62)
|
||||
return "\n".join(L)
|
||||
|
||||
|
||||
def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str:
|
||||
q = e["milch_kuehllast_kWh_tag"]
|
||||
wp = e["waermepumpe"]
|
||||
sp = e["speicher"]
|
||||
pv = e["pv"]
|
||||
netz = e["netzbezug"]
|
||||
bat = e["batterie"]
|
||||
hh = e["haushalte"]
|
||||
z = cfg["abholung"]["zyklus_tage"]
|
||||
milch = e["eingang"]["milch_l_tag"]
|
||||
ts = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
|
||||
|
||||
L = []
|
||||
L.append("# Auslegung Waermerueckgewinnung Milchkuehlung")
|
||||
L.append("")
|
||||
L.append(f"**Erstellt:** {ts}")
|
||||
L.append(f"**Eingang:** {milch:.0f} L Milch/Tag"
|
||||
f" ({cfg['milch']['temp_ein_C']:.0f} -> {cfg['milch']['temp_aus_C']:.0f} C)")
|
||||
if quelldateien:
|
||||
L.append(f"**Konfiguration:** {', '.join(quelldateien)}")
|
||||
L.append("")
|
||||
L.append(f"**Kuehllast der Milch:** {q:.1f} kWh/Tag")
|
||||
L.append("")
|
||||
|
||||
L.append("## Waermepumpe")
|
||||
L.append(f"COP {cfg['waermepumpe']['cop']:.2f}, Laufzeit {cfg['waermepumpe']['laufzeit_h_pro_tag']:.0f} h/Tag")
|
||||
L.append("")
|
||||
L.append("| Kenngroesse | Wert |")
|
||||
L.append("|-------------|------|")
|
||||
L.append(f"| Kaelteleistung (Verdampfer) | {wp['kaelteleistung_kW']:.1f} kW |")
|
||||
L.append(f"| Heizleistung (Kondensator) | {wp['heizleistung_kW']:.1f} kW |")
|
||||
L.append(f"| el. Leistung | {wp['elektrische_leistung_kW']:.1f} kW |")
|
||||
L.append(f"| Strombedarf | {wp['strom_kWh_tag']:.1f} kWh/Tag |")
|
||||
L.append(f"| Waerme in den Speicher | {wp['speicher_kWh_tag']:.1f} kWh/Tag |")
|
||||
L.append("")
|
||||
|
||||
L.append("## PV-Anlage (Jahresbilanz)")
|
||||
L.append("")
|
||||
L.append("| Kenngroesse | Wert |")
|
||||
L.append("|-------------|------|")
|
||||
L.append(f"| Jahresstrombedarf WP | {pv['jahresbedarf_kWh']:.0f} kWh/a |")
|
||||
L.append(f"| Leistung | {pv['kWp']:.1f} kWp |")
|
||||
L.append(f"| Dachflaeche | {pv['flaeche_m2']:.0f} m2 |")
|
||||
L.append("")
|
||||
|
||||
L.append("## Netzbezug (Wintermonate, Monatsbilanz)")
|
||||
L.append("")
|
||||
L.append("| Kenngroesse | Wert |")
|
||||
L.append("|-------------|------|")
|
||||
L.append(f"| Netzbezug | {netz['netzbezug_kWh']:.0f} kWh/a = {netz['netzbezug_anteil']*100:.0f} % |")
|
||||
L.append(f"| Sommerueberschuss | {netz['ueberschuss_kWh']:.0f} kWh/a |")
|
||||
L.append("")
|
||||
L.append("### Monatsbilanz")
|
||||
L.append("")
|
||||
L.append("| Monat | Bedarf kWh | PV kWh | Zukauf kWh |")
|
||||
L.append("|-------|-----------|--------|-----------|")
|
||||
for monat, werte in netz["monate"].items():
|
||||
L.append(f"| {monat} | {werte['bedarf_kWh']:.0f} | {werte['pv_kWh']:.0f} | {werte['zukauf_kWh']:.0f} |")
|
||||
L.append("")
|
||||
|
||||
L.append("## Batterie (Tag-/Nacht-Ueberbbrueckung)")
|
||||
L.append("")
|
||||
L.append("| Kenngroesse | Wert |")
|
||||
L.append("|-------------|------|")
|
||||
L.append(f"| nutzbare Kapazitaet | {bat['nutzbar_kWh']:.1f} kWh |")
|
||||
L.append(f"| Nennkapazitaet | {bat['nominal_kWh']:.1f} kWh |")
|
||||
L.append("")
|
||||
|
||||
L.append(f"## Versorgte Haushalte ({cfg['haushalt']['erwachsene']} Erw. + {cfg['haushalt']['kinder']} Kinder)")
|
||||
L.append("")
|
||||
L.append("| Kenngroesse | Wert |")
|
||||
L.append("|-------------|------|")
|
||||
L.append(f"| Warmwasser je Haushalt | {hh['ww_pro_haushalt_kWh_tag']:.1f} kWh/Tag |")
|
||||
L.append(f"| Warmwasser ganzjaehrig | {hh['haushalte_warmwasser']:.1f} Haushalte |")
|
||||
L.append(f"| max. Heizbedarf Winter | {hh['heizbedarf_winter_kWh_tag']:.1f} kWh/Tag/HH |")
|
||||
L.append(f"| Winterbedarf (Heiz+WW) | {hh['winter_pro_haushalt_kWh_tag']:.1f} kWh/Tag/HH |")
|
||||
L.append(f"| im Winter | {hh['haushalte_winter']:.1f} Haushalte |")
|
||||
L.append("")
|
||||
|
||||
passt = "ja" if sp["passt_in_einen_lkw"] else "NEIN - mehrere Behaelter noetig"
|
||||
L.append(f"## Latentspeicher ({cfg['pcm']['name']}, Modus: {cfg['pcm']['modus']})")
|
||||
L.append("")
|
||||
L.append("| Kenngroesse | Wert |")
|
||||
L.append("|-------------|------|")
|
||||
L.append(f"| Energiedichte | {sp['energiedichte_kWh_pro_kg']*1000:.1f} Wh/kg |")
|
||||
L.append(f"| Energie je Zyklus ({z} Tage) | {sp['energie_pro_zyklus_kWh']:.0f} kWh |")
|
||||
L.append(f"| Masse | {sp['masse_kg']:.0f} kg |")
|
||||
L.append(f"| Volumen | {sp['volumen_m3']:.1f} m3 |")
|
||||
L.append(f"| LKW-Auslastung Gewicht | {sp['auslastung_gewicht']*100:.0f} % |")
|
||||
L.append(f"| LKW-Auslastung Volumen | {sp['auslastung_volumen']*100:.0f} % |")
|
||||
L.append(f"| bindende Grenze | {sp['bindende_grenze']} |")
|
||||
L.append(f"| passt in einen LKW | {passt} |")
|
||||
L.append(f"| voller LKW nach | {sp['voller_lkw_tausch_tage']:.1f} Tagen |")
|
||||
L.append(f"| Energieinhalt voller LKW | {sp['voller_lkw_energie_kWh']:.0f} kWh |")
|
||||
|
||||
bk = e.get("brennstoffkosten")
|
||||
if bk and bk["vergleich"]:
|
||||
L.append("")
|
||||
L.append("## Wert der Waerme beim Kaeufer (Ersatzkosten fossil/Holz)")
|
||||
L.append("")
|
||||
L.append(f"Bewertet: voller LKW ~{bk['energie_lkw_kWh']:.0f} kWh, "
|
||||
f"Jahreserzeugung ~{bk['energie_jahr_kWh']:.0f} kWh")
|
||||
L.append("")
|
||||
L.append("| Brennstoff | ct/kWh (Nutzw.) | EUR/LKW | EUR/Jahr |")
|
||||
L.append("|------------|-----------------|---------|----------|")
|
||||
for v in bk["vergleich"]:
|
||||
L.append(f"| {v['name']} | {v['nutzwaerme_ct_kWh']:.1f} | "
|
||||
f"{v['eur_pro_lkw']:.0f} | {v['eur_pro_jahr']:.0f} |")
|
||||
L.append("")
|
||||
L.append("*ct/kWh = Brennstoffpreis ÷ Kesselwirkungsgrad*")
|
||||
|
||||
return "\n".join(L)
|
||||
# report_md wurde nach lib/report_md.py ausgelagert und oben importiert.
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
||||
Reference in New Issue
Block a user