mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2025-04-19 08:55:15 +00:00
Fix2 electricity price prediction. (#296)
Normalize electricity price prediction to €/Wh. Provide electricity price prediction by €/kWh for convenience. Allow to configure electricity price charges by €/kWh. Also added error page to fastapi rest server to get rid of annoying unrelated fault messages during testing. Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
This commit is contained in:
parent
45079ca29c
commit
c0ea13d0f4
@ -16,6 +16,7 @@ services:
|
|||||||
- latitude=52.2
|
- latitude=52.2
|
||||||
- longitude=13.4
|
- longitude=13.4
|
||||||
- elecprice_provider=ElecPriceAkkudoktor
|
- elecprice_provider=ElecPriceAkkudoktor
|
||||||
- elecprice_charges=0.21
|
- elecprice_charges_kwh=0.21
|
||||||
|
- server_fasthtml_host=none
|
||||||
ports:
|
ports:
|
||||||
- "${EOS_PORT}:${EOS_PORT}"
|
- "${EOS_PORT}:${EOS_PORT}"
|
||||||
|
@ -669,7 +669,7 @@
|
|||||||
"/strompreis": {
|
"/strompreis": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Fastapi Strompreis",
|
"summary": "Fastapi Strompreis",
|
||||||
"description": "Deprecated: Electricity Market Price Prediction.\n\nNote:\n Use '/v1/prediction/list?key=elecprice_marketprice' instead.",
|
"description": "Deprecated: Electricity Market Price Prediction per Wh (\u20ac/Wh).\n\nNote:\n Use '/v1/prediction/list?key=elecprice_marketprice_wh' or\n '/v1/prediction/list?key=elecprice_marketprice_kwh' instead.",
|
||||||
"operationId": "fastapi_strompreis_strompreis_get",
|
"operationId": "fastapi_strompreis_strompreis_get",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
@ -2498,7 +2498,7 @@
|
|||||||
"title": "Elecprice Provider",
|
"title": "Elecprice Provider",
|
||||||
"description": "Electricity price provider id of provider to be used."
|
"description": "Electricity price provider id of provider to be used."
|
||||||
},
|
},
|
||||||
"elecprice_charges": {
|
"elecprice_charges_kwh": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@ -2508,7 +2508,7 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "Elecprice Charges",
|
"title": "Elecprice Charges Kwh",
|
||||||
"description": "Electricity price charges (\u20ac/kWh)."
|
"description": "Electricity price charges (\u20ac/kWh)."
|
||||||
},
|
},
|
||||||
"prediction_hours": {
|
"prediction_hours": {
|
||||||
@ -5169,7 +5169,7 @@
|
|||||||
"title": "Elecprice Provider",
|
"title": "Elecprice Provider",
|
||||||
"description": "Electricity price provider id of provider to be used."
|
"description": "Electricity price provider id of provider to be used."
|
||||||
},
|
},
|
||||||
"elecprice_charges": {
|
"elecprice_charges_kwh": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@ -5179,7 +5179,7 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "Elecprice Charges",
|
"title": "Elecprice Charges Kwh",
|
||||||
"description": "Electricity price charges (\u20ac/kWh)."
|
"description": "Electricity price charges (\u20ac/kWh)."
|
||||||
},
|
},
|
||||||
"prediction_hours": {
|
"prediction_hours": {
|
||||||
|
@ -2,7 +2,7 @@ numpy==2.2.0
|
|||||||
numpydantic==1.6.4
|
numpydantic==1.6.4
|
||||||
matplotlib==3.10.0
|
matplotlib==3.10.0
|
||||||
fastapi[standard]==0.115.6
|
fastapi[standard]==0.115.6
|
||||||
python-fasthtml==0.9.1
|
python-fasthtml==0.10.3
|
||||||
uvicorn==0.34.0
|
uvicorn==0.34.0
|
||||||
scikit-learn==1.6.0
|
scikit-learn==1.6.0
|
||||||
timezonefinder==6.5.7
|
timezonefinder==6.5.7
|
||||||
|
@ -94,12 +94,11 @@ def prepare_optimization_real_parameters() -> OptimizationParameters:
|
|||||||
print(f"temperature_forecast: {temperature_forecast}")
|
print(f"temperature_forecast: {temperature_forecast}")
|
||||||
|
|
||||||
# Electricity Price (in Euro per Wh)
|
# Electricity Price (in Euro per Wh)
|
||||||
electricity_market_price_euros_per_kwh = prediction_eos.key_to_array(
|
strompreis_euro_pro_wh = prediction_eos.key_to_array(
|
||||||
key="elecprice_marketprice",
|
key="elecprice_marketprice_wh",
|
||||||
start_datetime=prediction_eos.start_datetime,
|
start_datetime=prediction_eos.start_datetime,
|
||||||
end_datetime=prediction_eos.end_datetime,
|
end_datetime=prediction_eos.end_datetime,
|
||||||
)
|
)
|
||||||
strompreis_euro_pro_wh = electricity_market_price_euros_per_kwh * 0.001
|
|
||||||
print(f"strompreis_euro_pro_wh: {strompreis_euro_pro_wh}")
|
print(f"strompreis_euro_pro_wh: {strompreis_euro_pro_wh}")
|
||||||
|
|
||||||
# Overall System Load (in W)
|
# Overall System Load (in W)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"data_folder_path": null,
|
"data_folder_path": null,
|
||||||
"data_output_path": null,
|
"data_output_path": null,
|
||||||
"data_output_subpath": null,
|
"data_output_subpath": null,
|
||||||
"elecprice_charges": 0.21,
|
"elecprice_charges_kwh": 0.21,
|
||||||
"elecprice_provider": null,
|
"elecprice_provider": null,
|
||||||
"elecpriceimport_file_path": null,
|
"elecpriceimport_file_path": null,
|
||||||
"latitude": 52.5,
|
"latitude": 52.5,
|
||||||
@ -102,6 +102,7 @@
|
|||||||
"pvforecast4_userhorizon": null,
|
"pvforecast4_userhorizon": null,
|
||||||
"pvforecast_provider": null,
|
"pvforecast_provider": null,
|
||||||
"pvforecastimport_file_path": null,
|
"pvforecastimport_file_path": null,
|
||||||
|
"server_fastapi_startup_server_fasthtml": true,
|
||||||
"server_fastapi_host": "0.0.0.0",
|
"server_fastapi_host": "0.0.0.0",
|
||||||
"server_fastapi_port": 8503,
|
"server_fastapi_port": 8503,
|
||||||
"server_fasthtml_host": "0.0.0.0",
|
"server_fasthtml_host": "0.0.0.0",
|
||||||
|
@ -211,8 +211,8 @@ class Devices(SingletonMixin, DevicesBase):
|
|||||||
interval=simulation_step,
|
interval=simulation_step,
|
||||||
)
|
)
|
||||||
# strompreis_euro_pro_wh[stunde]
|
# strompreis_euro_pro_wh[stunde]
|
||||||
elecprice_marketprice = self.prediction.key_to_array(
|
elecprice_marketprice_wh = self.prediction.key_to_array(
|
||||||
"elecprice_marketprice",
|
"elecprice_marketprice_wh",
|
||||||
start_datetime=self.start_datetime,
|
start_datetime=self.start_datetime,
|
||||||
end_datetime=self.end_datetime,
|
end_datetime=self.end_datetime,
|
||||||
interval=simulation_step,
|
interval=simulation_step,
|
||||||
|
@ -9,6 +9,6 @@ class ElecPriceCommonSettings(SettingsBaseModel):
|
|||||||
elecprice_provider: Optional[str] = Field(
|
elecprice_provider: Optional[str] = Field(
|
||||||
default=None, description="Electricity price provider id of provider to be used."
|
default=None, description="Electricity price provider id of provider to be used."
|
||||||
)
|
)
|
||||||
elecprice_charges: Optional[float] = Field(
|
elecprice_charges_kwh: Optional[float] = Field(
|
||||||
default=None, ge=0, description="Electricity price charges (€/kWh)."
|
default=None, ge=0, description="Electricity price charges (€/kWh)."
|
||||||
)
|
)
|
||||||
|
@ -7,7 +7,7 @@ Notes:
|
|||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field, computed_field
|
||||||
|
|
||||||
from akkudoktoreos.prediction.predictionabc import PredictionProvider, PredictionRecord
|
from akkudoktoreos.prediction.predictionabc import PredictionProvider, PredictionRecord
|
||||||
from akkudoktoreos.utils.logutil import get_logger
|
from akkudoktoreos.utils.logutil import get_logger
|
||||||
@ -23,10 +23,22 @@ class ElecPriceDataRecord(PredictionRecord):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
elecprice_marketprice: Optional[float] = Field(
|
elecprice_marketprice_wh: Optional[float] = Field(
|
||||||
None, description="Electricity market price (€/KWh)"
|
None, description="Electricity market price per Wh (€/Wh)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Computed fields
|
||||||
|
@computed_field # type: ignore[prop-decorator]
|
||||||
|
@property
|
||||||
|
def elecprice_marketprice_kwh(self) -> Optional[float]:
|
||||||
|
"""Electricity market price per kWh (€/kWh).
|
||||||
|
|
||||||
|
Convenience attribute calculated from `elecprice_marketprice_wh`.
|
||||||
|
"""
|
||||||
|
if self.elecprice_marketprice_wh is None:
|
||||||
|
return None
|
||||||
|
return self.elecprice_marketprice_wh * 1000.0
|
||||||
|
|
||||||
|
|
||||||
class ElecPriceProvider(PredictionProvider):
|
class ElecPriceProvider(PredictionProvider):
|
||||||
"""Abstract base class for electricity price providers.
|
"""Abstract base class for electricity price providers.
|
||||||
|
@ -134,7 +134,7 @@ class ElecPriceAkkudoktor(ElecPriceProvider):
|
|||||||
prices_of_hour = self.elecprice_8days[hour]
|
prices_of_hour = self.elecprice_8days[hour]
|
||||||
if np.isnan(prices_of_hour).all():
|
if np.isnan(prices_of_hour).all():
|
||||||
# No prediction prices available for this hour - use mean value of all prices
|
# No prediction prices available for this hour - use mean value of all prices
|
||||||
price_weighted_mean = np.nanmean(self.elecprice_marketprice_8day)
|
price_weighted_mean = np.nanmean(self.elecprice_marketprice_wh_8day)
|
||||||
else:
|
else:
|
||||||
weights = self.elecprice_8days_weights_day_of_week[day_of_week]
|
weights = self.elecprice_8days_weights_day_of_week[day_of_week]
|
||||||
prices_of_hour_masked: NDArray[Shape["24"]] = np.ma.MaskedArray(
|
prices_of_hour_masked: NDArray[Shape["24"]] = np.ma.MaskedArray(
|
||||||
@ -204,24 +204,28 @@ class ElecPriceAkkudoktor(ElecPriceProvider):
|
|||||||
elecprice_cache_file.seek(0)
|
elecprice_cache_file.seek(0)
|
||||||
self.elecprice_8days = np.load(elecprice_cache_file)
|
self.elecprice_8days = np.load(elecprice_cache_file)
|
||||||
|
|
||||||
# Get elecprice_charges
|
# Get elecprice_charges_kwh_kwh
|
||||||
charges = self.config.elecprice_charges if self.config.elecprice_charges else 0.0
|
charges_kwh = (
|
||||||
|
self.config.elecprice_charges_kwh if self.config.elecprice_charges_kwh else 0.0
|
||||||
|
)
|
||||||
|
|
||||||
for i in range(values_len):
|
for i in range(values_len):
|
||||||
original_datetime = akkudoktor_data.values[i].start
|
original_datetime = akkudoktor_data.values[i].start
|
||||||
dt = to_datetime(original_datetime, in_timezone=self.config.timezone)
|
dt = to_datetime(original_datetime, in_timezone=self.config.timezone)
|
||||||
akkudoktor_value = akkudoktor_data.values[i]
|
akkudoktor_value = akkudoktor_data.values[i]
|
||||||
price = akkudoktor_value.marketpriceEurocentPerKWh / 100 + charges
|
price_wh = (
|
||||||
|
akkudoktor_value.marketpriceEurocentPerKWh / (100 * 1000) + charges_kwh / 1000
|
||||||
|
)
|
||||||
|
|
||||||
if compare_datetimes(dt, self.start_datetime).lt:
|
if compare_datetimes(dt, self.start_datetime).lt:
|
||||||
# forecast data is too old
|
# forecast data is too old
|
||||||
self.elecprice_8days[dt.hour, dt.day_of_week] = price
|
self.elecprice_8days[dt.hour, dt.day_of_week] = price_wh
|
||||||
continue
|
continue
|
||||||
self.elecprice_8days[dt.hour, 7] = price
|
self.elecprice_8days[dt.hour, 7] = price_wh
|
||||||
|
|
||||||
record = ElecPriceDataRecord(
|
record = ElecPriceDataRecord(
|
||||||
date_time=dt,
|
date_time=dt,
|
||||||
elecprice_marketprice=price,
|
elecprice_marketprice_wh=price_wh,
|
||||||
)
|
)
|
||||||
self.append(record)
|
self.append(record)
|
||||||
|
|
||||||
@ -242,7 +246,7 @@ class ElecPriceAkkudoktor(ElecPriceProvider):
|
|||||||
|
|
||||||
record = ElecPriceDataRecord(
|
record = ElecPriceDataRecord(
|
||||||
date_time=dt,
|
date_time=dt,
|
||||||
elecprice_marketprice=value,
|
elecprice_marketprice_wh=value,
|
||||||
)
|
)
|
||||||
self.insert(0, record)
|
self.insert(0, record)
|
||||||
# Assure price ends at end_time
|
# Assure price ends at end_time
|
||||||
@ -253,6 +257,6 @@ class ElecPriceAkkudoktor(ElecPriceProvider):
|
|||||||
|
|
||||||
record = ElecPriceDataRecord(
|
record = ElecPriceDataRecord(
|
||||||
date_time=dt,
|
date_time=dt,
|
||||||
elecprice_marketprice=value,
|
elecprice_marketprice_wh=value,
|
||||||
)
|
)
|
||||||
self.append(record)
|
self.append(record)
|
||||||
|
@ -11,7 +11,7 @@ import pandas as pd
|
|||||||
import uvicorn
|
import uvicorn
|
||||||
from fastapi import FastAPI, Query, Request
|
from fastapi import FastAPI, Query, Request
|
||||||
from fastapi.exceptions import HTTPException
|
from fastapi.exceptions import HTTPException
|
||||||
from fastapi.responses import FileResponse, RedirectResponse, Response
|
from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse, Response
|
||||||
|
|
||||||
from akkudoktoreos.config.config import ConfigEOS, SettingsEOS, get_config
|
from akkudoktoreos.config.config import ConfigEOS, SettingsEOS, get_config
|
||||||
from akkudoktoreos.core.ems import get_ems
|
from akkudoktoreos.core.ems import get_ems
|
||||||
@ -37,6 +37,98 @@ measurement_eos = get_measurement()
|
|||||||
prediction_eos = get_prediction()
|
prediction_eos = get_prediction()
|
||||||
ems_eos = get_ems()
|
ems_eos = get_ems()
|
||||||
|
|
||||||
|
ERROR_PAGE_TEMPLATE = """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Energy Optimization System (EOS) Error</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.error-container {
|
||||||
|
background: white;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
max-width: 500px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.error-code {
|
||||||
|
font-size: 4rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #e53e3e;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.error-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: #2d3748;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
.error-message {
|
||||||
|
color: #4a5568;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
.error-details {
|
||||||
|
background: #f7fafc;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
text-align: left;
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
.back-button {
|
||||||
|
background: #3182ce;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
.back-button:hover {
|
||||||
|
background: #2c5282;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="error-container">
|
||||||
|
<h1 class="error-code">STATUS_CODE</h1>
|
||||||
|
<h2 class="error-title">ERROR_TITLE</h2>
|
||||||
|
<p class="error-message">ERROR_MESSAGE</p>
|
||||||
|
<div class="error-details">ERROR_DETAILS</div>
|
||||||
|
<a href="/docs" class="back-button">Back to Home</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def create_error_page(
|
||||||
|
status_code: str, error_title: str, error_message: str, error_details: str
|
||||||
|
) -> str:
|
||||||
|
"""Create an error page by replacing placeholders in the template."""
|
||||||
|
return (
|
||||||
|
ERROR_PAGE_TEMPLATE.replace("STATUS_CODE", status_code)
|
||||||
|
.replace("ERROR_TITLE", error_title)
|
||||||
|
.replace("ERROR_MESSAGE", error_message)
|
||||||
|
.replace("ERROR_DETAILS", error_details)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def start_fasthtml_server() -> subprocess.Popen:
|
def start_fasthtml_server() -> subprocess.Popen:
|
||||||
"""Start the fasthtml server as a subprocess."""
|
"""Start the fasthtml server as a subprocess."""
|
||||||
@ -301,10 +393,11 @@ def fastapi_prediction_list_get(
|
|||||||
|
|
||||||
@app.get("/strompreis")
|
@app.get("/strompreis")
|
||||||
def fastapi_strompreis() -> list[float]:
|
def fastapi_strompreis() -> list[float]:
|
||||||
"""Deprecated: Electricity Market Price Prediction.
|
"""Deprecated: Electricity Market Price Prediction per Wh (€/Wh).
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
Use '/v1/prediction/list?key=elecprice_marketprice' instead.
|
Use '/v1/prediction/list?key=elecprice_marketprice_wh' or
|
||||||
|
'/v1/prediction/list?key=elecprice_marketprice_kwh' instead.
|
||||||
"""
|
"""
|
||||||
settings = SettingsEOS(
|
settings = SettingsEOS(
|
||||||
elecprice_provider="ElecPriceAkkudoktor",
|
elecprice_provider="ElecPriceAkkudoktor",
|
||||||
@ -318,7 +411,7 @@ def fastapi_strompreis() -> list[float]:
|
|||||||
# Get the current date and the end date based on prediction hours
|
# Get the current date and the end date based on prediction hours
|
||||||
# Fetch prices for the specified date range
|
# Fetch prices for the specified date range
|
||||||
return prediction_eos.key_to_array(
|
return prediction_eos.key_to_array(
|
||||||
key="elecprice_marketprice",
|
key="elecprice_marketprice_wh",
|
||||||
start_datetime=prediction_eos.start_datetime,
|
start_datetime=prediction_eos.start_datetime,
|
||||||
end_datetime=prediction_eos.end_datetime,
|
end_datetime=prediction_eos.end_datetime,
|
||||||
).tolist()
|
).tolist()
|
||||||
@ -513,7 +606,7 @@ async def proxy_put(request: Request, path: str) -> Response:
|
|||||||
return await proxy(request, path)
|
return await proxy(request, path)
|
||||||
|
|
||||||
|
|
||||||
async def proxy(request: Request, path: str) -> Union[Response | RedirectResponse]:
|
async def proxy(request: Request, path: str) -> Union[Response | RedirectResponse | HTMLResponse]:
|
||||||
if config_eos.server_fasthtml_host and config_eos.server_fasthtml_port:
|
if config_eos.server_fasthtml_host and config_eos.server_fasthtml_port:
|
||||||
# Proxy to fasthtml server
|
# Proxy to fasthtml server
|
||||||
url = f"http://{config_eos.server_fasthtml_host}:{config_eos.server_fasthtml_port}/{path}"
|
url = f"http://{config_eos.server_fasthtml_host}:{config_eos.server_fasthtml_port}/{path}"
|
||||||
@ -521,6 +614,7 @@ async def proxy(request: Request, path: str) -> Union[Response | RedirectRespons
|
|||||||
|
|
||||||
data = await request.body()
|
data = await request.body()
|
||||||
|
|
||||||
|
try:
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
response = await client.get(url, headers=headers)
|
response = await client.get(url, headers=headers)
|
||||||
@ -530,6 +624,21 @@ async def proxy(request: Request, path: str) -> Union[Response | RedirectRespons
|
|||||||
response = await client.put(url, headers=headers, content=data)
|
response = await client.put(url, headers=headers, content=data)
|
||||||
elif request.method == "DELETE":
|
elif request.method == "DELETE":
|
||||||
response = await client.delete(url, headers=headers, content=data)
|
response = await client.delete(url, headers=headers, content=data)
|
||||||
|
except Exception as e:
|
||||||
|
error_page = create_error_page(
|
||||||
|
status_code="404",
|
||||||
|
error_title="Page Not Found",
|
||||||
|
error_message=f"""<pre>
|
||||||
|
Application server not reachable: '{url}'
|
||||||
|
Did you start the application server
|
||||||
|
or set 'server_fastapi_startup_server_fasthtml'?
|
||||||
|
If there is no application server intended please
|
||||||
|
set 'server_fasthtml_host' or 'server_fasthtml_port' to None.
|
||||||
|
</pre>
|
||||||
|
""",
|
||||||
|
error_details=f"{e}",
|
||||||
|
)
|
||||||
|
return HTMLResponse(content=error_page, status_code=404)
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
content=response.content,
|
content=response.content,
|
||||||
|
@ -144,7 +144,7 @@ def test_update_data(mock_get, elecprice_provider, sample_akkudoktor_1_json, cac
|
|||||||
|
|
||||||
# Assert we get prediction_hours prioce values by resampling
|
# Assert we get prediction_hours prioce values by resampling
|
||||||
np_price_array = elecprice_provider.key_to_array(
|
np_price_array = elecprice_provider.key_to_array(
|
||||||
key="elecprice_marketprice",
|
key="elecprice_marketprice_wh",
|
||||||
start_datetime=elecprice_provider.start_datetime,
|
start_datetime=elecprice_provider.start_datetime,
|
||||||
end_datetime=elecprice_provider.end_datetime,
|
end_datetime=elecprice_provider.end_datetime,
|
||||||
)
|
)
|
||||||
@ -203,7 +203,7 @@ def test_key_to_array_resampling(elecprice_provider):
|
|||||||
"""Test resampling of forecast data to NumPy array."""
|
"""Test resampling of forecast data to NumPy array."""
|
||||||
elecprice_provider.update_data(force_update=True)
|
elecprice_provider.update_data(force_update=True)
|
||||||
array = elecprice_provider.key_to_array(
|
array = elecprice_provider.key_to_array(
|
||||||
key="elecprice_marketprice",
|
key="elecprice_marketprice_wh",
|
||||||
start_datetime=elecprice_provider.start_datetime,
|
start_datetime=elecprice_provider.start_datetime,
|
||||||
end_datetime=elecprice_provider.end_datetime,
|
end_datetime=elecprice_provider.end_datetime,
|
||||||
)
|
)
|
||||||
|
@ -92,7 +92,7 @@ def test_import(elecprice_provider, sample_import_1_json, start_datetime, from_f
|
|||||||
assert elecprice_provider.start_datetime is not None
|
assert elecprice_provider.start_datetime is not None
|
||||||
assert elecprice_provider.total_hours is not None
|
assert elecprice_provider.total_hours is not None
|
||||||
assert compare_datetimes(elecprice_provider.start_datetime, ems_eos.start_datetime).equal
|
assert compare_datetimes(elecprice_provider.start_datetime, ems_eos.start_datetime).equal
|
||||||
values = sample_import_1_json["elecprice_marketprice"]
|
values = sample_import_1_json["elecprice_marketprice_wh"]
|
||||||
value_datetime_mapping = elecprice_provider.import_datetimes(
|
value_datetime_mapping = elecprice_provider.import_datetimes(
|
||||||
ems_eos.start_datetime, len(values)
|
ems_eos.start_datetime, len(values)
|
||||||
)
|
)
|
||||||
@ -101,7 +101,7 @@ def test_import(elecprice_provider, sample_import_1_json, start_datetime, from_f
|
|||||||
expected_datetime, expected_value_index = mapping
|
expected_datetime, expected_value_index = mapping
|
||||||
expected_value = values[expected_value_index]
|
expected_value = values[expected_value_index]
|
||||||
result_datetime = elecprice_provider.records[i].date_time
|
result_datetime = elecprice_provider.records[i].date_time
|
||||||
result_value = elecprice_provider.records[i]["elecprice_marketprice"]
|
result_value = elecprice_provider.records[i]["elecprice_marketprice_wh"]
|
||||||
|
|
||||||
# print(f"{i}: Expected: {expected_datetime}:{expected_value}")
|
# print(f"{i}: Expected: {expected_datetime}:{expected_value}")
|
||||||
# print(f"{i}: Result: {result_datetime}:{result_value}")
|
# print(f"{i}: Result: {result_datetime}:{result_value}")
|
||||||
|
16
tests/testdata/import_input_1.json
vendored
16
tests/testdata/import_input_1.json
vendored
@ -6,14 +6,14 @@
|
|||||||
488.89, 506.91, 804.89, 1141.98, 1056.97, 992.46, 1155.99, 827.01, 1257.98, 1232.67,
|
488.89, 506.91, 804.89, 1141.98, 1056.97, 992.46, 1155.99, 827.01, 1257.98, 1232.67,
|
||||||
871.26, 860.88, 1158.03, 1222.72, 1221.04, 949.99, 987.01, 733.99, 592.97
|
871.26, 860.88, 1158.03, 1222.72, 1221.04, 949.99, 987.01, 733.99, 592.97
|
||||||
],
|
],
|
||||||
"elecprice_marketprice": [
|
"elecprice_marketprice_wh": [
|
||||||
0.3384, 0.3318, 0.3284, 0.3283, 0.3289, 0.3334, 0.3290,
|
0.0003384, 0.0003318, 0.0003284, 0.0003283, 0.0003289, 0.0003334, 0.0003290,
|
||||||
0.3302, 0.3042, 0.2430, 0.2280, 0.2212, 0.2093, 0.1879,
|
0.0003302, 0.0003042, 0.0002430, 0.0002280, 0.0002212, 0.0002093, 0.0001879,
|
||||||
0.1838, 0.2004, 0.2198, 0.2270, 0.2997, 0.3195, 0.3081,
|
0.0001838, 0.0002004, 0.0002198, 0.0002270, 0.0002997, 0.0003195, 0.0003081,
|
||||||
0.2969, 0.2921, 0.2780, 0.3384, 0.3318, 0.3284, 0.3283,
|
0.0002969, 0.0002921, 0.0002780, 0.0003384, 0.0003318, 0.0003284, 0.0003283,
|
||||||
0.3289, 0.3334, 0.3290, 0.3302, 0.3042, 0.2430, 0.2280,
|
0.0003289, 0.0003334, 0.0003290, 0.0003302, 0.0003042, 0.0002430, 0.0002280,
|
||||||
0.2212, 0.2093, 0.1879, 0.1838, 0.2004, 0.2198, 0.2270,
|
0.0002212, 0.0002093, 0.0001879, 0.0001838, 0.0002004, 0.0002198, 0.0002270,
|
||||||
0.2997, 0.3195, 0.3081, 0.2969, 0.2921, 0.2780
|
0.0002997, 0.0003195, 0.0003081, 0.0002969, 0.0002921, 0.0002780
|
||||||
],
|
],
|
||||||
"pvforecast_ac_power": [
|
"pvforecast_ac_power": [
|
||||||
0, 0, 0, 0, 0, 0, 0, 8.05, 352.91, 728.51, 930.28, 1043.25, 1106.74, 1161.69,
|
0, 0, 0, 0, 0, 0, 0, 8.05, 352.91, 728.51, 930.28, 1043.25, 1106.74, 1161.69,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user