from datetime import datetime import numpy as np def replace_nan_with_none(data): if isinstance(data, dict): return {key: replace_nan_with_none(value) for key, value in data.items()} elif isinstance(data, list): return [replace_nan_with_none(element) for element in data] elif isinstance(data, np.ndarray): # Konvertiere das numpy-Array zu einer Liste und rekursiv ersetzen return replace_nan_with_none(data.tolist()) elif isinstance(data, (float, np.floating)) and np.isnan(data): # np.floating deckt auch numpy-NaNs ab return None else: return data class EnergieManagementSystem: def __init__( self, pv_prognose_wh=None, strompreis_euro_pro_wh=None, einspeiseverguetung_euro_pro_wh=None, eauto=None, gesamtlast=None, haushaltsgeraet=None, wechselrichter=None, ): self.akku = wechselrichter.akku # self.lastkurve_wh = lastkurve_wh self.gesamtlast = gesamtlast self.pv_prognose_wh = pv_prognose_wh self.strompreis_euro_pro_wh = ( strompreis_euro_pro_wh # Strompreis in Cent pro Wh ) self.einspeiseverguetung_euro_pro_wh = ( einspeiseverguetung_euro_pro_wh # Einspeisevergütung in Cent pro Wh ) self.eauto = eauto self.haushaltsgeraet = haushaltsgeraet self.wechselrichter = wechselrichter def set_akku_discharge_hours(self, ds): self.akku.set_discharge_per_hour(ds) def set_eauto_charge_hours(self, ds): self.eauto.set_charge_per_hour(ds) def set_haushaltsgeraet_start(self, ds, global_start_hour=0): self.haushaltsgeraet.set_startzeitpunkt(ds, global_start_hour=global_start_hour) def reset(self): self.eauto.reset() self.akku.reset() def simuliere_ab_jetzt(self): jetzt = datetime.now() start_stunde = jetzt.hour # Berechne die Anzahl der Stunden bis zum gleichen Zeitpunkt am nächsten Tag stunden_bis_ende_tag = 24 - start_stunde # Füge diese Stunden zum nächsten Tag hinzu gesamt_stunden = stunden_bis_ende_tag + 24 # Beginne die Simulation ab der aktuellen Stunde und führe sie für die berechnete Dauer aus return self.simuliere(start_stunde) def simuliere(self, start_stunde): lastkurve_wh = self.gesamtlast # Anzahl der Stunden berechnen assert ( len(lastkurve_wh) == len(self.pv_prognose_wh) == len(self.strompreis_euro_pro_wh) ), f"Arraygrößen stimmen nicht überein: Lastkurve = {len(lastkurve_wh)}, PV-Prognose = {len(self.pv_prognose_wh)}, Strompreis = {len(self.strompreis_euro_pro_wh)}" ende = min( len(lastkurve_wh), len(self.pv_prognose_wh), len(self.strompreis_euro_pro_wh), ) total_hours = ende - start_stunde # Initialisierung der Arrays mit NaN-Werten last_wh_pro_stunde = np.full(total_hours, np.nan) netzeinspeisung_wh_pro_stunde = np.full(total_hours, np.nan) netzbezug_wh_pro_stunde = np.full(total_hours, np.nan) kosten_euro_pro_stunde = np.full(total_hours, np.nan) einnahmen_euro_pro_stunde = np.full(total_hours, np.nan) akku_soc_pro_stunde = np.full(total_hours, np.nan) eauto_soc_pro_stunde = np.full(total_hours, np.nan) verluste_wh_pro_stunde = np.full(total_hours, np.nan) haushaltsgeraet_wh_pro_stunde = np.full(total_hours, np.nan) # Setze den initialen Ladezustand für Akku und E-Auto akku_soc_pro_stunde[start_stunde] = self.akku.ladezustand_in_prozent() if self.eauto: eauto_soc_pro_stunde[start_stunde] = self.eauto.ladezustand_in_prozent() for stunde in range(start_stunde + 1, ende): stunde_since_now = stunde - start_stunde # print(stunde_since_now) # Anfangszustände akku_soc_start = self.akku.ladezustand_in_prozent() eauto_soc_start = ( self.eauto.ladezustand_in_prozent() if self.eauto else None ) # Verbrauch und zusätzliche Lasten bestimmen verbrauch = self.gesamtlast[stunde] haushalts_last = 0 if self.haushaltsgeraet is not None: haushalts_last = self.haushaltsgeraet.get_last_fuer_stunde(stunde) verbrauch += haushalts_last haushaltsgeraet_wh_pro_stunde[stunde_since_now] = haushalts_last # PV-Erzeugung und Strompreis für die Stunde erzeugung = self.pv_prognose_wh[stunde] strompreis = self.strompreis_euro_pro_wh[stunde] # Verluste initialisieren verluste_wh_pro_stunde[stunde_since_now] = 0.0 # E-Auto-Verbrauch bestimmen if self.eauto: geladene_menge_eauto, verluste_eauto = self.eauto.energie_laden( None, stunde ) verbrauch += geladene_menge_eauto verluste_wh_pro_stunde[stunde_since_now] += verluste_eauto eauto_soc_pro_stunde[stunde_since_now] = ( self.eauto.ladezustand_in_prozent() ) # Wechselrichter-Logik netzeinspeisung, netzbezug, verluste, eigenverbrauch = ( self.wechselrichter.energie_verarbeiten(erzeugung, verbrauch, stunde) ) # Ergebnisse speichern netzeinspeisung_wh_pro_stunde[stunde_since_now] = netzeinspeisung netzbezug_wh_pro_stunde[stunde_since_now] = netzbezug verluste_wh_pro_stunde[stunde_since_now] += verluste last_wh_pro_stunde[stunde_since_now] = verbrauch # Finanzen berechnen kosten_euro_pro_stunde[stunde_since_now] = netzbezug * strompreis einnahmen_euro_pro_stunde[stunde_since_now] = ( netzeinspeisung * self.einspeiseverguetung_euro_pro_wh[stunde] ) # Letzter Akkuzustand speichern akku_soc_pro_stunde[stunde_since_now] = self.akku.ladezustand_in_prozent() # Gesamtkosten berechnen gesamtkosten_euro = np.nansum(kosten_euro_pro_stunde) - np.nansum( einnahmen_euro_pro_stunde ) out = { "Last_Wh_pro_Stunde": last_wh_pro_stunde, "Netzeinspeisung_Wh_pro_Stunde": netzeinspeisung_wh_pro_stunde, "Netzbezug_Wh_pro_Stunde": netzbezug_wh_pro_stunde, "Kosten_Euro_pro_Stunde": kosten_euro_pro_stunde, "akku_soc_pro_stunde": akku_soc_pro_stunde, "Einnahmen_Euro_pro_Stunde": einnahmen_euro_pro_stunde, "Gesamtbilanz_Euro": gesamtkosten_euro, "E-Auto_SoC_pro_Stunde": eauto_soc_pro_stunde, "Gesamteinnahmen_Euro": np.nansum(einnahmen_euro_pro_stunde), "Gesamtkosten_Euro": np.nansum(kosten_euro_pro_stunde), "Verluste_Pro_Stunde": verluste_wh_pro_stunde, "Gesamt_Verluste": np.nansum(verluste_wh_pro_stunde), "Haushaltsgeraet_wh_pro_stunde": haushaltsgeraet_wh_pro_stunde, } out = replace_nan_with_none(out) return out