Wallbox Leistung wird von der Lastprognose abgezogen

This commit is contained in:
Bla Bla 2024-08-30 11:49:44 +02:00
parent 5d5514c901
commit 65ecf4cf3c
6 changed files with 442 additions and 204 deletions

View File

@ -29,7 +29,7 @@ from config import *
app = Flask(__name__) app = Flask(__name__)
opt_class = optimization_problem(prediction_hours=48, strafe=10) opt_class = optimization_problem(prediction_hours=prediction_hours, strafe=10, optimization_hours=optimization_hours)
@ -224,7 +224,7 @@ def flask_optimize():
parameter = request.json parameter = request.json
# Erforderliche Parameter prüfen # Erforderliche Parameter prüfen
erforderliche_parameter = [ 'strompreis_euro_pro_wh', "gesamtlast",'pv_akku_cap', "einspeiseverguetung_euro_pro_wh", 'pv_forecast','temperature_forecast', 'eauto_min_soc', "eauto_cap","eauto_charge_efficiency","eauto_charge_power","eauto_soc","pv_soc","start_solution","haushaltsgeraet_dauer","haushaltsgeraet_wh"] erforderliche_parameter = [ 'preis_euro_pro_wh_akku','strompreis_euro_pro_wh', "gesamtlast",'pv_akku_cap', "einspeiseverguetung_euro_pro_wh", 'pv_forecast','temperature_forecast', 'eauto_min_soc', "eauto_cap","eauto_charge_efficiency","eauto_charge_power","eauto_soc","pv_soc","start_solution","haushaltsgeraet_dauer","haushaltsgeraet_wh"]
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

View File

@ -122,6 +122,17 @@ class PVAkku:
return geladene_menge, verluste_wh return geladene_menge, verluste_wh
def aktueller_energieinhalt(self):
"""
Diese Methode gibt die aktuelle Restenergie unter Berücksichtigung des Wirkungsgrades zurück.
Sie berücksichtigt dabei die Lade- und Entladeeffizienz.
"""
# Berechnung der Restenergie unter Berücksichtigung der Entladeeffizienz
nutzbare_energie = self.soc_wh * self.entlade_effizienz
return nutzbare_energie
# def energie_laden(self, wh, hour): # def energie_laden(self, wh, hour):
# if hour is not None and self.charge_array[hour] == 0: # if hour is not None and self.charge_array[hour] == 0:

View File

