diff --git a/README.md b/README.md index b2852d6..494d45e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ Dieses Projekt bietet eine umfassende Lösung zur Simulation und Optimierung eines Energiesystems, das auf erneuerbaren Energiequellen basiert. Mit Fokus auf Photovoltaik (PV)-Anlagen, Batteriespeichern (Akkus), Lastmanagement (Verbraucheranforderungen), Wärmepumpen, Elektrofahrzeugen und der Berücksichtigung von Strompreisdaten ermöglicht dieses System die Vorhersage und Optimierung des Energieflusses und der Kosten über einen bestimmten Zeitraum. ## Todo -- `Backend:` Flask Server - `Backend:` Mehr Optimierungsparameter - `Frontend:` User Management - `Frontend:` Grafische Ausgabe @@ -11,7 +10,7 @@ Dieses Projekt bietet eine umfassende Lösung zur Simulation und Optimierung ein - `Frontend:` Festeingestellte E-Autos / Wärmepumpen in DB - `Simulation:` Wärmepumpe allgemeineren Ansatz - `Simulation:` Strompreisvorhersage > 1D (Timeseries Forecast) -- +- `Dynamische Lasten:` z.B. eine Spülmaschine, welche gesteuert werdeb jabb, ## Installation @@ -42,8 +41,6 @@ In diesem Projekt werden verschiedene Klassen verwendet, um die Komponenten eine - `HeatPump`: Simuliert eine Wärmepumpe, einschließlich ihres Energieverbrauchs und ihrer Effizienz unter verschiedenen Betriebsbedingungen. -- `EAuto`: Repräsentiert ein Elektrofahrzeug mit spezifischen Ladeanforderungen und -zeiten, optimiert die Ladevorgänge basierend auf Energieverfügbarkeit und -kosten. - - `Strompreis`: Bietet Informationen zu den Strompreisen, ermöglicht die Optimierung des Energieverbrauchs und der -erzeugung basierend auf Tarifinformationen. - `EMS`: Das Energiemanagementsystem (EMS) koordiniert die Interaktion zwischen den verschiedenen Komponenten, führt die Optimierung durch und simuliert den Betrieb des gesamten Energiesystems. diff --git a/flask_server.py b/flask_server.py index 0b49a00..d66dfe8 100644 --- a/flask_server.py +++ b/flask_server.py @@ -11,6 +11,8 @@ from modules.class_load_container import * from modules.class_eauto import * from pprint import pprint +import matplotlib +matplotlib.use('Agg') # Setzt das Backend auf Agg import matplotlib.pyplot as plt from modules.visualize import * from deap import base, creator, tools, algorithms @@ -83,7 +85,7 @@ def optimize(): stats.register("min", np.min) stats.register("max", np.max) - algorithms.eaMuPlusLambda(population, toolbox, 50, 100, cxpb=0.5, mutpb=0.5, ngen=500, stats=stats, halloffame=hof, verbose=True) + algorithms.eaMuPlusLambda(population, toolbox, 100, 200, cxpb=0.3, mutpb=0.3, ngen=500, stats=stats, halloffame=hof, verbose=True) #algorithms.eaSimple(population, toolbox, cxpb=0.2, mutpb=0.2, ngen=1000, stats=stats, halloffame=hof, verbose=True) return hof[0] @@ -180,7 +182,7 @@ def durchfuehre_simulation(parameter): #print(o) - #visualisiere_ergebnisse(gesamtlast, pv_forecast, specific_date_prices, o,best_solution[0::2],best_solution[1::2] , temperature_forecast, start_hour, prediction_hours) + visualisiere_ergebnisse(gesamtlast, pv_forecast, specific_date_prices, o,best_solution[0::2],best_solution[1::2] , temperature_forecast, start_hour, prediction_hours) #print(eauto) return {"discharge_hours_bin":discharge_hours_bin, "eautocharge_hours_float":eautocharge_hours_float ,"result":o ,"eauto_obj":eauto} diff --git a/modules/class_strompreis.py b/modules/class_strompreis.py index e531d25..2201422 100644 --- a/modules/class_strompreis.py +++ b/modules/class_strompreis.py @@ -4,6 +4,17 @@ import numpy as np import json, os from datetime import datetime import hashlib, requests +import pytz + +# Beispiel: Umwandlung eines UTC-Zeitstempels in lokale Zeit +utc_time = datetime.strptime('2024-03-28T01:00:00.000Z', '%Y-%m-%dT%H:%M:%S.%fZ') +utc_time = utc_time.replace(tzinfo=pytz.utc) + +# Ersetzen Sie 'Europe/Berlin' mit Ihrer eigenen Zeitzone +local_time = utc_time.astimezone(pytz.timezone('Europe/Berlin')) +print(local_time) + + class HourlyElectricityPriceForecast: def __init__(self, source, cache_dir='cache', abgaben=0.00019): @@ -48,8 +59,12 @@ class HourlyElectricityPriceForecast: def get_price_for_daterange(self, start_date_str, end_date_str): """Gibt alle Preise zwischen dem Start- und Enddatum zurück.""" - start_date = datetime.strptime(start_date_str, "%Y-%m-%d") - end_date = datetime.strptime(end_date_str, "%Y-%m-%d") + start_date_utc = datetime.strptime(start_date_str, "%Y-%m-%d").replace(tzinfo=pytz.utc) + end_date_utc = datetime.strptime(end_date_str, "%Y-%m-%d").replace(tzinfo=pytz.utc) + start_date = start_date_utc.astimezone(pytz.timezone('Europe/Berlin')) + end_date = end_date_utc.astimezone(pytz.timezone('Europe/Berlin')) + + price_list = [] while start_date <= end_date: diff --git a/modules/visualize.py b/modules/visualize.py index af89491..9325161 100644 --- a/modules/visualize.py +++ b/modules/visualize.py @@ -1,6 +1,11 @@ import numpy as np from modules.class_load_container import Gesamtlast # Stellen Sie sicher, dass dies dem tatsächlichen Importpfad entspricht +import matplotlib +matplotlib.use('Agg') # Setzt das Backend auf Agg + import matplotlib.pyplot as plt +from matplotlib.backends.backend_pdf import PdfPages + def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, discharge_hours, laden_moeglich, temperature, start_hour, prediction_hours): @@ -8,140 +13,188 @@ def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, d ##################### # 24h ##################### - - # Last und PV-Erzeugung - plt.figure(figsize=(14, 14)) - plt.subplot(3, 2, 1) - stunden = np.arange(0, prediction_hours) - - - # Einzellasten plotten - for name, last_array in gesamtlast.lasten.items(): - plt.plot(stunden, last_array, label=f'{name} (Wh)', marker='o') - - # Gesamtlast berechnen und plotten - gesamtlast_array = gesamtlast.gesamtlast_berechnen() - plt.plot(stunden, gesamtlast_array, label='Gesamtlast (Wh)', marker='o', linewidth=2, linestyle='--') - plt.xlabel('Stunde') - plt.ylabel('Last (Wh)') - plt.title('Lastprofile') - plt.grid(True) - plt.legend() + with PdfPages('visualisierungsergebnisse.pdf') as pdf: + + + # Last und PV-Erzeugung + plt.figure(figsize=(14, 14)) + plt.subplot(3, 2, 1) + stunden = np.arange(0, prediction_hours) + + + # Einzellasten plotten + for name, last_array in gesamtlast.lasten.items(): + plt.plot(stunden, last_array, label=f'{name} (Wh)', marker='o') + + # Gesamtlast berechnen und plotten + gesamtlast_array = gesamtlast.gesamtlast_berechnen() + plt.plot(stunden, gesamtlast_array, label='Gesamtlast (Wh)', marker='o', linewidth=2, linestyle='--') + plt.xlabel('Stunde') + plt.ylabel('Last (Wh)') + plt.title('Lastprofile') + plt.grid(True) + plt.legend() - # Strompreise - stundenp = np.arange(1, len(strompreise)+1) - plt.subplot(3, 2, 2) - plt.plot(stundenp, strompreise, label='Strompreis (€/Wh)', color='purple', marker='s') - plt.title('Strompreise') - plt.xlabel('Stunde des Tages') - plt.ylabel('Preis (€/Wh)') - plt.legend() - plt.grid(True) + # Strompreise + stundenp = np.arange(0, len(strompreise)) + plt.subplot(3, 2, 2) + plt.plot(stundenp, strompreise, label='Strompreis (€/Wh)', color='purple', marker='s') + plt.title('Strompreise') + plt.xlabel('Stunde des Tages') + plt.ylabel('Preis (€/Wh)') + plt.legend() + plt.grid(True) - # Strompreise - stundenp = np.arange(1, len(strompreise)+1) - plt.subplot(3, 2, 3) - plt.plot(stunden, pv_forecast, label='PV-Erzeugung (Wh)', marker='x') - plt.title('PV Forecast') - plt.xlabel('Stunde des Tages') - plt.ylabel('Wh') - plt.legend() - plt.grid(True) + # Strompreise + stundenp = np.arange(1, len(strompreise)+1) + plt.subplot(3, 2, 3) + plt.plot(stunden, pv_forecast, label='PV-Erzeugung (Wh)', marker='x') + plt.title('PV Forecast') + plt.xlabel('Stunde des Tages') + plt.ylabel('Wh') + plt.legend() + plt.grid(True) - # Temperatur Forecast - plt.subplot(3, 2, 4) - plt.title('Temperatur Forecast °C') - plt.plot(stunden, temperature, label='Temperatur °C', marker='x') - plt.xlabel('Stunde des Tages') - plt.ylabel('°C') - plt.legend() - plt.grid(True) + # Temperatur Forecast + plt.subplot(3, 2, 4) + plt.title('Temperatur Forecast °C') + plt.plot(stunden, temperature, label='Temperatur °C', marker='x') + plt.xlabel('Stunde des Tages') + plt.ylabel('°C') + plt.legend() + plt.grid(True) + + pdf.savefig() # Speichert den aktuellen Figure-State im PDF + plt.close() # Schließt die aktuelle Figure, um Speicher freizugeben - ##################### - # Start_Hour - ##################### - - plt.figure(figsize=(14, 10)) - stunden = np.arange(start_hour, prediction_hours) - # 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['Netzbezug_Wh_pro_Stunde'], label='Netzbezug (Wh)', marker='^') - plt.plot(stunden, ergebnisse['Verluste_Pro_Stunde'], label='Verluste (Wh)', marker='^') - plt.title('Energiefluss pro Stunde') - plt.xlabel('Stunde') - plt.ylabel('Energie (Wh)') - plt.legend() - - - - - plt.subplot(3, 2, 2) - plt.plot(stunden, ergebnisse['akku_soc_pro_stunde'], label='PV Akku (%)', marker='x') - plt.plot(stunden, ergebnisse['E-Auto_SoC_pro_Stunde'], label='E-Auto Akku (%)', marker='x') - plt.legend(loc='upper left') + ##################### + # Start_Hour + ##################### + + plt.figure(figsize=(14, 10)) + stunden = np.arange(start_hour, prediction_hours) + # 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['Netzbezug_Wh_pro_Stunde'], label='Netzbezug (Wh)', marker='^') + plt.plot(stunden, ergebnisse['Verluste_Pro_Stunde'], label='Verluste (Wh)', marker='^') + plt.title('Energiefluss pro Stunde') + plt.xlabel('Stunde') + plt.ylabel('Energie (Wh)') + plt.legend() + + + + + plt.subplot(3, 2, 2) + plt.plot(stunden, ergebnisse['akku_soc_pro_stunde'], label='PV Akku (%)', marker='x') + plt.plot(stunden, ergebnisse['E-Auto_SoC_pro_Stunde'], label='E-Auto Akku (%)', marker='x') + plt.legend(loc='upper left') - ax1 = plt.subplot(3, 2, 3) - for hour, value in enumerate(discharge_hours): - #if value == 1: - ax1.axvspan(hour, hour+1, color='red',ymax=value, alpha=0.3, label='Entlademöglichkeit' if hour == 0 else "") - for hour, value in enumerate(laden_moeglich): - #if value == 1: - ax1.axvspan(hour, hour+1, color='green',ymax=value, alpha=0.3, label='Lademöglichkeit' if hour == 0 else "") - ax1.legend(loc='upper left') + ax1 = plt.subplot(3, 2, 3) + for hour, value in enumerate(discharge_hours): + #if value == 1: + ax1.axvspan(hour, hour+1, color='red',ymax=value, alpha=0.3, label='Entlademöglichkeit' if hour == 0 else "") + for hour, value in enumerate(laden_moeglich): + #if value == 1: + ax1.axvspan(hour, hour+1, color='green',ymax=value, alpha=0.3, label='Lademöglichkeit' if hour == 0 else "") + ax1.legend(loc='upper left') + pdf.savefig() # Speichert den aktuellen Figure-State im PDF + plt.close() # Schließt die aktuelle Figure, um Speicher freizugeben + + + + + + + plt.grid(True) + fig, axs = plt.subplots(1, 2, figsize=(14, 10)) # Erstellt 1x2 Raster von Subplots + gesamtkosten = ergebnisse['Gesamtkosten_Euro'] + gesamteinnahmen = ergebnisse['Gesamteinnahmen_Euro'] + gesamtbilanz = ergebnisse['Gesamtbilanz_Euro'] + verluste = ergebnisse['Gesamt_Verluste'] + + # Kosten und Einnahmen pro Stunde auf der ersten Achse (axs[0]) + axs[0].plot(stunden, ergebnisse['Kosten_Euro_pro_Stunde'], label='Kosten (Euro)', marker='o', color='red') + axs[0].plot(stunden, ergebnisse['Einnahmen_Euro_pro_Stunde'], label='Einnahmen (Euro)', marker='x', color='green') + axs[0].set_title('Finanzielle Bilanz pro Stunde') + axs[0].set_xlabel('Stunde') + axs[0].set_ylabel('Euro') + axs[0].legend() + axs[0].grid(True) + + # Zusammenfassende Finanzen auf der zweiten Achse (axs[1]) + labels = ['GesamtKosten [€]', 'GesamtEinnahmen [€]', 'GesamtBilanz [€]'] + werte = [gesamtkosten, gesamteinnahmen, gesamtbilanz] + colors = ['red' if wert > 0 else 'green' for wert in werte] + axs[1].bar(labels, werte, color=colors) + axs[1].set_title('Finanzübersicht') + axs[1].set_ylabel('Euro') + + # Zweite Achse (ax2) für die Verluste, geteilt mit axs[1] + ax2 = axs[1].twinx() + ax2.bar('GesamtVerluste', verluste, color='blue') + ax2.set_ylabel('Verluste [Wh]', color='blue') + ax2.tick_params(axis='y', labelcolor='blue') + + pdf.savefig() # Speichert die komplette Figure im PDF + plt.close() # Schließt die Figure + + + # plt.figure(figsize=(14, 10)) + # # Kosten und Einnahmen pro Stunde + # plt.subplot(1, 2, 1) + # 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) + # #plt.figure(figsize=(14, 10)) + # # Zusammenfassende Finanzen + # #fig, ax1 = plt.subplot(1, 2, 2) + # fig, ax1 = plt.subplots() + # gesamtkosten = ergebnisse['Gesamtkosten_Euro'] + # gesamteinnahmen = ergebnisse['Gesamteinnahmen_Euro'] + # gesamtbilanz = ergebnisse['Gesamtbilanz_Euro'] + # labels = ['GesamtKosten [€]', 'GesamtEinnahmen [€]', 'GesamtBilanz [€]'] + # werte = [gesamtkosten, gesamteinnahmen, gesamtbilanz] + # colors = ['red' if wert > 0 else 'green' for wert in werte] + + # ax1.bar(labels, werte, color=colors) + # ax1.set_ylabel('Euro') + # ax1.set_title('Finanzübersicht') + + # # Zweite Achse (ax2) für die Verluste, geteilt mit ax1 + # ax2 = ax1.twinx() + # verluste = ergebnisse['Gesamt_Verluste'] + # ax2.bar('GesamtVerluste', verluste, color='blue') + # ax2.set_ylabel('Verluste [Wh]', color='blue') + + # # Stellt sicher, dass die Achsenbeschriftungen der zweiten Achse in der gleichen Farbe angezeigt werden + # ax2.tick_params(axis='y', labelcolor='blue') + + # pdf.savefig() # Speichert den aktuellen Figure-State im PDF + # plt.close() # Schließt die aktuelle Figure, um Speicher freizugeben + + + # plt.title('Gesamtkosten') + # plt.ylabel('Euro') + + + # plt.legend() + # plt.grid(True) + + # plt.tight_layout() + #plt.show() + - - - - - - plt.grid(True) - plt.figure(figsize=(14, 10)) - # Kosten und Einnahmen pro Stunde - plt.subplot(1, 2, 1) - 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() - - - # Zusammenfassende Finanzen - fig, ax1 = plt.subplots() - gesamtkosten = ergebnisse['Gesamtkosten_Euro'] - gesamteinnahmen = ergebnisse['Gesamteinnahmen_Euro'] - gesamtbilanz = ergebnisse['Gesamtbilanz_Euro'] - labels = ['GesamtKosten [€]', 'GesamtEinnahmen [€]', 'GesamtBilanz [€]'] - werte = [gesamtkosten, gesamteinnahmen, gesamtbilanz] - colors = ['red' if wert > 0 else 'green' for wert in werte] - - ax1.bar(labels, werte, color=colors) - ax1.set_ylabel('Euro') - ax1.set_title('Finanzübersicht') - - # Zweite Achse (ax2) für die Verluste, geteilt mit ax1 - ax2 = ax1.twinx() - verluste = ergebnisse['Gesamt_Verluste'] - ax2.bar('GesamtVerluste', verluste, color='blue') - ax2.set_ylabel('Verluste [Wh]', color='blue') - - # Stellt sicher, dass die Achsenbeschriftungen der zweiten Achse in der gleichen Farbe angezeigt werden - ax2.tick_params(axis='y', labelcolor='blue') - - - # 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 9836928..b05c53d 100644 --- a/test.py +++ b/test.py @@ -74,7 +74,10 @@ filepath = os.path.join (r'test_data', r'strompreise_akkudokAPI.json') # Pfad z #price_forecast = HourlyElectricityPriceForecast(source=filepath) price_forecast = HourlyElectricityPriceForecast(source="https://api.akkudoktor.net/prices?start="+date_now+"&end="+date+"") specific_date_prices = price_forecast.get_price_for_daterange(date_now,date) - +# print("13:",specific_date_prices[13]) +# print("14:",specific_date_prices[14]) +# print("15:",specific_date_prices[15]) +# sys.exit() # WP ############## leistung_wp = wp.simulate_24h(temperature_forecast)