Fix API endpoint

This commit is contained in:
Dominique Lasserre 2025-01-19 00:42:39 +01:00
parent 3257dac92b
commit 95be7b914f
4 changed files with 291 additions and 464 deletions

View File

@ -91,6 +91,8 @@ Fastapi Optimize
- `start_hour` (query, optional): Defaults to current hour of the day. - `start_hour` (query, optional): Defaults to current hour of the day.
- `ngen` (query, optional): No description provided.
**Request Body**: **Request Body**:
- `application/json`: { - `application/json`: {
@ -203,31 +205,11 @@ Returns:
configuration (ConfigEOS): The current configuration after the write. configuration (ConfigEOS): The current configuration after the write.
``` ```
**Parameters**: **Request Body**:
- `general` (query, optional): No description provided. - `application/json`: {
"$ref": "#/components/schemas/SettingsEOS"
- `logging` (query, optional): No description provided. }
- `devices` (query, optional): No description provided.
- `measurement` (query, optional): No description provided.
- `optimization` (query, optional): No description provided.
- `prediction` (query, optional): No description provided.
- `elecprice` (query, optional): No description provided.
- `load` (query, optional): No description provided.
- `pvforecast` (query, optional): No description provided.
- `weather` (query, optional): No description provided.
- `server` (query, optional): No description provided.
- `utils` (query, optional): No description provided.
**Responses**: **Responses**:
@ -237,25 +219,6 @@ Returns:
--- ---
## GET /v1/config/file
**Links**: [local](http://localhost:8503/docs#/default/fastapi_config_file_get_v1_config_file_get), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_config_file_get_v1_config_file_get)
Fastapi Config File Get
```
Get the settings as defined by the EOS configuration file.
Returns:
settings (SettingsEOS): The settings defined by the EOS configuration file.
```
**Responses**:
- **200**: Successful Response
---
## PUT /v1/config/file ## PUT /v1/config/file
**Links**: [local](http://localhost:8503/docs#/default/fastapi_config_file_put_v1_config_file_put), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_config_file_put_v1_config_file_put) **Links**: [local](http://localhost:8503/docs#/default/fastapi_config_file_put_v1_config_file_put), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_config_file_put_v1_config_file_put)
@ -275,14 +238,14 @@ Returns:
--- ---
## POST /v1/config/update ## PUT /v1/config/reset
**Links**: [local](http://localhost:8503/docs#/default/fastapi_config_update_post_v1_config_update_post), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_config_update_post_v1_config_update_post) **Links**: [local](http://localhost:8503/docs#/default/fastapi_config_update_post_v1_config_reset_put), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_config_update_post_v1_config_reset_put)
Fastapi Config Update Post Fastapi Config Update Post
``` ```
Update the configuration from the EOS configuration file. Reset the configuration to the EOS configuration file.
Returns: Returns:
configuration (ConfigEOS): The current configuration after update. configuration (ConfigEOS): The current configuration after update.
@ -294,37 +257,6 @@ Returns:
--- ---
## PUT /v1/config/value
**Links**: [local](http://localhost:8503/docs#/default/fastapi_config_value_put_v1_config_value_put), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_config_value_put_v1_config_value_put)
Fastapi Config Value Put
```
Set the configuration option in the settings.
Args:
key (str): configuration key
value (Any): configuration value
Returns:
configuration (ConfigEOS): The current configuration after the write.
```
**Parameters**:
- `key` (query, required): configuration key
- `value` (query, required): configuration value
**Responses**:
- **200**: Successful Response
- **422**: Validation Error
---
## PUT /v1/measurement/data ## PUT /v1/measurement/data
**Links**: [local](http://localhost:8503/docs#/default/fastapi_measurement_data_put_v1_measurement_data_put), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_measurement_data_put_v1_measurement_data_put) **Links**: [local](http://localhost:8503/docs#/default/fastapi_measurement_data_put_v1_measurement_data_put), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_measurement_data_put_v1_measurement_data_put)
@ -594,6 +526,31 @@ Args:
--- ---
## GET /v1/prediction/providers
**Links**: [local](http://localhost:8503/docs#/default/fastapi_prediction_providers_get_v1_prediction_providers_get), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_prediction_providers_get_v1_prediction_providers_get)
Fastapi Prediction Providers Get
```
Get a list of available prediction providers.
Args:
enabled (bool): Return enabled/disabled providers. If unset, return all providers.
```
**Parameters**:
- `enabled` (query, optional): No description provided.
**Responses**:
- **200**: Successful Response
- **422**: Validation Error
---
## GET /v1/prediction/series ## GET /v1/prediction/series
**Links**: [local](http://localhost:8503/docs#/default/fastapi_prediction_series_get_v1_prediction_series_get), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_prediction_series_get_v1_prediction_series_get) **Links**: [local](http://localhost:8503/docs#/default/fastapi_prediction_series_get_v1_prediction_series_get), [eos](https://petstore3.swagger.io/?url=https://raw.githubusercontent.com/Akkudoktor-EOS/EOS/refs/heads/main/openapi.json#/default/fastapi_prediction_series_get_v1_prediction_series_get)

View File

@ -4949,7 +4949,7 @@
"general": { "general": {
"anyOf": [ "anyOf": [
{ {
"$ref": "#/components/schemas/ConfigCommonSettings-Output" "$ref": "#/components/schemas/ConfigCommonSettings-Input"
}, },
{ {
"type": "null" "type": "null"
@ -4969,7 +4969,7 @@
"logging": { "logging": {
"anyOf": [ "anyOf": [
{ {
"$ref": "#/components/schemas/LoggingCommonSettings-Output" "$ref": "#/components/schemas/LoggingCommonSettings-Input"
}, },
{ {
"type": "null" "type": "null"
@ -4999,7 +4999,7 @@
"prediction": { "prediction": {
"anyOf": [ "anyOf": [
{ {
"$ref": "#/components/schemas/PredictionCommonSettings-Output" "$ref": "#/components/schemas/PredictionCommonSettings-Input"
}, },
{ {
"type": "null" "type": "null"
@ -5009,7 +5009,7 @@
"pvforecast": { "pvforecast": {
"anyOf": [ "anyOf": [
{ {
"$ref": "#/components/schemas/PVForecastCommonSettings-Output" "$ref": "#/components/schemas/PVForecastCommonSettings-Input"
}, },
{ {
"type": "null" "type": "null"
@ -5514,7 +5514,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Gesamtlast" "summary": "Fastapi Gesamtlast",
"tags": [
"prediction"
]
} }
}, },
"/gesamtlast_simple": { "/gesamtlast_simple": {
@ -5558,7 +5561,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Gesamtlast Simple" "summary": "Fastapi Gesamtlast Simple",
"tags": [
"prediction"
]
} }
}, },
"/optimize": { "/optimize": {
@ -5582,6 +5588,22 @@
"description": "Defaults to current hour of the day.", "description": "Defaults to current hour of the day.",
"title": "Start Hour" "title": "Start Hour"
} }
},
{
"in": "query",
"name": "ngen",
"required": false,
"schema": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Ngen"
}
} }
], ],
"requestBody": { "requestBody": {
@ -5616,7 +5638,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Optimize" "summary": "Fastapi Optimize",
"tags": [
"optimize"
]
} }
}, },
"/pvforecast": { "/pvforecast": {
@ -5635,7 +5660,10 @@
"description": "Successful Response" "description": "Successful Response"
} }
}, },
"summary": "Fastapi Pvforecast" "summary": "Fastapi Pvforecast",
"tags": [
"prediction"
]
} }
}, },
"/strompreis": { "/strompreis": {
@ -5658,7 +5686,10 @@
"description": "Successful Response" "description": "Successful Response"
} }
}, },
"summary": "Fastapi Strompreis" "summary": "Fastapi Strompreis",
"tags": [
"prediction"
]
} }
}, },
"/v1/config": { "/v1/config": {
@ -5677,205 +5708,24 @@
"description": "Successful Response" "description": "Successful Response"
} }
}, },
"summary": "Fastapi Config Get" "summary": "Fastapi Config Get",
"tags": [
"config"
]
}, },
"put": { "put": {
"description": "Write the provided settings into the current settings.\n\nThe existing settings are completely overwritten. Note that for any setting\nvalue that is None, the configuration will fall back to values from other sources such as\nenvironment variables, the EOS configuration file, or default values.\n\nArgs:\n settings (SettingsEOS): The settings to write into the current settings.\n\nReturns:\n configuration (ConfigEOS): The current configuration after the write.", "description": "Write the provided settings into the current settings.\n\nThe existing settings are completely overwritten. Note that for any setting\nvalue that is None, the configuration will fall back to values from other sources such as\nenvironment variables, the EOS configuration file, or default values.\n\nArgs:\n settings (SettingsEOS): The settings to write into the current settings.\n\nReturns:\n configuration (ConfigEOS): The current configuration after the write.",
"operationId": "fastapi_config_put_v1_config_put", "operationId": "fastapi_config_put_v1_config_put",
"parameters": [ "requestBody": {
{ "content": {
"in": "query", "application/json": {
"name": "general", "schema": {
"required": false, "$ref": "#/components/schemas/SettingsEOS"
"schema": { }
"anyOf": [
{
"$ref": "#/components/schemas/ConfigCommonSettings-Input"
},
{
"type": "null"
}
],
"title": "General"
} }
}, },
{ "required": true
"in": "query", },
"name": "logging",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/LoggingCommonSettings-Input"
},
{
"type": "null"
}
],
"title": "Logging"
}
},
{
"in": "query",
"name": "devices",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/DevicesCommonSettings"
},
{
"type": "null"
}
],
"title": "Devices"
}
},
{
"in": "query",
"name": "measurement",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/MeasurementCommonSettings"
},
{
"type": "null"
}
],
"title": "Measurement"
}
},
{
"in": "query",
"name": "optimization",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/OptimizationCommonSettings"
},
{
"type": "null"
}
],
"title": "Optimization"
}
},
{
"in": "query",
"name": "prediction",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/PredictionCommonSettings-Input"
},
{
"type": "null"
}
],
"title": "Prediction"
}
},
{
"in": "query",
"name": "elecprice",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/ElecPriceCommonSettings"
},
{
"type": "null"
}
],
"title": "Elecprice"
}
},
{
"in": "query",
"name": "load",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/LoadCommonSettings"
},
{
"type": "null"
}
],
"title": "Load"
}
},
{
"in": "query",
"name": "pvforecast",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/PVForecastCommonSettings-Input"
},
{
"type": "null"
}
],
"title": "Pvforecast"
}
},
{
"in": "query",
"name": "weather",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/WeatherCommonSettings"
},
{
"type": "null"
}
],
"title": "Weather"
}
},
{
"in": "query",
"name": "server",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/ServerCommonSettings"
},
{
"type": "null"
}
],
"title": "Server"
}
},
{
"in": "query",
"name": "utils",
"required": false,
"schema": {
"anyOf": [
{
"$ref": "#/components/schemas/UtilsCommonSettings"
},
{
"type": "null"
}
],
"title": "Utils"
}
}
],
"responses": { "responses": {
"200": { "200": {
"content": { "content": {
@ -5898,27 +5748,13 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Config Put" "summary": "Fastapi Config Put",
"tags": [
"config"
]
} }
}, },
"/v1/config/file": { "/v1/config/file": {
"get": {
"description": "Get the settings as defined by the EOS configuration file.\n\nReturns:\n settings (SettingsEOS): The settings defined by the EOS configuration file.",
"operationId": "fastapi_config_file_get_v1_config_file_get",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SettingsEOS"
}
}
},
"description": "Successful Response"
}
},
"summary": "Fastapi Config File Get"
},
"put": { "put": {
"description": "Save the current configuration to the EOS configuration file.\n\nReturns:\n configuration (ConfigEOS): The current configuration that was saved.", "description": "Save the current configuration to the EOS configuration file.\n\nReturns:\n configuration (ConfigEOS): The current configuration that was saved.",
"operationId": "fastapi_config_file_put_v1_config_file_put", "operationId": "fastapi_config_file_put_v1_config_file_put",
@ -5934,55 +5770,16 @@
"description": "Successful Response" "description": "Successful Response"
} }
}, },
"summary": "Fastapi Config File Put" "summary": "Fastapi Config File Put",
"tags": [
"config"
]
} }
}, },
"/v1/config/update": { "/v1/config/reset": {
"post": {
"description": "Update the configuration from the EOS configuration file.\n\nReturns:\n configuration (ConfigEOS): The current configuration after update.",
"operationId": "fastapi_config_update_post_v1_config_update_post",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfigEOS"
}
}
},
"description": "Successful Response"
}
},
"summary": "Fastapi Config Update Post"
}
},
"/v1/config/value": {
"put": { "put": {
"description": "Set the configuration option in the settings.\n\nArgs:\n key (str): configuration key\n value (Any): configuration value\n\nReturns:\n configuration (ConfigEOS): The current configuration after the write.", "description": "Reset the configuration to the EOS configuration file.\n\nReturns:\n configuration (ConfigEOS): The current configuration after update.",
"operationId": "fastapi_config_value_put_v1_config_value_put", "operationId": "fastapi_config_update_post_v1_config_reset_put",
"parameters": [
{
"description": "configuration key",
"in": "query",
"name": "key",
"required": true,
"schema": {
"description": "configuration key",
"title": "Key",
"type": "string"
}
},
{
"description": "configuration value",
"in": "query",
"name": "value",
"required": true,
"schema": {
"description": "configuration value",
"title": "Value"
}
}
],
"responses": { "responses": {
"200": { "200": {
"content": { "content": {
@ -5993,19 +5790,12 @@
} }
}, },
"description": "Successful Response" "description": "Successful Response"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
"description": "Validation Error"
} }
}, },
"summary": "Fastapi Config Value Put" "summary": "Fastapi Config Update Post",
"tags": [
"config"
]
} }
}, },
"/v1/measurement/data": { "/v1/measurement/data": {
@ -6042,7 +5832,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Measurement Data Put" "summary": "Fastapi Measurement Data Put",
"tags": [
"measurement"
]
} }
}, },
"/v1/measurement/dataframe": { "/v1/measurement/dataframe": {
@ -6079,7 +5872,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Measurement Dataframe Put" "summary": "Fastapi Measurement Dataframe Put",
"tags": [
"measurement"
]
} }
}, },
"/v1/measurement/keys": { "/v1/measurement/keys": {
@ -6102,7 +5898,10 @@
"description": "Successful Response" "description": "Successful Response"
} }
}, },
"summary": "Fastapi Measurement Keys Get" "summary": "Fastapi Measurement Keys Get",
"tags": [
"measurement"
]
} }
}, },
"/v1/measurement/load-mr/series/by-name": { "/v1/measurement/load-mr/series/by-name": {
@ -6144,7 +5943,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Measurement Load Mr Series By Name Get" "summary": "Fastapi Measurement Load Mr Series By Name Get",
"tags": [
"measurement"
]
}, },
"put": { "put": {
"description": "Merge the meter readings series of given load name into EOS measurements at given datetime.", "description": "Merge the meter readings series of given load name into EOS measurements at given datetime.",
@ -6194,7 +5996,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Measurement Load Mr Series By Name Put" "summary": "Fastapi Measurement Load Mr Series By Name Put",
"tags": [
"measurement"
]
} }
}, },
"/v1/measurement/load-mr/value/by-name": { "/v1/measurement/load-mr/value/by-name": {
@ -6263,7 +6068,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Measurement Load Mr Value By Name Put" "summary": "Fastapi Measurement Load Mr Value By Name Put",
"tags": [
"measurement"
]
} }
}, },
"/v1/measurement/series": { "/v1/measurement/series": {
@ -6305,7 +6113,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Measurement Series Get" "summary": "Fastapi Measurement Series Get",
"tags": [
"measurement"
]
}, },
"put": { "put": {
"description": "Merge measurement given as series into given key.", "description": "Merge measurement given as series into given key.",
@ -6355,7 +6166,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Measurement Series Put" "summary": "Fastapi Measurement Series Put",
"tags": [
"measurement"
]
} }
}, },
"/v1/measurement/value": { "/v1/measurement/value": {
@ -6424,7 +6238,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Measurement Value Put" "summary": "Fastapi Measurement Value Put",
"tags": [
"measurement"
]
} }
}, },
"/v1/prediction/keys": { "/v1/prediction/keys": {
@ -6447,7 +6264,10 @@
"description": "Successful Response" "description": "Successful Response"
} }
}, },
"summary": "Fastapi Prediction Keys Get" "summary": "Fastapi Prediction Keys Get",
"tags": [
"prediction"
]
} }
}, },
"/v1/prediction/list": { "/v1/prediction/list": {
@ -6545,7 +6365,64 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Prediction List Get" "summary": "Fastapi Prediction List Get",
"tags": [
"prediction"
]
}
},
"/v1/prediction/providers": {
"get": {
"description": "Get a list of available prediction providers.\n\nArgs:\n enabled (bool): Return enabled/disabled providers. If unset, return all providers.",
"operationId": "fastapi_prediction_providers_get_v1_prediction_providers_get",
"parameters": [
{
"in": "query",
"name": "enabled",
"required": false,
"schema": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"type": "string"
},
"title": "Response Fastapi Prediction Providers Get V1 Prediction Providers Get",
"type": "array"
}
}
},
"description": "Successful Response"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
"description": "Validation Error"
}
},
"summary": "Fastapi Prediction Providers Get",
"tags": [
"prediction"
]
} }
}, },
"/v1/prediction/series": { "/v1/prediction/series": {
@ -6623,7 +6500,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Prediction Series Get" "summary": "Fastapi Prediction Series Get",
"tags": [
"prediction"
]
} }
}, },
"/v1/prediction/update": { "/v1/prediction/update": {
@ -6672,7 +6552,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Prediction Update" "summary": "Fastapi Prediction Update",
"tags": [
"prediction"
]
} }
}, },
"/v1/prediction/update/{provider_id}": { "/v1/prediction/update/{provider_id}": {
@ -6744,7 +6627,10 @@
"description": "Validation Error" "description": "Validation Error"
} }
}, },
"summary": "Fastapi Prediction Update Provider" "summary": "Fastapi Prediction Update Provider",
"tags": [
"prediction"
]
} }
}, },
"/visualization_results.pdf": { "/visualization_results.pdf": {
@ -6762,7 +6648,10 @@
"description": "Successful Response" "description": "Successful Response"
} }
}, },
"summary": "Get Pdf" "summary": "Get Pdf",
"tags": [
"optimize"
]
} }
} }
} }