@ -0,0 +1,235 @@
import json,sys, os
from datetime import datetime, timedelta, timezone
import numpy as np
from pprint import pprint
import pandas as pd
import matplotlib.pyplot as plt
# from sklearn.model_selection import train_test_split, GridSearchCV
# from sklearn.ensemble import GradientBoostingRegressor
# from xgboost import XGBRegressor
# from statsmodels.tsa.statespace.sarimax import SARIMAX
# from tensorflow.keras.models import Sequential
# from tensorflow.keras.layers import Dense, LSTM
# from tensorflow.keras.optimizers import Adam
# from sklearn.preprocessing import MinMaxScaler
# from sklearn.metrics import mean_squared_error, r2_score
import mariadb
# from sqlalchemy import create_engine
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error, r2_score
# Fügen Sie den übergeordneten Pfad zum sys.path hinzu
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from config import *
from modules.class_load import *
class LoadPredictionAdjuster:
def __init__(self, measured_data, predicted_data, load_forecast):
self.measured_data = measured_data
self.predicted_data = predicted_data
self.load_forecast = load_forecast
self.merged_data = self._merge_data()
self.train_data = None
self.test_data = None
self.weekday_diff = None
self.weekend_diff = None
def _remove_outliers(self, data, threshold=2):
# Berechne den Z-Score der 'Last'-Daten
data['Z-Score'] = np.abs((data['Last'] - data['Last'].mean()) / data['Last'].std())
# Filtere die Daten nach dem Schwellenwert
filtered_data = data[data['Z-Score'] < threshold]
return filtered_data.drop(columns=['Z-Score'])
def _merge_data(self):
merged_data = pd.merge(self.measured_data, self.predicted_data, on='time', how='inner')
merged_data['Hour'] = merged_data['time'].dt.hour
merged_data['DayOfWeek'] = merged_data['time'].dt.dayofweek
return merged_data
def calculate_weighted_mean(self, train_period_weeks=9, test_period_weeks=1):
self.merged_data = self._remove_outliers(self.merged_data)
train_end_date = self.merged_data['time'].max() - pd.Timedelta(weeks=test_period_weeks)
train_start_date = train_end_date - pd.Timedelta(weeks=train_period_weeks)
test_start_date = train_end_date + pd.Timedelta(hours=1)
test_end_date = test_start_date + pd.Timedelta(weeks=test_period_weeks) - pd.Timedelta(hours=1)
self.train_data = self.merged_data[(self.merged_data['time'] >= train_start_date) & (self.merged_data['time'] <= train_end_date)]
self.test_data = self.merged_data[(self.merged_data['time'] >= test_start_date) & (self.merged_data['time'] <= test_end_date)]
self.train_data['Difference'] = self.train_data['Last'] - self.train_data['Last Pred']
weekdays_train_data = self.train_data[self.train_data['DayOfWeek'] < 5]
weekends_train_data = self.train_data[self.train_data['DayOfWeek'] >= 5]
self.weekday_diff = weekdays_train_data.groupby('Hour').apply(self._weighted_mean_diff).dropna()
self.weekend_diff = weekends_train_data.groupby('Hour').apply(self._weighted_mean_diff).dropna()
def _weighted_mean_diff(self, data):
train_end_date = self.train_data['time'].max()
weights = 1 / (train_end_date - data['time']).dt.days.replace(0, np.nan)
weighted_mean = (data['Difference'] * weights).sum() / weights.sum()
return weighted_mean
def adjust_predictions(self):
self.train_data['Adjusted Pred'] = self.train_data.apply(self._adjust_row, axis=1)
self.test_data['Adjusted Pred'] = self.test_data.apply(self._adjust_row, axis=1)
def _adjust_row(self, row):
if row['DayOfWeek'] < 5:
return row['Last Pred'] + self.weekday_diff.get(row['Hour'], 0)
else:
return row['Last Pred'] + self.weekend_diff.get(row['Hour'], 0)
def plot_results(self):
self._plot_data(self.train_data, 'Training')
self._plot_data(self.test_data, 'Testing')
def _plot_data(self, data, data_type):
plt.figure(figsize=(14, 7))
plt.plot(data['time'], data['Last'], label=f'Actual Last - {data_type}', color='blue')
plt.plot(data['time'], data['Last Pred'], label=f'Predicted Last - {data_type}', color='red', linestyle='--')
plt.plot(data['time'], data['Adjusted Pred'], label=f'Adjusted Predicted Last - {data_type}', color='green', linestyle=':')
plt.xlabel('Time')
plt.ylabel('Load')
plt.title(f'Actual vs Predicted vs Adjusted Predicted Load ({data_type} Data)')
plt.legend()
plt.grid(True)
plt.show()
def evaluate_model(self):
mse = mean_squared_error(self.test_data['Last'], self.test_data['Adjusted Pred'])
r2 = r2_score(self.test_data['Last'], self.test_data['Adjusted Pred'])
print(f'Mean Squared Error: {mse}')
print(f'R-squared: {r2}')
def predict_next_hours(self, hours_ahead):
last_date = self.merged_data['time'].max()
future_dates = [last_date + pd.Timedelta(hours=i) for i in range(1, hours_ahead + 1)]
future_df = pd.DataFrame({'time': future_dates})
future_df['Hour'] = future_df['time'].dt.hour
future_df['DayOfWeek'] = future_df['time'].dt.dayofweek
future_df['Last Pred'] = future_df['time'].apply(self._forecast_next_hours)
future_df['Adjusted Pred'] = future_df.apply(self._adjust_row, axis=1)
return future_df
def _forecast_next_hours(self, timestamp):
date_str = timestamp.strftime('%Y-%m-%d')
hour = timestamp.hour
daily_forecast = self.load_forecast.get_daily_stats(date_str)
return daily_forecast[0][hour] if hour < len(daily_forecast[0]) else np.nan
class LastEstimator:
def __init__(self):
self.conn_params = db_config
self.conn = mariadb.connect(**self.conn_params)
def fetch_data(self, start_date, end_date):
queries = {
"Stromzaehler": f"SELECT DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') as timestamp, AVG(data) AS Stromzaehler FROM sensor_stromzaehler WHERE topic = 'stromzaehler leistung' AND timestamp BETWEEN '{start_date}' AND '{end_date}' GROUP BY 1 ORDER BY timestamp ASC",
"PV": f"SELECT DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') as timestamp, AVG(data) AS PV FROM data WHERE topic = 'solarallpower' AND timestamp BETWEEN '{start_date}' AND '{end_date}' GROUP BY 1 ORDER BY timestamp ASC",
"Batterie_Strom_PIP": f"SELECT DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') as timestamp, AVG(data) AS Batterie_Strom_PIP FROM pip WHERE topic = 'battery_current' AND timestamp BETWEEN '{start_date}' AND '{end_date}' GROUP BY 1 ORDER BY timestamp ASC",
"Batterie_Volt_PIP": f"SELECT DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') as timestamp, AVG(data) AS Batterie_Volt_PIP FROM pip WHERE topic = 'battery_voltage' AND timestamp BETWEEN '{start_date}' AND '{end_date}' GROUP BY 1 ORDER BY timestamp ASC",
"Stromzaehler_Raus": f"SELECT DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') as timestamp, AVG(data) AS Stromzaehler_Raus FROM sensor_stromzaehler WHERE topic = 'stromzaehler leistung raus' AND timestamp BETWEEN '{start_date}' AND '{end_date}' GROUP BY 1 ORDER BY timestamp ASC",
"Wallbox": f"SELECT DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') as timestamp, AVG(data) AS Wallbox_Leistung FROM wallbox WHERE topic = 'power_total' AND timestamp BETWEEN '{start_date}' AND '{end_date}' GROUP BY 1 ORDER BY timestamp ASC",
}
dataframes = {}
for key, query in queries.items():
dataframes[key] = pd.read_sql(query, self.conn)
return dataframes
def calculate_last(self, dataframes):
# Batterie_Leistung = Batterie_Strom_PIP * Batterie_Volt_PIP
dataframes["Batterie_Leistung"] = dataframes["Batterie_Strom_PIP"].merge(dataframes["Batterie_Volt_PIP"], on="timestamp", how="outer")
dataframes["Batterie_Leistung"]["Batterie_Leistung"] = dataframes["Batterie_Leistung"]["Batterie_Strom_PIP"] * dataframes["Batterie_Leistung"]["Batterie_Volt_PIP"]
# Stromzaehler_Saldo = Stromzaehler - Stromzaehler_Raus
dataframes["Stromzaehler_Saldo"] = dataframes["Stromzaehler"].merge(dataframes["Stromzaehler_Raus"], on="timestamp", how="outer")
dataframes["Stromzaehler_Saldo"]["Stromzaehler_Saldo"] = dataframes["Stromzaehler_Saldo"]["Stromzaehler"] - dataframes["Stromzaehler_Saldo"]["Stromzaehler_Raus"]
# Stromzaehler_Saldo - Batterie_Leistung
dataframes["Netzleistung"] = dataframes["Stromzaehler_Saldo"].merge(dataframes["Batterie_Leistung"], on="timestamp", how="outer")
dataframes["Netzleistung"]["Netzleistung"] = dataframes["Netzleistung"]["Stromzaehler_Saldo"] - dataframes["Netzleistung"]["Batterie_Leistung"]
# Füge die Wallbox-Leistung hinzu
dataframes["Netzleistung"] = dataframes["Netzleistung"].merge(dataframes["Wallbox"], on="timestamp", how="left")
dataframes["Netzleistung"]["Wallbox_Leistung"] = dataframes["Netzleistung"]["Wallbox_Leistung"].fillna(0) # Fülle fehlende Werte mit 0
# Last = Netzleistung + PV
# Berechne die endgültige Last
dataframes["Last"] = dataframes["Netzleistung"].merge(dataframes["PV"], on="timestamp", how="outer")
dataframes["Last"]["Last_ohneWallbox"] = dataframes["Last"]["Netzleistung"] + dataframes["Last"]["PV"]
dataframes["Last"]["Last"] = dataframes["Last"]["Netzleistung"] + dataframes["Last"]["PV"] - dataframes["Last"]["Wallbox_Leistung"]
return dataframes["Last"].dropna()
def get_last(self, start_date, end_date):
dataframes = self.fetch_data(start_date, end_date)
last_df = self.calculate_last(dataframes)
return last_df
if __name__ == '__main__':
estimator = LastEstimator()
start_date = "2024-06-01"
end_date = "2024-08-01"
last_df = estimator.get_last(start_date, end_date)
selected_columns = last_df[['timestamp', 'Last']]
selected_columns['time'] = pd.to_datetime(selected_columns['timestamp']).dt.floor('H')
selected_columns['Last'] = pd.to_numeric(selected_columns['Last'], errors='coerce')
# Drop rows with NaN values
cleaned_data = selected_columns.dropna()
print(cleaned_data)
# Create an instance of LoadForecast
lf = LoadForecast(filepath=r'.\load_profiles.npz', year_energy=6000*1000)
# Initialize an empty DataFrame to hold the forecast data
forecast_list = []
# Loop through each day in the date range
for single_date in pd.date_range(cleaned_data['time'].min().date(), cleaned_data['time'].max().date()):
date_str = single_date.strftime('%Y-%m-%d')
daily_forecast = lf.get_daily_stats(date_str)
mean_values = daily_forecast[0] # Extract the mean values
hours = [single_date + pd.Timedelta(hours=i) for i in range(24)]
daily_forecast_df = pd.DataFrame({'time': hours, 'Last Pred': mean_values})
forecast_list.append(daily_forecast_df)
# Concatenate all daily forecasts into a single DataFrame
forecast_df = pd.concat(forecast_list, ignore_index=True)
# Create an instance of the LoadPredictionAdjuster class
adjuster = LoadPredictionAdjuster(cleaned_data, forecast_df, lf)
# Calculate the weighted mean differences
adjuster.calculate_weighted_mean()
# Adjust the predictions
adjuster.adjust_predictions()
# Plot the results
adjuster.plot_results()
# Evaluate the model
adjuster.evaluate_model()
# Predict the next x hours
future_predictions = adjuster.predict_next_hours(48)
print(future_predictions)

