diff --git a/modules/class_ems.py b/modules/class_ems.py index fbe365c..882966e 100644 --- a/modules/class_ems.py +++ b/modules/class_ems.py @@ -1,32 +1,129 @@ +# class EnergieManagementSystem: + # def __init__(self, akku, lastkurve_wh, pv_prognose_wh): + # self.akku = akku + # self.lastkurve_wh = lastkurve_wh + # self.pv_prognose_wh = pv_prognose_wh + + # def simuliere(self): + # eigenverbrauch_wh = 0 + # netzeinspeisung_wh = 0 + # netzbezug_wh = 0 + + # for stunde in range(len(self.lastkurve_wh)): + # verbrauch = self.lastkurve_wh[stunde] + # erzeugung = self.pv_prognose_wh[stunde] + + # if erzeugung > verbrauch: + # überschuss = erzeugung - verbrauch + # eigenverbrauch_wh += verbrauch + # geladene_energie = min(überschuss, self.akku.kapazitaet_wh - self.akku.soc_wh) + # self.akku.energie_laden(geladene_energie) + # netzeinspeisung_wh += überschuss - geladene_energie + # else: + # eigenverbrauch_wh += erzeugung + # benötigte_energie = verbrauch - erzeugung + # aus_akku = self.akku.energie_abgeben(benötigte_energie) + # netzbezug_wh += benötigte_energie - aus_akku + + # return { + # 'Eigenverbrauch_Wh': eigenverbrauch_wh, + # 'Netzeinspeisung_Wh': netzeinspeisung_wh, + # 'Netzbezug_Wh': netzbezug_wh + # } + + class EnergieManagementSystem: - def __init__(self, akku, lastkurve_wh, pv_prognose_wh): + def __init__(self, akku, lastkurve_wh, pv_prognose_wh, strompreis_cent_pro_wh, einspeiseverguetung_cent_pro_wh): self.akku = akku self.lastkurve_wh = lastkurve_wh self.pv_prognose_wh = pv_prognose_wh - + self.strompreis_cent_pro_wh = strompreis_cent_pro_wh # Strompreis in Cent pro Wh + self.einspeiseverguetung_cent_pro_wh = einspeiseverguetung_cent_pro_wh # Einspeisevergütung in Cent pro Wh def simuliere(self): - eigenverbrauch_wh = 0 - netzeinspeisung_wh = 0 - netzbezug_wh = 0 + eigenverbrauch_wh_pro_stunde = [] + netzeinspeisung_wh_pro_stunde = [] + netzbezug_wh_pro_stunde = [] + kosten_euro_pro_stunde = [] + einnahmen_euro_pro_stunde = [] + akku_soc_pro_stunde = [] for stunde in range(len(self.lastkurve_wh)): verbrauch = self.lastkurve_wh[stunde] erzeugung = self.pv_prognose_wh[stunde] + strompreis = self.strompreis_cent_pro_wh[stunde] + + stündlicher_netzbezug_wh = 0 + stündliche_kosten_euro = 0 + stündliche_einnahmen_euro = 0 if erzeugung > verbrauch: überschuss = erzeugung - verbrauch - eigenverbrauch_wh += verbrauch geladene_energie = min(überschuss, self.akku.kapazitaet_wh - self.akku.soc_wh) self.akku.energie_laden(geladene_energie) - netzeinspeisung_wh += überschuss - geladene_energie + netzeinspeisung_wh_pro_stunde.append(überschuss - geladene_energie) + eigenverbrauch_wh_pro_stunde.append(verbrauch) + stündliche_einnahmen_euro = (überschuss - geladene_energie) * self.einspeiseverguetung_cent_pro_wh[stunde] / 100 + netzbezug_wh_pro_stunde.append(0.0) else: - eigenverbrauch_wh += erzeugung + netzeinspeisung_wh_pro_stunde.append(0.0) benötigte_energie = verbrauch - erzeugung aus_akku = self.akku.energie_abgeben(benötigte_energie) - netzbezug_wh += benötigte_energie - aus_akku + stündlicher_netzbezug_wh = benötigte_energie - aus_akku + netzbezug_wh_pro_stunde.append(stündlicher_netzbezug_wh) + eigenverbrauch_wh_pro_stunde.append(erzeugung) + stündliche_kosten_euro = stündlicher_netzbezug_wh * strompreis / 100 + akku_soc_pro_stunde.append(self.akku.ladezustand_in_prozent()) + kosten_euro_pro_stunde.append(stündliche_kosten_euro) + einnahmen_euro_pro_stunde.append(stündliche_einnahmen_euro) + + # Berechnung der Gesamtbilanzen + gesamtkosten_euro = sum(kosten_euro_pro_stunde) - sum(einnahmen_euro_pro_stunde) return { - 'Eigenverbrauch_Wh': eigenverbrauch_wh, - 'Netzeinspeisung_Wh': netzeinspeisung_wh, - 'Netzbezug_Wh': netzbezug_wh + 'Eigenverbrauch_Wh_pro_Stunde': eigenverbrauch_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, + 'Gesamtkosten_Euro': gesamtkosten_euro } + + # def simuliere(self): + # eigenverbrauch_wh = 0 + # netzeinspeisung_wh = 0 + # netzbezug_wh = 0 + # kosten_euro = 0 + # einnahmen_euro = 0 + + # for stunde in range(len(self.lastkurve_wh)): + # verbrauch = self.lastkurve_wh[stunde] + # erzeugung = self.pv_prognose_wh[stunde] + # strompreis = self.strompreis_cent_pro_wh[stunde] + + # if erzeugung > verbrauch: + # überschuss = erzeugung - verbrauch + # eigenverbrauch_wh += verbrauch + # geladene_energie = min(überschuss, self.akku.kapazitaet_wh - self.akku.soc_wh) + # self.akku.energie_laden(geladene_energie) + # netzeinspeisung_wh += überschuss - geladene_energie + # einnahmen_euro += (überschuss - geladene_energie) * self.einspeiseverguetung_cent_pro_wh[stunde] / 100 + # else: + # eigenverbrauch_wh += erzeugung + # benötigte_energie = verbrauch - erzeugung + # aus_akku = self.akku.energie_abgeben(benötigte_energie) + # netzbezug_wh += benötigte_energie - aus_akku + # print(strompreis) + + # kosten_euro += (benötigte_energie - aus_akku) * strompreis / 100 + + # gesamtkosten_euro = kosten_euro - einnahmen_euro + + # return { + # 'Eigenverbrauch_Wh': eigenverbrauch_wh, + # 'Netzeinspeisung_Wh': netzeinspeisung_wh, + # 'Netzbezug_Wh': netzbezug_wh, + # 'Kosten_Euro': kosten_euro, + # 'Einnahmen_Euro': einnahmen_euro, + # 'Gesamtkosten_Euro': gesamtkosten_euro + # } \ No newline at end of file diff --git a/modules/class_strompreis.py b/modules/class_strompreis.py index 069b41c..5ca5942 100644 --- a/modules/class_strompreis.py +++ b/modules/class_strompreis.py @@ -1,12 +1,13 @@ import json from datetime import datetime, timedelta, timezone +import numpy as np class HourlyElectricityPriceForecast: class PriceData: def __init__(self, total, energy, tax, starts_at, currency, level): - self.total = total - self.energy = energy - self.tax = tax + self.total = total/1000.0 + self.energy = energy/1000.0 + self.tax = tax/1000.0 self.starts_at = datetime.strptime(starts_at, '%Y-%m-%dT%H:%M:%S.%f%z') self.currency = currency @@ -38,8 +39,9 @@ class HourlyElectricityPriceForecast: def get_prices_for_date(self, query_date): query_date = datetime.strptime(query_date, '%Y-%m-%d').date() - prices_for_date = [price for price in self.price_data if price.starts_at.date() == query_date] - return prices_for_date + prices_for_date = [price.get_total() for price in self.price_data if price.starts_at.date() == query_date] + + return np.array(prices_for_date) def get_price_for_datetime(self, query_datetime): query_datetime = datetime.strptime(query_datetime, '%Y-%m-%d %H').replace(minute=0, second=0, microsecond=0) @@ -48,7 +50,7 @@ class HourlyElectricityPriceForecast: for price in self.price_data: #print(price.starts_at.replace(minute=0, second=0, microsecond=0) , " ", query_datetime, " == ",price.starts_at.replace(minute=0, second=0, microsecond=0) == query_datetime) if price.starts_at.replace(minute=0, second=0, microsecond=0) == query_datetime: - return price + return np.array(price) return None diff --git a/modules/visualize.py b/modules/visualize.py new file mode 100644 index 0000000..734f865 --- /dev/null +++ b/modules/visualize.py @@ -0,0 +1,69 @@ +import numpy as np +import matplotlib.pyplot as plt + + +def visualisiere_ergebnisse(last, pv_forecast, strompreise, ergebnisse): + stunden = np.arange(1, 25) # 1 bis 24 Stunden + + # Last und PV-Erzeugung + plt.figure(figsize=(14, 10)) + + plt.subplot(3, 1, 1) + plt.plot(stunden, last, label='Last (Wh)', marker='o') + plt.plot(stunden, pv_forecast, label='PV-Erzeugung (Wh)', marker='x') + plt.title('Last und PV-Erzeugung') + plt.xlabel('Stunde des Tages') + plt.ylabel('Energie (Wh)') + plt.legend() + plt.grid(True) + + # Strompreise + plt.subplot(3, 1, 2) + plt.plot(stunden, strompreise, label='Strompreis (Cent/Wh)', color='purple', marker='s') + plt.title('Strompreise') + plt.xlabel('Stunde des Tages') + plt.ylabel('Preis (Cent/Wh)') + plt.legend() + plt.grid(True) + + + plt.figure(figsize=(18, 12)) + + # Eigenverbrauch, Netzeinspeisung und Netzbezug + plt.subplot(3, 2, 1) + plt.plot(stunden, ergebnisse['Eigenverbrauch_Wh_pro_Stunde'], label='Eigenverbrauch (Wh)', marker='o') + plt.plot(stunden, ergebnisse['Netzeinspeisung_Wh_pro_Stunde'], label='Netzeinspeisung (Wh)', marker='x') + plt.plot(stunden, ergebnisse['akku_soc_pro_stunde'], label='Akku (%)', marker='x') + plt.plot(stunden, ergebnisse['Netzbezug_Wh_pro_Stunde'], label='Netzbezug (Wh)', marker='^') + plt.plot(stunden, pv_forecast, label='PV-Erzeugung (Wh)', marker='x') + plt.plot(stunden, last, label='Last (Wh)', marker='o') + + plt.title('Energiefluss pro Stunde') + plt.xlabel('Stunde') + plt.ylabel('Energie (Wh)') + plt.legend() + plt.grid(True) + + # Kosten und Einnahmen pro Stunde + plt.subplot(3, 2, 2) + plt.plot(stunden, ergebnisse['Kosten_Euro_pro_Stunde'], label='Kosten (Euro)', marker='o', color='red') + plt.plot(stunden, ergebnisse['Einnahmen_Euro_pro_Stunde'], label='Einnahmen (Euro)', marker='x', color='green') + plt.title('Finanzielle Bilanz pro Stunde') + plt.xlabel('Stunde') + plt.ylabel('Euro') + plt.legend() + plt.grid(True) + + # Zusammenfassende Finanzen + plt.subplot(3, 2, 3) + gesamtkosten = ergebnisse['Gesamtkosten_Euro'] + plt.bar('Gesamtkosten', gesamtkosten, color='red' if gesamtkosten > 0 else 'green') + plt.title('Gesamtkosten') + plt.ylabel('Euro') + + + plt.legend() + plt.grid(True) + + plt.tight_layout() + plt.show() diff --git a/test.py b/test.py index ddf98e8..fecd19e 100644 --- a/test.py +++ b/test.py @@ -5,14 +5,18 @@ from modules.class_load import * from modules.class_ems import * from modules.class_pv_forecast import * from modules.class_akku import * +from modules.class_strompreis import * from pprint import pprint +import matplotlib.pyplot as plt +from modules.visualize import * + date = "2024-02-16" -akku_size = 100 # Wh -year_energy = 200*1000 #Wh - +akku_size = 1000 # Wh +year_energy = 2000*1000 #Wh +einspeiseverguetung_cent_pro_wh = np.full(24, 7/1000.0) akku = PVAkku(akku_size) @@ -27,12 +31,21 @@ PVforecast = PVForecast(r'.\test_data\pvprognose.json') pv_forecast = PVforecast.get_forecast_for_date(date) pprint(pv_forecast.shape) +# Strompreise +filepath = r'.\test_data\strompreis.json' # Pfad zur JSON-Datei anpassen +price_forecast = HourlyElectricityPriceForecast(filepath) +specific_date_prices = price_forecast.get_prices_for_date(date) -ems = EnergieManagementSystem(akku, specific_date_load, pv_forecast) +# EMS / Stromzähler Bilanz +ems = EnergieManagementSystem(akku, specific_date_load, pv_forecast, specific_date_prices, einspeiseverguetung_cent_pro_wh) o = ems.simuliere() pprint(o) + +visualisiere_ergebnisse(specific_date_load, pv_forecast, specific_date_prices, o) + + # for data in forecast.get_forecast_data(): # print(data.get_date_time(), data.get_dc_power(), data.get_ac_power(), data.get_windspeed_10m(), data.get_temperature())for data in forecast.get_forecast_data():