Migrate from Flask to FastAPI (#163)

* Migrate from Flask to FastAPI

 * FastAPI migration:
    - Use pydantic model classes as input parameters to the
      data/calculation classes.
    - Interface field names changed to constructor parameter names (for
      simplicity only during transition, should be updated in a followup
      PR).
    - Add basic interface requirements (e.g. some values > 0, etc.).
 * Update tests for new data format.
 * Python requirement down to 3.9 (TypeGuard no longer needed)
 * Makefile: Add helpful targets (e.g. development server with reload)

* Move API doc from README to pydantic model classes (swagger)

 * Link to swagger.io with own openapi.yml.
 * Commit openapi.json and check with pytest for changes so the
   documentation is always up-to-date.

* Streamline docker

* FastAPI: Run startup action on dev server

 * Fix config for /strompreis, endpoint still broken however.

* test_openapi: Compare against docs/.../openapi.json

* Move fastapi to server/ submodule

 * See #187 for new repository structure.
This commit is contained in:
Dominique Lasserre
2024-11-15 22:27:25 +01:00
committed by GitHub
parent ed3226e522
commit f61665669f
38 changed files with 997 additions and 1331 deletions

View File

@@ -5,7 +5,11 @@ import time
import numpy as np
from akkudoktoreos.class_numpy_encoder import NumpyEncoder
from akkudoktoreos.class_optimize import optimization_problem
from akkudoktoreos.class_optimize import (
OptimizationParameters,
OptimizeResponse,
optimization_problem,
)
from akkudoktoreos.config import get_working_dir, load_config
from akkudoktoreos.visualize import visualisiere_ergebnisse
@@ -229,48 +233,52 @@ gesamtlast = [
start_solution = None
# Define parameters for the optimization problem
parameter = {
# Value of energy in battery (per Wh)
"preis_euro_pro_wh_akku": 0e-05,
# Initial state of charge (SOC) of PV battery (%)
"pv_soc": 15,
# Battery capacity (in Wh)
"pv_akku_cap": 26400,
# Yearly energy consumption (in Wh)
"year_energy": 4100000,
# Feed-in tariff for exporting electricity (per Wh)
"einspeiseverguetung_euro_pro_wh": 7e-05,
# Maximum heating power (in W)
"max_heizleistung": 1000,
# Overall load on the system
"gesamtlast": gesamtlast,
# PV generation forecast (48 hours)
"pv_forecast": pv_forecast,
# Temperature forecast (48 hours)
"temperature_forecast": temperature_forecast,
# Electricity price forecast (48 hours)
"strompreis_euro_pro_wh": strompreis_euro_pro_wh,
# Minimum SOC for electric car
"eauto_min_soc": 50,
# Electric car battery capacity (Wh)
"eauto_cap": 60000,
# Charging efficiency of the electric car
"eauto_charge_efficiency": 0.95,
# Charging power of the electric car (W)
"eauto_charge_power": 11040,
# Current SOC of the electric car (%)
"eauto_soc": 15,
# Current PV power generation (W)
"pvpowernow": 211.137503624,
# Initial solution for the optimization
"start_solution": start_solution,
# Household appliance consumption (Wh)
"haushaltsgeraet_wh": 5000,
# Duration of appliance usage (hours)
"haushaltsgeraet_dauer": 0,
# Minimum Soc PV Battery
"min_soc_prozent": 15,
}
parameters = OptimizationParameters(
**{
"ems": {
# Value of energy in battery (per Wh)
"preis_euro_pro_wh_akku": 0e-05,
# Feed-in tariff for exporting electricity (per Wh)
"einspeiseverguetung_euro_pro_wh": 7e-05,
# Overall load on the system
"gesamtlast": gesamtlast,
# PV generation forecast (48 hours)
"pv_prognose_wh": pv_forecast,
# Electricity price forecast (48 hours)
"strompreis_euro_pro_wh": strompreis_euro_pro_wh,
},
"pv_akku": {
# Battery capacity (in Wh)
"kapazitaet_wh": 26400,
# Initial state of charge (SOC) of PV battery (%)
"start_soc_prozent": 15,
# Minimum Soc PV Battery
"min_soc_prozent": 15,
},
"eauto": {
# Minimum SOC for electric car
"min_soc_prozent": 50,
# Electric car battery capacity (Wh)
"kapazitaet_wh": 60000,
# Charging efficiency of the electric car
"lade_effizienz": 0.95,
# Charging power of the electric car (W)
"max_ladeleistung_w": 11040,
# Current SOC of the electric car (%)
"start_soc_prozent": 5,
},
# "spuelmaschine": {
# # Household appliance consumption (Wh)
# "verbrauch_wh": 5000,
# # Duration of appliance usage (hours)
# "dauer_h": 0,
# },
# Temperature forecast (48 hours)
"temperature_forecast": temperature_forecast,
# Initial solution for the optimization
"start_solution": start_solution,
}
)
# Startzeit nehmen
start_time = time.time()
@@ -281,7 +289,7 @@ config = load_config(working_dir)
opt_class = optimization_problem(config, verbose=True, fixed_seed=42)
# Perform the optimisation based on the provided parameters and start hour
ergebnis = opt_class.optimierung_ems(parameter=parameter, start_hour=start_hour)
ergebnis = opt_class.optimierung_ems(parameters=parameters, start_hour=start_hour)
# Endzeit nehmen
end_time = time.time()
@@ -298,23 +306,23 @@ ac_charge, dc_charge, discharge = (
)
visualisiere_ergebnisse(
gesamtlast=gesamtlast,
pv_forecast=pv_forecast,
strompreise=strompreis_euro_pro_wh,
ergebnisse=ergebnis["result"],
ac=ac_charge,
dc=dc_charge,
discharge=discharge,
temperature=temperature_forecast,
start_hour=start_hour,
parameters.ems.gesamtlast,
parameters.ems.pv_prognose_wh,
parameters.ems.strompreis_euro_pro_wh,
ergebnis["result"],
ac_charge,
dc_charge,
discharge,
parameters.temperature_forecast,
start_hour,
einspeiseverguetung_euro_pro_wh=np.full(
config.eos.feed_in_tariff_eur_per_wh, parameter["einspeiseverguetung_euro_pro_wh"]
config.eos.feed_in_tariff_eur_per_wh, parameters.ems.einspeiseverguetung_euro_pro_wh
),
config=config,
filename="visualization_results.pdf",
extra_data=None,
)
json_data = NumpyEncoder.dumps(ergebnis)
print(json_data)
OptimizeResponse(**ergebnis)