View File

@ -159,10 +159,15 @@ class optimization_problem:
individual.extra_data = (o["Gesamtbilanz_Euro"],o["Gesamt_Verluste"], eauto_roi ) individual.extra_data = (o["Gesamtbilanz_Euro"],o["Gesamt_Verluste"], eauto_roi )
restenergie_akku = ems.akku.aktueller_energieinhalt()
restwert_akku = restenergie_akku*parameter["preis_euro_pro_wh_akku"]
# print(restenergie_akku)
# print(parameter["preis_euro_pro_wh_akku"])
# print(restwert_akku)
# print()
strafe = 0.0 strafe = 0.0
strafe = max(0,(parameter['eauto_min_soc']-ems.eauto.ladezustand_in_prozent()) * self.strafe ) strafe = max(0,(parameter['eauto_min_soc']-ems.eauto.ladezustand_in_prozent()) * self.strafe )
gesamtbilanz += strafe gesamtbilanz += strafe - restwert_akku
#gesamtbilanz += o["Gesamt_Verluste"]/10000.0 #gesamtbilanz += o["Gesamt_Verluste"]/10000.0
return (gesamtbilanz,) return (gesamtbilanz,)

View File

@ -1,11 +1,11 @@
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 datetime import datetime, timedelta
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 from dateutil import parser
import pandas as pd
class ForecastData: class ForecastData:
@ -15,9 +15,8 @@ class ForecastData:
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 self.ac_power_measurement = ac_power_measurement
# Getter für die ForecastData-Attribute
def get_date_time(self): def get_date_time(self):
return self.date_time return self.date_time
@ -28,7 +27,7 @@ class ForecastData:
return self.ac_power_measurement return self.ac_power_measurement
def get_ac_power(self): def get_ac_power(self):
if self.ac_power_measurement != None: if self.ac_power_measurement is not None:
return self.ac_power_measurement return self.ac_power_measurement
else: else:
return self.ac_power return self.ac_power
@ -54,59 +53,49 @@ class PVForecast:
elif url: elif url:
self.load_data_with_caching(url) self.load_data_with_caching(url)
# Überprüfung nach dem Laden der Daten
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): def update_ac_power_measurement(self, date_time=None, ac_power_measurement=None):
"""Aktualisiert einen DC-Leistungsmesswert oder fügt ihn hinzu."""
found = False found = False
target_timezone = tz.gettz('Europe/Berlin') input_date_hour = date_time.replace(minute=0, second=0, microsecond=0)
input_date_hour = date_time.astimezone(target_timezone).replace(minute=0, second=0, microsecond=0)
for forecast in self.forecast_data: 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) forecast_date_hour = parser.parse(forecast.date_time).replace(minute=0, second=0, microsecond=0)
#print(forecast_date_hour," ",input_date_hour)
if forecast_date_hour == input_date_hour: if forecast_date_hour == input_date_hour:
forecast.ac_power_measurement = ac_power_measurement forecast.ac_power_measurement = ac_power_measurement
found = True found = True
break 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):
self.meta = data.get('meta', {}) self.meta = data.get('meta', {})
all_values = data.get('values', []) all_values = data.get('values', [])
# Berechnung der Summe der DC- und AC-Leistungen für jeden Zeitstempel
for i in range(len(all_values[0])): # Annahme, dass alle Listen gleich lang sind for i in range(len(all_values[0])): # Annahme, dass alle Listen gleich lang sind
sum_dc_power = sum(values[i]['dcPower'] for values in all_values) sum_dc_power = sum(values[i]['dcPower'] for values in all_values)
sum_ac_power = sum(values[i]['power'] for values in all_values) sum_ac_power = sum(values[i]['power'] for values in all_values)
# Erstellen eines ForecastData-Objekts mit den summierten Werten # Zeige die ursprünglichen und berechneten Zeitstempel an
original_datetime = all_values[0][i].get('datetime')
#print(original_datetime," ",sum_dc_power," ",all_values[0][i]['dcPower'])
dt = datetime.strptime(original_datetime, "%Y-%m-%dT%H:%M:%S.%f%z")
dt = dt.replace(tzinfo=None)
#iso_datetime = parser.parse(original_datetime).isoformat() # Konvertiere zu ISO-Format
#print()
# Optional: 2 Stunden abziehen, um die Zeitanpassung zu testen
#adjusted_datetime = parser.parse(original_datetime) - timedelta(hours=2)
#print(f"Angepasste Zeitstempel: {adjusted_datetime.isoformat()}")
forecast = ForecastData( forecast = ForecastData(
date_time=all_values[0][i].get('datetime'), date_time=dt, # Verwende angepassten Zeitstempel
dc_power=sum_dc_power, dc_power=sum_dc_power,
ac_power=sum_ac_power, ac_power=sum_ac_power,
# Optional: Weitere Werte wie Windspeed und Temperature, falls benötigt
windspeed_10m=all_values[0][i].get('windspeed_10m'), windspeed_10m=all_values[0][i].get('windspeed_10m'),
temperature=all_values[0][i].get('temperature') temperature=all_values[0][i].get('temperature')
) )
self.forecast_data.append(forecast)
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:
@ -144,27 +133,15 @@ class PVForecast:
self.process_data(data) self.process_data(data)
def generate_cache_filename(self, url, date): def generate_cache_filename(self, url, date):
# Erzeugt einen SHA-256 Hash der URL als Dateinamen
cache_key = hashlib.sha256(f"{url}{date}".encode('utf-8')).hexdigest() cache_key = hashlib.sha256(f"{url}{date}".encode('utf-8')).hexdigest()
#cache_path = os.path.join(self.cache_dir, cache_key)
return f"cache_{cache_key}.json" return f"cache_{cache_key}.json"
def get_forecast_data(self): def get_forecast_data(self):
return self.forecast_data return self.forecast_data
# def get_forecast_for_date(self, input_date_str):
# 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 = []
# for d in daily_forecast_obj:
# daily_forecast.append(d.get_ac_power())
# 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")
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 parser.parse(data.get_date_time()).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_temperature()) daily_forecast.append(d.get_temperature())
@ -177,10 +154,10 @@ class PVForecast:
date_range_forecast = [] date_range_forecast = []
for data in self.forecast_data: for data in self.forecast_data:
data_date = datetime.strptime(data.get_date_time(), "%Y-%m-%dT%H:%M:%S.%f%z").date() data_date = data.get_date_time().date()#parser.parse(data.get_date_time()).date()
#print(data.get_date_time())
if start_date <= data_date <= end_date: if start_date <= data_date <= end_date:
date_range_forecast.append(data) date_range_forecast.append(data)
print(data.get_date_time()," ",data.get_ac_power())
ac_power_forecast = np.array([data.get_ac_power() for data in date_range_forecast]) ac_power_forecast = np.array([data.get_ac_power() for data in date_range_forecast])
@ -192,28 +169,36 @@ class PVForecast:
date_range_forecast = [] date_range_forecast = []
for data in self.forecast_data: for data in self.forecast_data:
data_date = datetime.strptime(data.get_date_time(), "%Y-%m-%dT%H:%M:%S.%f%z").date() data_date = data.get_date_time().date()
if start_date <= data_date <= end_date: if start_date <= data_date <= end_date:
date_range_forecast.append(data) date_range_forecast.append(data)
forecast_data = date_range_forecast temperature_forecast = [data.get_temperature() for data in date_range_forecast]
temperature_forecast = [data.get_temperature() for data in forecast_data]
return np.array(temperature_forecast)[:self.prediction_hours] return np.array(temperature_forecast)[:self.prediction_hours]
def get_forecast_dataframe(self):
# Wandelt die Vorhersagedaten in ein Pandas DataFrame um
data = [{
'date_time': f.get_date_time(),
'dc_power': f.get_dc_power(),
'ac_power': f.get_ac_power(),
'windspeed_10m': f.get_windspeed_10m(),
'temperature': f.get_temperature()
} for f in self.forecast_data]
# Erstelle ein DataFrame
df = pd.DataFrame(data)
return df
def print_ac_power_and_measurement(self): def print_ac_power_and_measurement(self):
"""Druckt die DC-Leistung und das Messwert für jede Stunde.""" """Druckt die DC-Leistung und den Messwert für jede Stunde."""
for forecast in self.forecast_data: for forecast in self.forecast_data:
date_time = forecast.date_time 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()}")
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__':
date_now = datetime.now()
forecast = PVForecast(prediction_hours=24, url="https://api.akkudoktor.net/forecast?lat=50.8588&lon=7.3747&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") forecast = PVForecast(prediction_hours=24, url="https://api.akkudoktor.net/forecast?lat=50.8588&lon=7.3747&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")
forecast.update_ac_power_measurement(date_time=datetime.now(), ac_power_measurement=1000) forecast.update_ac_power_measurement(date_time=datetime.now(), ac_power_measurement=1000)
forecast.print_ac_power_and_measurement() forecast.print_ac_power_and_measurement()