View File

@ -310,7 +310,7 @@ class ConfigEOS(SingletonMixin, SettingsEOSDefaults):
if not isinstance(settings, SettingsEOS): if not isinstance(settings, SettingsEOS):
raise ValueError(f"Settings must be an instance of SettingsEOS: '{settings}'.") raise ValueError(f"Settings must be an instance of SettingsEOS: '{settings}'.")
self.merge_settings_from_dict(settings.model_dump()) self.merge_settings_from_dict(settings.model_dump(exclude_none=True, exclude_unset=True))
def merge_settings_from_dict(self, data: dict) -> None: def merge_settings_from_dict(self, data: dict) -> None:
"""Merges the provided dictionary data into the current instance. """Merges the provided dictionary data into the current instance.

View File

@ -230,10 +230,6 @@ app = FastAPI(
root_path=str(Path(__file__).parent), root_path=str(Path(__file__).parent),
) )
# That's the problem
opt_class = optimization_problem(verbose=bool(config_eos.server.verbose))
server_dir = Path(__file__).parent.resolve() server_dir = Path(__file__).parent.resolve()
@ -241,66 +237,24 @@ class PdfResponse(FileResponse):
media_type = "application/pdf" media_type = "application/pdf"
@app.put("/v1/config/value") @app.put("/v1/config/reset", tags=["config"])
def fastapi_config_value_put(
key: Annotated[str, Query(description="configuration key")],
value: Annotated[Any, Query(description="configuration value")],
) -> ConfigEOS:
"""Set the configuration option in the settings.
Args:
key (str): configuration key
value (Any): configuration value
Returns:
configuration (ConfigEOS): The current configuration after the write.
"""
if key not in config_eos.config_keys:
raise HTTPException(status_code=404, detail=f"Key '{key}' is not available.")
if key in config_eos.config_keys_read_only:
raise HTTPException(status_code=404, detail=f"Key '{key}' is read only.")
try:
setattr(config_eos, key, value)
except Exception as e:
raise HTTPException(status_code=400, detail=f"Error on update of configuration: {e}")
return config_eos
@app.post("/v1/config/update")
def fastapi_config_update_post() -> ConfigEOS: def fastapi_config_update_post() -> ConfigEOS:
"""Update the configuration from the EOS configuration file. """Reset the configuration to the EOS configuration file.
Returns: Returns:
configuration (ConfigEOS): The current configuration after update. configuration (ConfigEOS): The current configuration after update.
""" """
try: try:
_, config_file_path = config_eos.from_config_file() config_eos.reset_settings()
except: except Exception as e:
raise HTTPException( raise HTTPException(
status_code=404, status_code=404,
detail=f"Cannot update configuration from file '{config_file_path}'.", detail=f"Cannot update configuration from file '{config_eos.config_file_path}': {e}",
) )
return config_eos return config_eos
@app.get("/v1/config/file") @app.put("/v1/config/file", tags=["config"])
def fastapi_config_file_get() -> SettingsEOS:
"""Get the settings as defined by the EOS configuration file.
Returns:
settings (SettingsEOS): The settings defined by the EOS configuration file.
"""
try:
settings, config_file_path = config_eos.settings_from_config_file()
except:
raise HTTPException(
status_code=404,
detail=f"Cannot read configuration from file '{config_file_path}'.",
)
return settings
@app.put("/v1/config/file")
def fastapi_config_file_put() -> ConfigEOS: def fastapi_config_file_put() -> ConfigEOS:
"""Save the current configuration to the EOS configuration file. """Save the current configuration to the EOS configuration file.
@ -317,7 +271,7 @@ def fastapi_config_file_put() -> ConfigEOS:
return config_eos return config_eos
@app.get("/v1/config") @app.get("/v1/config", tags=["config"])
def fastapi_config_get() -> ConfigEOS: def fastapi_config_get() -> ConfigEOS:
"""Get the current configuration. """Get the current configuration.
@ -327,10 +281,8 @@ def fastapi_config_get() -> ConfigEOS:
return config_eos return config_eos
@app.put("/v1/config") @app.put("/v1/config", tags=["config"])
def fastapi_config_put( def fastapi_config_put(settings: SettingsEOS) -> ConfigEOS:
settings: Annotated[SettingsEOS, Query(description="settings")],
) -> ConfigEOS:
"""Write the provided settings into the current settings. """Write the provided settings into the current settings.
The existing settings are completely overwritten. Note that for any setting The existing settings are completely overwritten. Note that for any setting
@ -350,13 +302,13 @@ def fastapi_config_put(
return config_eos return config_eos
@app.get("/v1/measurement/keys") @app.get("/v1/measurement/keys", tags=["measurement"])
def fastapi_measurement_keys_get() -> list[str]: def fastapi_measurement_keys_get() -> list[str]:
"""Get a list of available measurement keys.""" """Get a list of available measurement keys."""
return sorted(measurement_eos.record_keys) return sorted(measurement_eos.record_keys)
@app.get("/v1/measurement/load-mr/series/by-name") @app.get("/v1/measurement/load-mr/series/by-name", tags=["measurement"])
def fastapi_measurement_load_mr_series_by_name_get( def fastapi_measurement_load_mr_series_by_name_get(
name: Annotated[str, Query(description="Load name.")], name: Annotated[str, Query(description="Load name.")],
) -> PydanticDateTimeSeries: ) -> PydanticDateTimeSeries:
@ -372,7 +324,7 @@ def fastapi_measurement_load_mr_series_by_name_get(
return PydanticDateTimeSeries.from_series(pdseries) return PydanticDateTimeSeries.from_series(pdseries)
@app.put("/v1/measurement/load-mr/value/by-name") @app.put("/v1/measurement/load-mr/value/by-name", tags=["measurement"])
def fastapi_measurement_load_mr_value_by_name_put( def fastapi_measurement_load_mr_value_by_name_put(
datetime: Annotated[str, Query(description="Datetime.")], datetime: Annotated[str, Query(description="Datetime.")],
name: Annotated[str, Query(description="Load name.")], name: Annotated[str, Query(description="Load name.")],
@ -391,7 +343,7 @@ def fastapi_measurement_load_mr_value_by_name_put(
return PydanticDateTimeSeries.from_series(pdseries) return PydanticDateTimeSeries.from_series(pdseries)
@app.put("/v1/measurement/load-mr/series/by-name") @app.put("/v1/measurement/load-mr/series/by-name", tags=["measurement"])
def fastapi_measurement_load_mr_series_by_name_put( def fastapi_measurement_load_mr_series_by_name_put(
name: Annotated[str, Query(description="Load name.")], series: PydanticDateTimeSeries name: Annotated[str, Query(description="Load name.")], series: PydanticDateTimeSeries
) -> PydanticDateTimeSeries: ) -> PydanticDateTimeSeries:
@ -409,7 +361,7 @@ def fastapi_measurement_load_mr_series_by_name_put(
return PydanticDateTimeSeries.from_series(pdseries) return PydanticDateTimeSeries.from_series(pdseries)
@app.get("/v1/measurement/series") @app.get("/v1/measurement/series", tags=["measurement"])
def fastapi_measurement_series_get( def fastapi_measurement_series_get(
key: Annotated[str, Query(description="Prediction key.")], key: Annotated[str, Query(description="Prediction key.")],
) -> PydanticDateTimeSeries: ) -> PydanticDateTimeSeries:
@ -420,7 +372,7 @@ def fastapi_measurement_series_get(
return PydanticDateTimeSeries.from_series(pdseries) return PydanticDateTimeSeries.from_series(pdseries)
@app.put("/v1/measurement/value") @app.put("/v1/measurement/value", tags=["measurement"])
def fastapi_measurement_value_put( def fastapi_measurement_value_put(
datetime: Annotated[str, Query(description="Datetime.")], datetime: Annotated[str, Query(description="Datetime.")],
key: Annotated[str, Query(description="Prediction key.")], key: Annotated[str, Query(description="Prediction key.")],
@ -434,7 +386,7 @@ def fastapi_measurement_value_put(
return PydanticDateTimeSeries.from_series(pdseries) return PydanticDateTimeSeries.from_series(pdseries)
@app.put("/v1/measurement/series") @app.put("/v1/measurement/series", tags=["measurement"])
def fastapi_measurement_series_put( def fastapi_measurement_series_put(
key: Annotated[str, Query(description="Prediction key.")], series: PydanticDateTimeSeries key: Annotated[str, Query(description="Prediction key.")], series: PydanticDateTimeSeries
) -> PydanticDateTimeSeries: ) -> PydanticDateTimeSeries:
@ -447,27 +399,47 @@ def fastapi_measurement_series_put(
return PydanticDateTimeSeries.from_series(pdseries) return PydanticDateTimeSeries.from_series(pdseries)
@app.put("/v1/measurement/dataframe") @app.put("/v1/measurement/dataframe", tags=["measurement"])
def fastapi_measurement_dataframe_put(data: PydanticDateTimeDataFrame) -> None: def fastapi_measurement_dataframe_put(data: PydanticDateTimeDataFrame) -> None:
"""Merge the measurement data given as dataframe into EOS measurements.""" """Merge the measurement data given as dataframe into EOS measurements."""
dataframe = data.to_dataframe() dataframe = data.to_dataframe()
measurement_eos.import_from_dataframe(dataframe) measurement_eos.import_from_dataframe(dataframe)
@app.put("/v1/measurement/data") @app.put("/v1/measurement/data", tags=["measurement"])
def fastapi_measurement_data_put(data: PydanticDateTimeData) -> None: def fastapi_measurement_data_put(data: PydanticDateTimeData) -> None:
"""Merge the measurement data given as datetime data into EOS measurements.""" """Merge the measurement data given as datetime data into EOS measurements."""
datetimedata = data.to_dict() datetimedata = data.to_dict()
measurement_eos.import_from_dict(datetimedata) measurement_eos.import_from_dict(datetimedata)
@app.get("/v1/prediction/keys") @app.get("/v1/prediction/providers", tags=["prediction"])
def fastapi_prediction_providers_get(enabled: Optional[bool] = None) -> list[str]:
"""Get a list of available prediction providers.
Args:
enabled (bool): Return enabled/disabled providers. If unset, return all providers.
"""
if enabled is not None:
enabled_status = [enabled]
else:
enabled_status = [True, False]
return sorted(
[
provider.provider_id()
for provider in prediction_eos.providers
if provider.enabled() in enabled_status
]
)
@app.get("/v1/prediction/keys", tags=["prediction"])
def fastapi_prediction_keys_get() -> list[str]: def fastapi_prediction_keys_get() -> list[str]:
"""Get a list of available prediction keys.""" """Get a list of available prediction keys."""
return sorted(prediction_eos.record_keys) return sorted(prediction_eos.record_keys)
@app.get("/v1/prediction/series") @app.get("/v1/prediction/series", tags=["prediction"])
def fastapi_prediction_series_get( def fastapi_prediction_series_get(
key: Annotated[str, Query(description="Prediction key.")], key: Annotated[str, Query(description="Prediction key.")],
start_datetime: Annotated[ start_datetime: Annotated[
@ -504,7 +476,7 @@ def fastapi_prediction_series_get(
return PydanticDateTimeSeries.from_series(pdseries) return PydanticDateTimeSeries.from_series(pdseries)
@app.get("/v1/prediction/list") @app.get("/v1/prediction/list", tags=["prediction"])
def fastapi_prediction_list_get( def fastapi_prediction_list_get(
key: Annotated[str, Query(description="Prediction key.")], key: Annotated[str, Query(description="Prediction key.")],
start_datetime: Annotated[ start_datetime: Annotated[
@ -554,7 +526,7 @@ def fastapi_prediction_list_get(
return prediction_list return prediction_list
@app.post("/v1/prediction/update") @app.post("/v1/prediction/update", tags=["prediction"])
def fastapi_prediction_update(force_update: bool = False, force_enable: bool = False) -> Response: def fastapi_prediction_update(force_update: bool = False, force_enable: bool = False) -> Response:
"""Update predictions for all providers. """Update predictions for all providers.
@ -567,11 +539,12 @@ def fastapi_prediction_update(force_update: bool = False, force_enable: bool = F
try: try:
prediction_eos.update_data(force_update=force_update, force_enable=force_enable) prediction_eos.update_data(force_update=force_update, force_enable=force_enable)
except Exception as e: except Exception as e:
raise HTTPException(status_code=400, detail=f"Error on update of provider: {e}") raise e
# raise HTTPException(status_code=400, detail=f"Error on update of provider: {e}")
return Response() return Response()
@app.post("/v1/prediction/update/{provider_id}") @app.post("/v1/prediction/update/{provider_id}", tags=["prediction"])
def fastapi_prediction_update_provider( def fastapi_prediction_update_provider(
provider_id: str, force_update: Optional[bool] = False, force_enable: Optional[bool] = False provider_id: str, force_update: Optional[bool] = False, force_enable: Optional[bool] = False
) -> Response: ) -> Response:
@ -595,7 +568,7 @@ def fastapi_prediction_update_provider(
return Response() return Response()
@app.get("/strompreis") @app.get("/strompreis", tags=["prediction"])
def fastapi_strompreis() -> list[float]: def fastapi_strompreis() -> list[float]:
"""Deprecated: Electricity Market Price Prediction per Wh (€/Wh). """Deprecated: Electricity Market Price Prediction per Wh (€/Wh).
@ -649,7 +622,7 @@ class GesamtlastRequest(PydanticBaseModel):
hours: int hours: int
@app.post("/gesamtlast") @app.post("/gesamtlast", tags=["prediction"])
def fastapi_gesamtlast(request: GesamtlastRequest) -> list[float]: def fastapi_gesamtlast(request: GesamtlastRequest) -> list[float]:
"""Deprecated: Total Load Prediction with adjustment. """Deprecated: Total Load Prediction with adjustment.
@ -730,7 +703,7 @@ def fastapi_gesamtlast(request: GesamtlastRequest) -> list[float]:
return prediction_list return prediction_list
@app.get("/gesamtlast_simple") @app.get("/gesamtlast_simple", tags=["prediction"])
def fastapi_gesamtlast_simple(year_energy: float) -> list[float]: def fastapi_gesamtlast_simple(year_energy: float) -> list[float]:
"""Deprecated: Total Load Prediction. """Deprecated: Total Load Prediction.
@ -786,7 +759,7 @@ class ForecastResponse(PydanticBaseModel):
pvpower: list[float] pvpower: list[float]
@app.get("/pvforecast") @app.get("/pvforecast", tags=["prediction"])
def fastapi_pvforecast() -> ForecastResponse: def fastapi_pvforecast() -> ForecastResponse:
"""Deprecated: PV Forecast Prediction. """Deprecated: PV Forecast Prediction.
@ -841,30 +814,35 @@ def fastapi_pvforecast() -> ForecastResponse:
return ForecastResponse(temperature=temp_air, pvpower=ac_power) return ForecastResponse(temperature=temp_air, pvpower=ac_power)
@app.post("/optimize") @app.post("/optimize", tags=["optimize"])
def fastapi_optimize( def fastapi_optimize(
parameters: OptimizationParameters, parameters: OptimizationParameters,
start_hour: Annotated[ start_hour: Annotated[
Optional[int], Query(description="Defaults to current hour of the day.") Optional[int], Query(description="Defaults to current hour of the day.")
] = None, ] = None,
ngen: Optional[int] = None,
) -> OptimizeResponse: ) -> OptimizeResponse:
if start_hour is None: if start_hour is None:
start_hour = to_datetime().hour start_hour = to_datetime().hour
extra_args: dict[str, Any] = dict()
if ngen is not None:
extra_args["ngen"] = ngen
# TODO: Remove when config and prediction update is done by EMS. # TODO: Remove when config and prediction update is done by EMS.
config_eos.update() config_eos.update()
prediction_eos.update_data() prediction_eos.update_data()
# Perform optimization simulation # Perform optimization simulation
result = opt_class.optimierung_ems(parameters=parameters, start_hour=start_hour) opt_class = optimization_problem(verbose=bool(config_eos.server.verbose))
result = opt_class.optimierung_ems(parameters=parameters, start_hour=start_hour, **extra_args)
# print(result) # print(result)
return result return result
@app.get("/visualization_results.pdf", response_class=PdfResponse) @app.get("/visualization_results.pdf", response_class=PdfResponse, tags=["optimize"])
def get_pdf() -> PdfResponse: def get_pdf() -> PdfResponse:
# Endpoint to serve the generated PDF with visualization results # Endpoint to serve the generated PDF with visualization results
output_path = config_eos.config.data_output_path output_path = config_eos.general.data_output_path
if output_path is None or not output_path.is_dir(): if output_path is None or not output_path.is_dir():
raise HTTPException(status_code=404, detail=f"Output path does not exist: {output_path}.") raise HTTPException(status_code=404, detail=f"Output path does not exist: {output_path}.")
file_path = output_path / "visualization_results.pdf" file_path = output_path / "visualization_results.pdf"
@ -880,25 +858,28 @@ def site_map() -> RedirectResponse:
# Keep the proxy last to handle all requests that are not taken by the Rest API. # Keep the proxy last to handle all requests that are not taken by the Rest API.
if config_eos.server.startup_eosdash:
@app.delete("/{path:path}", include_in_schema=False) @app.delete("/{path:path}", include_in_schema=False)
async def proxy_delete(request: Request, path: str) -> Response: async def proxy_delete(request: Request, path: str) -> Response:
return await proxy(request, path) return await proxy(request, path)
@app.get("/{path:path}", include_in_schema=False)
async def proxy_get(request: Request, path: str) -> Response:
return await proxy(request, path)
@app.get("/{path:path}", include_in_schema=False) @app.post("/{path:path}", include_in_schema=False)
async def proxy_get(request: Request, path: str) -> Response: async def proxy_post(request: Request, path: str) -> Response:
return await proxy(request, path) return await proxy(request, path)
@app.put("/{path:path}", include_in_schema=False)
async def proxy_put(request: Request, path: str) -> Response:
return await proxy(request, path)
else:
@app.post("/{path:path}", include_in_schema=False) @app.get("/", include_in_schema=False)
async def proxy_post(request: Request, path: str) -> Response: def root() -> RedirectResponse:
return await proxy(request, path) return RedirectResponse(url="/docs")
@app.put("/{path:path}", include_in_schema=False)
async def proxy_put(request: Request, path: str) -> Response:
return await proxy(request, path)
async def proxy(request: Request, path: str) -> Union[Response | RedirectResponse | HTMLResponse]: async def proxy(request: Request, path: str) -> Union[Response | RedirectResponse | HTMLResponse]: