diff --git a/battery_model.pkl b/battery_model.pkl new file mode 100644 index 0000000..3ac50f2 Binary files /dev/null and b/battery_model.pkl differ diff --git a/flask_server.py b/flask_server.py index 57e51ac..ff2c3d6 100644 --- a/flask_server.py +++ b/flask_server.py @@ -9,6 +9,7 @@ from modules.class_heatpump import * from modules.class_load_container import * from modules.class_sommerzeit import * from modules.visualize import * +from modules.class_battery_soc_predictor import * import os from flask import Flask, send_from_directory from pprint import pprint @@ -27,6 +28,33 @@ app = Flask(__name__) opt_class = optimization_problem(prediction_hours=24, strafe=10) +soc_predictor = BatterySocPredictor.load_model('battery_model.pkl') + + +@app.route('/soc', methods=['GET']) +def flask_soc(): + if request.method == 'GET': + # URL-Parameter lesen + voltage = request.args.get('voltage') + current = request.args.get('current') + + # Erforderliche Parameter prüfen + if voltage is None or current is None: + missing_params = [] + if voltage is None: + missing_params.append('voltage') + if current is None: + missing_params.append('current') + return jsonify({"error": f"Fehlende Parameter: {', '.join(missing_params)}"}), 400 + + # Werte in ein numpy Array umwandeln + x = np.array( [[float(voltage), float(current)]] ) + + # Simulation durchführen + ergebnis = soc_predictor.predict(x) + print(ergebnis) + + return jsonify(ergebnis) @app.route('/optimize', methods=['POST']) @@ -45,21 +73,6 @@ def flask_optimize(): return jsonify(ergebnis) -@app.route('/optimize_worst_case', methods=['POST']) -def flask_optimize_worst_case(): - if request.method == 'POST': - parameter = request.json - - # 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","pvpowernow","haushaltsgeraet_dauer","haushaltsgeraet_wh"] - for p in erforderliche_parameter: - if p not in parameter: - return jsonify({"error": f"Fehlender Parameter: {p}"}), 400 - - # Simulation durchführen - ergebnis = opt_class.optimierung_ems(parameter=parameter, start_hour=datetime.now().hour, worst_case=True) - - return jsonify(ergebnis) @app.route('/visualisierungsergebnisse.pdf') def get_pdf(): diff --git a/modules/class_akku.py b/modules/class_akku.py index 83192f4..aac1bb0 100644 --- a/modules/class_akku.py +++ b/modules/class_akku.py @@ -1,6 +1,6 @@ import numpy as np 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,min_soc_prozent=0,max_soc_prozent=100): + def __init__(self, kapazitaet_wh=None, hours=None, lade_effizienz=0.8, entlade_effizienz=1.0,max_ladeleistung_w=None,start_soc_prozent=0,min_soc_prozent=0,max_soc_prozent=100): # Kapazität des Akkus in Wh self.kapazitaet_wh = kapazitaet_wh # Initialer Ladezustand des Akkus in Wh diff --git a/modules/class_battery_soc_predictor.py b/modules/class_battery_soc_predictor.py new file mode 100644 index 0000000..adde43e --- /dev/null +++ b/modules/class_battery_soc_predictor.py @@ -0,0 +1,175 @@ +import numpy as np +import pandas as pd +import joblib +from sklearn.preprocessing import StandardScaler +from sklearn.gaussian_process import GaussianProcessRegressor +from sklearn.gaussian_process.kernels import RBF, ConstantKernel, WhiteKernel +from sklearn.model_selection import train_test_split + +import numpy as np +import matplotlib.pyplot as plt + +class BatterySocPredictor: + def __init__(self): + # Initialisierung von Scaler und Gaußschem Prozessmodell + self.scaler = StandardScaler() + kernel = WhiteKernel(1.0, (1e-7, 1e3)) + RBF(length_scale=(0.1,0.1), length_scale_bounds=((1e-7, 1e3),(1e-7, 1e3))) + self.gp = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=10, alpha=1e-2, normalize_y=True) + + def fit(self, X, y): + # Transformiere die Zielvariable + y_transformed = np.log(y / (101 - y)) + # Skaliere die Features + X_scaled = self.scaler.fit_transform(X) + # Trainiere das Modell + self.gp.fit(X_scaled, y_transformed) + + def predict(self, X): + # Skaliere die Features + X_scaled = self.scaler.transform(X) + # Vorhersagen und Unsicherheiten + y_pred_transformed, sigma_transformed = self.gp.predict(X_scaled, return_std=True) + # Rücktransformieren der Vorhersagen + y_pred = 101 / (1 + np.exp(-y_pred_transformed)) + # Rücktransformieren der Unsicherheiten + sigmoid_y_pred = 1 / (1 + np.exp(-y_pred_transformed)) + sigma = sigma_transformed * 101 * sigmoid_y_pred * (1 - sigmoid_y_pred) + return float(y_pred), float(sigma) + + def save_model(self, file_path): + # Speichere das gesamte Modell-Objekt + joblib.dump(self, file_path) + + @staticmethod + def load_model(file_path): + # Lade das Modell-Objekt + return joblib.load(file_path) + + + + + +# # Daten laden und Modell verwenden +# data_path = 'train.csv' +# data = pd.read_csv(data_path) +# X = data[['battery_voltage', 'battery_current']] +# y = data['battery_soc'] + +# # Aufteilen der Daten in Trainings- und Testdatensätze +# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=42) + +# # Modell instanziieren und trainieren +# battery_model = BatteryModel() +# battery_model.fit(X_train, y_train) + +# # Modell speichern +# battery_model.save_model('battery_model.pkl') + +# # Modell für Vorhersagen laden +# loaded_model = BatteryModel.load_model('battery_model.pkl') + +# # Vorhersagen machen +# current_values = np.linspace(-100, 100, 5) +# voltage_range = np.linspace(48, 58, 50) +# for current in current_values: + # X_pred = np.column_stack([voltage_range, np.full(voltage_range.shape, current)]) + # y_pred, sigma = loaded_model.predict(X_pred) + # # Plotten der mittleren Vorhersage und des Konfidenzintervalls + # plt.plot(voltage_range, y_pred, label=f'Strom = {current:.1f} A') + # plt.fill_between(voltage_range, y_pred - 1.96 * sigma, y_pred + 1.96 * sigma, alpha=0.2) + +# # Hinzufügen von Titel und Legende zum Plot +# plt.title('Vorhergesagter SoC als Funktion der Batteriespannung bei verschiedenen Strömen') +# plt.xlabel('Batteriespannung (V)') +# plt.ylabel('State of Charge (SoC %)') +# plt.legend() +# plt.show() + + + +# sys.exit() + + + + + +# # Daten laden +# data_path = 'train.csv' +# data = pd.read_csv(data_path) + +# # Spalten auswählen +# X = data[['battery_voltage', 'battery_current']] # Merkmale +# y = data['battery_soc'] # Zielvariable + +# # Aufteilung der Daten in Trainings- und Testset + +# # Transformiere die Zielvariable +# y_transformed = np.log(y / (101 - y)) + + +# # X Normalisierung +# scaler = StandardScaler() +# X_scaled = scaler.fit_transform(X) + + +# # Aufteilen der Daten in Trainings- und Testdatensätze +# X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_transformed, test_size=0.5, random_state=42) + +# # Kernel und Modell definieren +# kernel = WhiteKernel(1.0, (1e-7, 1e3)) + RBF(length_scale=(0.1,0.1), length_scale_bounds=((1e-7, 1e3),(1e-7, 1e3))) #* ConstantKernel(constant_value=1.0, constant_value_bounds=(1e-05, 100000.0)) + +# gp = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=10, alpha=1e-2, normalize_y=True) + +# # Modell trainieren +# gp.fit(X_train, y_train) + +# # Vorhersagen und Rücktransformieren +# #y_pred_transformed, sigma = gp.predict(X_test, return_std=True) +# #y_pred = 100 / (1 + np.exp(-y_pred_transformed)) + + +# # Ergebnisse anzeigen +# #print("Vorhersagen:", y_pred) +# #print("Unsicherheit der Vorhersagen:", sigma) + + +# # Angenommen, 'gp' ist dein trainiertes Gaußsches Prozessmodell +# joblib.dump(gp, 'gaussian_process_model.pkl') + + + +# # Festlegen der Ströme und Spannungsrange für die Vorhersagen +# current_values = np.linspace(-100, 100, 5) +# voltage_range = np.linspace(48, 58, 50) + +# # Erstellen einer Figur für die Plots +# plt.figure(figsize=(12, 8)) + +# # Für jeden Stromwert einen Plot erstellen +# for current in current_values: + # # Erstellen von Vorhersagedatenpunkten + # X_pred = np.column_stack([voltage_range, np.full(voltage_range.shape, current)]) + # X_pred_scaled = scaler.transform(X_pred) # Standardisierung + + # # Vorhersage des SoC und der Unsicherheit + # y_pred_transformed, sigma_transformed = gp.predict(X_pred_scaled, return_std=True) + # y_pred = 101 / (1 + np.exp(-y_pred_transformed)) # Rücktransformation + + # sigmoid_y_pred = 1 / (1 + np.exp(-y_pred_transformed)) + # sigma = sigma_transformed * 101 * sigmoid_y_pred * (1 - sigmoid_y_pred) + + + # # Plotten der mittleren Vorhersage und des Konfidenzintervalls + # plt.plot(voltage_range, y_pred, label=f'Strom = {current:.1f} A') + # plt.fill_between(voltage_range, y_pred - 1.96 * sigma, y_pred + 1.96 * sigma, alpha=0.2) + +# # Hinzufügen von Titel und Legende zum Plot +# plt.title('Vorhergesagter SoC als Funktion der Batteriespannung bei verschiedenen Strömen') +# plt.xlabel('Batteriespannung (V)') +# plt.ylabel('State of Charge (SoC %)') +# plt.legend() +# plt.show() + + + +