264
test.py
View File

@ -21,7 +21,9 @@ import random
import os import os
start_hour = 8
start_hour = 11
pv_forecast= [ pv_forecast= [
0, 0,
@ -31,46 +33,46 @@ pv_forecast= [
0, 0,
0, 0,
0, 0,
46.0757222688471, 35.4104640357043,
474.780954810247, 436.191574979506,
1049.36036517475, 734.585613834398,
1676.86962934168, 914.346108603927,
2037.0885036865, 1019.5228214119,
2600.03233682621, 1766.84136350058,
5307.79424852068, 5980.60975052259,
5214.54927119013, 6236.00681862336,
5392.8995394438, 5893.38154543782,
4229.09283442043, 4309.88538120413,
3568.84965239262, 3338.29004915145,
2627.95972505784, 2177.55660706753,
1618.04209206715, 1091.00542545193,
718.733713468062, 437.819525591319,
102.060092599437, 44.2226537829726,
0, 0,
0, 0,
0, 0,
0, 0,
-0.0269415125679914,
0, 0,
-0.068771006309608,
0, 0,
0.0275649587447597,
0, 0,
53.980235336087, 0,
543.602674801833, 25.5745140893473,
852.52597210804, 494.188146846569,
964.253104261402, 943.821134036728,
1043.15079499546, 1458.66413119635,
1333.69973977172, 1819.46147983229,
6901.19158127423, 2127.45430524539,
6590.62442617817, 2267.78128099068,
6161.97317306069, 5944.86706099518,
4530.33886807194, 5337.1322153025,
3535.37982191984, 4376.56125932204,
2388.65608163334, 3020.00212091936,
1365.10812389941, 2414.53994231359,
557.452392556485, 1373.626161377,
82.376303341511, 517.764497317134,
0.026903650788687, 35.619750070296,
0,
0 0
] ]
temperature_forecast= [ temperature_forecast= [
@ -125,104 +127,104 @@ temperature_forecast= [
] ]
strompreis_euro_pro_wh = [ strompreis_euro_pro_wh = [
0.00031540228, 0.00033840228,
0.00031000228, 0.00033180228,
0.00029390228, 0.00032840228,
0.00028410228, 0.00032830228,
0.00028840228, 0.00032890228,
0.00028800228, 0.00033340228,
0.00030930228, 0.00032900228,
0.00031390228, 0.00033020228,
0.00031540228, 0.00030420228,
0.00028120228, 0.00024300228,
0.00022820228, 0.00022800228,
0.00022310228, 0.00022120228,
0.00021500228, 0.00020930228,
0.00020770228, 0.00018790228,
0.00020670228, 0.00018380228,
0.00021200228, 0.00020040228,
0.00021540228, 0.00021980228,
0.00023000228, 0.00022700228,
0.00029530228, 0.00029970228,
0.00032990228, 0.00031950228,
0.00036840228, 0.00030810228,
0.00035900228, 0.00029690228,
0.00033140228, 0.00029210228,
0.00031370228, 0.00027800228,
0.00031540228, 0.00033840228,
0.00031000228, 0.00033180228,
0.00029390228, 0.00032840228,
0.00028410228, 0.00032830228,
0.00028840228, 0.00032890228,
0.00028800228, 0.00033340228,
0.00030930228, 0.00032900228,
0.00031390228, 0.00033020228,
0.00031540228, 0.00030420228,
0.00028120228, 0.00024300228,
0.00022820228, 0.00022800228,
0.00022310228, 0.00022120228,
0.00021500228, 0.00020930228,
0.00020770228, 0.00018790228,
0.00020670228, 0.00018380228,
0.00021200228, 0.00020040228,
0.00021540228, 0.00021980228,
0.00023000228, 0.00022700228,
0.00029530228, 0.00029970228,
0.00032990228, 0.00031950228,
0.00036840228, 0.00030810228,
0.00035900228, 0.00029690228,
0.00033140228, 0.00029210228,
0.00031370228 0.00027800228
] ]
gesamtlast= [ gesamtlast= [
723.794862683391, 546.16318964697,
743.491222629184, 893.072526185525,
836.32034938972, 448.7325491406,
870.858204290382, 460.696954446666,
877.988917620097, 497.688171532182,
857.94124236693, 468.186120420737,
535.7468553632, 424.440426628658,
658.119336334815, 454.341890696582,
955.15298014833, 1070.45287392313,
2636.705125629, 1096.46234344204,
1321.53672393798, 1199.71317588613,
1488.77669263834, 1294.39989535284,
1129.61536474922, 1459.42631059004,
1261.47022563591, 1295.23757474948,
1308.42804416213, 1304.65748778424,
1740.76791896787, 1187.47511606455,
989.769241971553, 1309.49984671163,
1291.60060799951, 1106.60773651081,
1360.9198505883, 1098.98136451936,
1290.04968399465, 2112.82264661039,
989.968377880823, 1143.37118921705,
1121.41872787695, 858.863135790621,
1250.64584231737, 787.018517493612,
852.708926147066, 693.683533270357,
723.492531379247, 545.860858342826,
743.121389279149, 892.702692835489,
835.959858325763, 448.372058076642,
870.44547874543, 460.284228901714,
878.758616187391, 498.457870099476,
858.773385266073, 469.01826331988,
535.600426631561, 424.293997897019,
658.438388271842, 454.660942633609,
955.420012089818, 1070.71990586461,
2636.68835629389, 1096.44557410693,
1321.54382666298, 1199.72027861112,
1489.13090434992, 1294.75410706442,
1129.80079639256, 1459.61174223338,
1262.0092664333, 1295.77661554687,
1308.72647023183, 1304.95591385395,
1741.92058921559, 1188.62778631227,
990.700392687782, 1310.43099742786,
1293.57876397944, 1108.58589249073,
1363.67698321638, 1101.73849714744,
1291.28280716443, 2114.05576978017,
990.277508651153, 1143.68031998738,
1121.16294287294, 858.607350786608,
1250.20143586737, 786.574111043611,
852.488808763652 693.463415886943
] ]
start_solution= [ start_solution= [
@ -323,7 +325,7 @@ start_solution= [
1, 1,
1 1
] ]
parameter= {'pv_soc': 92.4052, 'pv_akku_cap': 30000, 'year_energy': 4100000, 'einspeiseverguetung_euro_pro_wh': 7e-05, 'max_heizleistung': 1000,"gesamtlast":gesamtlast, 'pv_forecast': pv_forecast, "temperature_forecast":temperature_forecast, "strompreis_euro_pro_wh":strompreis_euro_pro_wh, 'eauto_min_soc': 100, 'eauto_cap': 60000, 'eauto_charge_efficiency': 0.95, 'eauto_charge_power': 6900, 'eauto_soc': 30, 'pvpowernow': 211.137503624, 'start_solution': start_solution, 'haushaltsgeraet_wh': 937, 'haushaltsgeraet_dauer': 0} parameter= {"preis_euro_pro_wh_akku": 30e-05,'pv_soc': 60.4052, 'pv_akku_cap': 30000, 'year_energy': 4100000, 'einspeiseverguetung_euro_pro_wh': 7e-05, 'max_heizleistung': 1000,"gesamtlast":gesamtlast, 'pv_forecast': pv_forecast, "temperature_forecast":temperature_forecast, "strompreis_euro_pro_wh":strompreis_euro_pro_wh, 'eauto_min_soc': 80, 'eauto_cap': 60000, 'eauto_charge_efficiency': 0.95, 'eauto_charge_power': 7590, 'eauto_soc': 53, 'pvpowernow': 211.137503624, 'start_solution': start_solution, 'haushaltsgeraet_wh': 937, 'haushaltsgeraet_dauer': 0}