feat: add fixed electricity prediction with time window support (#930)
Some checks are pending
Bump Version / Bump Version Workflow (push) Waiting to run
docker-build / platform-excludes (push) Waiting to run
docker-build / build (push) Blocked by required conditions
docker-build / merge (push) Blocked by required conditions
pre-commit / pre-commit (push) Waiting to run
Run Pytest on Pull Request / test (push) Waiting to run

Add a fixed electricity prediction that supports prices per time window.
The time windows may flexible be defined by day or date.

The prediction documentation is updated to also cover the ElecPriceFixed
provider.

The feature includes several changes that are not directly related to the
electricity price prediction implementation but are necessary to keep
EOS running properly and to test and document the changes.

* feat: add value time windows

    Add time windows with an associated float value.

* feat: harden eos measurements endpoints error detection and reporting

    Cover more errors that may be raised during endpoint access. Report the
    errors including trace information to ease debugging.

* feat: extend server configuration to cover all arguments

    Make the argument controlled options also available in server configuration.

* fix: eos config configuration by cli arguments

    Move the command line argument handling to config eos so that it is
    excuted whenever eos config is rebuild or reset.

* chore: extend measurement endpoint system test

* chore: refactor time windows

    Move time windows to configabc as they are only used in configurations.
    Also move all tests to test_configabc.

* chore: provide config update errors in eosdash with summarized error text

    If there is an update error provide the error text as a summary. On click
    provide the full error text.

* chore: force eosdash ip address and port in makefile dev run

    Ensure eosdash ip address and port are correctly set for development runs.

Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
This commit is contained in:
Bobby Noelte
2026-03-11 17:18:45 +01:00
committed by GitHub
parent 850d6b7c74
commit cf477d91a3
35 changed files with 3778 additions and 1491 deletions

View File

@@ -8,7 +8,7 @@
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "v0.2.0.dev2603071785688456"
"version": "v0.2.0.dev2603110720349451"
},
"paths": {
"/v1/admin/cache/clear": {
@@ -929,7 +929,6 @@
"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": {
@@ -3371,6 +3370,10 @@
1.19
]
},
"elecpricefixed": {
"$ref": "#/components/schemas/ElecPriceFixedCommonSettings-Input",
"description": "Fixed electricity price provider settings."
},
"elecpriceimport": {
"$ref": "#/components/schemas/ElecPriceImportCommonSettings",
"description": "Import provider settings."
@@ -3434,6 +3437,10 @@
1.19
]
},
"elecpricefixed": {
"$ref": "#/components/schemas/ElecPriceFixedCommonSettings-Output",
"description": "Fixed electricity price provider settings."
},
"elecpriceimport": {
"$ref": "#/components/schemas/ElecPriceImportCommonSettings",
"description": "Import provider settings."
@@ -3474,6 +3481,60 @@
"title": "ElecPriceEnergyChartsCommonSettings",
"description": "Common settings for Energy Charts electricity price provider."
},
"ElecPriceFixedCommonSettings-Input": {
"properties": {
"time_windows": {
"$ref": "#/components/schemas/ValueTimeWindowSequence-Input",
"description": "Sequence of time windows defining the fixed price schedule. If not provided, no fixed pricing is applied.",
"examples": [
{
"windows": [
{
"duration": "8 hours",
"start_time": "00:00",
"value": 0.288
},
{
"duration": "16 hours",
"start_time": "08:00",
"value": 0.34
}
]
}
]
}
},
"type": "object",
"title": "ElecPriceFixedCommonSettings",
"description": "Common configuration settings for fixed electricity pricing.\n\nThis model defines a fixed electricity price schedule using a sequence\nof time windows. Each window specifies a time interval and the electricity\nprice applicable during that interval."
},
"ElecPriceFixedCommonSettings-Output": {
"properties": {
"time_windows": {
"$ref": "#/components/schemas/ValueTimeWindowSequence-Output",
"description": "Sequence of time windows defining the fixed price schedule. If not provided, no fixed pricing is applied.",
"examples": [
{
"windows": [
{
"duration": "8 hours",
"start_time": "00:00",
"value": 0.288
},
{
"duration": "16 hours",
"start_time": "08:00",
"value": 0.34
}
]
}
]
}
},
"type": "object",
"title": "ElecPriceFixedCommonSettings",
"description": "Common configuration settings for fixed electricity pricing.\n\nThis model defines a fixed electricity price schedule using a sequence\nof time windows. Each window specifies a time interval and the electricity\nprice applicable during that interval."
},
"ElecPriceImportCommonSettings": {
"properties": {
"import_file_path": {
@@ -8369,6 +8430,38 @@
"examples": [
10
]
},
"run_as_user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Run As User",
"description": "The name of the target user to switch to. If ``None`` (default), the current effective user is used and no privilege change is attempted.",
"examples": [
null,
"user"
]
},
"reload": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Reload",
"description": "Enable server auto-reload for debugging or development. Default is False. Monitors the package directory for changes and reloads the server.",
"default": false,
"examples": [
true
]
}
},
"type": "object",
@@ -8704,13 +8797,19 @@
"properties": {
"start_time": {
"title": "Start Time",
"description": "Start time of the time window (time of day)."
"description": "Naive start time of the time window (time of day, no timezone). Interpreted in the timezone of the datetime passed to contains() or earliest_start_time().",
"examples": [
"00:00:00"
]
},
"duration": {
"type": "string",
"format": "duration",
"title": "Duration",
"description": "Duration of the time window starting from `start_time`."
"description": "Duration of the time window starting from `start_time`.",
"examples": [
"2 hours"
]
},
"day_of_week": {
"anyOf": [
@@ -8725,7 +8824,10 @@
}
],
"title": "Day Of Week",
"description": "Optional day of the week restriction. Can be specified as integer (0=Monday to 6=Sunday) or localized weekday name. If None, applies every day unless `date` is set."
"description": "Optional day of the week restriction. Can be specified as integer (0=Monday to 6=Sunday) or localized weekday name. If None, applies every day unless `date` is set.",
"examples": [
null
]
},
"date": {
"anyOf": [
@@ -8738,7 +8840,10 @@
}
],
"title": "Date",
"description": "Optional specific calendar date for the time window. Overrides `day_of_week` if set."
"description": "Optional specific calendar date for the time window. Naive \u2014 matched against the local date of the datetime passed to contains(). Overrides `day_of_week` if set.",
"examples": [
null
]
},
"locale": {
"anyOf": [
@@ -8750,7 +8855,10 @@
}
],
"title": "Locale",
"description": "Locale used to parse weekday names in `day_of_week` when given as string. If not set, Pendulum's default locale is used. Examples: 'en', 'de', 'fr', etc."
"description": "Locale used to parse weekday names in `day_of_week` when given as string. If not set, Pendulum's default locale is used. Examples: 'en', 'de', 'fr', etc.",
"examples": [
null
]
}
},
"type": "object",
@@ -8759,19 +8867,25 @@
"duration"
],
"title": "TimeWindow",
"description": "Model defining a daily or specific date time window with optional localization support.\n\nRepresents a time interval starting at `start_time` and lasting for `duration`.\nCan restrict applicability to a specific day of the week or a specific calendar date.\nSupports day names in multiple languages via locale-aware parsing."
"description": "Model defining a daily or date time window with optional localization support.\n\nRepresents a time interval starting at `start_time` and lasting for `duration`.\nCan restrict applicability to a specific day of the week or a specific calendar date.\nSupports day names in multiple languages via locale-aware parsing.\n\nTimezone contract:\n\n``start_time`` is always **naive** (no ``tzinfo``). It is interpreted as a\nlocal wall-clock time in whatever timezone the caller's ``date_time`` or\n``reference_date`` carries. When those arguments are timezone-aware the\nwindow boundaries are evaluated in that timezone; when they are naive,\narithmetic is performed as-is (no timezone conversion occurs).\n\n``date``, being a calendar ``Date`` object, is inherently timezone-free.\n\nThis design avoids the ambiguity that arises when a stored ``start_time``\ncarries its own timezone that differs from the caller's timezone, and keeps\nthe model serialisable without timezone state."
},
"TimeWindow-Output": {
"properties": {
"start_time": {
"type": "string",
"title": "Start Time",
"description": "Start time of the time window (time of day)."
"description": "Naive start time of the time window (time of day, no timezone). Interpreted in the timezone of the datetime passed to contains() or earliest_start_time().",
"examples": [
"00:00:00"
]
},
"duration": {
"type": "string",
"title": "Duration",
"description": "Duration of the time window starting from `start_time`."
"description": "Duration of the time window starting from `start_time`.",
"examples": [
"2 hours"
]
},
"day_of_week": {
"anyOf": [
@@ -8786,7 +8900,10 @@
}
],
"title": "Day Of Week",
"description": "Optional day of the week restriction. Can be specified as integer (0=Monday to 6=Sunday) or localized weekday name. If None, applies every day unless `date` is set."
"description": "Optional day of the week restriction. Can be specified as integer (0=Monday to 6=Sunday) or localized weekday name. If None, applies every day unless `date` is set.",
"examples": [
null
]
},
"date": {
"anyOf": [
@@ -8799,7 +8916,10 @@
}
],
"title": "Date",
"description": "Optional specific calendar date for the time window. Overrides `day_of_week` if set."
"description": "Optional specific calendar date for the time window. Naive \u2014 matched against the local date of the datetime passed to contains(). Overrides `day_of_week` if set.",
"examples": [
null
]
},
"locale": {
"anyOf": [
@@ -8811,7 +8931,10 @@
}
],
"title": "Locale",
"description": "Locale used to parse weekday names in `day_of_week` when given as string. If not set, Pendulum's default locale is used. Examples: 'en', 'de', 'fr', etc."
"description": "Locale used to parse weekday names in `day_of_week` when given as string. If not set, Pendulum's default locale is used. Examples: 'en', 'de', 'fr', etc.",
"examples": [
null
]
}
},
"type": "object",
@@ -8820,22 +8943,15 @@
"duration"
],
"title": "TimeWindow",
"description": "Model defining a daily or specific date time window with optional localization support.\n\nRepresents a time interval starting at `start_time` and lasting for `duration`.\nCan restrict applicability to a specific day of the week or a specific calendar date.\nSupports day names in multiple languages via locale-aware parsing."
"description": "Model defining a daily or date time window with optional localization support.\n\nRepresents a time interval starting at `start_time` and lasting for `duration`.\nCan restrict applicability to a specific day of the week or a specific calendar date.\nSupports day names in multiple languages via locale-aware parsing.\n\nTimezone contract:\n\n``start_time`` is always **naive** (no ``tzinfo``). It is interpreted as a\nlocal wall-clock time in whatever timezone the caller's ``date_time`` or\n``reference_date`` carries. When those arguments are timezone-aware the\nwindow boundaries are evaluated in that timezone; when they are naive,\narithmetic is performed as-is (no timezone conversion occurs).\n\n``date``, being a calendar ``Date`` object, is inherently timezone-free.\n\nThis design avoids the ambiguity that arises when a stored ``start_time``\ncarries its own timezone that differs from the caller's timezone, and keeps\nthe model serialisable without timezone state."
},
"TimeWindowSequence-Input": {
"properties": {
"windows": {
"anyOf": [
{
"items": {
"$ref": "#/components/schemas/TimeWindow-Input"
},
"type": "array"
},
{
"type": "null"
}
],
"items": {
"$ref": "#/components/schemas/TimeWindow-Input"
},
"type": "array",
"title": "Windows",
"description": "List of TimeWindow objects that make up this sequence."
}
@@ -8847,17 +8963,10 @@
"TimeWindowSequence-Output": {
"properties": {
"windows": {
"anyOf": [
{
"items": {
"$ref": "#/components/schemas/TimeWindow-Output"
},
"type": "array"
},
{
"type": "null"
}
],
"items": {
"$ref": "#/components/schemas/TimeWindow-Output"
},
"type": "array",
"title": "Windows",
"description": "List of TimeWindow objects that make up this sequence."
}
@@ -8912,6 +9021,220 @@
],
"title": "ValidationError"
},
"ValueTimeWindow-Input": {
"properties": {
"start_time": {
"title": "Start Time",
"description": "Naive start time of the time window (time of day, no timezone). Interpreted in the timezone of the datetime passed to contains() or earliest_start_time().",
"examples": [
"00:00:00"
]
},
"duration": {
"type": "string",
"format": "duration",
"title": "Duration",
"description": "Duration of the time window starting from `start_time`.",
"examples": [
"2 hours"
]
},
"day_of_week": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Day Of Week",
"description": "Optional day of the week restriction. Can be specified as integer (0=Monday to 6=Sunday) or localized weekday name. If None, applies every day unless `date` is set.",
"examples": [
null
]
},
"date": {
"anyOf": [
{
"type": "string",
"format": "date"
},
{
"type": "null"
}
],
"title": "Date",
"description": "Optional specific calendar date for the time window. Naive \u2014 matched against the local date of the datetime passed to contains(). Overrides `day_of_week` if set.",
"examples": [
null
]
},
"locale": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Locale",
"description": "Locale used to parse weekday names in `day_of_week` when given as string. If not set, Pendulum's default locale is used. Examples: 'en', 'de', 'fr', etc.",
"examples": [
null
]
},
"value": {
"anyOf": [
{
"type": "number",
"minimum": 0.0
},
{
"type": "null"
}
],
"title": "Value",
"description": "Value applicable during this time window.",
"examples": [
0.288
]
}
},
"type": "object",
"required": [
"start_time",
"duration"
],
"title": "ValueTimeWindow",
"description": "Value applicable during a specific time window.\n\nThis model extends `TimeWindow` by associating a value with the defined time interval."
},
"ValueTimeWindow-Output": {
"properties": {
"start_time": {
"type": "string",
"title": "Start Time",
"description": "Naive start time of the time window (time of day, no timezone). Interpreted in the timezone of the datetime passed to contains() or earliest_start_time().",
"examples": [
"00:00:00"
]
},
"duration": {
"type": "string",
"title": "Duration",
"description": "Duration of the time window starting from `start_time`.",
"examples": [
"2 hours"
]
},
"day_of_week": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Day Of Week",
"description": "Optional day of the week restriction. Can be specified as integer (0=Monday to 6=Sunday) or localized weekday name. If None, applies every day unless `date` is set.",
"examples": [
null
]
},
"date": {
"anyOf": [
{
"type": "string",
"format": "date"
},
{
"type": "null"
}
],
"title": "Date",
"description": "Optional specific calendar date for the time window. Naive \u2014 matched against the local date of the datetime passed to contains(). Overrides `day_of_week` if set.",
"examples": [
null
]
},
"locale": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Locale",
"description": "Locale used to parse weekday names in `day_of_week` when given as string. If not set, Pendulum's default locale is used. Examples: 'en', 'de', 'fr', etc.",
"examples": [
null
]
},
"value": {
"anyOf": [
{
"type": "number",
"minimum": 0.0
},
{
"type": "null"
}
],
"title": "Value",
"description": "Value applicable during this time window.",
"examples": [
0.288
]
}
},
"type": "object",
"required": [
"start_time",
"duration"
],
"title": "ValueTimeWindow",
"description": "Value applicable during a specific time window.\n\nThis model extends `TimeWindow` by associating a value with the defined time interval."
},
"ValueTimeWindowSequence-Input": {
"properties": {
"windows": {
"items": {
"$ref": "#/components/schemas/ValueTimeWindow-Input"
},
"type": "array",
"title": "Windows",
"description": "Ordered list of value time windows. Each window defines a time interval and an associated value."
}
},
"type": "object",
"title": "ValueTimeWindowSequence",
"description": "Sequence of value time windows.\n\nThis model specializes `TimeWindowSequence` to ensure that all\ncontained windows are instances of `ValueTimeWindow`.\nIt provides the full set of sequence operations (containment checks,\navailability, start time calculations) for value windows."
},
"ValueTimeWindowSequence-Output": {
"properties": {
"windows": {
"items": {
"$ref": "#/components/schemas/ValueTimeWindow-Output"
},
"type": "array",
"title": "Windows",
"description": "Ordered list of value time windows. Each window defines a time interval and an associated value."
}
},
"type": "object",
"title": "ValueTimeWindowSequence",
"description": "Sequence of value time windows.\n\nThis model specializes `TimeWindowSequence` to ensure that all\ncontained windows are instances of `ValueTimeWindow`.\nIt provides the full set of sequence operations (containment checks,\navailability, start time calculations) for value windows."
},
"WeatherCommonProviderSettings": {
"properties": {
"WeatherImport": {