From 8e69caba73d99ffd46bad92d5e60fa9de687e86f Mon Sep 17 00:00:00 2001 From: redmoon2711 <115375226+redmoon2711@users.noreply.github.com> Date: Sat, 19 Jul 2025 08:55:16 +0200 Subject: [PATCH] feat(VRM forecast): add load and pv forecast by VRM API (#611) Add support for fetching forecasts from the VRM API by Victron Energy. Retrieve forecasts for PV generation and total load of a Victron system from the internet. Tests for the new modules have been added, and the documentation has been updated accordingly. Signed-off-by: redmoon2711 --- docs/_generated/config.md | 58 +- docs/akkudoktoreos/prediction.md | 49 +- openapi.json | 9685 +++++++++-------- src/akkudoktoreos/prediction/load.py | 7 +- src/akkudoktoreos/prediction/loadvrm.py | 109 + src/akkudoktoreos/prediction/prediction.py | 8 + src/akkudoktoreos/prediction/pvforecast.py | 9 +- src/akkudoktoreos/prediction/pvforecastvrm.py | 110 + tests/test_loadvrm.py | 116 + tests/test_prediction.py | 20 +- tests/test_pvforecastvrm.py | 116 + 11 files changed, 5458 insertions(+), 4829 deletions(-) create mode 100644 src/akkudoktoreos/prediction/loadvrm.py create mode 100644 src/akkudoktoreos/prediction/pvforecastvrm.py create mode 100644 tests/test_loadvrm.py create mode 100644 tests/test_pvforecastvrm.py diff --git a/docs/_generated/config.md b/docs/_generated/config.md index b47d2f0..3cea607 100644 --- a/docs/_generated/config.md +++ b/docs/_generated/config.md @@ -477,7 +477,7 @@ Validators: | Name | Environment Variable | Type | Read-Only | Default | Description | | ---- | -------------------- | ---- | --------- | ------- | ----------- | | provider | `EOS_LOAD__PROVIDER` | `Optional[str]` | `rw` | `None` | Load provider id of provider to be used. | -| provider_settings | `EOS_LOAD__PROVIDER_SETTINGS` | `Union[akkudoktoreos.prediction.loadakkudoktor.LoadAkkudoktorCommonSettings, akkudoktoreos.prediction.loadimport.LoadImportCommonSettings, NoneType]` | `rw` | `None` | Provider settings | +| provider_settings | `EOS_LOAD__PROVIDER_SETTINGS` | `Union[akkudoktoreos.prediction.loadakkudoktor.LoadAkkudoktorCommonSettings, akkudoktoreos.prediction.loadvrm.LoadVrmCommonSettings, akkudoktoreos.prediction.loadimport.LoadImportCommonSettings, NoneType]` | `rw` | `None` | Provider settings | ::: ### Example Input/Output @@ -520,6 +520,33 @@ Validators: } ``` +### Common settings for VRM API + +:::{table} load::provider_settings +:widths: 10 10 5 5 30 +:align: left + +| Name | Type | Read-Only | Default | Description | +| ---- | ---- | --------- | ------- | ----------- | +| load_vrm_token | `str` | `rw` | `your-token` | Token for Connecting VRM API | +| load_vrm_idsite | `int` | `rw` | `12345` | VRM-Installation-ID | +::: + +#### Example Input/Output + +```{eval-rst} +.. code-block:: json + + { + "load": { + "provider_settings": { + "load_vrm_token": "your-token", + "load_vrm_idsite": 12345 + } + } + } +``` + ### Common settings for load data import from file :::{table} load::provider_settings @@ -554,7 +581,7 @@ Validators: | Name | Environment Variable | Type | Read-Only | Default | Description | | ---- | -------------------- | ---- | --------- | ------- | ----------- | | provider | `EOS_PVFORECAST__PROVIDER` | `Optional[str]` | `rw` | `None` | PVForecast provider id of provider to be used. | -| provider_settings | `EOS_PVFORECAST__PROVIDER_SETTINGS` | `Optional[akkudoktoreos.prediction.pvforecastimport.PVForecastImportCommonSettings]` | `rw` | `None` | Provider settings | +| provider_settings | `EOS_PVFORECAST__PROVIDER_SETTINGS` | `Union[akkudoktoreos.prediction.pvforecastimport.PVForecastImportCommonSettings, akkudoktoreos.prediction.pvforecastvrm.PVforecastVrmCommonSettings, NoneType]` | `rw` | `None` | Provider settings | | planes | `EOS_PVFORECAST__PLANES` | `Optional[list[akkudoktoreos.prediction.pvforecast.PVForecastPlaneSetting]]` | `rw` | `None` | Plane configuration. | | max_planes | `EOS_PVFORECAST__MAX_PLANES` | `Optional[int]` | `rw` | `0` | Maximum number of planes that can be set | | planes_peakpower | | `List[float]` | `ro` | `N/A` | Compute a list of the peak power per active planes. | @@ -795,6 +822,33 @@ Validators: } ``` +### Common settings for VRM API + +:::{table} pvforecast::provider_settings +:widths: 10 10 5 5 30 +:align: left + +| Name | Type | Read-Only | Default | Description | +| ---- | ---- | --------- | ------- | ----------- | +| pvforecast_vrm_token | `str` | `rw` | `your-token` | Token for Connecting VRM API | +| pvforecast_vrm_idsite | `int` | `rw` | `12345` | VRM-Installation-ID | +::: + +#### Example Input/Output + +```{eval-rst} +.. code-block:: json + + { + "pvforecast": { + "provider_settings": { + "pvforecast_vrm_token": "your-token", + "pvforecast_vrm_idsite": 12345 + } + } + } +``` + ### Common settings for pvforecast data import from file or JSON string :::{table} pvforecast::provider_settings diff --git a/docs/akkudoktoreos/prediction.md b/docs/akkudoktoreos/prediction.md index 5600095..42e7a28 100644 --- a/docs/akkudoktoreos/prediction.md +++ b/docs/akkudoktoreos/prediction.md @@ -184,6 +184,7 @@ Configuration options: - `provider`: Load provider id of provider to be used. - `LoadAkkudoktor`: Retrieves from local database. + - `LoadVrm`: Retrieves data from the VRM API by Victron Energy. - `LoadImport`: Imports from a file or JSON string. - `provider_settings.loadakkudoktor_year_energy`: Yearly energy consumption (kWh). @@ -196,6 +197,27 @@ The `LoadAkkudoktor` provider retrieves generic load data from a local database align with the annual energy consumption specified in the `loadakkudoktor_year_energy` configuration option. +### LoadVrm Provider + +The `LoadVrm` provider retrieves load forecast data from the VRM API by Victron Energy. +To receive forecasts, the system data must be configured under Dynamic ESS in the VRM portal. +To query the forecasts, an API token is required, which can also be created in the VRM portal under Preferences. +This token must be stored in the EOS configuration along with the VRM-Installations-ID. + +```python + { + "load": { + "provider": "LoadVrm", + "provider_settings": { + "load_vrm_token": "dummy-token", + "load_vrm_idsite": 12345 + } +``` + +The prediction keys for the load forecast data are: + +- `load_mean`: Predicted load mean value (W). + ### LoadImport Provider The `LoadImport` provider is designed to import load forecast data from a file or a JSON @@ -234,6 +256,7 @@ Configuration options: - `provider`: PVForecast provider id of provider to be used. - `PVForecastAkkudoktor`: Retrieves from Akkudoktor.net. + - `PVForecastVrm`: Retrieves data from the VRM API by Victron Energy. - `PVForecastImport`: Imports from a file or JSON string. - `planes[].surface_tilt`: Tilt angle from horizontal plane. Ignored for two-axis tracking. @@ -422,6 +445,28 @@ Example: } ``` +### PVForecastVrm Provider + +The `PVForecastVrm` provider retrieves pv power forecast data from the VRM API by Victron Energy. +To receive forecasts, the system data must be configured under Dynamic ESS in the VRM portal. +To query the forecasts, an API token is required, which can also be created in the VRM portal under Preferences. +This token must be stored in the EOS configuration along with the VRM-Installations-ID. + +```python + { + "pvforecast": { + "provider": "PVForecastVrm", + "provider_settings": { + "pvforecast_vrm_token": "dummy-token", + "pvforecast_vrm_idsite": 12345 + } + } +``` + +The prediction keys for the PV forecast data are: + +- `pvforecast_dc_power`: Total DC power (W). + ### PVForecastImport Provider The `PVForecastImport` provider is designed to import PV forecast data from a file or a JSON @@ -430,8 +475,8 @@ becomes available. The prediction keys for the PV forecast data are: -- `pvforecast_ac_power`: Total DC power (W). -- `pvforecast_dc_power`: Total AC power (W). +- `pvforecast_ac_power`: Total AC power (W). +- `pvforecast_dc_power`: Total DC power (W). The PV forecast data must be provided in one of the formats described in . The data source can be given in the diff --git a/openapi.json b/openapi.json index 64f4596..fa3ca5e 100644 --- a/openapi.json +++ b/openapi.json @@ -1,4833 +1,4894 @@ { - "openapi": "3.1.0", - "info": { - "title": "Akkudoktor-EOS", - "description": "This project provides a comprehensive solution for simulating and optimizing an energy system based on renewable energy sources. With a focus on photovoltaic (PV) systems, battery storage (batteries), load management (consumer requirements), heat pumps, electric vehicles, and consideration of electricity price data, this system enables forecasting and optimization of energy flow and costs over a specified period.", - "version": "0.0.1" - }, - "paths": { - "/v1/admin/cache/clear": { - "post": { - "tags": [ - "admin" - ], - "summary": "Fastapi Admin Cache Clear Post", - "description": "Clear the cache from expired data.\n\nDeletes expired cache files.\n\nArgs:\n clear_all (Optional[bool]): Delete all cached files. Default is False.\n\nReturns:\n data (dict): The management data after cleanup.", - "operationId": "fastapi_admin_cache_clear_post_v1_admin_cache_clear_post", - "parameters": [ - { - "name": "clear_all", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Clear All" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response Fastapi Admin Cache Clear Post V1 Admin Cache Clear Post" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } + "openapi": "3.1.0", + "info": { + "title": "Akkudoktor-EOS", + "description": "This project provides a comprehensive solution for simulating and optimizing an energy system based on renewable energy sources. With a focus on photovoltaic (PV) systems, battery storage (batteries), load management (consumer requirements), heat pumps, electric vehicles, and consideration of electricity price data, this system enables forecasting and optimization of energy flow and costs over a specified period.", + "version": "0.0.1" }, - "/v1/admin/cache/save": { - "post": { - "tags": [ - "admin" - ], - "summary": "Fastapi Admin Cache Save Post", - "description": "Save the current cache management data.\n\nReturns:\n data (dict): The management data that was saved.", - "operationId": "fastapi_admin_cache_save_post_v1_admin_cache_save_post", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response Fastapi Admin Cache Save Post V1 Admin Cache Save Post" - } - } - } - } - } - } - }, - "/v1/admin/cache/load": { - "post": { - "tags": [ - "admin" - ], - "summary": "Fastapi Admin Cache Load Post", - "description": "Load cache management data.\n\nReturns:\n data (dict): The management data that was loaded.", - "operationId": "fastapi_admin_cache_load_post_v1_admin_cache_load_post", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response Fastapi Admin Cache Load Post V1 Admin Cache Load Post" - } - } - } - } - } - } - }, - "/v1/admin/cache": { - "get": { - "tags": [ - "admin" - ], - "summary": "Fastapi Admin Cache Get", - "description": "Current cache management data.\n\nReturns:\n data (dict): The management data.", - "operationId": "fastapi_admin_cache_get_v1_admin_cache_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response Fastapi Admin Cache Get V1 Admin Cache Get" - } - } - } - } - } - } - }, - "/v1/admin/server/restart": { - "post": { - "tags": [ - "admin" - ], - "summary": "Fastapi Admin Server Restart Post", - "description": "Restart the server.\n\nRestart EOS properly by starting a new instance before exiting the old one.", - "operationId": "fastapi_admin_server_restart_post_v1_admin_server_restart_post", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response Fastapi Admin Server Restart Post V1 Admin Server Restart Post" - } - } - } - } - } - } - }, - "/v1/admin/server/shutdown": { - "post": { - "tags": [ - "admin" - ], - "summary": "Fastapi Admin Server Shutdown Post", - "description": "Shutdown the server.", - "operationId": "fastapi_admin_server_shutdown_post_v1_admin_server_shutdown_post", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response Fastapi Admin Server Shutdown Post V1 Admin Server Shutdown Post" - } - } - } - } - } - } - }, - "/v1/health": { - "get": { - "summary": "Fastapi Health Get", - "description": "Health check endpoint to verify that the EOS server is alive.", - "operationId": "fastapi_health_get_v1_health_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - } - } - } - }, - "/v1/config/reset": { - "post": { - "tags": [ - "config" - ], - "summary": "Fastapi Config Reset Post", - "description": "Reset the configuration to the EOS configuration file.\n\nReturns:\n configuration (ConfigEOS): The current configuration after update.", - "operationId": "fastapi_config_reset_post_v1_config_reset_post", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConfigEOS" - } - } - } - } - } - } - }, - "/v1/config/file": { - "put": { - "tags": [ - "config" - ], - "summary": "Fastapi Config File Put", - "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", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConfigEOS" - } - } - } - } - } - } - }, - "/v1/config": { - "get": { - "tags": [ - "config" - ], - "summary": "Fastapi Config Get", - "description": "Get the current configuration.\n\nReturns:\n configuration (ConfigEOS): The current configuration.", - "operationId": "fastapi_config_get_v1_config_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConfigEOS" - } - } - } - } - } - }, - "put": { - "tags": [ - "config" - ], - "summary": "Fastapi Config Put", - "description": "Update the current config with the provided settings.\n\nNote that for any setting value that is None or unset, the configuration will fall back to\nvalues from other sources such as environment variables, the EOS configuration file, or default\nvalues.\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", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SettingsEOS" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConfigEOS" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/config/{path}": { - "put": { - "tags": [ - "config" - ], - "summary": "Fastapi Config Put Key", - "description": "Update a nested key or index in the config model.\n\nArgs:\n path (str): The nested path to the key (e.g., \"general/latitude\" or \"optimize/nested_list/0\").\n value (Any): The new value to assign to the key or index at path.\n\nReturns:\n configuration (ConfigEOS): The current configuration after the update.", - "operationId": "fastapi_config_put_key_v1_config__path__put", - "parameters": [ - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string", - "description": "The nested path to the configuration key (e.g., general/latitude).", - "title": "Path" - }, - "description": "The nested path to the configuration key (e.g., general/latitude)." - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - {}, - { - "type": "null" - } + "paths": { + "/v1/admin/cache/clear": { + "post": { + "tags": [ + "admin" ], - "description": "The value to assign to the specified configuration path (can be None).", - "title": "Value" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConfigEOS" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "get": { - "tags": [ - "config" - ], - "summary": "Fastapi Config Get Key", - "description": "Get the value of a nested key or index in the config model.\n\nArgs:\n path (str): The nested path to the key (e.g., \"general/latitude\" or \"optimize/nested_list/0\").\n\nReturns:\n value (Any): The value of the selected nested key.", - "operationId": "fastapi_config_get_key_v1_config__path__get", - "parameters": [ - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string", - "description": "The nested path to the configuration key (e.g., general/latitude).", - "title": "Path" - }, - "description": "The nested path to the configuration key (e.g., general/latitude)." - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/logging/log": { - "get": { - "tags": [ - "logging" - ], - "summary": "Fastapi Logging Get Log", - "description": "Get structured log entries from the EOS log file.\n\nFilters and returns log entries based on the specified query parameters. The log\nfile is expected to contain newline-delimited JSON entries.\n\nArgs:\n limit (int): Maximum number of entries to return.\n level (Optional[str]): Filter logs by severity level (e.g., DEBUG, INFO).\n contains (Optional[str]): Return only logs that include this string in the message.\n regex (Optional[str]): Return logs that match this regular expression in the message.\n from_time (Optional[str]): ISO 8601 timestamp to filter logs not older than this.\n to_time (Optional[str]): ISO 8601 timestamp to filter logs not newer than this.\n tail (bool): If True, fetch the most recent log entries (like `tail`).\n\nReturns:\n JSONResponse: A JSON list of log entries.", - "operationId": "fastapi_logging_get_log_v1_logging_log_get", - "parameters": [ - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "description": "Maximum number of log entries to return.", - "default": 100, - "title": "Limit" - }, - "description": "Maximum number of log entries to return." - }, - { - "name": "level", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Filter by log level (e.g., INFO, ERROR).", - "title": "Level" - }, - "description": "Filter by log level (e.g., INFO, ERROR)." - }, - { - "name": "contains", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Filter logs containing this substring.", - "title": "Contains" - }, - "description": "Filter logs containing this substring." - }, - { - "name": "regex", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Filter logs by matching regex in message.", - "title": "Regex" - }, - "description": "Filter logs by matching regex in message." - }, - { - "name": "from_time", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Start time (ISO format) for filtering logs.", - "title": "From Time" - }, - "description": "Start time (ISO format) for filtering logs." - }, - { - "name": "to_time", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "End time (ISO format) for filtering logs.", - "title": "To Time" - }, - "description": "End time (ISO format) for filtering logs." - }, - { - "name": "tail", - "in": "query", - "required": false, - "schema": { - "type": "boolean", - "description": "If True, returns the most recent lines (tail mode).", - "default": false, - "title": "Tail" - }, - "description": "If True, returns the most recent lines (tail mode)." - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/measurement/keys": { - "get": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Keys Get", - "description": "Get a list of available measurement keys.", - "operationId": "fastapi_measurement_keys_get_v1_measurement_keys_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Response Fastapi Measurement Keys Get V1 Measurement Keys Get" - } - } - } - } - } - } - }, - "/v1/measurement/load-mr/series/by-name": { - "get": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Load Mr Series By Name Get", - "description": "Get the meter reading of given load name as series.", - "operationId": "fastapi_measurement_load_mr_series_by_name_get_v1_measurement_load_mr_series_by_name_get", - "parameters": [ - { - "name": "name", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Load name.", - "title": "Name" - }, - "description": "Load name." - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "put": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Load Mr Series By Name Put", - "description": "Merge the meter readings series of given load name into EOS measurements at given datetime.", - "operationId": "fastapi_measurement_load_mr_series_by_name_put_v1_measurement_load_mr_series_by_name_put", - "parameters": [ - { - "name": "name", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Load name.", - "title": "Name" - }, - "description": "Load name." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/measurement/load-mr/value/by-name": { - "put": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Load Mr Value By Name Put", - "description": "Merge the meter reading of given load name and value into EOS measurements at given datetime.", - "operationId": "fastapi_measurement_load_mr_value_by_name_put_v1_measurement_load_mr_value_by_name_put", - "parameters": [ - { - "name": "datetime", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Datetime.", - "title": "Datetime" - }, - "description": "Datetime." - }, - { - "name": "name", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Load name.", - "title": "Name" - }, - "description": "Load name." - }, - { - "name": "value", - "in": "query", - "required": true, - "schema": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ], - "title": "Value" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/measurement/series": { - "get": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Series Get", - "description": "Get the measurements of given key as series.", - "operationId": "fastapi_measurement_series_get_v1_measurement_series_get", - "parameters": [ - { - "name": "key", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Prediction key.", - "title": "Key" - }, - "description": "Prediction key." - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "put": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Series Put", - "description": "Merge measurement given as series into given key.", - "operationId": "fastapi_measurement_series_put_v1_measurement_series_put", - "parameters": [ - { - "name": "key", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Prediction key.", - "title": "Key" - }, - "description": "Prediction key." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/measurement/value": { - "put": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Value Put", - "description": "Merge the measurement of given key and value into EOS measurements at given datetime.", - "operationId": "fastapi_measurement_value_put_v1_measurement_value_put", - "parameters": [ - { - "name": "datetime", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Datetime.", - "title": "Datetime" - }, - "description": "Datetime." - }, - { - "name": "key", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Prediction key.", - "title": "Key" - }, - "description": "Prediction key." - }, - { - "name": "value", - "in": "query", - "required": true, - "schema": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ], - "title": "Value" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/measurement/dataframe": { - "put": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Dataframe Put", - "description": "Merge the measurement data given as dataframe into EOS measurements.", - "operationId": "fastapi_measurement_dataframe_put_v1_measurement_dataframe_put", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeDataFrame" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/measurement/data": { - "put": { - "tags": [ - "measurement" - ], - "summary": "Fastapi Measurement Data Put", - "description": "Merge the measurement data given as datetime data into EOS measurements.", - "operationId": "fastapi_measurement_data_put_v1_measurement_data_put", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeData" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/prediction/providers": { - "get": { - "tags": [ - "prediction" - ], - "summary": "Fastapi 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": [ - { - "name": "enabled", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Enabled" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "string" - }, - "title": "Response Fastapi Prediction Providers Get V1 Prediction Providers Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/prediction/keys": { - "get": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Prediction Keys Get", - "description": "Get a list of available prediction keys.", - "operationId": "fastapi_prediction_keys_get_v1_prediction_keys_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Response Fastapi Prediction Keys Get V1 Prediction Keys Get" - } - } - } - } - } - } - }, - "/v1/prediction/series": { - "get": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Prediction Series Get", - "description": "Get prediction for given key within given date range as series.\n\nArgs:\n key (str): Prediction key\n start_datetime (Optional[str]): Starting datetime (inclusive).\n Defaults to start datetime of latest prediction.\n end_datetime (Optional[str]: Ending datetime (exclusive).\n Defaults to end datetime of latest prediction.", - "operationId": "fastapi_prediction_series_get_v1_prediction_series_get", - "parameters": [ - { - "name": "key", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Prediction key.", - "title": "Key" - }, - "description": "Prediction key." - }, - { - "name": "start_datetime", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Starting datetime (inclusive).", - "title": "Start Datetime" - }, - "description": "Starting datetime (inclusive)." - }, - { - "name": "end_datetime", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Ending datetime (exclusive).", - "title": "End Datetime" - }, - "description": "Ending datetime (exclusive)." - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeSeries" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/prediction/dataframe": { - "get": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Prediction Dataframe Get", - "description": "Get prediction for given key within given date range as series.\n\nArgs:\n key (str): Prediction key\n start_datetime (Optional[str]): Starting datetime (inclusive).\n Defaults to start datetime of latest prediction.\n end_datetime (Optional[str]: Ending datetime (exclusive).\n\nDefaults to end datetime of latest prediction.", - "operationId": "fastapi_prediction_dataframe_get_v1_prediction_dataframe_get", - "parameters": [ - { - "name": "keys", - "in": "query", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Prediction keys.", - "title": "Keys" - }, - "description": "Prediction keys." - }, - { - "name": "start_datetime", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Starting datetime (inclusive).", - "title": "Start Datetime" - }, - "description": "Starting datetime (inclusive)." - }, - { - "name": "end_datetime", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Ending datetime (exclusive).", - "title": "End Datetime" - }, - "description": "Ending datetime (exclusive)." - }, - { - "name": "interval", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Time duration for each interval. Defaults to 1 hour.", - "title": "Interval" - }, - "description": "Time duration for each interval. Defaults to 1 hour." - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PydanticDateTimeDataFrame" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/prediction/list": { - "get": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Prediction List Get", - "description": "Get prediction for given key within given date range as value list.\n\nArgs:\n key (str): Prediction key\n start_datetime (Optional[str]): Starting datetime (inclusive).\n Defaults to start datetime of latest prediction.\n end_datetime (Optional[str]: Ending datetime (exclusive).\n Defaults to end datetime of latest prediction.\n interval (Optional[str]): Time duration for each interval.\n Defaults to 1 hour.", - "operationId": "fastapi_prediction_list_get_v1_prediction_list_get", - "parameters": [ - { - "name": "key", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Prediction key.", - "title": "Key" - }, - "description": "Prediction key." - }, - { - "name": "start_datetime", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Starting datetime (inclusive).", - "title": "Start Datetime" - }, - "description": "Starting datetime (inclusive)." - }, - { - "name": "end_datetime", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Ending datetime (exclusive).", - "title": "End Datetime" - }, - "description": "Ending datetime (exclusive)." - }, - { - "name": "interval", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Time duration for each interval. Defaults to 1 hour.", - "title": "Interval" - }, - "description": "Time duration for each interval. Defaults to 1 hour." - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": {}, - "title": "Response Fastapi Prediction List Get V1 Prediction List Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/prediction/import/{provider_id}": { - "put": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Prediction Import Provider", - "description": "Import prediction for given provider ID.\n\nArgs:\n provider_id: ID of provider to update.\n data: Prediction data.\n force_enable: Update data even if provider is disabled.\n Defaults to False.", - "operationId": "fastapi_prediction_import_provider_v1_prediction_import__provider_id__put", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "description": "Provider ID.", - "title": "Provider Id" - }, - "description": "Provider ID." - }, - { - "name": "force_enable", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Force Enable" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/PydanticDateTimeDataFrame" - }, - { - "$ref": "#/components/schemas/PydanticDateTimeData" - }, - { - "type": "object", - "additionalProperties": true - }, - { - "type": "null" - } - ], - "title": "Data" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/prediction/update": { - "post": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Prediction Update", - "description": "Update predictions for all providers.\n\nArgs:\n force_update: Update data even if it is already cached.\n Defaults to False.\n force_enable: Update data even if provider is disabled.\n Defaults to False.", - "operationId": "fastapi_prediction_update_v1_prediction_update_post", - "parameters": [ - { - "name": "force_update", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": false, - "title": "Force Update" - } - }, - { - "name": "force_enable", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": false, - "title": "Force Enable" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/v1/prediction/update/{provider_id}": { - "post": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Prediction Update Provider", - "description": "Update predictions for given provider ID.\n\nArgs:\n provider_id: ID of provider to update.\n force_update: Update data even if it is already cached.\n Defaults to False.\n force_enable: Update data even if provider is disabled.\n Defaults to False.", - "operationId": "fastapi_prediction_update_provider_v1_prediction_update__provider_id__post", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Provider Id" - } - }, - { - "name": "force_update", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": false, - "title": "Force Update" - } - }, - { - "name": "force_enable", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": false, - "title": "Force Enable" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/strompreis": { - "get": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Strompreis", - "description": "Deprecated: Electricity Market Price Prediction per Wh (\u20ac/Wh).\n\nElectricity prices start at 00.00.00 today and are provided for 48 hours.\nIf no prices are available the missing ones at the start of the series are\nfilled with the first available price.\n\nNote:\n Electricity price charges are added.\n\nNote:\n Set ElecPriceAkkudoktor as provider, then update data with\n '/v1/prediction/update'\n and then request data with\n '/v1/prediction/list?key=elecprice_marketprice_wh' or\n '/v1/prediction/list?key=elecprice_marketprice_kwh' instead.", - "operationId": "fastapi_strompreis_strompreis_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Response Fastapi Strompreis Strompreis Get" - } - } - } - } - } - } - }, - "/gesamtlast": { - "post": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Gesamtlast", - "description": "Deprecated: Total Load Prediction with adjustment.\n\nEndpoint to handle total load prediction adjusted by latest measured data.\n\nTotal load prediction starts at 00.00.00 today and is provided for 48 hours.\nIf no prediction values are available the missing ones at the start of the series are\nfilled with the first available prediction value.\n\nNote:\n Use '/v1/prediction/list?key=load_mean_adjusted' instead.\n Load energy meter readings to be added to EOS measurement by:\n '/v1/measurement/load-mr/value/by-name' or\n '/v1/measurement/value'", - "operationId": "fastapi_gesamtlast_gesamtlast_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GesamtlastRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Response Fastapi Gesamtlast Gesamtlast Post" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/gesamtlast_simple": { - "get": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Gesamtlast Simple", - "description": "Deprecated: Total Load Prediction.\n\nEndpoint to handle total load prediction.\n\nTotal load prediction starts at 00.00.00 today and is provided for 48 hours.\nIf no prediction values are available the missing ones at the start of the series are\nfilled with the first available prediction value.\n\nArgs:\n year_energy (float): Yearly energy consumption in Wh.\n\nNote:\n Set LoadAkkudoktor as provider, then update data with\n '/v1/prediction/update'\n and then request data with\n '/v1/prediction/list?key=load_mean' instead.", - "operationId": "fastapi_gesamtlast_simple_gesamtlast_simple_get", - "parameters": [ - { - "name": "year_energy", - "in": "query", - "required": true, - "schema": { - "type": "number", - "title": "Year Energy" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "number" - }, - "title": "Response Fastapi Gesamtlast Simple Gesamtlast Simple Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/pvforecast": { - "get": { - "tags": [ - "prediction" - ], - "summary": "Fastapi Pvforecast", - "description": "Deprecated: PV Forecast Prediction.\n\nEndpoint to handle PV forecast prediction.\n\nPVForecast starts at 00.00.00 today and is provided for 48 hours.\nIf no forecast values are available the missing ones at the start of the series are\nfilled with the first available forecast value.\n\nNote:\n Set PVForecastAkkudoktor as provider, then update data with\n '/v1/prediction/update'\n and then request data with\n '/v1/prediction/list?key=pvforecast_ac_power' and\n '/v1/prediction/list?key=pvforecastakkudoktor_temp_air' instead.", - "operationId": "fastapi_pvforecast_pvforecast_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForecastResponse" - } - } - } - } - } - } - }, - "/optimize": { - "post": { - "tags": [ - "optimize" - ], - "summary": "Fastapi Optimize", - "operationId": "fastapi_optimize_optimize_post", - "parameters": [ - { - "name": "start_hour", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Defaults to current hour of the day.", - "title": "Start Hour" - }, - "description": "Defaults to current hour of the day." - }, - { - "name": "ngen", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Ngen" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OptimizationParameters" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OptimizeResponse" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/visualization_results.pdf": { - "get": { - "tags": [ - "optimize" - ], - "summary": "Get Pdf", - "operationId": "get_pdf_visualization_results_pdf_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/pdf": { - "schema": { - "type": "string" - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "BaseBatteryParameters": { - "properties": { - "device_id": { - "type": "string", - "title": "Device Id", - "description": "ID of battery", - "examples": [ - "battery1" - ] - }, - "hours": { - "anyOf": [ - { - "type": "integer", - "exclusiveMinimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Hours", - "description": "Number of prediction hours. Defaults to global config prediction hours.", - "examples": [ - null - ] - }, - "capacity_wh": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Capacity Wh", - "description": "An integer representing the capacity of the battery in watt-hours.", - "examples": [ - 8000 - ] - }, - "charging_efficiency": { - "type": "number", - "maximum": 1.0, - "exclusiveMinimum": 0.0, - "title": "Charging Efficiency", - "description": "A float representing the charging efficiency of the battery.", - "default": 0.88 - }, - "discharging_efficiency": { - "type": "number", - "maximum": 1.0, - "exclusiveMinimum": 0.0, - "title": "Discharging Efficiency", - "description": "A float representing the discharge efficiency of the battery.", - "default": 0.88 - }, - "max_charge_power_w": { - "anyOf": [ - { - "type": "number", - "exclusiveMinimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Max Charge Power W", - "description": "Maximum charging power in watts.", - "default": 5000 - }, - "initial_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Initial Soc Percentage", - "description": "An integer representing the state of charge of the battery at the **start** of the current hour (not the current state).", - "default": 0, - "examples": [ - 42 - ] - }, - "min_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Min Soc Percentage", - "description": "An integer representing the minimum state of charge (SOC) of the battery in percentage.", - "default": 0, - "examples": [ - 10 - ] - }, - "max_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Max Soc Percentage", - "description": "An integer representing the maximum state of charge (SOC) of the battery in percentage.", - "default": 100 - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "device_id", - "capacity_wh" - ], - "title": "BaseBatteryParameters", - "description": "Battery Device Simulation Configuration." - }, - "CacheCommonSettings": { - "properties": { - "subpath": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Subpath", - "description": "Sub-path for the EOS cache data directory.", - "default": "cache" - }, - "cleanup_interval": { - "type": "number", - "title": "Cleanup Interval", - "description": "Intervall in seconds for EOS file cache cleanup.", - "default": 300 - } - }, - "type": "object", - "title": "CacheCommonSettings", - "description": "Cache Configuration." - }, - "ConfigEOS": { - "properties": { - "general": { - "$ref": "#/components/schemas/GeneralSettings-Output", - "default": { - "data_output_subpath": "output", - "latitude": 52.52, - "longitude": 13.405, - "timezone": "Europe/Berlin", - "config_folder_path": "/home/user/.config/net.akkudoktoreos.net", - "config_file_path": "/home/user/.config/net.akkudoktoreos.net/EOS.config.json" - } - }, - "cache": { - "$ref": "#/components/schemas/CacheCommonSettings", - "default": { - "subpath": "cache", - "cleanup_interval": 300.0 - } - }, - "ems": { - "$ref": "#/components/schemas/EnergyManagementCommonSettings", - "default": { - "startup_delay": 5.0 - } - }, - "logging": { - "$ref": "#/components/schemas/LoggingCommonSettings-Output", - "default": { - "file_path": "/home/user/.local/share/net.akkudoktoreos.net/output/eos.log" - } - }, - "devices": { - "$ref": "#/components/schemas/DevicesCommonSettings", - "default": {} - }, - "measurement": { - "$ref": "#/components/schemas/MeasurementCommonSettings", - "default": {} - }, - "optimization": { - "$ref": "#/components/schemas/OptimizationCommonSettings", - "default": { - "hours": 48, - "penalty": 10, - "ev_available_charge_rates_percent": [ - 0.0, - 0.375, - 0.5, - 0.625, - 0.75, - 0.875, - 1.0 - ] - } - }, - "prediction": { - "$ref": "#/components/schemas/PredictionCommonSettings", - "default": { - "hours": 48, - "historic_hours": 48 - } - }, - "elecprice": { - "$ref": "#/components/schemas/ElecPriceCommonSettings", - "default": {} - }, - "load": { - "$ref": "#/components/schemas/LoadCommonSettings", - "default": {} - }, - "pvforecast": { - "$ref": "#/components/schemas/PVForecastCommonSettings-Output", - "default": { - "max_planes": 0, - "planes_peakpower": [], - "planes_azimuth": [], - "planes_tilt": [], - "planes_userhorizon": [], - "planes_inverter_paco": [] - } - }, - "weather": { - "$ref": "#/components/schemas/WeatherCommonSettings", - "default": {} - }, - "server": { - "$ref": "#/components/schemas/ServerCommonSettings", - "default": { - "host": "127.0.0.1", - "port": 8503, - "verbose": false, - "startup_eosdash": true, - "eosdash_host": "127.0.0.1", - "eosdash_port": 8504 - } - }, - "utils": { - "$ref": "#/components/schemas/UtilsCommonSettings", - "default": {} - } - }, - "additionalProperties": false, - "type": "object", - "title": "ConfigEOS", - "description": "Singleton configuration handler for the EOS application.\n\nConfigEOS extends `SettingsEOS` with support for default configuration paths and automatic\ninitialization.\n\n`ConfigEOS` ensures that only one instance of the class is created throughout the application,\nallowing consistent access to EOS configuration settings. This singleton instance loads\nconfiguration data from a predefined set of directories or creates a default configuration if\nnone is found.\n\nInitialization Process:\n - Upon instantiation, the singleton instance attempts to load a configuration file in this order:\n 1. The directory specified by the `EOS_CONFIG_DIR` environment variable\n 2. The directory specified by the `EOS_DIR` environment variable.\n 3. A platform specific default directory for EOS.\n 4. The current working directory.\n - The first available configuration file found in these directories is loaded.\n - If no configuration file is found, a default configuration file is created in the platform\n specific default directory, and default settings are loaded into it.\n\nAttributes from the loaded configuration are accessible directly as instance attributes of\n`ConfigEOS`, providing a centralized, shared configuration object for EOS.\n\nSingleton Behavior:\n - This class uses the `SingletonMixin` to ensure that all requests for `ConfigEOS` return\n the same instance, which contains the most up-to-date configuration. Modifying the configuration\n in one part of the application reflects across all references to this class.\n\nAttributes:\n config_folder_path (Optional[Path]): Path to the configuration directory.\n config_file_path (Optional[Path]): Path to the configuration file.\n\nRaises:\n FileNotFoundError: If no configuration file is found, and creating a default configuration fails.\n\nExample:\n To initialize and access configuration attributes (only one instance is created):\n ```python\n config_eos = ConfigEOS() # Always returns the same instance\n print(config_eos.prediction.hours) # Access a setting from the loaded configuration\n ```" - }, - "DevicesCommonSettings": { - "properties": { - "batteries": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/BaseBatteryParameters" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Batteries", - "description": "List of battery/ev devices", - "examples": [ - [ - { - "capacity_wh": 8000, - "device_id": "battery1" - } - ] - ] - }, - "inverters": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/InverterParameters" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Inverters", - "description": "List of inverters", - "examples": [ - [] - ] - }, - "home_appliances": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/HomeApplianceParameters" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Home Appliances", - "description": "List of home appliances", - "examples": [ - [] - ] - } - }, - "type": "object", - "title": "DevicesCommonSettings", - "description": "Base configuration for devices simulation settings." - }, - "ElecPriceCommonSettings": { - "properties": { - "provider": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Provider", - "description": "Electricity price provider id of provider to be used.", - "examples": [ - "ElecPriceAkkudoktor" - ] - }, - "charges_kwh": { - "anyOf": [ - { - "type": "number", - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Charges Kwh", - "description": "Electricity price charges (\u20ac/kWh).", - "examples": [ - 0.21 - ] - }, - "provider_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/ElecPriceImportCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Provider settings", - "examples": [ - null - ] - } - }, - "type": "object", - "title": "ElecPriceCommonSettings", - "description": "Electricity Price Prediction Configuration." - }, - "ElecPriceImportCommonSettings": { - "properties": { - "import_file_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Import File Path", - "description": "Path to the file to import elecprice data from.", - "examples": [ - null, - "/path/to/prices.json" - ] - }, - "import_json": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Import Json", - "description": "JSON string, dictionary of electricity price forecast value lists.", - "examples": [ - "{\"elecprice_marketprice_wh\": [0.0003384, 0.0003318, 0.0003284]}" - ] - } - }, - "type": "object", - "title": "ElecPriceImportCommonSettings", - "description": "Common settings for elecprice data import from file or JSON String." - }, - "ElectricVehicleParameters": { - "properties": { - "device_id": { - "type": "string", - "title": "Device Id", - "description": "ID of electric vehicle", - "examples": [ - "ev1" - ] - }, - "hours": { - "anyOf": [ - { - "type": "integer", - "exclusiveMinimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Hours", - "description": "Number of prediction hours. Defaults to global config prediction hours.", - "examples": [ - null - ] - }, - "capacity_wh": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Capacity Wh", - "description": "An integer representing the capacity of the battery in watt-hours.", - "examples": [ - 8000 - ] - }, - "charging_efficiency": { - "type": "number", - "maximum": 1.0, - "exclusiveMinimum": 0.0, - "title": "Charging Efficiency", - "description": "A float representing the charging efficiency of the battery.", - "default": 0.88 - }, - "discharging_efficiency": { - "type": "number", - "maximum": 1.0, - "exclusiveMinimum": 0.0, - "title": "Discharging Efficiency", - "description": "A float representing the discharge efficiency of the battery.", - "default": 1.0 - }, - "max_charge_power_w": { - "anyOf": [ - { - "type": "number", - "exclusiveMinimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Max Charge Power W", - "description": "Maximum charging power in watts.", - "default": 5000 - }, - "initial_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Initial Soc Percentage", - "description": "An integer representing the current state of charge (SOC) of the battery in percentage.", - "default": 0, - "examples": [ - 42 - ] - }, - "min_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Min Soc Percentage", - "description": "An integer representing the minimum state of charge (SOC) of the battery in percentage.", - "default": 0, - "examples": [ - 10 - ] - }, - "max_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Max Soc Percentage", - "description": "An integer representing the maximum state of charge (SOC) of the battery in percentage.", - "default": 100 - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "device_id", - "capacity_wh" - ], - "title": "ElectricVehicleParameters", - "description": "Battery Electric Vehicle Device Simulation Configuration." - }, - "ElectricVehicleResult": { - "properties": { - "device_id": { - "type": "string", - "title": "Device Id", - "description": "ID of electric vehicle", - "examples": [ - "ev1" - ] - }, - "hours": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Hours", - "description": "Number of hours in the simulation.", - "examples": [ - 24 - ] - }, - "charge_array": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Charge Array", - "description": "Hourly charging status (0 for no charging, 1 for charging)." - }, - "discharge_array": { - "items": { - "type": "integer" - }, - "type": "array", - "title": "Discharge Array", - "description": "Hourly discharging status (0 for no discharging, 1 for discharging)." - }, - "discharging_efficiency": { - "type": "number", - "title": "Discharging Efficiency", - "description": "The discharge efficiency as a float.." - }, - "capacity_wh": { - "type": "integer", - "title": "Capacity Wh", - "description": "Capacity of the EV\u2019s battery in watt-hours." - }, - "charging_efficiency": { - "type": "number", - "title": "Charging Efficiency", - "description": "Charging efficiency as a float.." - }, - "max_charge_power_w": { - "type": "integer", - "title": "Max Charge Power W", - "description": "Maximum charging power in watts." - }, - "soc_wh": { - "type": "number", - "title": "Soc Wh", - "description": "State of charge of the battery in watt-hours at the start of the simulation." - }, - "initial_soc_percentage": { - "type": "integer", - "title": "Initial Soc Percentage", - "description": "State of charge at the start of the simulation in percentage." - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "device_id", - "hours", - "charge_array", - "discharge_array", - "discharging_efficiency", - "capacity_wh", - "charging_efficiency", - "max_charge_power_w", - "soc_wh", - "initial_soc_percentage" - ], - "title": "ElectricVehicleResult", - "description": "Result class containing information related to the electric vehicle's charging and discharging behavior." - }, - "EnergyManagementCommonSettings": { - "properties": { - "startup_delay": { - "type": "number", - "minimum": 1.0, - "title": "Startup Delay", - "description": "Startup delay in seconds for EOS energy management runs.", - "default": 5 - }, - "interval": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Interval", - "description": "Intervall in seconds between EOS energy management runs.", - "examples": [ - "300" - ] - } - }, - "type": "object", - "title": "EnergyManagementCommonSettings", - "description": "Energy Management Configuration." - }, - "EnergyManagementParameters": { - "properties": { - "pv_prognose_wh": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Pv Prognose Wh", - "description": "An array of floats representing the forecasted photovoltaic output in watts for different time intervals." - }, - "strompreis_euro_pro_wh": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Strompreis Euro Pro Wh", - "description": "An array of floats representing the electricity price in euros per watt-hour for different time intervals." - }, - "einspeiseverguetung_euro_pro_wh": { - "anyOf": [ - { - "items": { - "type": "number" - }, - "type": "array" - }, - { - "type": "number" - } - ], - "title": "Einspeiseverguetung Euro Pro Wh", - "description": "A float or array of floats representing the feed-in compensation in euros per watt-hour." - }, - "preis_euro_pro_wh_akku": { - "type": "number", - "title": "Preis Euro Pro Wh Akku", - "description": "A float representing the cost of battery energy per watt-hour." - }, - "gesamtlast": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Gesamtlast", - "description": "An array of floats representing the total load (consumption) in watts for different time intervals." - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "pv_prognose_wh", - "strompreis_euro_pro_wh", - "einspeiseverguetung_euro_pro_wh", - "preis_euro_pro_wh_akku", - "gesamtlast" - ], - "title": "EnergyManagementParameters" - }, - "ForecastResponse": { - "properties": { - "temperature": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Temperature" - }, - "pvpower": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Pvpower" - } - }, - "type": "object", - "required": [ - "temperature", - "pvpower" - ], - "title": "ForecastResponse" - }, - "GeneralSettings-Input": { - "properties": { - "data_folder_path": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Data Folder Path", - "description": "Path to EOS data directory.", - "examples": [ - null, - "/home/eos/data" - ] - }, - "data_output_subpath": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Data Output Subpath", - "description": "Sub-path for the EOS output data directory.", - "default": "output" - }, - "latitude": { - "anyOf": [ - { - "type": "number", - "maximum": 90.0, - "minimum": -90.0 - }, - { - "type": "null" - } - ], - "title": "Latitude", - "description": "Latitude in decimal degrees, between -90 and 90, north is positive (ISO 19115) (\u00b0)", - "default": 52.52 - }, - "longitude": { - "anyOf": [ - { - "type": "number", - "maximum": 180.0, - "minimum": -180.0 - }, - { - "type": "null" - } - ], - "title": "Longitude", - "description": "Longitude in decimal degrees, within -180 to 180 (\u00b0)", - "default": 13.405 - } - }, - "type": "object", - "title": "GeneralSettings", - "description": "Settings for common configuration.\n\nGeneral configuration to set directories of cache and output files and system location (latitude\nand longitude).\nValidators ensure each parameter is within a specified range. A computed property, `timezone`,\ndetermines the time zone based on latitude and longitude.\n\nAttributes:\n latitude (Optional[float]): Latitude in degrees, must be between -90 and 90.\n longitude (Optional[float]): Longitude in degrees, must be between -180 and 180.\n\nProperties:\n timezone (Optional[str]): Computed time zone string based on the specified latitude\n and longitude." - }, - "GeneralSettings-Output": { - "properties": { - "data_folder_path": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Data Folder Path", - "description": "Path to EOS data directory.", - "examples": [ - null, - "/home/eos/data" - ] - }, - "data_output_subpath": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Data Output Subpath", - "description": "Sub-path for the EOS output data directory.", - "default": "output" - }, - "latitude": { - "anyOf": [ - { - "type": "number", - "maximum": 90.0, - "minimum": -90.0 - }, - { - "type": "null" - } - ], - "title": "Latitude", - "description": "Latitude in decimal degrees, between -90 and 90, north is positive (ISO 19115) (\u00b0)", - "default": 52.52 - }, - "longitude": { - "anyOf": [ - { - "type": "number", - "maximum": 180.0, - "minimum": -180.0 - }, - { - "type": "null" - } - ], - "title": "Longitude", - "description": "Longitude in decimal degrees, within -180 to 180 (\u00b0)", - "default": 13.405 - }, - "timezone": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Timezone", - "description": "Compute timezone based on latitude and longitude.", - "readOnly": true - }, - "data_output_path": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Data Output Path", - "description": "Compute data_output_path based on data_folder_path.", - "readOnly": true - }, - "config_folder_path": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Config Folder Path", - "description": "Path to EOS configuration directory.", - "readOnly": true - }, - "config_file_path": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Config File Path", - "description": "Path to EOS configuration file.", - "readOnly": true - } - }, - "type": "object", - "required": [ - "timezone", - "data_output_path", - "config_folder_path", - "config_file_path" - ], - "title": "GeneralSettings", - "description": "Settings for common configuration.\n\nGeneral configuration to set directories of cache and output files and system location (latitude\nand longitude).\nValidators ensure each parameter is within a specified range. A computed property, `timezone`,\ndetermines the time zone based on latitude and longitude.\n\nAttributes:\n latitude (Optional[float]): Latitude in degrees, must be between -90 and 90.\n longitude (Optional[float]): Longitude in degrees, must be between -180 and 180.\n\nProperties:\n timezone (Optional[str]): Computed time zone string based on the specified latitude\n and longitude." - }, - "GesamtlastRequest": { - "properties": { - "year_energy": { - "type": "number", - "title": "Year Energy" - }, - "measured_data": { - "items": { - "additionalProperties": true, - "type": "object" - }, - "type": "array", - "title": "Measured Data" - }, - "hours": { - "type": "integer", - "title": "Hours" - } - }, - "type": "object", - "required": [ - "year_energy", - "measured_data", - "hours" - ], - "title": "GesamtlastRequest" - }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - "type": "array", - "title": "Detail" - } - }, - "type": "object", - "title": "HTTPValidationError" - }, - "HomeApplianceParameters": { - "properties": { - "device_id": { - "type": "string", - "title": "Device Id", - "description": "ID of home appliance", - "examples": [ - "dishwasher" - ] - }, - "hours": { - "anyOf": [ - { - "type": "integer", - "exclusiveMinimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Hours", - "description": "Number of prediction hours. Defaults to global config prediction hours.", - "examples": [ - null - ] - }, - "consumption_wh": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Consumption Wh", - "description": "An integer representing the energy consumption of a household device in watt-hours.", - "examples": [ - 2000 - ] - }, - "duration_h": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Duration H", - "description": "An integer representing the usage duration of a household device in hours.", - "examples": [ - 3 - ] - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "device_id", - "consumption_wh", - "duration_h" - ], - "title": "HomeApplianceParameters", - "description": "Home Appliance Device Simulation Configuration." - }, - "InverterParameters": { - "properties": { - "device_id": { - "type": "string", - "title": "Device Id", - "description": "ID of inverter", - "examples": [ - "inverter1" - ] - }, - "hours": { - "anyOf": [ - { - "type": "integer", - "exclusiveMinimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Hours", - "description": "Number of prediction hours. Defaults to global config prediction hours.", - "examples": [ - null - ] - }, - "max_power_wh": { - "type": "number", - "exclusiveMinimum": 0.0, - "title": "Max Power Wh", - "examples": [ - 10000 - ] - }, - "battery_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Battery Id", - "description": "ID of battery", - "examples": [ - null, - "battery1" - ] - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "device_id", - "max_power_wh" - ], - "title": "InverterParameters", - "description": "Inverter Device Simulation Configuration." - }, - "LoadAkkudoktorCommonSettings": { - "properties": { - "loadakkudoktor_year_energy": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Loadakkudoktor Year Energy", - "description": "Yearly energy consumption (kWh).", - "examples": [ - 40421 - ] - } - }, - "type": "object", - "title": "LoadAkkudoktorCommonSettings", - "description": "Common settings for load data import from file." - }, - "LoadCommonSettings": { - "properties": { - "provider": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Provider", - "description": "Load provider id of provider to be used.", - "examples": [ - "LoadAkkudoktor" - ] - }, - "provider_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/LoadAkkudoktorCommonSettings" - }, - { - "$ref": "#/components/schemas/LoadImportCommonSettings" - }, - { - "type": "null" - } - ], - "title": "Provider Settings", - "description": "Provider settings", - "examples": [ - null - ] - } - }, - "type": "object", - "title": "LoadCommonSettings", - "description": "Load Prediction Configuration." - }, - "LoadImportCommonSettings": { - "properties": { - "import_file_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Import File Path", - "description": "Path to the file to import load data from.", - "examples": [ - null, - "/path/to/yearly_load.json" - ] - }, - "import_json": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Import Json", - "description": "JSON string, dictionary of load forecast value lists.", - "examples": [ - "{\"load0_mean\": [676.71, 876.19, 527.13]}" - ] - } - }, - "type": "object", - "title": "LoadImportCommonSettings", - "description": "Common settings for load data import from file or JSON string." - }, - "LoggingCommonSettings-Input": { - "properties": { - "level": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Level", - "deprecated": true - }, - "console_level": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Console Level", - "description": "Logging level when logging to console.", - "examples": [ - "TRACE", - "DEBUG", - "INFO", - "WARNING", - "ERROR", - "CRITICAL" - ] - }, - "file_level": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "File Level", - "description": "Logging level when logging to file.", - "examples": [ - "TRACE", - "DEBUG", - "INFO", - "WARNING", - "ERROR", - "CRITICAL" - ] - } - }, - "type": "object", - "title": "LoggingCommonSettings", - "description": "Logging Configuration." - }, - "LoggingCommonSettings-Output": { - "properties": { - "level": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Level", - "deprecated": true - }, - "console_level": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Console Level", - "description": "Logging level when logging to console.", - "examples": [ - "TRACE", - "DEBUG", - "INFO", - "WARNING", - "ERROR", - "CRITICAL" - ] - }, - "file_level": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "File Level", - "description": "Logging level when logging to file.", - "examples": [ - "TRACE", - "DEBUG", - "INFO", - "WARNING", - "ERROR", - "CRITICAL" - ] - }, - "file_path": { - "anyOf": [ - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "File Path", - "description": "Computed log file path based on data output path.", - "readOnly": true - } - }, - "type": "object", - "required": [ - "file_path" - ], - "title": "LoggingCommonSettings", - "description": "Logging Configuration." - }, - "MeasurementCommonSettings": { - "properties": { - "load0_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Load0 Name", - "description": "Name of the load0 source", - "examples": [ - "Household", - "Heat Pump" - ] - }, - "load1_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Load1 Name", - "description": "Name of the load1 source", - "examples": [ - null - ] - }, - "load2_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Load2 Name", - "description": "Name of the load2 source", - "examples": [ - null - ] - }, - "load3_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Load3 Name", - "description": "Name of the load3 source", - "examples": [ - null - ] - }, - "load4_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Load4 Name", - "description": "Name of the load4 source", - "examples": [ - null - ] - } - }, - "type": "object", - "title": "MeasurementCommonSettings", - "description": "Measurement Configuration." - }, - "OptimizationCommonSettings": { - "properties": { - "hours": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Hours", - "description": "Number of hours into the future for optimizations.", - "default": 48 - }, - "penalty": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Penalty", - "description": "Penalty factor used in optimization.", - "default": 10 - }, - "ev_available_charge_rates_percent": { - "anyOf": [ - { - "items": { - "type": "number" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Ev Available Charge Rates Percent", - "description": "Charge rates available for the EV in percent of maximum charge.", - "default": [ - 0.0, - 0.375, - 0.5, - 0.625, - 0.75, - 0.875, - 1.0 - ] - } - }, - "type": "object", - "title": "OptimizationCommonSettings", - "description": "General Optimization Configuration.\n\nAttributes:\n hours (int): Number of hours for optimizations." - }, - "OptimizationParameters": { - "properties": { - "ems": { - "$ref": "#/components/schemas/EnergyManagementParameters" - }, - "pv_akku": { - "anyOf": [ - { - "$ref": "#/components/schemas/SolarPanelBatteryParameters" - }, - { - "type": "null" - } - ] - }, - "inverter": { - "anyOf": [ - { - "$ref": "#/components/schemas/InverterParameters" - }, - { - "type": "null" - } - ] - }, - "eauto": { - "anyOf": [ - { - "$ref": "#/components/schemas/ElectricVehicleParameters" - }, - { - "type": "null" - } - ] - }, - "dishwasher": { - "anyOf": [ - { - "$ref": "#/components/schemas/HomeApplianceParameters" - }, - { - "type": "null" - } - ] - }, - "temperature_forecast": { - "anyOf": [ - { - "items": { - "anyOf": [ + "summary": "Fastapi Admin Cache Clear Post", + "description": "Clear the cache from expired data.\n\nDeletes expired cache files.\n\nArgs:\n clear_all (Optional[bool]): Delete all cached files. Default is False.\n\nReturns:\n data (dict): The management data after cleanup.", + "operationId": "fastapi_admin_cache_clear_post_v1_admin_cache_clear_post", + "parameters": [ { - "type": "number" + "name": "clear_all", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Clear All" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true, + "title": "Response Fastapi Admin Cache Clear Post V1 Admin Cache Clear Post" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/admin/cache/save": { + "post": { + "tags": [ + "admin" + ], + "summary": "Fastapi Admin Cache Save Post", + "description": "Save the current cache management data.\n\nReturns:\n data (dict): The management data that was saved.", + "operationId": "fastapi_admin_cache_save_post_v1_admin_cache_save_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Fastapi Admin Cache Save Post V1 Admin Cache Save Post" + } + } + } + } + } + } + }, + "/v1/admin/cache/load": { + "post": { + "tags": [ + "admin" + ], + "summary": "Fastapi Admin Cache Load Post", + "description": "Load cache management data.\n\nReturns:\n data (dict): The management data that was loaded.", + "operationId": "fastapi_admin_cache_load_post_v1_admin_cache_load_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Fastapi Admin Cache Load Post V1 Admin Cache Load Post" + } + } + } + } + } + } + }, + "/v1/admin/cache": { + "get": { + "tags": [ + "admin" + ], + "summary": "Fastapi Admin Cache Get", + "description": "Current cache management data.\n\nReturns:\n data (dict): The management data.", + "operationId": "fastapi_admin_cache_get_v1_admin_cache_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Fastapi Admin Cache Get V1 Admin Cache Get" + } + } + } + } + } + } + }, + "/v1/admin/server/restart": { + "post": { + "tags": [ + "admin" + ], + "summary": "Fastapi Admin Server Restart Post", + "description": "Restart the server.\n\nRestart EOS properly by starting a new instance before exiting the old one.", + "operationId": "fastapi_admin_server_restart_post_v1_admin_server_restart_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Fastapi Admin Server Restart Post V1 Admin Server Restart Post" + } + } + } + } + } + } + }, + "/v1/admin/server/shutdown": { + "post": { + "tags": [ + "admin" + ], + "summary": "Fastapi Admin Server Shutdown Post", + "description": "Shutdown the server.", + "operationId": "fastapi_admin_server_shutdown_post_v1_admin_server_shutdown_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Fastapi Admin Server Shutdown Post V1 Admin Server Shutdown Post" + } + } + } + } + } + } + }, + "/v1/health": { + "get": { + "summary": "Fastapi Health Get", + "description": "Health check endpoint to verify that the EOS server is alive.", + "operationId": "fastapi_health_get_v1_health_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/v1/config/reset": { + "post": { + "tags": [ + "config" + ], + "summary": "Fastapi Config Reset Post", + "description": "Reset the configuration to the EOS configuration file.\n\nReturns:\n configuration (ConfigEOS): The current configuration after update.", + "operationId": "fastapi_config_reset_post_v1_config_reset_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigEOS" + } + } + } + } + } + } + }, + "/v1/config/file": { + "put": { + "tags": [ + "config" + ], + "summary": "Fastapi Config File Put", + "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", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigEOS" + } + } + } + } + } + } + }, + "/v1/config": { + "get": { + "tags": [ + "config" + ], + "summary": "Fastapi Config Get", + "description": "Get the current configuration.\n\nReturns:\n configuration (ConfigEOS): The current configuration.", + "operationId": "fastapi_config_get_v1_config_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigEOS" + } + } + } + } + } + }, + "put": { + "tags": [ + "config" + ], + "summary": "Fastapi Config Put", + "description": "Update the current config with the provided settings.\n\nNote that for any setting value that is None or unset, the configuration will fall back to\nvalues from other sources such as environment variables, the EOS configuration file, or default\nvalues.\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", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsEOS" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigEOS" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/config/{path}": { + "put": { + "tags": [ + "config" + ], + "summary": "Fastapi Config Put Key", + "description": "Update a nested key or index in the config model.\n\nArgs:\n path (str): The nested path to the key (e.g., \"general/latitude\" or \"optimize/nested_list/0\").\n value (Any): The new value to assign to the key or index at path.\n\nReturns:\n configuration (ConfigEOS): The current configuration after the update.", + "operationId": "fastapi_config_put_key_v1_config__path__put", + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "schema": { + "type": "string", + "description": "The nested path to the configuration key (e.g., general/latitude).", + "title": "Path" + }, + "description": "The nested path to the configuration key (e.g., general/latitude)." + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "description": "The value to assign to the specified configuration path (can be None).", + "title": "Value" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigEOS" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "config" + ], + "summary": "Fastapi Config Get Key", + "description": "Get the value of a nested key or index in the config model.\n\nArgs:\n path (str): The nested path to the key (e.g., \"general/latitude\" or \"optimize/nested_list/0\").\n\nReturns:\n value (Any): The value of the selected nested key.", + "operationId": "fastapi_config_get_key_v1_config__path__get", + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "schema": { + "type": "string", + "description": "The nested path to the configuration key (e.g., general/latitude).", + "title": "Path" + }, + "description": "The nested path to the configuration key (e.g., general/latitude)." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/logging/log": { + "get": { + "tags": [ + "logging" + ], + "summary": "Fastapi Logging Get Log", + "description": "Get structured log entries from the EOS log file.\n\nFilters and returns log entries based on the specified query parameters. The log\nfile is expected to contain newline-delimited JSON entries.\n\nArgs:\n limit (int): Maximum number of entries to return.\n level (Optional[str]): Filter logs by severity level (e.g., DEBUG, INFO).\n contains (Optional[str]): Return only logs that include this string in the message.\n regex (Optional[str]): Return logs that match this regular expression in the message.\n from_time (Optional[str]): ISO 8601 timestamp to filter logs not older than this.\n to_time (Optional[str]): ISO 8601 timestamp to filter logs not newer than this.\n tail (bool): If True, fetch the most recent log entries (like `tail`).\n\nReturns:\n JSONResponse: A JSON list of log entries.", + "operationId": "fastapi_logging_get_log_v1_logging_log_get", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "description": "Maximum number of log entries to return.", + "default": 100, + "title": "Limit" + }, + "description": "Maximum number of log entries to return." }, { - "type": "null" + "name": "level", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by log level (e.g., INFO, ERROR).", + "title": "Level" + }, + "description": "Filter by log level (e.g., INFO, ERROR)." + }, + { + "name": "contains", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter logs containing this substring.", + "title": "Contains" + }, + "description": "Filter logs containing this substring." + }, + { + "name": "regex", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter logs by matching regex in message.", + "title": "Regex" + }, + "description": "Filter logs by matching regex in message." + }, + { + "name": "from_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Start time (ISO format) for filtering logs.", + "title": "From Time" + }, + "description": "Start time (ISO format) for filtering logs." + }, + { + "name": "to_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End time (ISO format) for filtering logs.", + "title": "To Time" + }, + "description": "End time (ISO format) for filtering logs." + }, + { + "name": "tail", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "If True, returns the most recent lines (tail mode).", + "default": false, + "title": "Tail" + }, + "description": "If True, returns the most recent lines (tail mode)." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Temperature Forecast", - "description": "An array of floats representing the temperature forecast in degrees Celsius for different time intervals." - }, - "start_solution": { - "anyOf": [ - { - "items": { - "type": "number" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Start Solution", - "description": "Can be `null` or contain a previous solution (if available)." - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "ems", - "pv_akku", - "inverter", - "eauto" - ], - "title": "OptimizationParameters" - }, - "OptimizeResponse": { - "properties": { - "ac_charge": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Ac Charge", - "description": "Array with AC charging values as relative power (0-1), other values set to 0." - }, - "dc_charge": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Dc Charge", - "description": "Array with DC charging values as relative power (0-1), other values set to 0." - }, - "discharge_allowed": { - "items": { - "type": "integer" - }, - "type": "array", - "title": "Discharge Allowed", - "description": "Array with discharge values (1 for discharge, 0 otherwise)." - }, - "eautocharge_hours_float": { - "anyOf": [ - { - "items": { - "type": "number" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Eautocharge Hours Float", - "description": "TBD" - }, - "result": { - "$ref": "#/components/schemas/SimulationResult" - }, - "eauto_obj": { - "anyOf": [ - { - "$ref": "#/components/schemas/ElectricVehicleResult" - }, - { - "type": "null" - } - ] - }, - "start_solution": { - "anyOf": [ - { - "items": { - "type": "number" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Start Solution", - "description": "An array of binary values (0 or 1) representing a possible starting solution for the simulation." - }, - "washingstart": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Washingstart", - "description": "Can be `null` or contain an object representing the start of washing (if applicable)." - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "ac_charge", - "dc_charge", - "discharge_allowed", - "eautocharge_hours_float", - "result", - "eauto_obj" - ], - "title": "OptimizeResponse", - "description": "**Note**: The first value of \"Last_Wh_per_hour\", \"Netzeinspeisung_Wh_per_hour\", and \"Netzbezug_Wh_per_hour\", will be set to null in the JSON output and represented as NaN or None in the corresponding classes' data returns. This approach is adopted to ensure that the current hour's processing remains unchanged." - }, - "PVForecastCommonSettings-Input": { - "properties": { - "provider": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Provider", - "description": "PVForecast provider id of provider to be used.", - "examples": [ - "PVForecastAkkudoktor" - ] - }, - "provider_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/PVForecastImportCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Provider settings", - "examples": [ - null - ] - }, - "planes": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/PVForecastPlaneSetting" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Planes", - "description": "Plane configuration.", - "examples": [ - [ - { - "inverter_paco": 6000, - "loss": 14.0, - "modules_per_string": 20, - "mountingplace": "free", - "optimal_surface_tilt": false, - "optimalangles": false, - "peakpower": 5.0, - "pvtechchoice": "crystSi", - "strings_per_inverter": 2, - "surface_azimuth": 180.0, - "surface_tilt": 10.0, - "trackingtype": 0, - "userhorizon": [ - 10.0, - 20.0, - 30.0 - ] - }, - { - "inverter_paco": 4000, - "loss": 14.0, - "modules_per_string": 20, - "mountingplace": "free", - "optimal_surface_tilt": false, - "optimalangles": false, - "peakpower": 3.5, - "pvtechchoice": "crystSi", - "strings_per_inverter": 2, - "surface_azimuth": 90.0, - "surface_tilt": 20.0, - "trackingtype": 1, - "userhorizon": [ - 5.0, - 15.0, - 25.0 - ] } - ] - ] - }, - "max_planes": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Max Planes", - "description": "Maximum number of planes that can be set", - "default": 0 - } - }, - "type": "object", - "title": "PVForecastCommonSettings", - "description": "PV Forecast Configuration." - }, - "PVForecastCommonSettings-Output": { - "properties": { - "provider": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Provider", - "description": "PVForecast provider id of provider to be used.", - "examples": [ - "PVForecastAkkudoktor" - ] - }, - "provider_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/PVForecastImportCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Provider settings", - "examples": [ - null - ] - }, - "planes": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/PVForecastPlaneSetting" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Planes", - "description": "Plane configuration.", - "examples": [ - [ - { - "inverter_paco": 6000, - "loss": 14.0, - "modules_per_string": 20, - "mountingplace": "free", - "optimal_surface_tilt": false, - "optimalangles": false, - "peakpower": 5.0, - "pvtechchoice": "crystSi", - "strings_per_inverter": 2, - "surface_azimuth": 180.0, - "surface_tilt": 10.0, - "trackingtype": 0, - "userhorizon": [ - 10.0, - 20.0, - 30.0 - ] - }, - { - "inverter_paco": 4000, - "loss": 14.0, - "modules_per_string": 20, - "mountingplace": "free", - "optimal_surface_tilt": false, - "optimalangles": false, - "peakpower": 3.5, - "pvtechchoice": "crystSi", - "strings_per_inverter": 2, - "surface_azimuth": 90.0, - "surface_tilt": 20.0, - "trackingtype": 1, - "userhorizon": [ - 5.0, - 15.0, - 25.0 - ] - } - ] - ] - }, - "max_planes": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Max Planes", - "description": "Maximum number of planes that can be set", - "default": 0 - }, - "planes_peakpower": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Planes Peakpower", - "description": "Compute a list of the peak power per active planes.", - "readOnly": true - }, - "planes_azimuth": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Planes Azimuth", - "description": "Compute a list of the azimuths per active planes.", - "readOnly": true - }, - "planes_tilt": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Planes Tilt", - "description": "Compute a list of the tilts per active planes.", - "readOnly": true - }, - "planes_userhorizon": { - "title": "Planes Userhorizon", - "description": "Compute a list of the user horizon per active planes.", - "readOnly": true - }, - "planes_inverter_paco": { - "title": "Planes Inverter Paco", - "description": "Compute a list of the maximum power rating of the inverter per active planes.", - "readOnly": true - } - }, - "type": "object", - "required": [ - "planes_peakpower", - "planes_azimuth", - "planes_tilt", - "planes_userhorizon", - "planes_inverter_paco" - ], - "title": "PVForecastCommonSettings", - "description": "PV Forecast Configuration." - }, - "PVForecastImportCommonSettings": { - "properties": { - "import_file_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Import File Path", - "description": "Path to the file to import PV forecast data from.", - "examples": [ - null, - "/path/to/pvforecast.json" - ] - }, - "import_json": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Import Json", - "description": "JSON string, dictionary of PV forecast value lists.", - "examples": [ - "{\"pvforecast_ac_power\": [0, 8.05, 352.91]}" - ] - } - }, - "type": "object", - "title": "PVForecastImportCommonSettings", - "description": "Common settings for pvforecast data import from file or JSON string." - }, - "PVForecastPlaneSetting": { - "properties": { - "surface_tilt": { - "anyOf": [ - { - "type": "number", - "maximum": 90.0, - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Surface Tilt", - "description": "Tilt angle from horizontal plane. Ignored for two-axis tracking.", - "default": 30.0, - "examples": [ - 10.0, - 20.0 - ] - }, - "surface_azimuth": { - "anyOf": [ - { - "type": "number", - "maximum": 360.0, - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Surface Azimuth", - "description": "Orientation (azimuth angle) of the (fixed) plane. Clockwise from north (north=0, east=90, south=180, west=270).", - "default": 180.0, - "examples": [ - 180.0, - 90.0 - ] - }, - "userhorizon": { - "anyOf": [ - { - "items": { - "type": "number" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Userhorizon", - "description": "Elevation of horizon in degrees, at equally spaced azimuth clockwise from north.", - "examples": [ - [ - 10.0, - 20.0, - 30.0 - ], - [ - 5.0, - 15.0, - 25.0 - ] - ] - }, - "peakpower": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Peakpower", - "description": "Nominal power of PV system in kW.", - "examples": [ - 5.0, - 3.5 - ] - }, - "pvtechchoice": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Pvtechchoice", - "description": "PV technology. One of 'crystSi', 'CIS', 'CdTe', 'Unknown'.", - "default": "crystSi" - }, - "mountingplace": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Mountingplace", - "description": "Type of mounting for PV system. Options are 'free' for free-standing and 'building' for building-integrated.", - "default": "free" - }, - "loss": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Loss", - "description": "Sum of PV system losses in percent", - "default": 14.0 - }, - "trackingtype": { - "anyOf": [ - { - "type": "integer", - "maximum": 5.0, - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Trackingtype", - "description": "Type of suntracking. 0=fixed, 1=single horizontal axis aligned north-south, 2=two-axis tracking, 3=vertical axis tracking, 4=single horizontal axis aligned east-west, 5=single inclined axis aligned north-south.", - "examples": [ - 0, - 1, - 2, - 3, - 4, - 5 - ] - }, - "optimal_surface_tilt": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Optimal Surface Tilt", - "description": "Calculate the optimum tilt angle. Ignored for two-axis tracking.", - "default": false, - "examples": [ - false - ] - }, - "optimalangles": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Optimalangles", - "description": "Calculate the optimum tilt and azimuth angles. Ignored for two-axis tracking.", - "default": false, - "examples": [ - false - ] - }, - "albedo": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Albedo", - "description": "Proportion of the light hitting the ground that it reflects back.", - "examples": [ - null - ] - }, - "module_model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Module Model", - "description": "Model of the PV modules of this plane.", - "examples": [ - null - ] - }, - "inverter_model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Inverter Model", - "description": "Model of the inverter of this plane.", - "examples": [ - null - ] - }, - "inverter_paco": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Inverter Paco", - "description": "AC power rating of the inverter [W].", - "examples": [ - 6000, - 4000 - ] - }, - "modules_per_string": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Modules Per String", - "description": "Number of the PV modules of the strings of this plane.", - "examples": [ - 20 - ] - }, - "strings_per_inverter": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Strings Per Inverter", - "description": "Number of the strings of the inverter of this plane.", - "examples": [ - 2 - ] - } - }, - "type": "object", - "title": "PVForecastPlaneSetting", - "description": "PV Forecast Plane Configuration." - }, - "PredictionCommonSettings": { - "properties": { - "hours": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Hours", - "description": "Number of hours into the future for predictions", - "default": 48 - }, - "historic_hours": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Historic Hours", - "description": "Number of hours into the past for historical predictions data", - "default": 48 - } - }, - "type": "object", - "title": "PredictionCommonSettings", - "description": "General Prediction Configuration.\n\nThis class provides configuration for prediction settings, allowing users to specify\nparameters such as the forecast duration (in hours).\nValidators ensure each parameter is within a specified range.\n\nAttributes:\n hours (Optional[int]): Number of hours into the future for predictions.\n Must be non-negative.\n historic_hours (Optional[int]): Number of hours into the past for historical data.\n Must be non-negative.\n\nValidators:\n validate_hours (int): Ensures `hours` is a non-negative integer.\n validate_historic_hours (int): Ensures `historic_hours` is a non-negative integer." - }, - "PydanticDateTimeData": { - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "integer" - }, - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "type": "array" } - ] }, - "type": "object", - "title": "PydanticDateTimeData", - "description": "Pydantic model for time series data with consistent value lengths.\n\nThis model validates a dictionary where:\n- Keys are strings representing data series names\n- Values are lists of numeric or string values\n- Special keys 'start_datetime' and 'interval' can contain string values\nfor time series indexing\n- All value lists must have the same length\n\nExample:\n {\n \"start_datetime\": \"2024-01-01 00:00:00\", # optional\n \"interval\": \"1 Hour\", # optional\n \"load_mean\": [20.5, 21.0, 22.1],\n \"load_min\": [18.5, 19.0, 20.1]\n }" - }, - "PydanticDateTimeDataFrame": { - "properties": { - "data": { - "additionalProperties": { - "additionalProperties": true, - "type": "object" - }, - "type": "object", - "title": "Data" - }, - "dtypes": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Dtypes" - }, - "tz": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Tz", - "description": "Timezone for datetime values" - }, - "datetime_columns": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Datetime Columns", - "description": "Columns to be treated as datetime" - } + "/v1/measurement/keys": { + "get": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Keys Get", + "description": "Get a list of available measurement keys.", + "operationId": "fastapi_measurement_keys_get_v1_measurement_keys_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Response Fastapi Measurement Keys Get V1 Measurement Keys Get" + } + } + } + } + } + } }, - "type": "object", - "required": [ - "data" - ], - "title": "PydanticDateTimeDataFrame", - "description": "Pydantic model for validating pandas DataFrame data with datetime index." - }, - "PydanticDateTimeSeries": { - "properties": { - "data": { - "additionalProperties": true, - "type": "object", - "title": "Data" - }, - "dtype": { - "type": "string", - "title": "Dtype", - "default": "float64" - }, - "tz": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Tz" - } + "/v1/measurement/load-mr/series/by-name": { + "get": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Load Mr Series By Name Get", + "description": "Get the meter reading of given load name as series.", + "operationId": "fastapi_measurement_load_mr_series_by_name_get_v1_measurement_load_mr_series_by_name_get", + "parameters": [ + { + "name": "name", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Load name.", + "title": "Name" + }, + "description": "Load name." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "put": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Load Mr Series By Name Put", + "description": "Merge the meter readings series of given load name into EOS measurements at given datetime.", + "operationId": "fastapi_measurement_load_mr_series_by_name_put_v1_measurement_load_mr_series_by_name_put", + "parameters": [ + { + "name": "name", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Load name.", + "title": "Name" + }, + "description": "Load name." + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } }, - "type": "object", - "required": [ - "data" - ], - "title": "PydanticDateTimeSeries", - "description": "Pydantic model for validating pandas Series with datetime index in JSON format.\n\nThis model handles Series data serialized with orient='index', where the keys are\ndatetime strings and values are the series values. Provides validation and\nconversion between JSON and pandas Series with datetime index.\n\nAttributes:\n data (Dict[str, Any]): Dictionary mapping datetime strings to values.\n dtype (str): The data type of the series values.\n tz (str | None): Timezone name if the datetime index is timezone-aware." - }, - "ServerCommonSettings": { - "properties": { - "host": { - "anyOf": [ - { - "type": "string", - "format": "ipvanyaddress" - }, - { - "type": "null" - } - ], - "title": "Host", - "description": "EOS server IP address.", - "default": "127.0.0.1" - }, - "port": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Port", - "description": "EOS server IP port number.", - "default": 8503 - }, - "verbose": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Verbose", - "description": "Enable debug output", - "default": false - }, - "startup_eosdash": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Startup Eosdash", - "description": "EOS server to start EOSdash server.", - "default": true - }, - "eosdash_host": { - "anyOf": [ - { - "type": "string", - "format": "ipvanyaddress" - }, - { - "type": "null" - } - ], - "title": "Eosdash Host", - "description": "EOSdash server IP address.", - "default": "127.0.0.1" - }, - "eosdash_port": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Eosdash Port", - "description": "EOSdash server IP port number.", - "default": 8504 - } + "/v1/measurement/load-mr/value/by-name": { + "put": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Load Mr Value By Name Put", + "description": "Merge the meter reading of given load name and value into EOS measurements at given datetime.", + "operationId": "fastapi_measurement_load_mr_value_by_name_put_v1_measurement_load_mr_value_by_name_put", + "parameters": [ + { + "name": "datetime", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Datetime.", + "title": "Datetime" + }, + "description": "Datetime." + }, + { + "name": "name", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Load name.", + "title": "Name" + }, + "description": "Load name." + }, + { + "name": "value", + "in": "query", + "required": true, + "schema": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "title": "Value" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } }, - "type": "object", - "title": "ServerCommonSettings", - "description": "Server Configuration." - }, - "SettingsEOS": { - "properties": { - "general": { - "anyOf": [ - { - "$ref": "#/components/schemas/GeneralSettings-Input" - }, - { - "type": "null" - } - ], - "description": "General Settings" - }, - "cache": { - "anyOf": [ - { - "$ref": "#/components/schemas/CacheCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Cache Settings" - }, - "ems": { - "anyOf": [ - { - "$ref": "#/components/schemas/EnergyManagementCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Energy Management Settings" - }, - "logging": { - "anyOf": [ - { - "$ref": "#/components/schemas/LoggingCommonSettings-Input" - }, - { - "type": "null" - } - ], - "description": "Logging Settings" - }, - "devices": { - "anyOf": [ - { - "$ref": "#/components/schemas/DevicesCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Devices Settings" - }, - "measurement": { - "anyOf": [ - { - "$ref": "#/components/schemas/MeasurementCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Measurement Settings" - }, - "optimization": { - "anyOf": [ - { - "$ref": "#/components/schemas/OptimizationCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Optimization Settings" - }, - "prediction": { - "anyOf": [ - { - "$ref": "#/components/schemas/PredictionCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Prediction Settings" - }, - "elecprice": { - "anyOf": [ - { - "$ref": "#/components/schemas/ElecPriceCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Electricity Price Settings" - }, - "load": { - "anyOf": [ - { - "$ref": "#/components/schemas/LoadCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Load Settings" - }, - "pvforecast": { - "anyOf": [ - { - "$ref": "#/components/schemas/PVForecastCommonSettings-Input" - }, - { - "type": "null" - } - ], - "description": "PV Forecast Settings" - }, - "weather": { - "anyOf": [ - { - "$ref": "#/components/schemas/WeatherCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Weather Settings" - }, - "server": { - "anyOf": [ - { - "$ref": "#/components/schemas/ServerCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Server Settings" - }, - "utils": { - "anyOf": [ - { - "$ref": "#/components/schemas/UtilsCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Utilities Settings" - } + "/v1/measurement/series": { + "get": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Series Get", + "description": "Get the measurements of given key as series.", + "operationId": "fastapi_measurement_series_get_v1_measurement_series_get", + "parameters": [ + { + "name": "key", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Prediction key.", + "title": "Key" + }, + "description": "Prediction key." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "put": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Series Put", + "description": "Merge measurement given as series into given key.", + "operationId": "fastapi_measurement_series_put_v1_measurement_series_put", + "parameters": [ + { + "name": "key", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Prediction key.", + "title": "Key" + }, + "description": "Prediction key." + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } }, - "additionalProperties": false, - "type": "object", - "title": "SettingsEOS", - "description": "Settings for all EOS.\n\nUsed by updating the configuration with specific settings only." - }, - "SimulationResult": { - "properties": { - "Last_Wh_pro_Stunde": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" + "/v1/measurement/value": { + "put": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Value Put", + "description": "Merge the measurement of given key and value into EOS measurements at given datetime.", + "operationId": "fastapi_measurement_value_put_v1_measurement_value_put", + "parameters": [ + { + "name": "datetime", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Datetime.", + "title": "Datetime" + }, + "description": "Datetime." + }, + { + "name": "key", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Prediction key.", + "title": "Key" + }, + "description": "Prediction key." + }, + { + "name": "value", + "in": "query", + "required": true, + "schema": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "title": "Value" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } } - ] - }, - "type": "array", - "title": "Last Wh Pro Stunde", - "description": "TBD" - }, - "EAuto_SoC_pro_Stunde": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Eauto Soc Pro Stunde", - "description": "The state of charge of the EV for each hour." - }, - "Einnahmen_Euro_pro_Stunde": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Einnahmen Euro Pro Stunde", - "description": "The revenue from grid feed-in or other sources in euros per hour." - }, - "Gesamt_Verluste": { - "type": "number", - "title": "Gesamt Verluste", - "description": "The total losses in watt-hours over the entire period." - }, - "Gesamtbilanz_Euro": { - "type": "number", - "title": "Gesamtbilanz Euro", - "description": "The total balance of revenues minus costs in euros." - }, - "Gesamteinnahmen_Euro": { - "type": "number", - "title": "Gesamteinnahmen Euro", - "description": "The total revenues in euros." - }, - "Gesamtkosten_Euro": { - "type": "number", - "title": "Gesamtkosten Euro", - "description": "The total costs in euros." - }, - "Home_appliance_wh_per_hour": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Home Appliance Wh Per Hour", - "description": "The energy consumption of a household appliance in watt-hours per hour." - }, - "Kosten_Euro_pro_Stunde": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Kosten Euro Pro Stunde", - "description": "The costs in euros per hour." - }, - "Netzbezug_Wh_pro_Stunde": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Netzbezug Wh Pro Stunde", - "description": "The grid energy drawn in watt-hours per hour." - }, - "Netzeinspeisung_Wh_pro_Stunde": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Netzeinspeisung Wh Pro Stunde", - "description": "The energy fed into the grid in watt-hours per hour." - }, - "Verluste_Pro_Stunde": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Verluste Pro Stunde", - "description": "The losses in watt-hours per hour." - }, - "akku_soc_pro_stunde": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Akku Soc Pro Stunde", - "description": "The state of charge of the battery (not the EV) in percentage per hour." - }, - "Electricity_price": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Electricity Price", - "description": "Used Electricity Price, including predictions" - } + } }, - "additionalProperties": false, - "type": "object", - "required": [ - "Last_Wh_pro_Stunde", - "EAuto_SoC_pro_Stunde", - "Einnahmen_Euro_pro_Stunde", - "Gesamt_Verluste", - "Gesamtbilanz_Euro", - "Gesamteinnahmen_Euro", - "Gesamtkosten_Euro", - "Home_appliance_wh_per_hour", - "Kosten_Euro_pro_Stunde", - "Netzbezug_Wh_pro_Stunde", - "Netzeinspeisung_Wh_pro_Stunde", - "Verluste_Pro_Stunde", - "akku_soc_pro_stunde", - "Electricity_price" - ], - "title": "SimulationResult", - "description": "This object contains the results of the simulation and provides insights into various parameters over the entire forecast period." - }, - "SolarPanelBatteryParameters": { - "properties": { - "device_id": { - "type": "string", - "title": "Device Id", - "description": "ID of battery", - "examples": [ - "battery1" - ] - }, - "hours": { - "anyOf": [ - { - "type": "integer", - "exclusiveMinimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Hours", - "description": "Number of prediction hours. Defaults to global config prediction hours.", - "examples": [ - null - ] - }, - "capacity_wh": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Capacity Wh", - "description": "An integer representing the capacity of the battery in watt-hours.", - "examples": [ - 8000 - ] - }, - "charging_efficiency": { - "type": "number", - "maximum": 1.0, - "exclusiveMinimum": 0.0, - "title": "Charging Efficiency", - "description": "A float representing the charging efficiency of the battery.", - "default": 0.88 - }, - "discharging_efficiency": { - "type": "number", - "maximum": 1.0, - "exclusiveMinimum": 0.0, - "title": "Discharging Efficiency", - "description": "A float representing the discharge efficiency of the battery.", - "default": 0.88 - }, - "max_charge_power_w": { - "anyOf": [ - { - "type": "number", - "exclusiveMinimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Max Charge Power W", - "description": "Maximum charging power in watts.", - "default": 5000 - }, - "initial_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Initial Soc Percentage", - "description": "An integer representing the state of charge of the battery at the **start** of the current hour (not the current state).", - "default": 0, - "examples": [ - 42 - ] - }, - "min_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Min Soc Percentage", - "description": "An integer representing the minimum state of charge (SOC) of the battery in percentage.", - "default": 0, - "examples": [ - 10 - ] - }, - "max_soc_percentage": { - "type": "integer", - "maximum": 100.0, - "minimum": 0.0, - "title": "Max Soc Percentage", - "description": "An integer representing the maximum state of charge (SOC) of the battery in percentage.", - "default": 100 - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "device_id", - "capacity_wh" - ], - "title": "SolarPanelBatteryParameters" - }, - "UtilsCommonSettings": { - "properties": {}, - "type": "object", - "title": "UtilsCommonSettings", - "description": "Utils Configuration." - }, - "ValidationError": { - "properties": { - "loc": { - "items": { - "anyOf": [ - { - "type": "string" + "/v1/measurement/dataframe": { + "put": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Dataframe Put", + "description": "Merge the measurement data given as dataframe into EOS measurements.", + "operationId": "fastapi_measurement_dataframe_put_v1_measurement_dataframe_put", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeDataFrame" + } + } + }, + "required": true }, - { - "type": "integer" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } } - ] + } + }, + "/v1/measurement/data": { + "put": { + "tags": [ + "measurement" + ], + "summary": "Fastapi Measurement Data Put", + "description": "Merge the measurement data given as datetime data into EOS measurements.", + "operationId": "fastapi_measurement_data_put_v1_measurement_data_put", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeData" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/prediction/providers": { + "get": { + "tags": [ + "prediction" + ], + "summary": "Fastapi 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": [ + { + "name": "enabled", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Enabled" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Response Fastapi Prediction Providers Get V1 Prediction Providers Get" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/prediction/keys": { + "get": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Prediction Keys Get", + "description": "Get a list of available prediction keys.", + "operationId": "fastapi_prediction_keys_get_v1_prediction_keys_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Response Fastapi Prediction Keys Get V1 Prediction Keys Get" + } + } + } + } + } + } + }, + "/v1/prediction/series": { + "get": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Prediction Series Get", + "description": "Get prediction for given key within given date range as series.\n\nArgs:\n key (str): Prediction key\n start_datetime (Optional[str]): Starting datetime (inclusive).\n Defaults to start datetime of latest prediction.\n end_datetime (Optional[str]: Ending datetime (exclusive).\n Defaults to end datetime of latest prediction.", + "operationId": "fastapi_prediction_series_get_v1_prediction_series_get", + "parameters": [ + { + "name": "key", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Prediction key.", + "title": "Key" + }, + "description": "Prediction key." + }, + { + "name": "start_datetime", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Starting datetime (inclusive).", + "title": "Start Datetime" + }, + "description": "Starting datetime (inclusive)." + }, + { + "name": "end_datetime", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Ending datetime (exclusive).", + "title": "End Datetime" + }, + "description": "Ending datetime (exclusive)." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeSeries" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/prediction/dataframe": { + "get": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Prediction Dataframe Get", + "description": "Get prediction for given key within given date range as series.\n\nArgs:\n key (str): Prediction key\n start_datetime (Optional[str]): Starting datetime (inclusive).\n Defaults to start datetime of latest prediction.\n end_datetime (Optional[str]: Ending datetime (exclusive).\n\nDefaults to end datetime of latest prediction.", + "operationId": "fastapi_prediction_dataframe_get_v1_prediction_dataframe_get", + "parameters": [ + { + "name": "keys", + "in": "query", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Prediction keys.", + "title": "Keys" + }, + "description": "Prediction keys." + }, + { + "name": "start_datetime", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Starting datetime (inclusive).", + "title": "Start Datetime" + }, + "description": "Starting datetime (inclusive)." + }, + { + "name": "end_datetime", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Ending datetime (exclusive).", + "title": "End Datetime" + }, + "description": "Ending datetime (exclusive)." + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Time duration for each interval. Defaults to 1 hour.", + "title": "Interval" + }, + "description": "Time duration for each interval. Defaults to 1 hour." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PydanticDateTimeDataFrame" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/prediction/list": { + "get": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Prediction List Get", + "description": "Get prediction for given key within given date range as value list.\n\nArgs:\n key (str): Prediction key\n start_datetime (Optional[str]): Starting datetime (inclusive).\n Defaults to start datetime of latest prediction.\n end_datetime (Optional[str]: Ending datetime (exclusive).\n Defaults to end datetime of latest prediction.\n interval (Optional[str]): Time duration for each interval.\n Defaults to 1 hour.", + "operationId": "fastapi_prediction_list_get_v1_prediction_list_get", + "parameters": [ + { + "name": "key", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Prediction key.", + "title": "Key" + }, + "description": "Prediction key." + }, + { + "name": "start_datetime", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Starting datetime (inclusive).", + "title": "Start Datetime" + }, + "description": "Starting datetime (inclusive)." + }, + { + "name": "end_datetime", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Ending datetime (exclusive).", + "title": "End Datetime" + }, + "description": "Ending datetime (exclusive)." + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Time duration for each interval. Defaults to 1 hour.", + "title": "Interval" + }, + "description": "Time duration for each interval. Defaults to 1 hour." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": {}, + "title": "Response Fastapi Prediction List Get V1 Prediction List Get" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/prediction/import/{provider_id}": { + "put": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Prediction Import Provider", + "description": "Import prediction for given provider ID.\n\nArgs:\n provider_id: ID of provider to update.\n data: Prediction data.\n force_enable: Update data even if provider is disabled.\n Defaults to False.", + "operationId": "fastapi_prediction_import_provider_v1_prediction_import__provider_id__put", + "parameters": [ + { + "name": "provider_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "description": "Provider ID.", + "title": "Provider Id" + }, + "description": "Provider ID." + }, + { + "name": "force_enable", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Force Enable" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/PydanticDateTimeDataFrame" + }, + { + "$ref": "#/components/schemas/PydanticDateTimeData" + }, + { + "type": "object", + "additionalProperties": true + }, + { + "type": "null" + } + ], + "title": "Data" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/prediction/update": { + "post": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Prediction Update", + "description": "Update predictions for all providers.\n\nArgs:\n force_update: Update data even if it is already cached.\n Defaults to False.\n force_enable: Update data even if provider is disabled.\n Defaults to False.", + "operationId": "fastapi_prediction_update_v1_prediction_update_post", + "parameters": [ + { + "name": "force_update", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "title": "Force Update" + } + }, + { + "name": "force_enable", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "title": "Force Enable" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/prediction/update/{provider_id}": { + "post": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Prediction Update Provider", + "description": "Update predictions for given provider ID.\n\nArgs:\n provider_id: ID of provider to update.\n force_update: Update data even if it is already cached.\n Defaults to False.\n force_enable: Update data even if provider is disabled.\n Defaults to False.", + "operationId": "fastapi_prediction_update_provider_v1_prediction_update__provider_id__post", + "parameters": [ + { + "name": "provider_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Provider Id" + } + }, + { + "name": "force_update", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "title": "Force Update" + } + }, + { + "name": "force_enable", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "title": "Force Enable" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/strompreis": { + "get": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Strompreis", + "description": "Deprecated: Electricity Market Price Prediction per Wh (\u20ac/Wh).\n\nElectricity prices start at 00.00.00 today and are provided for 48 hours.\nIf no prices are available the missing ones at the start of the series are\nfilled with the first available price.\n\nNote:\n Electricity price charges are added.\n\nNote:\n Set ElecPriceAkkudoktor as provider, then update data with\n '/v1/prediction/update'\n and then request data with\n '/v1/prediction/list?key=elecprice_marketprice_wh' or\n '/v1/prediction/list?key=elecprice_marketprice_kwh' instead.", + "operationId": "fastapi_strompreis_strompreis_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Response Fastapi Strompreis Strompreis Get" + } + } + } + } + } + } + }, + "/gesamtlast": { + "post": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Gesamtlast", + "description": "Deprecated: Total Load Prediction with adjustment.\n\nEndpoint to handle total load prediction adjusted by latest measured data.\n\nTotal load prediction starts at 00.00.00 today and is provided for 48 hours.\nIf no prediction values are available the missing ones at the start of the series are\nfilled with the first available prediction value.\n\nNote:\n Use '/v1/prediction/list?key=load_mean_adjusted' instead.\n Load energy meter readings to be added to EOS measurement by:\n '/v1/measurement/load-mr/value/by-name' or\n '/v1/measurement/value'", + "operationId": "fastapi_gesamtlast_gesamtlast_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GesamtlastRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Response Fastapi Gesamtlast Gesamtlast Post" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/gesamtlast_simple": { + "get": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Gesamtlast Simple", + "description": "Deprecated: Total Load Prediction.\n\nEndpoint to handle total load prediction.\n\nTotal load prediction starts at 00.00.00 today and is provided for 48 hours.\nIf no prediction values are available the missing ones at the start of the series are\nfilled with the first available prediction value.\n\nArgs:\n year_energy (float): Yearly energy consumption in Wh.\n\nNote:\n Set LoadAkkudoktor as provider, then update data with\n '/v1/prediction/update'\n and then request data with\n '/v1/prediction/list?key=load_mean' instead.", + "operationId": "fastapi_gesamtlast_simple_gesamtlast_simple_get", + "parameters": [ + { + "name": "year_energy", + "in": "query", + "required": true, + "schema": { + "type": "number", + "title": "Year Energy" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "number" + }, + "title": "Response Fastapi Gesamtlast Simple Gesamtlast Simple Get" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/pvforecast": { + "get": { + "tags": [ + "prediction" + ], + "summary": "Fastapi Pvforecast", + "description": "Deprecated: PV Forecast Prediction.\n\nEndpoint to handle PV forecast prediction.\n\nPVForecast starts at 00.00.00 today and is provided for 48 hours.\nIf no forecast values are available the missing ones at the start of the series are\nfilled with the first available forecast value.\n\nNote:\n Set PVForecastAkkudoktor as provider, then update data with\n '/v1/prediction/update'\n and then request data with\n '/v1/prediction/list?key=pvforecast_ac_power' and\n '/v1/prediction/list?key=pvforecastakkudoktor_temp_air' instead.", + "operationId": "fastapi_pvforecast_pvforecast_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForecastResponse" + } + } + } + } + } + } + }, + "/optimize": { + "post": { + "tags": [ + "optimize" + ], + "summary": "Fastapi Optimize", + "operationId": "fastapi_optimize_optimize_post", + "parameters": [ + { + "name": "start_hour", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Defaults to current hour of the day.", + "title": "Start Hour" + }, + "description": "Defaults to current hour of the day." + }, + { + "name": "ngen", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ngen" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OptimizationParameters" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OptimizeResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/visualization_results.pdf": { + "get": { + "tags": [ + "optimize" + ], + "summary": "Get Pdf", + "operationId": "get_pdf_visualization_results_pdf_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/pdf": { + "schema": { + "type": "string" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "BaseBatteryParameters": { + "properties": { + "device_id": { + "type": "string", + "title": "Device Id", + "description": "ID of battery", + "examples": [ + "battery1" + ] + }, + "hours": { + "anyOf": [ + { + "type": "integer", + "exclusiveMinimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Hours", + "description": "Number of prediction hours. Defaults to global config prediction hours.", + "examples": [ + null + ] + }, + "capacity_wh": { + "type": "integer", + "exclusiveMinimum": 0.0, + "title": "Capacity Wh", + "description": "An integer representing the capacity of the battery in watt-hours.", + "examples": [ + 8000 + ] + }, + "charging_efficiency": { + "type": "number", + "maximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Charging Efficiency", + "description": "A float representing the charging efficiency of the battery.", + "default": 0.88 + }, + "discharging_efficiency": { + "type": "number", + "maximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Discharging Efficiency", + "description": "A float representing the discharge efficiency of the battery.", + "default": 0.88 + }, + "max_charge_power_w": { + "anyOf": [ + { + "type": "number", + "exclusiveMinimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Max Charge Power W", + "description": "Maximum charging power in watts.", + "default": 5000 + }, + "initial_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Initial Soc Percentage", + "description": "An integer representing the state of charge of the battery at the **start** of the current hour (not the current state).", + "default": 0, + "examples": [ + 42 + ] + }, + "min_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Min Soc Percentage", + "description": "An integer representing the minimum state of charge (SOC) of the battery in percentage.", + "default": 0, + "examples": [ + 10 + ] + }, + "max_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Max Soc Percentage", + "description": "An integer representing the maximum state of charge (SOC) of the battery in percentage.", + "default": 100 + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "device_id", + "capacity_wh" + ], + "title": "BaseBatteryParameters", + "description": "Battery Device Simulation Configuration." }, - "type": "array", - "title": "Location" - }, - "msg": { - "type": "string", - "title": "Message" - }, - "type": { - "type": "string", - "title": "Error Type" - } - }, - "type": "object", - "required": [ - "loc", - "msg", - "type" - ], - "title": "ValidationError" - }, - "WeatherCommonSettings": { - "properties": { - "provider": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Provider", - "description": "Weather provider id of provider to be used.", - "examples": [ - "WeatherImport" - ] - }, - "provider_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/WeatherImportCommonSettings" - }, - { - "type": "null" - } - ], - "description": "Provider settings", - "examples": [ - null - ] - } - }, - "type": "object", - "title": "WeatherCommonSettings", - "description": "Weather Forecast Configuration." - }, - "WeatherImportCommonSettings": { - "properties": { - "import_file_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "path" - }, - { - "type": "null" - } - ], - "title": "Import File Path", - "description": "Path to the file to import weather data from.", - "examples": [ - null, - "/path/to/weather_data.json" - ] - }, - "import_json": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Import Json", - "description": "JSON string, dictionary of weather forecast value lists.", - "examples": [ - "{\"weather_temp_air\": [18.3, 17.8, 16.9]}" - ] - } - }, - "type": "object", - "title": "WeatherImportCommonSettings", - "description": "Common settings for weather data import from file or JSON string." - } + "CacheCommonSettings": { + "properties": { + "subpath": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Subpath", + "description": "Sub-path for the EOS cache data directory.", + "default": "cache" + }, + "cleanup_interval": { + "type": "number", + "title": "Cleanup Interval", + "description": "Intervall in seconds for EOS file cache cleanup.", + "default": 300 + } + }, + "type": "object", + "title": "CacheCommonSettings", + "description": "Cache Configuration." + }, + "ConfigEOS": { + "properties": { + "general": { + "$ref": "#/components/schemas/GeneralSettings-Output", + "default": { + "data_output_subpath": "output", + "latitude": 52.52, + "longitude": 13.405, + "timezone": "Europe/Berlin", + "config_folder_path": "/home/user/.config/net.akkudoktoreos.net", + "config_file_path": "/home/user/.config/net.akkudoktoreos.net/EOS.config.json" + } + }, + "cache": { + "$ref": "#/components/schemas/CacheCommonSettings", + "default": { + "subpath": "cache", + "cleanup_interval": 300.0 + } + }, + "ems": { + "$ref": "#/components/schemas/EnergyManagementCommonSettings", + "default": { + "startup_delay": 5.0 + } + }, + "logging": { + "$ref": "#/components/schemas/LoggingCommonSettings-Output", + "default": { + "file_path": "/home/user/.local/share/net.akkudoktoreos.net/output/eos.log" + } + }, + "devices": { + "$ref": "#/components/schemas/DevicesCommonSettings", + "default": {} + }, + "measurement": { + "$ref": "#/components/schemas/MeasurementCommonSettings", + "default": {} + }, + "optimization": { + "$ref": "#/components/schemas/OptimizationCommonSettings", + "default": { + "hours": 48, + "penalty": 10, + "ev_available_charge_rates_percent": [ + 0.0, + 0.375, + 0.5, + 0.625, + 0.75, + 0.875, + 1.0 + ] + } + }, + "prediction": { + "$ref": "#/components/schemas/PredictionCommonSettings", + "default": { + "hours": 48, + "historic_hours": 48 + } + }, + "elecprice": { + "$ref": "#/components/schemas/ElecPriceCommonSettings", + "default": {} + }, + "load": { + "$ref": "#/components/schemas/LoadCommonSettings", + "default": {} + }, + "pvforecast": { + "$ref": "#/components/schemas/PVForecastCommonSettings-Output", + "default": { + "max_planes": 0, + "planes_peakpower": [], + "planes_azimuth": [], + "planes_tilt": [], + "planes_userhorizon": [], + "planes_inverter_paco": [] + } + }, + "weather": { + "$ref": "#/components/schemas/WeatherCommonSettings", + "default": {} + }, + "server": { + "$ref": "#/components/schemas/ServerCommonSettings", + "default": { + "host": "127.0.0.1", + "port": 8503, + "verbose": false, + "startup_eosdash": true, + "eosdash_host": "127.0.0.1", + "eosdash_port": 8504 + } + }, + "utils": { + "$ref": "#/components/schemas/UtilsCommonSettings", + "default": {} + } + }, + "additionalProperties": false, + "type": "object", + "title": "ConfigEOS", + "description": "Singleton configuration handler for the EOS application.\n\nConfigEOS extends `SettingsEOS` with support for default configuration paths and automatic\ninitialization.\n\n`ConfigEOS` ensures that only one instance of the class is created throughout the application,\nallowing consistent access to EOS configuration settings. This singleton instance loads\nconfiguration data from a predefined set of directories or creates a default configuration if\nnone is found.\n\nInitialization Process:\n - Upon instantiation, the singleton instance attempts to load a configuration file in this order:\n 1. The directory specified by the `EOS_CONFIG_DIR` environment variable\n 2. The directory specified by the `EOS_DIR` environment variable.\n 3. A platform specific default directory for EOS.\n 4. The current working directory.\n - The first available configuration file found in these directories is loaded.\n - If no configuration file is found, a default configuration file is created in the platform\n specific default directory, and default settings are loaded into it.\n\nAttributes from the loaded configuration are accessible directly as instance attributes of\n`ConfigEOS`, providing a centralized, shared configuration object for EOS.\n\nSingleton Behavior:\n - This class uses the `SingletonMixin` to ensure that all requests for `ConfigEOS` return\n the same instance, which contains the most up-to-date configuration. Modifying the configuration\n in one part of the application reflects across all references to this class.\n\nAttributes:\n config_folder_path (Optional[Path]): Path to the configuration directory.\n config_file_path (Optional[Path]): Path to the configuration file.\n\nRaises:\n FileNotFoundError: If no configuration file is found, and creating a default configuration fails.\n\nExample:\n To initialize and access configuration attributes (only one instance is created):\n ```python\n config_eos = ConfigEOS() # Always returns the same instance\n print(config_eos.prediction.hours) # Access a setting from the loaded configuration\n ```" + }, + "DevicesCommonSettings": { + "properties": { + "batteries": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/BaseBatteryParameters" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Batteries", + "description": "List of battery/ev devices", + "examples": [ + [ + { + "capacity_wh": 8000, + "device_id": "battery1" + } + ] + ] + }, + "inverters": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/InverterParameters" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Inverters", + "description": "List of inverters", + "examples": [ + [] + ] + }, + "home_appliances": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/HomeApplianceParameters" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Home Appliances", + "description": "List of home appliances", + "examples": [ + [] + ] + } + }, + "type": "object", + "title": "DevicesCommonSettings", + "description": "Base configuration for devices simulation settings." + }, + "ElecPriceCommonSettings": { + "properties": { + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Provider", + "description": "Electricity price provider id of provider to be used.", + "examples": [ + "ElecPriceAkkudoktor" + ] + }, + "charges_kwh": { + "anyOf": [ + { + "type": "number", + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Charges Kwh", + "description": "Electricity price charges (\u20ac/kWh).", + "examples": [ + 0.21 + ] + }, + "provider_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/ElecPriceImportCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Provider settings", + "examples": [ + null + ] + } + }, + "type": "object", + "title": "ElecPriceCommonSettings", + "description": "Electricity Price Prediction Configuration." + }, + "ElecPriceImportCommonSettings": { + "properties": { + "import_file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Import File Path", + "description": "Path to the file to import elecprice data from.", + "examples": [ + null, + "/path/to/prices.json" + ] + }, + "import_json": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Import Json", + "description": "JSON string, dictionary of electricity price forecast value lists.", + "examples": [ + "{\"elecprice_marketprice_wh\": [0.0003384, 0.0003318, 0.0003284]}" + ] + } + }, + "type": "object", + "title": "ElecPriceImportCommonSettings", + "description": "Common settings for elecprice data import from file or JSON String." + }, + "ElectricVehicleParameters": { + "properties": { + "device_id": { + "type": "string", + "title": "Device Id", + "description": "ID of electric vehicle", + "examples": [ + "ev1" + ] + }, + "hours": { + "anyOf": [ + { + "type": "integer", + "exclusiveMinimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Hours", + "description": "Number of prediction hours. Defaults to global config prediction hours.", + "examples": [ + null + ] + }, + "capacity_wh": { + "type": "integer", + "exclusiveMinimum": 0.0, + "title": "Capacity Wh", + "description": "An integer representing the capacity of the battery in watt-hours.", + "examples": [ + 8000 + ] + }, + "charging_efficiency": { + "type": "number", + "maximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Charging Efficiency", + "description": "A float representing the charging efficiency of the battery.", + "default": 0.88 + }, + "discharging_efficiency": { + "type": "number", + "maximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Discharging Efficiency", + "description": "A float representing the discharge efficiency of the battery.", + "default": 1.0 + }, + "max_charge_power_w": { + "anyOf": [ + { + "type": "number", + "exclusiveMinimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Max Charge Power W", + "description": "Maximum charging power in watts.", + "default": 5000 + }, + "initial_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Initial Soc Percentage", + "description": "An integer representing the current state of charge (SOC) of the battery in percentage.", + "default": 0, + "examples": [ + 42 + ] + }, + "min_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Min Soc Percentage", + "description": "An integer representing the minimum state of charge (SOC) of the battery in percentage.", + "default": 0, + "examples": [ + 10 + ] + }, + "max_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Max Soc Percentage", + "description": "An integer representing the maximum state of charge (SOC) of the battery in percentage.", + "default": 100 + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "device_id", + "capacity_wh" + ], + "title": "ElectricVehicleParameters", + "description": "Battery Electric Vehicle Device Simulation Configuration." + }, + "ElectricVehicleResult": { + "properties": { + "device_id": { + "type": "string", + "title": "Device Id", + "description": "ID of electric vehicle", + "examples": [ + "ev1" + ] + }, + "hours": { + "type": "integer", + "exclusiveMinimum": 0.0, + "title": "Hours", + "description": "Number of hours in the simulation.", + "examples": [ + 24 + ] + }, + "charge_array": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Charge Array", + "description": "Hourly charging status (0 for no charging, 1 for charging)." + }, + "discharge_array": { + "items": { + "type": "integer" + }, + "type": "array", + "title": "Discharge Array", + "description": "Hourly discharging status (0 for no discharging, 1 for discharging)." + }, + "discharging_efficiency": { + "type": "number", + "title": "Discharging Efficiency", + "description": "The discharge efficiency as a float.." + }, + "capacity_wh": { + "type": "integer", + "title": "Capacity Wh", + "description": "Capacity of the EV\u2019s battery in watt-hours." + }, + "charging_efficiency": { + "type": "number", + "title": "Charging Efficiency", + "description": "Charging efficiency as a float.." + }, + "max_charge_power_w": { + "type": "integer", + "title": "Max Charge Power W", + "description": "Maximum charging power in watts." + }, + "soc_wh": { + "type": "number", + "title": "Soc Wh", + "description": "State of charge of the battery in watt-hours at the start of the simulation." + }, + "initial_soc_percentage": { + "type": "integer", + "title": "Initial Soc Percentage", + "description": "State of charge at the start of the simulation in percentage." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "device_id", + "hours", + "charge_array", + "discharge_array", + "discharging_efficiency", + "capacity_wh", + "charging_efficiency", + "max_charge_power_w", + "soc_wh", + "initial_soc_percentage" + ], + "title": "ElectricVehicleResult", + "description": "Result class containing information related to the electric vehicle's charging and discharging behavior." + }, + "EnergyManagementCommonSettings": { + "properties": { + "startup_delay": { + "type": "number", + "minimum": 1.0, + "title": "Startup Delay", + "description": "Startup delay in seconds for EOS energy management runs.", + "default": 5 + }, + "interval": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Interval", + "description": "Intervall in seconds between EOS energy management runs.", + "examples": [ + "300" + ] + } + }, + "type": "object", + "title": "EnergyManagementCommonSettings", + "description": "Energy Management Configuration." + }, + "EnergyManagementParameters": { + "properties": { + "pv_prognose_wh": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Pv Prognose Wh", + "description": "An array of floats representing the forecasted photovoltaic output in watts for different time intervals." + }, + "strompreis_euro_pro_wh": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Strompreis Euro Pro Wh", + "description": "An array of floats representing the electricity price in euros per watt-hour for different time intervals." + }, + "einspeiseverguetung_euro_pro_wh": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "type": "number" + } + ], + "title": "Einspeiseverguetung Euro Pro Wh", + "description": "A float or array of floats representing the feed-in compensation in euros per watt-hour." + }, + "preis_euro_pro_wh_akku": { + "type": "number", + "title": "Preis Euro Pro Wh Akku", + "description": "A float representing the cost of battery energy per watt-hour." + }, + "gesamtlast": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Gesamtlast", + "description": "An array of floats representing the total load (consumption) in watts for different time intervals." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "pv_prognose_wh", + "strompreis_euro_pro_wh", + "einspeiseverguetung_euro_pro_wh", + "preis_euro_pro_wh_akku", + "gesamtlast" + ], + "title": "EnergyManagementParameters" + }, + "ForecastResponse": { + "properties": { + "temperature": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Temperature" + }, + "pvpower": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Pvpower" + } + }, + "type": "object", + "required": [ + "temperature", + "pvpower" + ], + "title": "ForecastResponse" + }, + "GeneralSettings-Input": { + "properties": { + "data_folder_path": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Data Folder Path", + "description": "Path to EOS data directory.", + "examples": [ + null, + "/home/eos/data" + ] + }, + "data_output_subpath": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Data Output Subpath", + "description": "Sub-path for the EOS output data directory.", + "default": "output" + }, + "latitude": { + "anyOf": [ + { + "type": "number", + "maximum": 90.0, + "minimum": -90.0 + }, + { + "type": "null" + } + ], + "title": "Latitude", + "description": "Latitude in decimal degrees, between -90 and 90, north is positive (ISO 19115) (\u00b0)", + "default": 52.52 + }, + "longitude": { + "anyOf": [ + { + "type": "number", + "maximum": 180.0, + "minimum": -180.0 + }, + { + "type": "null" + } + ], + "title": "Longitude", + "description": "Longitude in decimal degrees, within -180 to 180 (\u00b0)", + "default": 13.405 + } + }, + "type": "object", + "title": "GeneralSettings", + "description": "Settings for common configuration.\n\nGeneral configuration to set directories of cache and output files and system location (latitude\nand longitude).\nValidators ensure each parameter is within a specified range. A computed property, `timezone`,\ndetermines the time zone based on latitude and longitude.\n\nAttributes:\n latitude (Optional[float]): Latitude in degrees, must be between -90 and 90.\n longitude (Optional[float]): Longitude in degrees, must be between -180 and 180.\n\nProperties:\n timezone (Optional[str]): Computed time zone string based on the specified latitude\n and longitude." + }, + "GeneralSettings-Output": { + "properties": { + "data_folder_path": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Data Folder Path", + "description": "Path to EOS data directory.", + "examples": [ + null, + "/home/eos/data" + ] + }, + "data_output_subpath": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Data Output Subpath", + "description": "Sub-path for the EOS output data directory.", + "default": "output" + }, + "latitude": { + "anyOf": [ + { + "type": "number", + "maximum": 90.0, + "minimum": -90.0 + }, + { + "type": "null" + } + ], + "title": "Latitude", + "description": "Latitude in decimal degrees, between -90 and 90, north is positive (ISO 19115) (\u00b0)", + "default": 52.52 + }, + "longitude": { + "anyOf": [ + { + "type": "number", + "maximum": 180.0, + "minimum": -180.0 + }, + { + "type": "null" + } + ], + "title": "Longitude", + "description": "Longitude in decimal degrees, within -180 to 180 (\u00b0)", + "default": 13.405 + }, + "timezone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Timezone", + "description": "Compute timezone based on latitude and longitude.", + "readOnly": true + }, + "data_output_path": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Data Output Path", + "description": "Compute data_output_path based on data_folder_path.", + "readOnly": true + }, + "config_folder_path": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Config Folder Path", + "description": "Path to EOS configuration directory.", + "readOnly": true + }, + "config_file_path": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Config File Path", + "description": "Path to EOS configuration file.", + "readOnly": true + } + }, + "type": "object", + "required": [ + "timezone", + "data_output_path", + "config_folder_path", + "config_file_path" + ], + "title": "GeneralSettings", + "description": "Settings for common configuration.\n\nGeneral configuration to set directories of cache and output files and system location (latitude\nand longitude).\nValidators ensure each parameter is within a specified range. A computed property, `timezone`,\ndetermines the time zone based on latitude and longitude.\n\nAttributes:\n latitude (Optional[float]): Latitude in degrees, must be between -90 and 90.\n longitude (Optional[float]): Longitude in degrees, must be between -180 and 180.\n\nProperties:\n timezone (Optional[str]): Computed time zone string based on the specified latitude\n and longitude." + }, + "GesamtlastRequest": { + "properties": { + "year_energy": { + "type": "number", + "title": "Year Energy" + }, + "measured_data": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array", + "title": "Measured Data" + }, + "hours": { + "type": "integer", + "title": "Hours" + } + }, + "type": "object", + "required": [ + "year_energy", + "measured_data", + "hours" + ], + "title": "GesamtlastRequest" + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail" + } + }, + "type": "object", + "title": "HTTPValidationError" + }, + "HomeApplianceParameters": { + "properties": { + "device_id": { + "type": "string", + "title": "Device Id", + "description": "ID of home appliance", + "examples": [ + "dishwasher" + ] + }, + "hours": { + "anyOf": [ + { + "type": "integer", + "exclusiveMinimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Hours", + "description": "Number of prediction hours. Defaults to global config prediction hours.", + "examples": [ + null + ] + }, + "consumption_wh": { + "type": "integer", + "exclusiveMinimum": 0.0, + "title": "Consumption Wh", + "description": "An integer representing the energy consumption of a household device in watt-hours.", + "examples": [ + 2000 + ] + }, + "duration_h": { + "type": "integer", + "exclusiveMinimum": 0.0, + "title": "Duration H", + "description": "An integer representing the usage duration of a household device in hours.", + "examples": [ + 3 + ] + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "device_id", + "consumption_wh", + "duration_h" + ], + "title": "HomeApplianceParameters", + "description": "Home Appliance Device Simulation Configuration." + }, + "InverterParameters": { + "properties": { + "device_id": { + "type": "string", + "title": "Device Id", + "description": "ID of inverter", + "examples": [ + "inverter1" + ] + }, + "hours": { + "anyOf": [ + { + "type": "integer", + "exclusiveMinimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Hours", + "description": "Number of prediction hours. Defaults to global config prediction hours.", + "examples": [ + null + ] + }, + "max_power_wh": { + "type": "number", + "exclusiveMinimum": 0.0, + "title": "Max Power Wh", + "examples": [ + 10000 + ] + }, + "battery_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Battery Id", + "description": "ID of battery", + "examples": [ + null, + "battery1" + ] + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "device_id", + "max_power_wh" + ], + "title": "InverterParameters", + "description": "Inverter Device Simulation Configuration." + }, + "LoadAkkudoktorCommonSettings": { + "properties": { + "loadakkudoktor_year_energy": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Loadakkudoktor Year Energy", + "description": "Yearly energy consumption (kWh).", + "examples": [ + 40421 + ] + } + }, + "type": "object", + "title": "LoadAkkudoktorCommonSettings", + "description": "Common settings for load data import from file." + }, + "LoadCommonSettings": { + "properties": { + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Provider", + "description": "Load provider id of provider to be used.", + "examples": [ + "LoadAkkudoktor" + ] + }, + "provider_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/LoadAkkudoktorCommonSettings" + }, + { + "$ref": "#/components/schemas/LoadVrmCommonSettings" + }, + { + "$ref": "#/components/schemas/LoadImportCommonSettings" + }, + { + "type": "null" + } + ], + "title": "Provider Settings", + "description": "Provider settings", + "examples": [ + null + ] + } + }, + "type": "object", + "title": "LoadCommonSettings", + "description": "Load Prediction Configuration." + }, + "LoadImportCommonSettings": { + "properties": { + "import_file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Import File Path", + "description": "Path to the file to import load data from.", + "examples": [ + null, + "/path/to/yearly_load.json" + ] + }, + "import_json": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Import Json", + "description": "JSON string, dictionary of load forecast value lists.", + "examples": [ + "{\"load0_mean\": [676.71, 876.19, 527.13]}" + ] + } + }, + "type": "object", + "title": "LoadImportCommonSettings", + "description": "Common settings for load data import from file or JSON string." + }, + "LoadVrmCommonSettings": { + "properties": { + "load_vrm_token": { + "type": "string", + "title": "Load Vrm Token", + "description": "Token for Connecting VRM API", + "default": "your-token", + "examples": [ + "your-token" + ] + }, + "load_vrm_idsite": { + "type": "integer", + "title": "Load Vrm Idsite", + "description": "VRM-Installation-ID", + "default": 12345, + "examples": [ + 12345 + ] + } + }, + "type": "object", + "title": "LoadVrmCommonSettings", + "description": "Common settings for VRM API." + }, + "LoggingCommonSettings-Input": { + "properties": { + "level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Level", + "deprecated": true + }, + "console_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Console Level", + "description": "Logging level when logging to console.", + "examples": [ + "TRACE", + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL" + ] + }, + "file_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "File Level", + "description": "Logging level when logging to file.", + "examples": [ + "TRACE", + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL" + ] + } + }, + "type": "object", + "title": "LoggingCommonSettings", + "description": "Logging Configuration." + }, + "LoggingCommonSettings-Output": { + "properties": { + "level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Level", + "deprecated": true + }, + "console_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Console Level", + "description": "Logging level when logging to console.", + "examples": [ + "TRACE", + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL" + ] + }, + "file_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "File Level", + "description": "Logging level when logging to file.", + "examples": [ + "TRACE", + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL" + ] + }, + "file_path": { + "anyOf": [ + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "File Path", + "description": "Computed log file path based on data output path.", + "readOnly": true + } + }, + "type": "object", + "required": [ + "file_path" + ], + "title": "LoggingCommonSettings", + "description": "Logging Configuration." + }, + "MeasurementCommonSettings": { + "properties": { + "load0_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Load0 Name", + "description": "Name of the load0 source", + "examples": [ + "Household", + "Heat Pump" + ] + }, + "load1_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Load1 Name", + "description": "Name of the load1 source", + "examples": [ + null + ] + }, + "load2_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Load2 Name", + "description": "Name of the load2 source", + "examples": [ + null + ] + }, + "load3_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Load3 Name", + "description": "Name of the load3 source", + "examples": [ + null + ] + }, + "load4_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Load4 Name", + "description": "Name of the load4 source", + "examples": [ + null + ] + } + }, + "type": "object", + "title": "MeasurementCommonSettings", + "description": "Measurement Configuration." + }, + "OptimizationCommonSettings": { + "properties": { + "hours": { + "anyOf": [ + { + "type": "integer", + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Hours", + "description": "Number of hours into the future for optimizations.", + "default": 48 + }, + "penalty": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Penalty", + "description": "Penalty factor used in optimization.", + "default": 10 + }, + "ev_available_charge_rates_percent": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Ev Available Charge Rates Percent", + "description": "Charge rates available for the EV in percent of maximum charge.", + "default": [ + 0.0, + 0.375, + 0.5, + 0.625, + 0.75, + 0.875, + 1.0 + ] + } + }, + "type": "object", + "title": "OptimizationCommonSettings", + "description": "General Optimization Configuration.\n\nAttributes:\n hours (int): Number of hours for optimizations." + }, + "OptimizationParameters": { + "properties": { + "ems": { + "$ref": "#/components/schemas/EnergyManagementParameters" + }, + "pv_akku": { + "anyOf": [ + { + "$ref": "#/components/schemas/SolarPanelBatteryParameters" + }, + { + "type": "null" + } + ] + }, + "inverter": { + "anyOf": [ + { + "$ref": "#/components/schemas/InverterParameters" + }, + { + "type": "null" + } + ] + }, + "eauto": { + "anyOf": [ + { + "$ref": "#/components/schemas/ElectricVehicleParameters" + }, + { + "type": "null" + } + ] + }, + "dishwasher": { + "anyOf": [ + { + "$ref": "#/components/schemas/HomeApplianceParameters" + }, + { + "type": "null" + } + ] + }, + "temperature_forecast": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Temperature Forecast", + "description": "An array of floats representing the temperature forecast in degrees Celsius for different time intervals." + }, + "start_solution": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Start Solution", + "description": "Can be `null` or contain a previous solution (if available)." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "ems", + "pv_akku", + "inverter", + "eauto" + ], + "title": "OptimizationParameters" + }, + "OptimizeResponse": { + "properties": { + "ac_charge": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Ac Charge", + "description": "Array with AC charging values as relative power (0-1), other values set to 0." + }, + "dc_charge": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Dc Charge", + "description": "Array with DC charging values as relative power (0-1), other values set to 0." + }, + "discharge_allowed": { + "items": { + "type": "integer" + }, + "type": "array", + "title": "Discharge Allowed", + "description": "Array with discharge values (1 for discharge, 0 otherwise)." + }, + "eautocharge_hours_float": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Eautocharge Hours Float", + "description": "TBD" + }, + "result": { + "$ref": "#/components/schemas/SimulationResult" + }, + "eauto_obj": { + "anyOf": [ + { + "$ref": "#/components/schemas/ElectricVehicleResult" + }, + { + "type": "null" + } + ] + }, + "start_solution": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Start Solution", + "description": "An array of binary values (0 or 1) representing a possible starting solution for the simulation." + }, + "washingstart": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Washingstart", + "description": "Can be `null` or contain an object representing the start of washing (if applicable)." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "ac_charge", + "dc_charge", + "discharge_allowed", + "eautocharge_hours_float", + "result", + "eauto_obj" + ], + "title": "OptimizeResponse", + "description": "**Note**: The first value of \"Last_Wh_per_hour\", \"Netzeinspeisung_Wh_per_hour\", and \"Netzbezug_Wh_per_hour\", will be set to null in the JSON output and represented as NaN or None in the corresponding classes' data returns. This approach is adopted to ensure that the current hour's processing remains unchanged." + }, + "PVForecastCommonSettings-Input": { + "properties": { + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Provider", + "description": "PVForecast provider id of provider to be used.", + "examples": [ + "PVForecastAkkudoktor" + ] + }, + "provider_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/PVForecastImportCommonSettings" + }, + { + "$ref": "#/components/schemas/PVforecastVrmCommonSettings" + }, + { + "type": "null" + } + ], + "title": "Provider Settings", + "description": "Provider settings", + "examples": [ + null + ] + }, + "planes": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/PVForecastPlaneSetting" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Planes", + "description": "Plane configuration.", + "examples": [ + [ + { + "inverter_paco": 6000, + "loss": 14.0, + "modules_per_string": 20, + "mountingplace": "free", + "optimal_surface_tilt": false, + "optimalangles": false, + "peakpower": 5.0, + "pvtechchoice": "crystSi", + "strings_per_inverter": 2, + "surface_azimuth": 180.0, + "surface_tilt": 10.0, + "trackingtype": 0, + "userhorizon": [ + 10.0, + 20.0, + 30.0 + ] + }, + { + "inverter_paco": 4000, + "loss": 14.0, + "modules_per_string": 20, + "mountingplace": "free", + "optimal_surface_tilt": false, + "optimalangles": false, + "peakpower": 3.5, + "pvtechchoice": "crystSi", + "strings_per_inverter": 2, + "surface_azimuth": 90.0, + "surface_tilt": 20.0, + "trackingtype": 1, + "userhorizon": [ + 5.0, + 15.0, + 25.0 + ] + } + ] + ] + }, + "max_planes": { + "anyOf": [ + { + "type": "integer", + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Max Planes", + "description": "Maximum number of planes that can be set", + "default": 0 + } + }, + "type": "object", + "title": "PVForecastCommonSettings", + "description": "PV Forecast Configuration." + }, + "PVForecastCommonSettings-Output": { + "properties": { + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Provider", + "description": "PVForecast provider id of provider to be used.", + "examples": [ + "PVForecastAkkudoktor" + ] + }, + "provider_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/PVForecastImportCommonSettings" + }, + { + "$ref": "#/components/schemas/PVforecastVrmCommonSettings" + }, + { + "type": "null" + } + ], + "title": "Provider Settings", + "description": "Provider settings", + "examples": [ + null + ] + }, + "planes": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/PVForecastPlaneSetting" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Planes", + "description": "Plane configuration.", + "examples": [ + [ + { + "inverter_paco": 6000, + "loss": 14.0, + "modules_per_string": 20, + "mountingplace": "free", + "optimal_surface_tilt": false, + "optimalangles": false, + "peakpower": 5.0, + "pvtechchoice": "crystSi", + "strings_per_inverter": 2, + "surface_azimuth": 180.0, + "surface_tilt": 10.0, + "trackingtype": 0, + "userhorizon": [ + 10.0, + 20.0, + 30.0 + ] + }, + { + "inverter_paco": 4000, + "loss": 14.0, + "modules_per_string": 20, + "mountingplace": "free", + "optimal_surface_tilt": false, + "optimalangles": false, + "peakpower": 3.5, + "pvtechchoice": "crystSi", + "strings_per_inverter": 2, + "surface_azimuth": 90.0, + "surface_tilt": 20.0, + "trackingtype": 1, + "userhorizon": [ + 5.0, + 15.0, + 25.0 + ] + } + ] + ] + }, + "max_planes": { + "anyOf": [ + { + "type": "integer", + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Max Planes", + "description": "Maximum number of planes that can be set", + "default": 0 + }, + "planes_peakpower": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Planes Peakpower", + "description": "Compute a list of the peak power per active planes.", + "readOnly": true + }, + "planes_azimuth": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Planes Azimuth", + "description": "Compute a list of the azimuths per active planes.", + "readOnly": true + }, + "planes_tilt": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Planes Tilt", + "description": "Compute a list of the tilts per active planes.", + "readOnly": true + }, + "planes_userhorizon": { + "title": "Planes Userhorizon", + "description": "Compute a list of the user horizon per active planes.", + "readOnly": true + }, + "planes_inverter_paco": { + "title": "Planes Inverter Paco", + "description": "Compute a list of the maximum power rating of the inverter per active planes.", + "readOnly": true + } + }, + "type": "object", + "required": [ + "planes_peakpower", + "planes_azimuth", + "planes_tilt", + "planes_userhorizon", + "planes_inverter_paco" + ], + "title": "PVForecastCommonSettings", + "description": "PV Forecast Configuration." + }, + "PVForecastImportCommonSettings": { + "properties": { + "import_file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Import File Path", + "description": "Path to the file to import PV forecast data from.", + "examples": [ + null, + "/path/to/pvforecast.json" + ] + }, + "import_json": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Import Json", + "description": "JSON string, dictionary of PV forecast value lists.", + "examples": [ + "{\"pvforecast_ac_power\": [0, 8.05, 352.91]}" + ] + } + }, + "type": "object", + "title": "PVForecastImportCommonSettings", + "description": "Common settings for pvforecast data import from file or JSON string." + }, + "PVForecastPlaneSetting": { + "properties": { + "surface_tilt": { + "anyOf": [ + { + "type": "number", + "maximum": 90.0, + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Surface Tilt", + "description": "Tilt angle from horizontal plane. Ignored for two-axis tracking.", + "default": 30.0, + "examples": [ + 10.0, + 20.0 + ] + }, + "surface_azimuth": { + "anyOf": [ + { + "type": "number", + "maximum": 360.0, + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Surface Azimuth", + "description": "Orientation (azimuth angle) of the (fixed) plane. Clockwise from north (north=0, east=90, south=180, west=270).", + "default": 180.0, + "examples": [ + 180.0, + 90.0 + ] + }, + "userhorizon": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Userhorizon", + "description": "Elevation of horizon in degrees, at equally spaced azimuth clockwise from north.", + "examples": [ + [ + 10.0, + 20.0, + 30.0 + ], + [ + 5.0, + 15.0, + 25.0 + ] + ] + }, + "peakpower": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Peakpower", + "description": "Nominal power of PV system in kW.", + "examples": [ + 5.0, + 3.5 + ] + }, + "pvtechchoice": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Pvtechchoice", + "description": "PV technology. One of 'crystSi', 'CIS', 'CdTe', 'Unknown'.", + "default": "crystSi" + }, + "mountingplace": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Mountingplace", + "description": "Type of mounting for PV system. Options are 'free' for free-standing and 'building' for building-integrated.", + "default": "free" + }, + "loss": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Loss", + "description": "Sum of PV system losses in percent", + "default": 14.0 + }, + "trackingtype": { + "anyOf": [ + { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Trackingtype", + "description": "Type of suntracking. 0=fixed, 1=single horizontal axis aligned north-south, 2=two-axis tracking, 3=vertical axis tracking, 4=single horizontal axis aligned east-west, 5=single inclined axis aligned north-south.", + "examples": [ + 0, + 1, + 2, + 3, + 4, + 5 + ] + }, + "optimal_surface_tilt": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Optimal Surface Tilt", + "description": "Calculate the optimum tilt angle. Ignored for two-axis tracking.", + "default": false, + "examples": [ + false + ] + }, + "optimalangles": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Optimalangles", + "description": "Calculate the optimum tilt and azimuth angles. Ignored for two-axis tracking.", + "default": false, + "examples": [ + false + ] + }, + "albedo": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Albedo", + "description": "Proportion of the light hitting the ground that it reflects back.", + "examples": [ + null + ] + }, + "module_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Module Model", + "description": "Model of the PV modules of this plane.", + "examples": [ + null + ] + }, + "inverter_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Inverter Model", + "description": "Model of the inverter of this plane.", + "examples": [ + null + ] + }, + "inverter_paco": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Inverter Paco", + "description": "AC power rating of the inverter [W].", + "examples": [ + 6000, + 4000 + ] + }, + "modules_per_string": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Modules Per String", + "description": "Number of the PV modules of the strings of this plane.", + "examples": [ + 20 + ] + }, + "strings_per_inverter": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Strings Per Inverter", + "description": "Number of the strings of the inverter of this plane.", + "examples": [ + 2 + ] + } + }, + "type": "object", + "title": "PVForecastPlaneSetting", + "description": "PV Forecast Plane Configuration." + }, + "PVforecastVrmCommonSettings": { + "properties": { + "pvforecast_vrm_token": { + "type": "string", + "title": "Pvforecast Vrm Token", + "description": "Token for Connecting VRM API", + "default": "your-token", + "examples": [ + "your-token" + ] + }, + "pvforecast_vrm_idsite": { + "type": "integer", + "title": "Pvforecast Vrm Idsite", + "description": "VRM-Installation-ID", + "default": 12345, + "examples": [ + 12345 + ] + } + }, + "type": "object", + "title": "PVforecastVrmCommonSettings", + "description": "Common settings for VRM API." + }, + "PredictionCommonSettings": { + "properties": { + "hours": { + "anyOf": [ + { + "type": "integer", + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Hours", + "description": "Number of hours into the future for predictions", + "default": 48 + }, + "historic_hours": { + "anyOf": [ + { + "type": "integer", + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Historic Hours", + "description": "Number of hours into the past for historical predictions data", + "default": 48 + } + }, + "type": "object", + "title": "PredictionCommonSettings", + "description": "General Prediction Configuration.\n\nThis class provides configuration for prediction settings, allowing users to specify\nparameters such as the forecast duration (in hours).\nValidators ensure each parameter is within a specified range.\n\nAttributes:\n hours (Optional[int]): Number of hours into the future for predictions.\n Must be non-negative.\n historic_hours (Optional[int]): Number of hours into the past for historical data.\n Must be non-negative.\n\nValidators:\n validate_hours (int): Ensures `hours` is a non-negative integer.\n validate_historic_hours (int): Ensures `historic_hours` is a non-negative integer." + }, + "PydanticDateTimeData": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "type": "array" + } + ] + }, + "type": "object", + "title": "PydanticDateTimeData", + "description": "Pydantic model for time series data with consistent value lengths.\n\nThis model validates a dictionary where:\n- Keys are strings representing data series names\n- Values are lists of numeric or string values\n- Special keys 'start_datetime' and 'interval' can contain string values\nfor time series indexing\n- All value lists must have the same length\n\nExample:\n {\n \"start_datetime\": \"2024-01-01 00:00:00\", # optional\n \"interval\": \"1 Hour\", # optional\n \"load_mean\": [20.5, 21.0, 22.1],\n \"load_min\": [18.5, 19.0, 20.1]\n }" + }, + "PydanticDateTimeDataFrame": { + "properties": { + "data": { + "additionalProperties": { + "additionalProperties": true, + "type": "object" + }, + "type": "object", + "title": "Data" + }, + "dtypes": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Dtypes" + }, + "tz": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tz", + "description": "Timezone for datetime values" + }, + "datetime_columns": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Datetime Columns", + "description": "Columns to be treated as datetime" + } + }, + "type": "object", + "required": [ + "data" + ], + "title": "PydanticDateTimeDataFrame", + "description": "Pydantic model for validating pandas DataFrame data with datetime index." + }, + "PydanticDateTimeSeries": { + "properties": { + "data": { + "additionalProperties": true, + "type": "object", + "title": "Data" + }, + "dtype": { + "type": "string", + "title": "Dtype", + "default": "float64" + }, + "tz": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tz" + } + }, + "type": "object", + "required": [ + "data" + ], + "title": "PydanticDateTimeSeries", + "description": "Pydantic model for validating pandas Series with datetime index in JSON format.\n\nThis model handles Series data serialized with orient='index', where the keys are\ndatetime strings and values are the series values. Provides validation and\nconversion between JSON and pandas Series with datetime index.\n\nAttributes:\n data (Dict[str, Any]): Dictionary mapping datetime strings to values.\n dtype (str): The data type of the series values.\n tz (str | None): Timezone name if the datetime index is timezone-aware." + }, + "ServerCommonSettings": { + "properties": { + "host": { + "anyOf": [ + { + "type": "string", + "format": "ipvanyaddress" + }, + { + "type": "null" + } + ], + "title": "Host", + "description": "EOS server IP address.", + "default": "127.0.0.1" + }, + "port": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Port", + "description": "EOS server IP port number.", + "default": 8503 + }, + "verbose": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Verbose", + "description": "Enable debug output", + "default": false + }, + "startup_eosdash": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Startup Eosdash", + "description": "EOS server to start EOSdash server.", + "default": true + }, + "eosdash_host": { + "anyOf": [ + { + "type": "string", + "format": "ipvanyaddress" + }, + { + "type": "null" + } + ], + "title": "Eosdash Host", + "description": "EOSdash server IP address.", + "default": "127.0.0.1" + }, + "eosdash_port": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Eosdash Port", + "description": "EOSdash server IP port number.", + "default": 8504 + } + }, + "type": "object", + "title": "ServerCommonSettings", + "description": "Server Configuration." + }, + "SettingsEOS": { + "properties": { + "general": { + "anyOf": [ + { + "$ref": "#/components/schemas/GeneralSettings-Input" + }, + { + "type": "null" + } + ], + "description": "General Settings" + }, + "cache": { + "anyOf": [ + { + "$ref": "#/components/schemas/CacheCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Cache Settings" + }, + "ems": { + "anyOf": [ + { + "$ref": "#/components/schemas/EnergyManagementCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Energy Management Settings" + }, + "logging": { + "anyOf": [ + { + "$ref": "#/components/schemas/LoggingCommonSettings-Input" + }, + { + "type": "null" + } + ], + "description": "Logging Settings" + }, + "devices": { + "anyOf": [ + { + "$ref": "#/components/schemas/DevicesCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Devices Settings" + }, + "measurement": { + "anyOf": [ + { + "$ref": "#/components/schemas/MeasurementCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Measurement Settings" + }, + "optimization": { + "anyOf": [ + { + "$ref": "#/components/schemas/OptimizationCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Optimization Settings" + }, + "prediction": { + "anyOf": [ + { + "$ref": "#/components/schemas/PredictionCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Prediction Settings" + }, + "elecprice": { + "anyOf": [ + { + "$ref": "#/components/schemas/ElecPriceCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Electricity Price Settings" + }, + "load": { + "anyOf": [ + { + "$ref": "#/components/schemas/LoadCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Load Settings" + }, + "pvforecast": { + "anyOf": [ + { + "$ref": "#/components/schemas/PVForecastCommonSettings-Input" + }, + { + "type": "null" + } + ], + "description": "PV Forecast Settings" + }, + "weather": { + "anyOf": [ + { + "$ref": "#/components/schemas/WeatherCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Weather Settings" + }, + "server": { + "anyOf": [ + { + "$ref": "#/components/schemas/ServerCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Server Settings" + }, + "utils": { + "anyOf": [ + { + "$ref": "#/components/schemas/UtilsCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Utilities Settings" + } + }, + "additionalProperties": false, + "type": "object", + "title": "SettingsEOS", + "description": "Settings for all EOS.\n\nUsed by updating the configuration with specific settings only." + }, + "SimulationResult": { + "properties": { + "Last_Wh_pro_Stunde": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Last Wh Pro Stunde", + "description": "TBD" + }, + "EAuto_SoC_pro_Stunde": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Eauto Soc Pro Stunde", + "description": "The state of charge of the EV for each hour." + }, + "Einnahmen_Euro_pro_Stunde": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Einnahmen Euro Pro Stunde", + "description": "The revenue from grid feed-in or other sources in euros per hour." + }, + "Gesamt_Verluste": { + "type": "number", + "title": "Gesamt Verluste", + "description": "The total losses in watt-hours over the entire period." + }, + "Gesamtbilanz_Euro": { + "type": "number", + "title": "Gesamtbilanz Euro", + "description": "The total balance of revenues minus costs in euros." + }, + "Gesamteinnahmen_Euro": { + "type": "number", + "title": "Gesamteinnahmen Euro", + "description": "The total revenues in euros." + }, + "Gesamtkosten_Euro": { + "type": "number", + "title": "Gesamtkosten Euro", + "description": "The total costs in euros." + }, + "Home_appliance_wh_per_hour": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Home Appliance Wh Per Hour", + "description": "The energy consumption of a household appliance in watt-hours per hour." + }, + "Kosten_Euro_pro_Stunde": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Kosten Euro Pro Stunde", + "description": "The costs in euros per hour." + }, + "Netzbezug_Wh_pro_Stunde": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Netzbezug Wh Pro Stunde", + "description": "The grid energy drawn in watt-hours per hour." + }, + "Netzeinspeisung_Wh_pro_Stunde": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Netzeinspeisung Wh Pro Stunde", + "description": "The energy fed into the grid in watt-hours per hour." + }, + "Verluste_Pro_Stunde": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Verluste Pro Stunde", + "description": "The losses in watt-hours per hour." + }, + "akku_soc_pro_stunde": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Akku Soc Pro Stunde", + "description": "The state of charge of the battery (not the EV) in percentage per hour." + }, + "Electricity_price": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array", + "title": "Electricity Price", + "description": "Used Electricity Price, including predictions" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "Last_Wh_pro_Stunde", + "EAuto_SoC_pro_Stunde", + "Einnahmen_Euro_pro_Stunde", + "Gesamt_Verluste", + "Gesamtbilanz_Euro", + "Gesamteinnahmen_Euro", + "Gesamtkosten_Euro", + "Home_appliance_wh_per_hour", + "Kosten_Euro_pro_Stunde", + "Netzbezug_Wh_pro_Stunde", + "Netzeinspeisung_Wh_pro_Stunde", + "Verluste_Pro_Stunde", + "akku_soc_pro_stunde", + "Electricity_price" + ], + "title": "SimulationResult", + "description": "This object contains the results of the simulation and provides insights into various parameters over the entire forecast period." + }, + "SolarPanelBatteryParameters": { + "properties": { + "device_id": { + "type": "string", + "title": "Device Id", + "description": "ID of battery", + "examples": [ + "battery1" + ] + }, + "hours": { + "anyOf": [ + { + "type": "integer", + "exclusiveMinimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Hours", + "description": "Number of prediction hours. Defaults to global config prediction hours.", + "examples": [ + null + ] + }, + "capacity_wh": { + "type": "integer", + "exclusiveMinimum": 0.0, + "title": "Capacity Wh", + "description": "An integer representing the capacity of the battery in watt-hours.", + "examples": [ + 8000 + ] + }, + "charging_efficiency": { + "type": "number", + "maximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Charging Efficiency", + "description": "A float representing the charging efficiency of the battery.", + "default": 0.88 + }, + "discharging_efficiency": { + "type": "number", + "maximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Discharging Efficiency", + "description": "A float representing the discharge efficiency of the battery.", + "default": 0.88 + }, + "max_charge_power_w": { + "anyOf": [ + { + "type": "number", + "exclusiveMinimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Max Charge Power W", + "description": "Maximum charging power in watts.", + "default": 5000 + }, + "initial_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Initial Soc Percentage", + "description": "An integer representing the state of charge of the battery at the **start** of the current hour (not the current state).", + "default": 0, + "examples": [ + 42 + ] + }, + "min_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Min Soc Percentage", + "description": "An integer representing the minimum state of charge (SOC) of the battery in percentage.", + "default": 0, + "examples": [ + 10 + ] + }, + "max_soc_percentage": { + "type": "integer", + "maximum": 100.0, + "minimum": 0.0, + "title": "Max Soc Percentage", + "description": "An integer representing the maximum state of charge (SOC) of the battery in percentage.", + "default": 100 + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "device_id", + "capacity_wh" + ], + "title": "SolarPanelBatteryParameters" + }, + "UtilsCommonSettings": { + "properties": {}, + "type": "object", + "title": "UtilsCommonSettings", + "description": "Utils Configuration." + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "type": "array", + "title": "Location" + }, + "msg": { + "type": "string", + "title": "Message" + }, + "type": { + "type": "string", + "title": "Error Type" + } + }, + "type": "object", + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError" + }, + "WeatherCommonSettings": { + "properties": { + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Provider", + "description": "Weather provider id of provider to be used.", + "examples": [ + "WeatherImport" + ] + }, + "provider_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/WeatherImportCommonSettings" + }, + { + "type": "null" + } + ], + "description": "Provider settings", + "examples": [ + null + ] + } + }, + "type": "object", + "title": "WeatherCommonSettings", + "description": "Weather Forecast Configuration." + }, + "WeatherImportCommonSettings": { + "properties": { + "import_file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "path" + }, + { + "type": "null" + } + ], + "title": "Import File Path", + "description": "Path to the file to import weather data from.", + "examples": [ + null, + "/path/to/weather_data.json" + ] + }, + "import_json": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Import Json", + "description": "JSON string, dictionary of weather forecast value lists.", + "examples": [ + "{\"weather_temp_air\": [18.3, 17.8, 16.9]}" + ] + } + }, + "type": "object", + "title": "WeatherImportCommonSettings", + "description": "Common settings for weather data import from file or JSON string." + } + } } - } } \ No newline at end of file diff --git a/src/akkudoktoreos/prediction/load.py b/src/akkudoktoreos/prediction/load.py index eacd923..495effe 100644 --- a/src/akkudoktoreos/prediction/load.py +++ b/src/akkudoktoreos/prediction/load.py @@ -8,6 +8,7 @@ from akkudoktoreos.config.configabc import SettingsBaseModel from akkudoktoreos.prediction.loadabc import LoadProvider from akkudoktoreos.prediction.loadakkudoktor import LoadAkkudoktorCommonSettings from akkudoktoreos.prediction.loadimport import LoadImportCommonSettings +from akkudoktoreos.prediction.loadvrm import LoadVrmCommonSettings from akkudoktoreos.prediction.prediction import get_prediction prediction_eos = get_prediction() @@ -29,9 +30,9 @@ class LoadCommonSettings(SettingsBaseModel): examples=["LoadAkkudoktor"], ) - provider_settings: Optional[Union[LoadAkkudoktorCommonSettings, LoadImportCommonSettings]] = ( - Field(default=None, description="Provider settings", examples=[None]) - ) + provider_settings: Optional[ + Union[LoadAkkudoktorCommonSettings, LoadVrmCommonSettings, LoadImportCommonSettings] + ] = Field(default=None, description="Provider settings", examples=[None]) # Validators @field_validator("provider", mode="after") diff --git a/src/akkudoktoreos/prediction/loadvrm.py b/src/akkudoktoreos/prediction/loadvrm.py new file mode 100644 index 0000000..1d84bbf --- /dev/null +++ b/src/akkudoktoreos/prediction/loadvrm.py @@ -0,0 +1,109 @@ +"""Retrieves load forecast data from VRM API.""" + +from typing import Any, Optional, Union + +import requests +from loguru import logger +from pendulum import DateTime +from pydantic import Field, ValidationError + +from akkudoktoreos.config.configabc import SettingsBaseModel +from akkudoktoreos.core.pydantic import PydanticBaseModel +from akkudoktoreos.prediction.loadabc import LoadProvider +from akkudoktoreos.utils.datetimeutil import to_datetime + + +class VrmForecastRecords(PydanticBaseModel): + vrm_consumption_fc: list[tuple[int, float]] + solar_yield_forecast: list[tuple[int, float]] + + +class VrmForecastResponse(PydanticBaseModel): + success: bool + records: VrmForecastRecords + totals: dict + + +class LoadVrmCommonSettings(SettingsBaseModel): + """Common settings for VRM API.""" + + load_vrm_token: str = Field( + default="your-token", description="Token for Connecting VRM API", examples=["your-token"] + ) + load_vrm_idsite: int = Field(default=12345, description="VRM-Installation-ID", examples=[12345]) + + +class LoadVrm(LoadProvider): + """Fetch Load forecast data from VRM API.""" + + @classmethod + def provider_id(cls) -> str: + return "LoadVrm" + + @classmethod + def _validate_data(cls, json_str: Union[bytes, Any]) -> VrmForecastResponse: + """Validate the VRM API load forecast response.""" + try: + return VrmForecastResponse.model_validate_json(json_str) + except ValidationError as e: + error_msg = "\n".join( + f"Field: {' -> '.join(str(x) for x in err['loc'])}\n" + f"Error: {err['msg']}\nType: {err['type']}" + for err in e.errors() + ) + logger.error(f"VRM-API schema validation failed:\n{error_msg}") + raise ValueError(error_msg) + + def _request_forecast(self, start_ts: int, end_ts: int) -> VrmForecastResponse: + """Fetch forecast data from Victron VRM API.""" + base_url = "https://vrmapi.victronenergy.com/v2/installations" + installation_id = self.config.load.provider_settings.load_vrm_idsite + api_token = self.config.load.provider_settings.load_vrm_token + + url = f"{base_url}/{installation_id}/stats?type=forecast&start={start_ts}&end={end_ts}&interval=hours" + headers = {"X-Authorization": f"Token {api_token}", "Content-Type": "application/json"} + + logger.debug(f"Requesting VRM load forecast: {url}") + try: + response = requests.get(url, headers=headers, timeout=30) + response.raise_for_status() + except requests.RequestException as e: + logger.error(f"Error during VRM API request: {e}") + raise RuntimeError("Failed to fetch load forecast from VRM API") from e + + self.update_datetime = to_datetime(in_timezone=self.config.general.timezone) + return self._validate_data(response.content) + + def _ts_to_datetime(self, timestamp: int) -> DateTime: + """Convert UNIX ms timestamp to timezone-aware datetime.""" + return to_datetime(timestamp / 1000, in_timezone=self.config.general.timezone) + + def _update_data(self, force_update: Optional[bool] = False) -> None: + """Fetch and store VRM load forecast as load_mean and related values.""" + start_date = self.start_datetime.start_of("day") + end_date = self.start_datetime.add(hours=self.config.prediction.hours) + start_ts = int(start_date.timestamp()) + end_ts = int(end_date.timestamp()) + + logger.info(f"Updating Load forecast from VRM: {start_date} to {end_date}") + vrm_forecast_data = self._request_forecast(start_ts, end_ts) + + load_mean_data = [] + for timestamp, value in vrm_forecast_data.records.vrm_consumption_fc: + date = self._ts_to_datetime(timestamp) + rounded_value = round(value, 2) + + self.update_value( + date, + {"load_mean": rounded_value, "load_std": 0.0, "load_mean_adjusted": rounded_value}, + ) + + load_mean_data.append((date, rounded_value)) + + logger.debug(f"Updated load_mean with {len(load_mean_data)} entries.") + self.update_datetime = to_datetime(in_timezone=self.config.general.timezone) + + +if __name__ == "__main__": + lv = LoadVrm() + lv._update_data() diff --git a/src/akkudoktoreos/prediction/prediction.py b/src/akkudoktoreos/prediction/prediction.py index a147bf9..f3f7fde 100644 --- a/src/akkudoktoreos/prediction/prediction.py +++ b/src/akkudoktoreos/prediction/prediction.py @@ -36,9 +36,11 @@ from akkudoktoreos.prediction.elecpriceenergycharts import ElecPriceEnergyCharts from akkudoktoreos.prediction.elecpriceimport import ElecPriceImport from akkudoktoreos.prediction.loadakkudoktor import LoadAkkudoktor from akkudoktoreos.prediction.loadimport import LoadImport +from akkudoktoreos.prediction.loadvrm import LoadVrm from akkudoktoreos.prediction.predictionabc import PredictionContainer from akkudoktoreos.prediction.pvforecastakkudoktor import PVForecastAkkudoktor from akkudoktoreos.prediction.pvforecastimport import PVForecastImport +from akkudoktoreos.prediction.pvforecastvrm import PVForecastVrm from akkudoktoreos.prediction.weatherbrightsky import WeatherBrightSky from akkudoktoreos.prediction.weatherclearoutside import WeatherClearOutside from akkudoktoreos.prediction.weatherimport import WeatherImport @@ -87,8 +89,10 @@ class Prediction(PredictionContainer): ElecPriceEnergyCharts, ElecPriceImport, LoadAkkudoktor, + LoadVrm, LoadImport, PVForecastAkkudoktor, + PVForecastVrm, PVForecastImport, WeatherBrightSky, WeatherClearOutside, @@ -102,8 +106,10 @@ elecprice_akkudoktor = ElecPriceAkkudoktor() elecprice_energy_charts = ElecPriceEnergyCharts() elecprice_import = ElecPriceImport() load_akkudoktor = LoadAkkudoktor() +load_vrm = LoadVrm() load_import = LoadImport() pvforecast_akkudoktor = PVForecastAkkudoktor() +pvforecast_vrm = PVForecastVrm() pvforecast_import = PVForecastImport() weather_brightsky = WeatherBrightSky() weather_clearoutside = WeatherClearOutside() @@ -120,8 +126,10 @@ def get_prediction() -> Prediction: elecprice_energy_charts, elecprice_import, load_akkudoktor, + load_vrm, load_import, pvforecast_akkudoktor, + pvforecast_vrm, pvforecast_import, weather_brightsky, weather_clearoutside, diff --git a/src/akkudoktoreos/prediction/pvforecast.py b/src/akkudoktoreos/prediction/pvforecast.py index 2bd93b6..1dc9c88 100644 --- a/src/akkudoktoreos/prediction/pvforecast.py +++ b/src/akkudoktoreos/prediction/pvforecast.py @@ -1,6 +1,6 @@ """PV forecast module for PV power predictions.""" -from typing import Any, List, Optional, Self +from typing import Any, List, Optional, Self, Union from pydantic import Field, computed_field, field_validator, model_validator @@ -8,6 +8,7 @@ from akkudoktoreos.config.configabc import SettingsBaseModel from akkudoktoreos.prediction.prediction import get_prediction from akkudoktoreos.prediction.pvforecastabc import PVForecastProvider from akkudoktoreos.prediction.pvforecastimport import PVForecastImportCommonSettings +from akkudoktoreos.prediction.pvforecastvrm import PVforecastVrmCommonSettings from akkudoktoreos.utils.docs import get_model_structure_from_examples prediction_eos = get_prediction() @@ -134,9 +135,9 @@ class PVForecastCommonSettings(SettingsBaseModel): examples=["PVForecastAkkudoktor"], ) - provider_settings: Optional[PVForecastImportCommonSettings] = Field( - default=None, description="Provider settings", examples=[None] - ) + provider_settings: Optional[ + Union[PVForecastImportCommonSettings, PVforecastVrmCommonSettings] + ] = Field(default=None, description="Provider settings", examples=[None]) planes: Optional[list[PVForecastPlaneSetting]] = Field( default=None, diff --git a/src/akkudoktoreos/prediction/pvforecastvrm.py b/src/akkudoktoreos/prediction/pvforecastvrm.py new file mode 100644 index 0000000..7d3ccd4 --- /dev/null +++ b/src/akkudoktoreos/prediction/pvforecastvrm.py @@ -0,0 +1,110 @@ +"""Retrieves pvforecast data from VRM API.""" + +from typing import Any, Optional, Union + +import requests +from loguru import logger +from pendulum import DateTime +from pydantic import Field, ValidationError + +from akkudoktoreos.config.configabc import SettingsBaseModel +from akkudoktoreos.core.pydantic import PydanticBaseModel +from akkudoktoreos.prediction.pvforecastabc import PVForecastProvider +from akkudoktoreos.utils.datetimeutil import to_datetime + + +class VrmForecastRecords(PydanticBaseModel): + vrm_consumption_fc: list[tuple[int, float]] + solar_yield_forecast: list[tuple[int, float]] + + +class VrmForecastResponse(PydanticBaseModel): + success: bool + records: VrmForecastRecords + totals: dict + + +class PVforecastVrmCommonSettings(SettingsBaseModel): + """Common settings for VRM API.""" + + pvforecast_vrm_token: str = Field( + default="your-token", description="Token for Connecting VRM API", examples=["your-token"] + ) + pvforecast_vrm_idsite: int = Field( + default=12345, description="VRM-Installation-ID", examples=[12345] + ) + + +class PVForecastVrm(PVForecastProvider): + """Fetch and process PV forecast data from VRM API.""" + + @classmethod + def provider_id(cls) -> str: + """Return the unique identifier for the PV-Forecast-Provider.""" + return "PVForecastVrm" + + @classmethod + def _validate_data(cls, json_str: Union[bytes, Any]) -> VrmForecastResponse: + """Validate the VRM forecast response data against the expected schema.""" + try: + return VrmForecastResponse.model_validate_json(json_str) + except ValidationError as e: + error_msg = "\n".join( + f"Field: {' -> '.join(str(x) for x in err['loc'])}\n" + f"Error: {err['msg']}\nType: {err['type']}" + for err in e.errors() + ) + logger.error(f"VRM-API schema change:\n{error_msg}") + raise ValueError(error_msg) + + def _request_forecast(self, start_ts: int, end_ts: int) -> VrmForecastResponse: + """Fetch forecast data from Victron VRM API.""" + source = "https://vrmapi.victronenergy.com/v2/installations" + id_site = self.config.pvforecast.provider_settings.pvforecast_vrm_idsite + api_token = self.config.pvforecast.provider_settings.pvforecast_vrm_token + headers = {"X-Authorization": f"Token {api_token}", "Content-Type": "application/json"} + url = f"{source}/{id_site}/stats?type=forecast&start={start_ts}&end={end_ts}&interval=hours" + logger.debug(f"Requesting VRM forecast: {url}") + + try: + response = requests.get(url, headers=headers, timeout=30) + response.raise_for_status() + except requests.RequestException as e: + logger.error(f"Failed to fetch pvforecast: {e}") + raise RuntimeError("Failed to fetch pvforecast from VRM API") from e + + self.update_datetime = to_datetime(in_timezone=self.config.general.timezone) + return self._validate_data(response.content) + + def _ts_to_datetime(self, timestamp: int) -> DateTime: + """Convert UNIX ms timestamp to timezone-aware datetime.""" + return to_datetime(timestamp / 1000, in_timezone=self.config.general.timezone) + + def _update_data(self, force_update: Optional[bool] = False) -> None: + """Update forecast data in the PVForecastDataRecord format.""" + start_date = self.start_datetime.start_of("day") + end_date = self.start_datetime.add(hours=self.config.prediction.hours) + start_ts = int(start_date.timestamp()) + end_ts = int(end_date.timestamp()) + + logger.info(f"Updating PV forecast from VRM: {start_date} to {end_date}") + vrm_forecast_data = self._request_forecast(start_ts, end_ts) + + pv_forecast = [] + for timestamp, value in vrm_forecast_data.records.solar_yield_forecast: + date = self._ts_to_datetime(timestamp) + dc_power = round(value, 2) + ac_power = round(dc_power * 0.96, 2) + self.update_value( + date, {"pvforecast_dc_power": dc_power, "pvforecast_ac_power": ac_power} + ) + pv_forecast.append((date, dc_power)) + + logger.debug(f"Updated pvforecast_dc_power with {len(pv_forecast)} entries.") + self.update_datetime = to_datetime(in_timezone=self.config.general.timezone) + + +# Example usage +if __name__ == "__main__": + pv = PVForecastVrm() + pv._update_data() diff --git a/tests/test_loadvrm.py b/tests/test_loadvrm.py new file mode 100644 index 0000000..eca4523 --- /dev/null +++ b/tests/test_loadvrm.py @@ -0,0 +1,116 @@ +import json +from unittest.mock import call, patch + +import pendulum +import pytest +import requests + +from akkudoktoreos.prediction.loadvrm import ( + LoadVrm, + VrmForecastRecords, + VrmForecastResponse, +) + + +@pytest.fixture +def load_vrm_instance(config_eos): + # Settings für LoadVrm + settings = { + "load": { + "provider": "LoadVrm", + "provider_settings": { + "load_vrm_token": "dummy-token", + "load_vrm_idsite": 12345 + } + } + } + config_eos.merge_settings_from_dict(settings) + # start_datetime initialize + start_dt = pendulum.datetime(2025, 1, 1, tz='Europe/Berlin') + + # create LoadVrm-instance with config and start_datetime + lv = LoadVrm(config=config_eos.load, start_datetime=start_dt) + + return lv + + +def mock_forecast_response(): + """Return a fake VrmForecastResponse with sample data.""" + return VrmForecastResponse( + success=True, + records=VrmForecastRecords( + vrm_consumption_fc=[ + (pendulum.datetime(2025, 1, 1, 0, 0, tz='Europe/Berlin').int_timestamp * 1000, 100.5), + (pendulum.datetime(2025, 1, 1, 1, 0, tz='Europe/Berlin').int_timestamp * 1000, 101.2) + ], + solar_yield_forecast=[] + ), + totals={} + ) + + +def test_update_data_calls_update_value(load_vrm_instance): + with patch.object(load_vrm_instance, "_request_forecast", return_value=mock_forecast_response()), \ + patch.object(LoadVrm, "update_value") as mock_update: + + load_vrm_instance._update_data() + + assert mock_update.call_count == 2 + + expected_calls = [ + call( + pendulum.datetime(2025, 1, 1, 0, 0, 0, tz='Europe/Berlin'), + {"load_mean": 100.5, "load_std": 0.0, "load_mean_adjusted": 100.5} + ), + call( + pendulum.datetime(2025, 1, 1, 1, 0, 0, tz='Europe/Berlin'), + {"load_mean": 101.2, "load_std": 0.0, "load_mean_adjusted": 101.2} + ), + ] + + mock_update.assert_has_calls(expected_calls, any_order=False) + + +def test_validate_data_accepts_valid_json(): + """Test that _validate_data doesn't raise with valid input.""" + response = mock_forecast_response() + json_data = response.model_dump_json() + + validated = LoadVrm._validate_data(json_data) + assert validated.success + assert len(validated.records.vrm_consumption_fc) == 2 + + +def test_validate_data_raises_on_invalid_json(): + """_validate_data should raise ValueError on schema mismatch.""" + invalid_json = json.dumps({"success": True}) # missing 'records' + + with pytest.raises(ValueError) as exc_info: + LoadVrm._validate_data(invalid_json) + + assert "Field:" in str(exc_info.value) + assert "records" in str(exc_info.value) + + +def test_request_forecast_raises_on_http_error(load_vrm_instance): + with patch("requests.get", side_effect=requests.Timeout("Request timed out")) as mock_get: + with pytest.raises(RuntimeError) as exc_info: + load_vrm_instance._request_forecast(0, 1) + + assert "Failed to fetch load forecast" in str(exc_info.value) + mock_get.assert_called_once() + + +def test_update_data_does_nothing_on_empty_forecast(load_vrm_instance): + empty_response = VrmForecastResponse( + success=True, + records=VrmForecastRecords(vrm_consumption_fc=[], solar_yield_forecast=[]), + totals={} + ) + + with patch.object(load_vrm_instance, "_request_forecast", return_value=empty_response), \ + patch.object(LoadVrm, "update_value") as mock_update: + + load_vrm_instance._update_data() + + mock_update.assert_not_called() diff --git a/tests/test_prediction.py b/tests/test_prediction.py index 18331b5..de5fbbf 100644 --- a/tests/test_prediction.py +++ b/tests/test_prediction.py @@ -6,6 +6,7 @@ from akkudoktoreos.prediction.elecpriceenergycharts import ElecPriceEnergyCharts from akkudoktoreos.prediction.elecpriceimport import ElecPriceImport from akkudoktoreos.prediction.loadakkudoktor import LoadAkkudoktor from akkudoktoreos.prediction.loadimport import LoadImport +from akkudoktoreos.prediction.loadvrm import LoadVrm from akkudoktoreos.prediction.prediction import ( Prediction, PredictionCommonSettings, @@ -13,6 +14,7 @@ from akkudoktoreos.prediction.prediction import ( ) from akkudoktoreos.prediction.pvforecastakkudoktor import PVForecastAkkudoktor from akkudoktoreos.prediction.pvforecastimport import PVForecastImport +from akkudoktoreos.prediction.pvforecastvrm import PVForecastVrm from akkudoktoreos.prediction.weatherbrightsky import WeatherBrightSky from akkudoktoreos.prediction.weatherclearoutside import WeatherClearOutside from akkudoktoreos.prediction.weatherimport import WeatherImport @@ -32,8 +34,10 @@ def forecast_providers(): ElecPriceEnergyCharts(), ElecPriceImport(), LoadAkkudoktor(), + LoadVrm(), LoadImport(), PVForecastAkkudoktor(), + PVForecastVrm(), PVForecastImport(), WeatherBrightSky(), WeatherClearOutside(), @@ -73,12 +77,14 @@ def test_provider_sequence(prediction): assert isinstance(prediction.providers[1], ElecPriceEnergyCharts) assert isinstance(prediction.providers[2], ElecPriceImport) assert isinstance(prediction.providers[3], LoadAkkudoktor) - assert isinstance(prediction.providers[4], LoadImport) - assert isinstance(prediction.providers[5], PVForecastAkkudoktor) - assert isinstance(prediction.providers[6], PVForecastImport) - assert isinstance(prediction.providers[7], WeatherBrightSky) - assert isinstance(prediction.providers[8], WeatherClearOutside) - assert isinstance(prediction.providers[9], WeatherImport) + assert isinstance(prediction.providers[4], LoadVrm) + assert isinstance(prediction.providers[5], LoadImport) + assert isinstance(prediction.providers[6], PVForecastAkkudoktor) + assert isinstance(prediction.providers[7], PVForecastVrm) + assert isinstance(prediction.providers[8], PVForecastImport) + assert isinstance(prediction.providers[9], WeatherBrightSky) + assert isinstance(prediction.providers[10], WeatherClearOutside) + assert isinstance(prediction.providers[11], WeatherImport) def test_provider_by_id(prediction, forecast_providers): @@ -95,8 +101,10 @@ def test_prediction_repr(prediction): assert "ElecPriceEnergyCharts" in result assert "ElecPriceImport" in result assert "LoadAkkudoktor" in result + assert "LoadVrm" in result assert "LoadImport" in result assert "PVForecastAkkudoktor" in result + assert "PVForecastVrm" in result assert "PVForecastImport" in result assert "WeatherBrightSky" in result assert "WeatherClearOutside" in result diff --git a/tests/test_pvforecastvrm.py b/tests/test_pvforecastvrm.py new file mode 100644 index 0000000..4aa3740 --- /dev/null +++ b/tests/test_pvforecastvrm.py @@ -0,0 +1,116 @@ +import json +from unittest.mock import call, patch + +import pendulum +import pytest +import requests + +from akkudoktoreos.prediction.pvforecastvrm import ( + PVForecastVrm, + VrmForecastRecords, + VrmForecastResponse, +) + + +@pytest.fixture +def pvforecast_instance(config_eos): + # Settings for PVForecastVrm + settings = { + "pvforecast": { + "provider": "PVForecastVrm", + "provider_settings": { + "pvforecast_vrm_token": "dummy-token", + "pvforecast_vrm_idsite": 12345 + } + } + } + config_eos.merge_settings_from_dict(settings) + # start_datetime initialize + start_dt = pendulum.datetime(2025, 1, 1, tz='Europe/Berlin') + + # create PVForecastVrm-instance with config and start_datetime + pv = PVForecastVrm(config=config_eos.load, start_datetime=start_dt) + + return pv + + +def mock_forecast_response(): + """Return a fake VrmForecastResponse with sample data.""" + return VrmForecastResponse( + success=True, + records=VrmForecastRecords( + vrm_consumption_fc=[], + solar_yield_forecast=[ + (pendulum.datetime(2025, 1, 1, 0, 0, tz='Europe/Berlin').int_timestamp * 1000, 120.0), + (pendulum.datetime(2025, 1, 1, 1, 0, tz='Europe/Berlin').int_timestamp * 1000, 130.0) + ] + ), + totals={} + ) + + +def test_update_data_updates_dc_and_ac_power(pvforecast_instance): + with patch.object(pvforecast_instance, "_request_forecast", return_value=mock_forecast_response()), \ + patch.object(PVForecastVrm, "update_value") as mock_update: + + pvforecast_instance._update_data() + + # Check that update_value was called correctly + assert mock_update.call_count == 2 + + expected_calls = [ + call( + pendulum.datetime(2025, 1, 1, 0, 0, tz='Europe/Berlin'), + {"pvforecast_dc_power": 120.0, "pvforecast_ac_power": 115.2} + ), + call( + pendulum.datetime(2025, 1, 1, 1, 0, tz='Europe/Berlin'), + {"pvforecast_dc_power": 130.0, "pvforecast_ac_power": 124.8} + ), + ] + + mock_update.assert_has_calls(expected_calls, any_order=False) + + +def test_validate_data_accepts_valid_json(): + """Test that _validate_data doesn't raise with valid input.""" + response = mock_forecast_response() + json_data = response.model_dump_json() + + validated = PVForecastVrm._validate_data(json_data) + assert validated.success + assert len(validated.records.solar_yield_forecast) == 2 + + +def test_validate_data_invalid_json_raises(): + """Test that _validate_data raises with invalid input.""" + invalid_json = json.dumps({"success": True}) # missing 'records' + with pytest.raises(ValueError) as exc_info: + PVForecastVrm._validate_data(invalid_json) + assert "Field:" in str(exc_info.value) + assert "records" in str(exc_info.value) + + +def test_request_forecast_raises_on_http_error(pvforecast_instance): + """Ensure _request_forecast raises RuntimeError on HTTP failure.""" + with patch("requests.get", side_effect=requests.Timeout("Request timed out")) as mock_get: + with pytest.raises(RuntimeError) as exc_info: + pvforecast_instance._request_forecast(0, 1) + + assert "Failed to fetch pvforecast" in str(exc_info.value) + mock_get.assert_called_once() + + +def test_update_data_skips_on_empty_forecast(pvforecast_instance): + """Ensure no update_value calls are made if no forecast data is present.""" + empty_response = VrmForecastResponse( + success=True, + records=VrmForecastRecords(vrm_consumption_fc=[], solar_yield_forecast=[]), + totals={} + ) + + with patch.object(pvforecast_instance, "_request_forecast", return_value=empty_response), \ + patch.object(PVForecastVrm, "update_value") as mock_update: + + pvforecast_instance._update_data() + mock_update.assert_not_called()