diff --git a/modules/class_eauto.py b/modules/class_eauto.py new file mode 100644 index 0000000..a572dcc --- /dev/null +++ b/modules/class_eauto.py @@ -0,0 +1,122 @@ +import json +from datetime import datetime, timedelta, timezone +import numpy as np +from pprint import pprint + +class EAuto: + def __init__(self, soc=None, capacity = None, power_charge = None, load_allowed = None): + self.soc = soc + self.akku_kapazitaet = capacity + self.ladegeschwindigkeit = power_charge + self.laden_moeglich = None + self.stuendlicher_soc = [] + self.stuendliche_last = [] # Hinzugefügt für die Speicherung der stündlichen Last + self.laden_moeglich = load_allowed + self.berechne_ladevorgang() + + def set_laden_moeglich(self, laden_moeglich): + self.laden_moeglich = laden_moeglich + self.stuendlicher_soc = [self.soc] # Beginnt mit dem aktuellen SoC + self.stuendliche_last = [] # Zurücksetzen der stündlichen Last + + def berechne_ladevorgang(self): + if self.laden_moeglich is None: + print("Lademöglichkeit wurde nicht gesetzt.") + return + + for moeglich in self.laden_moeglich: + if moeglich == 1 and self.soc < 100: + geladene_energie = min(self.ladegeschwindigkeit, (100 - self.soc) / 100 * self.akku_kapazitaet) + self.soc += geladene_energie / self.akku_kapazitaet * 100 + self.soc = min(100, self.soc) + self.stuendliche_last.append(geladene_energie) + else: + self.stuendliche_last.append(0) # Keine Ladung in dieser Stunde + self.stuendlicher_soc.append(self.soc) + + # Umwandlung der stündlichen Last in ein NumPy-Array + self.stuendliche_last = np.array(self.stuendliche_last) + + def get_stuendliche_last(self): + """Gibt das NumPy-Array mit der stündlichen Last zurück.""" + return self.stuendliche_last + + def get_stuendlicher_soc(self): + """Gibt den stündlichen SoC als Liste zurück.""" + return self.stuendlicher_soc + + +# class EAuto: + # def __init__(self, soc, akku_kapazitaet, ladegeschwindigkeit): + # self.soc = soc + # self.akku_kapazitaet = akku_kapazitaet + # self.ladegeschwindigkeit = ladegeschwindigkeit + # self.laden_moeglich = None + # # Initialisieren des Arrays für den stündlichen SoC + # self.stuendlicher_soc = [] + + # def set_laden_moeglich(self, laden_moeglich): + # """ + # Setzt das Array, das angibt, wann das Laden möglich ist. + # :param laden_moeglich: Ein Array von 0 und 1, das die Lademöglichkeit angibt + # """ + # self.laden_moeglich = laden_moeglich + # # Zurücksetzen des stündlichen SoC Arrays bei jeder neuen Lademöglichkeit + # self.stuendlicher_soc = [self.soc] # Start-SoC hinzufügen + + # def berechne_ladevorgang(self): + # """ + # Berechnet den Ladevorgang basierend auf der Ladegeschwindigkeit und der Lademöglichkeit. + # Aktualisiert den SoC entsprechend und speichert den stündlichen SoC. + # """ + # if self.laden_moeglich is None: + # print("Lademöglichkeit wurde nicht gesetzt.") + # return + + # for i, moeglich in enumerate(self.laden_moeglich): + # if moeglich == 1: + # # Berechnen, wie viel Energie in einer Stunde geladen werden kann + # geladene_energie = min(self.ladegeschwindigkeit, (100 - self.soc) / 100 * self.akku_kapazitaet) + # # Aktualisieren des SoC + # self.soc += geladene_energie / self.akku_kapazitaet * 100 + # # Sicherstellen, dass der SoC nicht über 100% geht + # self.soc = min(100, self.soc) + # print(f"Stunde {i}: Geladen {geladene_energie} kWh, neuer SoC: {self.soc}%") + # else: + # # Wenn nicht geladen wird, bleibt der SoC gleich + # print(f"Stunde {i}: Nicht geladen, SoC bleibt bei {self.soc}%") + # self.stuendlicher_soc.append(self.soc) # Aktuellen SoC zum Array hinzufügen + # if self.soc >= 100: + # print("Akku vollständig geladen.") + # break + + # def berechne_benoetigte_energie(self): + # """ + # Berechnet die Gesamtenergie, die benötigt wird, um den Akku vollständig zu laden. + # """ + # return (100 - self.soc) / 100 * self.akku_kapazitaet + + # def get_stuendlicher_soc(self): + # """ + # Gibt den stündlichen Ladezustand (SoC) als Array zurück. + # """ + # return self.stuendlicher_soc + + +if __name__ == "__main__": + # Initialisierung des Elektroauto-Ladens + mein_eauto = EAuto(soc=50, akku_kapazitaet=60, ladegeschwindigkeit=11) + + # Festlegen, wann das Laden möglich ist (1 = Laden erlaubt, 0 = Laden nicht erlaubt) + # Beispiel: Laden ist nur während der Nachtstunden und frühen Morgenstunden erlaubt + laden_moeglich = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] + mein_eauto.set_laden_moeglich(laden_moeglich) + + # Durchführen des Ladevorgangs + mein_eauto.berechne_ladevorgang() + + # Abrufen und Ausgeben des stündlichen Ladezustands + stuendlicher_soc = mein_eauto.get_stuendlicher_soc() + print("\nStündlicher SoC während des Ladevorgangs:") + for stunde, soc in enumerate(stuendlicher_soc): + print(f"Stunde {stunde}: SoC = {soc}%") diff --git a/modules/class_ems.py b/modules/class_ems.py index 5abbf72..d03e6c0 100644 --- a/modules/class_ems.py +++ b/modules/class_ems.py @@ -1,6 +1,5 @@ from datetime import datetime from pprint import pprint -from modules.class_generic_load import * class EnergieManagementSystem: diff --git a/modules/class_strompreis.py b/modules/class_strompreis.py index 73fcb90..e531d25 100644 --- a/modules/class_strompreis.py +++ b/modules/class_strompreis.py @@ -6,11 +6,12 @@ from datetime import datetime import hashlib, requests class HourlyElectricityPriceForecast: - def __init__(self, source, cache_dir='cache'): + def __init__(self, source, cache_dir='cache', abgaben=0.00019): self.cache_dir = cache_dir if not os.path.exists(self.cache_dir): os.makedirs(self.cache_dir) self.prices = self.load_data(source) + self.abgaben = abgaben def load_data(self, source): if source.startswith('http'): @@ -42,8 +43,8 @@ class HourlyElectricityPriceForecast: def get_price_for_date(self, date_str): """Gibt alle Preise für das spezifizierte Datum zurück.""" - date_prices = [entry["marketpriceEurocentPerKWh"] for entry in self.prices if date_str in entry['end']] - return np.array(date_prices)/(1000.0*100.0) + date_prices = [entry["marketpriceEurocentPerKWh"]+self.abgaben for entry in self.prices if date_str in entry['end']] + return np.array(date_prices)/(1000.0*100.0) + self.abgaben def get_price_for_daterange(self, start_date_str, end_date_str): """Gibt alle Preise zwischen dem Start- und Enddatum zurück.""" @@ -61,107 +62,3 @@ class HourlyElectricityPriceForecast: return np.array(price_list) - - - - # def get_price_for_hour(self, datetime_str): - # """Gibt den Preis für die spezifizierte Stunde zurück.""" - # hour_price = [entry for entry in self.prices if datetime_str in entry['start']] - # return hour_price[0] if hour_price else None - -# # Beispiel zur Verwendung der Klasse -# filepath = '/mnt/data/strompreise_akkudokAPI.json' # Pfad zur JSON-Datei -# strompreise = Strompreise(filepath) - -# # Preise für ein spezifisches Datum erhalten -# date_str = '2024-02-25' -# prices_for_date = strompreise.get_price_for_date(date_str) -# print(f"Preise für {date_str}: {prices_for_date}") - -# # Preis für eine spezifische Stunde erhalten -# datetime_str = '2024-02-25T15:00:00.000Z' -# price_for_hour = strompreise.get_price_for_hour(datetime_str) -# print(f"Preis für {datetime_str}: {price_for_hour}") - - - - - -# class HourlyElectricityPriceForecast: - # class PriceData: - # def __init__(self, total, energy, tax, starts_at, currency, level): - # 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 - # self.level = level - - # # Getter-Methoden - # def get_total(self): - # return self.total - - # def get_energy(self): - # return self.energy - - # def get_tax(self): - # return self.tax - - # def get_starts_at(self): - # return self.starts_at - - # def get_currency(self): - # return self.currency - - # def get_level(self): - # return self.level - - # def __init__(self, filepath): - # self.filepath = filepath - # self.price_data = [] - # self.load_data() - - # def get_prices_for_date(self, query_date): - # query_date = datetime.strptime(query_date, '%Y-%m-%d').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) - # query_datetime = query_datetime.replace(tzinfo=timezone(timedelta(hours=1))) - - # 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 np.array(price) - # return None - - - # def load_data(self): - # with open(self.filepath, 'r') as file: - # data = json.load(file) - # for item in data['payload']: - # self.price_data.append(self.PriceData( - # total=item['total'], - # energy=item['energy'], - # tax=item['tax'], - # starts_at=item['startsAt'], - # currency=item['currency'], - # level=item['level'] - # )) - - # def get_price_data(self): - # return self.price_data - -# # Beispiel für die Verwendung der Klasse -# if __name__ == '__main__': - # filepath = r'..\test_data\strompreis.json' # Pfad zur JSON-Datei anpassen - # price_forecast = HourlyElectricityPriceForecast(filepath) - # specific_date_prices = price_forecast.get_prices_for_date('2024-02-16') # Datum anpassen - - # specific_date_prices = price_forecast.get_price_for_datetime('2024-02-16 12') - # print(specific_date_prices) - # #for price in price_forecast.get_price_data(): - # # print(price.get_starts_at(), price.get_total(), price.get_currency()) diff --git a/modules/visualize.py b/modules/visualize.py index 99861d0..03490e6 100644 --- a/modules/visualize.py +++ b/modules/visualize.py @@ -1,26 +1,35 @@ import numpy as np import matplotlib.pyplot as plt +import numpy as np +import matplotlib.pyplot as plt +from modules.class_load_container import Gesamtlast # Stellen Sie sicher, dass dies dem tatsächlichen Importpfad entspricht -def visualisiere_ergebnisse(last,leistung_haushalt,leistung_wp, pv_forecast, strompreise, ergebnisse): - - #print(last) - stunden = np.arange(1, len(last)+1) # 1 bis 24 Stunden +def visualisiere_ergebnisse(gesamtlast,leistung_haushalt,leistung_wp, pv_forecast, strompreise, ergebnisse): + + # 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, leistung_haushalt, label='leistung_haushalt (Wh)', marker='o') - plt.plot(stunden, leistung_wp, label='leistung_wp (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() + stunden = np.arange(1, len(next(iter(gesamtlast.lasten.values()))) + 1) + + + # 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) diff --git a/test.py b/test.py index 664c8ab..1197448 100644 --- a/test.py +++ b/test.py @@ -7,8 +7,9 @@ from modules.class_pv_forecast import * from modules.class_akku import * from modules.class_strompreis import * from modules.class_heatpump import * -from modules.class_generic_load import * from modules.class_load_container import * +from modules.class_eauto import * + from pprint import pprint import matplotlib.pyplot as plt from modules.visualize import * @@ -33,6 +34,13 @@ wp = Waermepumpe(max_heizleistung,prediction_hours) akku = PVAkku(akku_size,prediction_hours) discharge_array = np.full(prediction_hours,1) +laden_moeglich = np.full(prediction_hours,1) +eauto = EAuto(soc=60, capacity = 60000, power_charge = 7000, load_allowed = laden_moeglich) + + + + + #Gesamtlast ############# @@ -46,12 +54,6 @@ lf = LoadForecast(filepath=r'load_profiles.npz', year_energy=year_energy) leistung_haushalt = lf.get_stats_for_date_range(date_now,date)[0,...].flatten() gesamtlast.hinzufuegen("Haushalt", leistung_haushalt) -# Generic Load -############## -# zusatzlast1 = generic_load() -# zusatzlast1.setze_last(24+12, 0.5, 2000) # Startet um 1 Uhr, dauert 0.5 Stunden, mit 2 kW - - # PV Forecast ############### #PVforecast = PVForecast(filepath=os.path.join(r'test_data', r'pvprognose.json')) @@ -73,21 +75,26 @@ specific_date_prices = price_forecast.get_price_for_daterange(date_now,date) leistung_wp = wp.simulate_24h(temperature_forecast) gesamtlast.hinzufuegen("Heatpump", leistung_wp) -# print(gesamtlast.gesamtlast_berechnen()) -# sys.exit() + +# EAuto +###################### +leistung_eauto = eauto.get_stuendliche_last() +gesamtlast.hinzufuegen("eauto", leistung_eauto) + +print(gesamtlast.gesamtlast_berechnen()) # EMS / Stromzähler Bilanz ems = EnergieManagementSystem(akku, gesamtlast.gesamtlast_berechnen(), pv_forecast, specific_date_prices, einspeiseverguetung_cent_pro_wh) -o = ems.simuliere_ab_jetzt() +o = ems.simuliere(0)#ems.simuliere_ab_jetzt() pprint(o) pprint(o["Gesamtbilanz_Euro"]) -visualisiere_ergebnisse(gesamtlast.gesamtlast_berechnen(),leistung_haushalt,leistung_wp, pv_forecast, specific_date_prices, o) +visualisiere_ergebnisse(gesamtlast,leistung_haushalt,leistung_wp, pv_forecast, specific_date_prices, o) -sys.exit() +#sys.exit() # Optimierung