mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2025-06-28 00:46:53 +00:00
Sommerzeit Probleme (bei Zeitumstellung gibt es eine Stunde weniger)
Für die PVForecast kann jetzt ein aktuelle Messwert der PV Leistung eingegeben werden!
This commit is contained in:
parent
203860cfbf
commit
e6c04183cf
@ -1,6 +1,5 @@
|
|||||||
from flask import Flask, jsonify, request
|
from flask import Flask, jsonify, request
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from datetime import datetime
|
|
||||||
from modules.class_load import *
|
from modules.class_load import *
|
||||||
from modules.class_ems import *
|
from modules.class_ems import *
|
||||||
from modules.class_pv_forecast import *
|
from modules.class_pv_forecast import *
|
||||||
@ -8,23 +7,37 @@ from modules.class_akku import *
|
|||||||
from modules.class_strompreis import *
|
from modules.class_strompreis import *
|
||||||
from modules.class_heatpump import *
|
from modules.class_heatpump import *
|
||||||
from modules.class_load_container import *
|
from modules.class_load_container import *
|
||||||
from modules.class_eauto import *
|
from modules.class_sommerzeit import *
|
||||||
|
from modules.visualize import *
|
||||||
|
import os
|
||||||
|
from flask import Flask, send_from_directory
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import matplotlib
|
import matplotlib
|
||||||
matplotlib.use('Agg') # Setzt das Backend auf Agg
|
matplotlib.use('Agg') # Setzt das Backend auf Agg
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from modules.visualize import *
|
import string
|
||||||
|
from datetime import datetime
|
||||||
from deap import base, creator, tools, algorithms
|
from deap import base, creator, tools, algorithms
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import random
|
import random
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
# if ist_dst_wechsel(datetime.now()):
|
||||||
start_hour = datetime.now().hour
|
# prediction_hours = 23 # Anpassung auf 23 Stunden für DST-Wechseltage
|
||||||
|
# else:
|
||||||
|
# prediction_hours = 24 # Standardwert für Tage ohne DST-Wechsel
|
||||||
prediction_hours = 24
|
prediction_hours = 24
|
||||||
|
start_hour = datetime.now().hour
|
||||||
hohe_strafe = 10.0
|
hohe_strafe = 10.0
|
||||||
|
# print(prediction_hours)
|
||||||
|
# sys.exit()
|
||||||
|
|
||||||
|
def isfloat(num):
|
||||||
|
try:
|
||||||
|
float(num)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def evaluate_inner(individual, ems):
|
def evaluate_inner(individual, ems):
|
||||||
@ -91,7 +104,7 @@ def optimize(start_solution=None):
|
|||||||
population.insert(0, creator.Individual(start_solution))
|
population.insert(0, creator.Individual(start_solution))
|
||||||
|
|
||||||
#algorithms.eaMuPlusLambda(population, toolbox, 100, 200, cxpb=0.3, mutpb=0.3, 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.5, mutpb=0.8, ngen=200, stats=stats, halloffame=hof, verbose=True)
|
algorithms.eaSimple(population, toolbox, cxpb=0.8, mutpb=0.8, ngen=400, stats=stats, halloffame=hof, verbose=True)
|
||||||
return hof[0]
|
return hof[0]
|
||||||
|
|
||||||
|
|
||||||
@ -104,6 +117,8 @@ app = Flask(__name__)
|
|||||||
# Ersetzen Sie diese Logik durch Ihren eigentlichen Optimierungscode
|
# Ersetzen Sie diese Logik durch Ihren eigentlichen Optimierungscode
|
||||||
def durchfuehre_simulation(parameter):
|
def durchfuehre_simulation(parameter):
|
||||||
|
|
||||||
|
start_hour = datetime.now().hour
|
||||||
|
|
||||||
############
|
############
|
||||||
# Parameter
|
# Parameter
|
||||||
############
|
############
|
||||||
@ -113,7 +128,7 @@ def durchfuehre_simulation(parameter):
|
|||||||
akku_size = parameter['pv_akku_cap'] # Wh
|
akku_size = parameter['pv_akku_cap'] # Wh
|
||||||
year_energy = parameter['year_energy'] #2000*1000 #Wh
|
year_energy = parameter['year_energy'] #2000*1000 #Wh
|
||||||
|
|
||||||
einspeiseverguetung_cent_pro_wh = np.full(prediction_hours, parameter["einspeiseverguetung_euro_pro_wh"]) #= # € / Wh 7/(1000.0*100.0)
|
einspeiseverguetung_euro_pro_wh = np.full(prediction_hours, parameter["einspeiseverguetung_euro_pro_wh"]) #= # € / Wh 7/(1000.0*100.0)
|
||||||
|
|
||||||
max_heizleistung = parameter['max_heizleistung'] #1000 # 5 kW Heizleistung
|
max_heizleistung = parameter['max_heizleistung'] #1000 # 5 kW Heizleistung
|
||||||
wp = Waermepumpe(max_heizleistung,prediction_hours)
|
wp = Waermepumpe(max_heizleistung,prediction_hours)
|
||||||
@ -146,8 +161,14 @@ def durchfuehre_simulation(parameter):
|
|||||||
###############
|
###############
|
||||||
#PVforecast = PVForecast(filepath=os.path.join(r'test_data', r'pvprognose.json'))
|
#PVforecast = PVForecast(filepath=os.path.join(r'test_data', r'pvprognose.json'))
|
||||||
PVforecast = PVForecast(prediction_hours = prediction_hours, url=pv_forecast_url)
|
PVforecast = PVForecast(prediction_hours = prediction_hours, url=pv_forecast_url)
|
||||||
|
#print("PVPOWER",parameter['pvpowernow'])
|
||||||
|
if isfloat(parameter['pvpowernow']):
|
||||||
|
PVforecast.update_ac_power_measurement(date_time=datetime.now(), ac_power_measurement=float(parameter['pvpowernow']))
|
||||||
|
#PVforecast.print_ac_power_and_measurement()
|
||||||
pv_forecast = PVforecast.get_pv_forecast_for_date_range(date_now,date) #get_forecast_for_date(date)
|
pv_forecast = PVforecast.get_pv_forecast_for_date_range(date_now,date) #get_forecast_for_date(date)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
temperature_forecast = PVforecast.get_temperature_for_date_range(date_now,date)
|
temperature_forecast = PVforecast.get_temperature_for_date_range(date_now,date)
|
||||||
|
|
||||||
|
|
||||||
@ -165,7 +186,7 @@ def durchfuehre_simulation(parameter):
|
|||||||
leistung_wp = wp.simulate_24h(temperature_forecast)
|
leistung_wp = wp.simulate_24h(temperature_forecast)
|
||||||
gesamtlast.hinzufuegen("Heatpump", leistung_wp)
|
gesamtlast.hinzufuegen("Heatpump", leistung_wp)
|
||||||
|
|
||||||
ems = EnergieManagementSystem(akku=akku, gesamtlast = gesamtlast, pv_prognose_wh=pv_forecast, strompreis_cent_pro_wh=specific_date_prices, einspeiseverguetung_cent_pro_wh=einspeiseverguetung_cent_pro_wh, eauto=eauto)
|
ems = EnergieManagementSystem(akku=akku, gesamtlast = gesamtlast, pv_prognose_wh=pv_forecast, strompreis_euro_pro_wh=specific_date_prices, einspeiseverguetung_euro_pro_wh=einspeiseverguetung_euro_pro_wh, eauto=eauto)
|
||||||
o = ems.simuliere(start_hour)
|
o = ems.simuliere(start_hour)
|
||||||
|
|
||||||
|
|
||||||
@ -189,7 +210,9 @@ def durchfuehre_simulation(parameter):
|
|||||||
|
|
||||||
#print(o)
|
#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,einspeiseverguetung_euro_pro_wh)
|
||||||
|
|
||||||
|
os.system("scp visualisierungsergebnisse.pdf andreas@192.168.1.135:")
|
||||||
|
|
||||||
#print(eauto)
|
#print(eauto)
|
||||||
return {"discharge_hours_bin":discharge_hours_bin, "eautocharge_hours_float":eautocharge_hours_float ,"result":o ,"eauto_obj":eauto,"start_solution":best_solution}
|
return {"discharge_hours_bin":discharge_hours_bin, "eautocharge_hours_float":eautocharge_hours_float ,"result":o ,"eauto_obj":eauto,"start_solution":best_solution}
|
||||||
@ -203,7 +226,7 @@ def simulation():
|
|||||||
parameter = request.json
|
parameter = request.json
|
||||||
|
|
||||||
# Erforderliche Parameter prüfen
|
# Erforderliche Parameter prüfen
|
||||||
erforderliche_parameter = [ 'pv_akku_cap', 'year_energy',"einspeiseverguetung_euro_pro_wh", 'max_heizleistung', 'pv_forecast_url', 'eauto_min_soc', "eauto_cap","eauto_charge_efficiency","eauto_charge_power","eauto_soc","pv_soc","start_solution"]
|
erforderliche_parameter = [ 'pv_akku_cap', 'year_energy',"einspeiseverguetung_euro_pro_wh", 'max_heizleistung', 'pv_forecast_url', 'eauto_min_soc', "eauto_cap","eauto_charge_efficiency","eauto_charge_power","eauto_soc","pv_soc","start_solution","pvpowernow"]
|
||||||
for p in erforderliche_parameter:
|
for p in erforderliche_parameter:
|
||||||
if p not in parameter:
|
if p not in parameter:
|
||||||
return jsonify({"error": f"Fehlender Parameter: {p}"}), 400
|
return jsonify({"error": f"Fehlender Parameter: {p}"}), 400
|
||||||
@ -217,6 +240,10 @@ def simulation():
|
|||||||
|
|
||||||
return jsonify(ergebnis)
|
return jsonify(ergebnis)
|
||||||
|
|
||||||
|
@app.route('/visualisierungsergebnisse.pdf')
|
||||||
|
def get_pdf():
|
||||||
|
return send_from_directory('', 'visualisierungsergebnisse.pdf')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
class PVAkku:
|
class PVAkku:
|
||||||
def __init__(self, kapazitaet_wh=None, hours=None, lade_effizienz=0.9, entlade_effizienz=0.9,max_ladeleistung_w=None,start_soc_prozent=0):
|
def __init__(self, kapazitaet_wh=None, hours=None, lade_effizienz=0.9, entlade_effizienz=0.9,max_ladeleistung_w=None,start_soc_prozent=0,min_soc_prozent=0,max_soc_prozent=100):
|
||||||
# Kapazität des Akkus in Wh
|
# Kapazität des Akkus in Wh
|
||||||
self.kapazitaet_wh = kapazitaet_wh
|
self.kapazitaet_wh = kapazitaet_wh
|
||||||
# Initialer Ladezustand des Akkus in Wh
|
# Initialer Ladezustand des Akkus in Wh
|
||||||
@ -13,6 +13,9 @@ class PVAkku:
|
|||||||
self.lade_effizienz = lade_effizienz
|
self.lade_effizienz = lade_effizienz
|
||||||
self.entlade_effizienz = entlade_effizienz
|
self.entlade_effizienz = entlade_effizienz
|
||||||
self.max_ladeleistung_w = max_ladeleistung_w if max_ladeleistung_w else self.kapazitaet_wh
|
self.max_ladeleistung_w = max_ladeleistung_w if max_ladeleistung_w else self.kapazitaet_wh
|
||||||
|
self.min_soc_prozent = min_soc_prozent
|
||||||
|
self.max_soc_prozent = max_soc_prozent
|
||||||
|
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
@ -94,13 +97,16 @@ class PVAkku:
|
|||||||
wh = wh if wh is not None else self.max_ladeleistung_w
|
wh = wh if wh is not None else self.max_ladeleistung_w
|
||||||
|
|
||||||
# Berechnung der tatsächlichen Lademenge unter Berücksichtigung der Ladeeffizienz
|
# Berechnung der tatsächlichen Lademenge unter Berücksichtigung der Ladeeffizienz
|
||||||
effektive_lademenge = min(wh, self.max_ladeleistung_w) * self.lade_effizienz
|
effektive_lademenge = min(wh, self.max_ladeleistung_w)
|
||||||
|
|
||||||
# Aktualisierung des Ladezustands ohne die Kapazität zu überschreiten
|
# Aktualisierung des Ladezustands ohne die Kapazität zu überschreiten
|
||||||
geladene_menge = min(self.kapazitaet_wh - self.soc_wh, effektive_lademenge)
|
geladene_menge_ohne_verlust = min(self.kapazitaet_wh - self.soc_wh, effektive_lademenge)
|
||||||
|
|
||||||
|
geladene_menge = geladene_menge_ohne_verlust * self.lade_effizienz
|
||||||
|
|
||||||
self.soc_wh += geladene_menge
|
self.soc_wh += geladene_menge
|
||||||
|
|
||||||
verluste_wh = geladene_menge* (1.0-self.lade_effizienz)
|
verluste_wh = geladene_menge_ohne_verlust* (1.0-self.lade_effizienz)
|
||||||
|
|
||||||
return geladene_menge, verluste_wh
|
return geladene_menge, verluste_wh
|
||||||
# effektive_lademenge = wh * self.lade_effizienz
|
# effektive_lademenge = wh * self.lade_effizienz
|
||||||
|
@ -3,13 +3,13 @@ from pprint import pprint
|
|||||||
|
|
||||||
|
|
||||||
class EnergieManagementSystem:
|
class EnergieManagementSystem:
|
||||||
def __init__(self, akku=None, pv_prognose_wh=None, strompreis_cent_pro_wh=None, einspeiseverguetung_cent_pro_wh=None, eauto=None, gesamtlast=None):
|
def __init__(self, akku=None, pv_prognose_wh=None, strompreis_euro_pro_wh=None, einspeiseverguetung_euro_pro_wh=None, eauto=None, gesamtlast=None):
|
||||||
self.akku = akku
|
self.akku = akku
|
||||||
#self.lastkurve_wh = lastkurve_wh
|
#self.lastkurve_wh = lastkurve_wh
|
||||||
self.gesamtlast = gesamtlast
|
self.gesamtlast = gesamtlast
|
||||||
self.pv_prognose_wh = pv_prognose_wh
|
self.pv_prognose_wh = pv_prognose_wh
|
||||||
self.strompreis_cent_pro_wh = strompreis_cent_pro_wh # Strompreis in Cent pro Wh
|
self.strompreis_euro_pro_wh = strompreis_euro_pro_wh # Strompreis in Cent pro Wh
|
||||||
self.einspeiseverguetung_cent_pro_wh = einspeiseverguetung_cent_pro_wh # Einspeisevergütung in Cent pro Wh
|
self.einspeiseverguetung_euro_pro_wh = einspeiseverguetung_euro_pro_wh # Einspeisevergütung in Cent pro Wh
|
||||||
self.eauto = eauto
|
self.eauto = eauto
|
||||||
|
|
||||||
def set_akku_discharge_hours(self, ds):
|
def set_akku_discharge_hours(self, ds):
|
||||||
@ -46,7 +46,7 @@ class EnergieManagementSystem:
|
|||||||
lastkurve_wh = self.gesamtlast.gesamtlast_berechnen()
|
lastkurve_wh = self.gesamtlast.gesamtlast_berechnen()
|
||||||
|
|
||||||
|
|
||||||
ende = min( len(lastkurve_wh),len(self.pv_prognose_wh), len(self.strompreis_cent_pro_wh))
|
ende = min( len(lastkurve_wh),len(self.pv_prognose_wh), len(self.strompreis_euro_pro_wh))
|
||||||
#print(ende)
|
#print(ende)
|
||||||
# Berechnet das Ende basierend auf der Länge der Lastkurve
|
# Berechnet das Ende basierend auf der Länge der Lastkurve
|
||||||
for stunde in range(start_stunde, ende):
|
for stunde in range(start_stunde, ende):
|
||||||
@ -54,7 +54,7 @@ class EnergieManagementSystem:
|
|||||||
# Anpassung, um sicherzustellen, dass Indizes korrekt sind
|
# Anpassung, um sicherzustellen, dass Indizes korrekt sind
|
||||||
verbrauch = lastkurve_wh[stunde]
|
verbrauch = lastkurve_wh[stunde]
|
||||||
erzeugung = self.pv_prognose_wh[stunde]
|
erzeugung = self.pv_prognose_wh[stunde]
|
||||||
strompreis = self.strompreis_cent_pro_wh[stunde] if stunde < len(self.strompreis_cent_pro_wh) else self.strompreis_cent_pro_wh[-1]
|
strompreis = self.strompreis_euro_pro_wh[stunde] if stunde < len(self.strompreis_euro_pro_wh) else self.strompreis_euro_pro_wh[-1]
|
||||||
verluste_wh_pro_stunde.append(0.0)
|
verluste_wh_pro_stunde.append(0.0)
|
||||||
#eauto_soc = self.eauto.get_stuendlicher_soc()[stunde]
|
#eauto_soc = self.eauto.get_stuendlicher_soc()[stunde]
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ class EnergieManagementSystem:
|
|||||||
#print("verluste_laden_akku:",verluste_laden_akku)
|
#print("verluste_laden_akku:",verluste_laden_akku)
|
||||||
netzeinspeisung_wh_pro_stunde.append(überschuss - geladene_energie-verluste_laden_akku)
|
netzeinspeisung_wh_pro_stunde.append(überschuss - geladene_energie-verluste_laden_akku)
|
||||||
eigenverbrauch_wh_pro_stunde.append(verbrauch)
|
eigenverbrauch_wh_pro_stunde.append(verbrauch)
|
||||||
stündliche_einnahmen_euro = (überschuss - geladene_energie-verluste_laden_akku) * self.einspeiseverguetung_cent_pro_wh[stunde]
|
stündliche_einnahmen_euro = (überschuss - geladene_energie-verluste_laden_akku) * self.einspeiseverguetung_euro_pro_wh[stunde]
|
||||||
#print(überschuss," ", geladene_energie," ",verluste_laden_akku)
|
#print(überschuss," ", geladene_energie," ",verluste_laden_akku)
|
||||||
netzbezug_wh_pro_stunde.append(0.0)
|
netzbezug_wh_pro_stunde.append(0.0)
|
||||||
else:
|
else:
|
||||||
|
@ -4,15 +4,18 @@ from datetime import datetime
|
|||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import json, sys, os
|
import json, sys, os
|
||||||
import requests, hashlib
|
import requests, hashlib
|
||||||
|
from dateutil import parser, tz
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ForecastData:
|
class ForecastData:
|
||||||
def __init__(self, date_time, dc_power, ac_power, windspeed_10m, temperature):
|
def __init__(self, date_time, dc_power, ac_power, windspeed_10m=None, temperature=None,ac_power_measurement=None):
|
||||||
self.date_time = date_time
|
self.date_time = date_time
|
||||||
self.dc_power = dc_power
|
self.dc_power = dc_power
|
||||||
self.ac_power = ac_power
|
self.ac_power = ac_power
|
||||||
self.windspeed_10m = windspeed_10m
|
self.windspeed_10m = windspeed_10m
|
||||||
self.temperature = temperature
|
self.temperature = temperature
|
||||||
|
self.ac_power_measurement = None
|
||||||
|
|
||||||
# Getter für die ForecastData-Attribute
|
# Getter für die ForecastData-Attribute
|
||||||
def get_date_time(self):
|
def get_date_time(self):
|
||||||
@ -21,7 +24,13 @@ class ForecastData:
|
|||||||
def get_dc_power(self):
|
def get_dc_power(self):
|
||||||
return self.dc_power
|
return self.dc_power
|
||||||
|
|
||||||
|
def ac_power_measurement(self):
|
||||||
|
return self.ac_power_measurement
|
||||||
|
|
||||||
def get_ac_power(self):
|
def get_ac_power(self):
|
||||||
|
if self.ac_power_measurement != None:
|
||||||
|
return self.ac_power_measurement
|
||||||
|
else:
|
||||||
return self.ac_power
|
return self.ac_power
|
||||||
|
|
||||||
def get_windspeed_10m(self):
|
def get_windspeed_10m(self):
|
||||||
@ -36,6 +45,7 @@ class PVForecast:
|
|||||||
self.forecast_data = []
|
self.forecast_data = []
|
||||||
self.cache_dir = cache_dir
|
self.cache_dir = cache_dir
|
||||||
self.prediction_hours = prediction_hours
|
self.prediction_hours = prediction_hours
|
||||||
|
self.current_measurement = None
|
||||||
|
|
||||||
if not os.path.exists(self.cache_dir):
|
if not os.path.exists(self.cache_dir):
|
||||||
os.makedirs(self.cache_dir)
|
os.makedirs(self.cache_dir)
|
||||||
@ -48,6 +58,32 @@ class PVForecast:
|
|||||||
if len(self.forecast_data) < self.prediction_hours:
|
if len(self.forecast_data) < self.prediction_hours:
|
||||||
raise ValueError(f"Die Vorhersage muss mindestens {self.prediction_hours} Stunden umfassen, aber es wurden nur {len(self.forecast_data)} Stunden vorhergesagt.")
|
raise ValueError(f"Die Vorhersage muss mindestens {self.prediction_hours} Stunden umfassen, aber es wurden nur {len(self.forecast_data)} Stunden vorhergesagt.")
|
||||||
|
|
||||||
|
def update_ac_power_measurement(self, date_time=None, ac_power_measurement=None):
|
||||||
|
"""Aktualisiert einen DC-Leistungsmesswert oder fügt ihn hinzu."""
|
||||||
|
found = False
|
||||||
|
target_timezone = tz.gettz('Europe/Berlin')
|
||||||
|
input_date_hour = date_time.astimezone(target_timezone).replace(minute=0, second=0, microsecond=0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for forecast in self.forecast_data:
|
||||||
|
forecast_date_hour = datetime.strptime(forecast.date_time, "%Y-%m-%dT%H:%M:%S.%f%z").astimezone(target_timezone).replace(minute=0, second=0, microsecond=0)
|
||||||
|
|
||||||
|
|
||||||
|
#print(forecast_date_hour," ",input_date_hour)
|
||||||
|
if forecast_date_hour == input_date_hour:
|
||||||
|
forecast.ac_power_measurement = ac_power_measurement
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
# if not found:
|
||||||
|
# # Erstelle ein neues ForecastData-Objekt, falls kein entsprechender Zeitstempel gefunden wurde
|
||||||
|
# # Hier kannst du entscheiden, wie die anderen Werte gesetzt werden sollen, falls keine Vorhersage existiert
|
||||||
|
# new_forecast = ForecastData(date_time, dc_power=None, ac_power=None, dc_power_measurement=dc_power_measurement)
|
||||||
|
# self.forecast_data.append(new_forecast)
|
||||||
|
# # Liste sortieren, um sie chronologisch zu ordnen
|
||||||
|
# self.forecast_data.sort(key=lambda x: datetime.strptime(x.date_time, "%Y-%m-%dT%H:%M:%S.%f%z").replace(minute=0, second=0, microsecond=0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def process_data(self, data):
|
def process_data(self, data):
|
||||||
@ -71,16 +107,6 @@ class PVForecast:
|
|||||||
|
|
||||||
self.forecast_data.append(forecast)
|
self.forecast_data.append(forecast)
|
||||||
|
|
||||||
# values = data.get('values', [])[0]
|
|
||||||
# for value in values:
|
|
||||||
# forecast = ForecastData(
|
|
||||||
# date_time=value.get('datetime'),
|
|
||||||
# dc_power=value.get('dcPower'),
|
|
||||||
# ac_power=value.get('power'),
|
|
||||||
# windspeed_10m=value.get('windspeed_10m'),
|
|
||||||
# temperature=value.get('temperature')
|
|
||||||
# )
|
|
||||||
# self.forecast_data.append(forecast)
|
|
||||||
|
|
||||||
def load_data_from_file(self, filepath):
|
def load_data_from_file(self, filepath):
|
||||||
with open(filepath, 'r') as file:
|
with open(filepath, 'r') as file:
|
||||||
@ -127,14 +153,14 @@ class PVForecast:
|
|||||||
return self.forecast_data
|
return self.forecast_data
|
||||||
|
|
||||||
|
|
||||||
def get_forecast_for_date(self, input_date_str):
|
# def get_forecast_for_date(self, input_date_str):
|
||||||
input_date = datetime.strptime(input_date_str, "%Y-%m-%d")
|
# input_date = datetime.strptime(input_date_str, "%Y-%m-%d")
|
||||||
daily_forecast_obj = [data for data in self.forecast_data if datetime.strptime(data.get_date_time(), "%Y-%m-%dT%H:%M:%S.%f%z").date() == input_date.date()]
|
# daily_forecast_obj = [data for data in self.forecast_data if datetime.strptime(data.get_date_time(), "%Y-%m-%dT%H:%M:%S.%f%z").date() == input_date.date()]
|
||||||
daily_forecast = []
|
# daily_forecast = []
|
||||||
for d in daily_forecast_obj:
|
# for d in daily_forecast_obj:
|
||||||
daily_forecast.append(d.get_ac_power())
|
# daily_forecast.append(d.get_ac_power())
|
||||||
|
|
||||||
return np.array(daily_forecast)
|
# return np.array(daily_forecast)
|
||||||
|
|
||||||
def get_temperature_forecast_for_date(self, input_date_str):
|
def get_temperature_forecast_for_date(self, input_date_str):
|
||||||
input_date = datetime.strptime(input_date_str, "%Y-%m-%d")
|
input_date = datetime.strptime(input_date_str, "%Y-%m-%d")
|
||||||
@ -175,12 +201,19 @@ class PVForecast:
|
|||||||
return np.array(temperature_forecast)[:self.prediction_hours]
|
return np.array(temperature_forecast)[:self.prediction_hours]
|
||||||
|
|
||||||
|
|
||||||
|
def print_ac_power_and_measurement(self):
|
||||||
|
"""Druckt die DC-Leistung und das Messwert für jede Stunde."""
|
||||||
|
for forecast in self.forecast_data:
|
||||||
|
date_time = forecast.date_time
|
||||||
|
|
||||||
|
|
||||||
|
print(f"Zeit: {date_time}, DC: {forecast.dc_power}, AC: {forecast.ac_power}, Messwert: {forecast.ac_power_measurement} AC GET: {forecast.get_ac_power()}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Beispiel für die Verwendung der Klasse
|
# Beispiel für die Verwendung der Klasse
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
forecast = PVForecast(r'..\test_data\pvprognose.json')
|
date_now = datetime.now()
|
||||||
for data in forecast.get_forecast_data():
|
forecast = PVForecast(prediction_hours = 24, url="https://api.akkudoktor.net/forecast?lat=52.52&lon=13.405&power=5000&azimuth=-10&tilt=7&powerInvertor=10000&horizont=20,27,22,20&power=4800&azimuth=-90&tilt=7&powerInvertor=10000&horizont=30,30,30,50&power=1400&azimuth=-40&tilt=60&powerInvertor=2000&horizont=60,30,0,30&power=1600&azimuth=5&tilt=45&powerInvertor=1400&horizont=45,25,30,60&past_days=5&cellCoEff=-0.36&inverterEfficiency=0.8&albedo=0.25&timezone=Europe%2FBerlin&hourly=relativehumidity_2m%2Cwindspeed_10m")
|
||||||
print(data.get_date_time(), data.get_dc_power(), data.get_ac_power(), data.get_windspeed_10m(), data.get_temperature())
|
forecast.update_ac_power_measurement(date_time=datetime.now(), ac_power_measurement=1000)
|
||||||
|
forecast.print_ac_power_and_measurement()
|
||||||
|
26
modules/class_sommerzeit.py
Normal file
26
modules/class_sommerzeit.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import datetime
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
def ist_dst_wechsel(tag, timezone="Europe/Berlin"):
|
||||||
|
"""Prüft, ob an einem gegebenen Tag die Sommerzeit beginnt oder endet."""
|
||||||
|
tz = pytz.timezone(timezone)
|
||||||
|
# Hole den aktuellen Tag und den nächsten Tag
|
||||||
|
aktueller_tag = datetime.datetime(tag.year, tag.month, tag.day)
|
||||||
|
naechster_tag = aktueller_tag + datetime.timedelta(days=1)
|
||||||
|
|
||||||
|
# Lokalisiere die Tage in der gegebenen Zeitzone
|
||||||
|
aktueller_tag_localized = tz.localize(aktueller_tag, is_dst=None)
|
||||||
|
naechster_tag_localized = tz.localize(naechster_tag, is_dst=None)
|
||||||
|
|
||||||
|
# Prüfe, ob die UTC-Offsets unterschiedlich sind (DST-Wechsel)
|
||||||
|
dst_wechsel = aktueller_tag_localized.dst() != naechster_tag_localized.dst()
|
||||||
|
|
||||||
|
return dst_wechsel, aktueller_tag_localized.dst(), naechster_tag_localized.dst()
|
||||||
|
|
||||||
|
|
||||||
|
# Beispielverwendung
|
||||||
|
start_datum = datetime.datetime(2024, 3, 31) # Datum der DST-Umstellung
|
||||||
|
if ist_dst_wechsel(start_datum):
|
||||||
|
prediction_hours = 23 # Anpassung auf 23 Stunden für DST-Wechseltage
|
||||||
|
else:
|
||||||
|
prediction_hours = 24 # Standardwert für Tage ohne DST-Wechsel
|
@ -1,14 +1,15 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
from modules.class_sommerzeit import *
|
||||||
from modules.class_load_container import Gesamtlast # Stellen Sie sicher, dass dies dem tatsächlichen Importpfad entspricht
|
from modules.class_load_container import Gesamtlast # Stellen Sie sicher, dass dies dem tatsächlichen Importpfad entspricht
|
||||||
import matplotlib
|
import matplotlib
|
||||||
matplotlib.use('Agg') # Setzt das Backend auf Agg
|
matplotlib.use('Agg') # Setzt das Backend auf Agg
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from matplotlib.backends.backend_pdf import PdfPages
|
from matplotlib.backends.backend_pdf import PdfPages
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, discharge_hours, laden_moeglich, temperature, start_hour, prediction_hours,einspeiseverguetung_euro_pro_wh):
|
||||||
def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, discharge_hours, laden_moeglich, temperature, start_hour, prediction_hours):
|
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
# 24h
|
# 24h
|
||||||
@ -18,7 +19,7 @@ def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, d
|
|||||||
|
|
||||||
# Last und PV-Erzeugung
|
# Last und PV-Erzeugung
|
||||||
plt.figure(figsize=(14, 14))
|
plt.figure(figsize=(14, 14))
|
||||||
plt.subplot(3, 2, 1)
|
plt.subplot(3, 3, 1)
|
||||||
stunden = np.arange(0, prediction_hours)
|
stunden = np.arange(0, prediction_hours)
|
||||||
|
|
||||||
|
|
||||||
@ -56,8 +57,19 @@ def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, d
|
|||||||
plt.legend()
|
plt.legend()
|
||||||
plt.grid(True)
|
plt.grid(True)
|
||||||
|
|
||||||
# Temperatur Forecast
|
# Vergütung
|
||||||
|
stundenp = np.arange(0, len(strompreise))
|
||||||
plt.subplot(3, 2, 4)
|
plt.subplot(3, 2, 4)
|
||||||
|
plt.plot(stunden, einspeiseverguetung_euro_pro_wh, label='Vergütung €/Wh', marker='x')
|
||||||
|
plt.title('Vergütung')
|
||||||
|
plt.xlabel('Stunde des Tages')
|
||||||
|
plt.ylabel('€/Wh')
|
||||||
|
plt.legend()
|
||||||
|
plt.grid(True)
|
||||||
|
|
||||||
|
|
||||||
|
# Temperatur Forecast
|
||||||
|
plt.subplot(3, 2, 5)
|
||||||
plt.title('Temperatur Forecast °C')
|
plt.title('Temperatur Forecast °C')
|
||||||
plt.plot(stunden, temperature, label='Temperatur °C', marker='x')
|
plt.plot(stunden, temperature, label='Temperatur °C', marker='x')
|
||||||
plt.xlabel('Stunde des Tages')
|
plt.xlabel('Stunde des Tages')
|
||||||
@ -74,7 +86,13 @@ def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, d
|
|||||||
#####################
|
#####################
|
||||||
|
|
||||||
plt.figure(figsize=(14, 10))
|
plt.figure(figsize=(14, 10))
|
||||||
stunden = np.arange(start_hour, prediction_hours)
|
|
||||||
|
if ist_dst_wechsel(datetime.now()):
|
||||||
|
stunden = np.arange(start_hour, prediction_hours-1)
|
||||||
|
else:
|
||||||
|
stunden = np.arange(start_hour, prediction_hours-1)
|
||||||
|
|
||||||
|
|
||||||
# Eigenverbrauch, Netzeinspeisung und Netzbezug
|
# Eigenverbrauch, Netzeinspeisung und Netzbezug
|
||||||
plt.subplot(3, 2, 1)
|
plt.subplot(3, 2, 1)
|
||||||
plt.plot(stunden, ergebnisse['Eigenverbrauch_Wh_pro_Stunde'], label='Eigenverbrauch (Wh)', marker='o')
|
plt.plot(stunden, ergebnisse['Eigenverbrauch_Wh_pro_Stunde'], label='Eigenverbrauch (Wh)', marker='o')
|
||||||
@ -112,6 +130,7 @@ def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, d
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
plt.grid(True)
|
plt.grid(True)
|
||||||
fig, axs = plt.subplots(1, 2, figsize=(14, 10)) # Erstellt 1x2 Raster von Subplots
|
fig, axs = plt.subplots(1, 2, figsize=(14, 10)) # Erstellt 1x2 Raster von Subplots
|
||||||
gesamtkosten = ergebnisse['Gesamtkosten_Euro']
|
gesamtkosten = ergebnisse['Gesamtkosten_Euro']
|
||||||
|
Loading…
x
Reference in New Issue
Block a user