mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-08-31 12:46:38 +00:00
feat(optimization): schedule any number of flexible consumers
Replace the single hourly "dishwasher" home appliance with a list of flexible consumers (home_appliances). Each consumer defines its load either as an explicit power profile (energy-preservingly resampled onto the optimization slot grid, incl. 15-min and non-integer interval ratios) or the flat consumption_wh/duration_h fallback, and runs ONCE or DAILY within its time windows and the optimization horizon. - ConsumerScheduleMode + shared load-definition validation (XOR of profile/fallback, reject negative/NaN/inf, unique device_id) - ApplianceGeneLayout: variable appliance gene block (index into allowed_start_slots), ONCE/DAILY calendar-day based, no snapping - per-device output: result.home_appliance_energy_wh, appliance_starts (absolute local times), per-device solution columns and DDBC RUN/OFF instructions on state transitions only - deprecate dishwasher/washingstart/Home_appliance_wh_per_hour with backward-compatible mapping and explicit conflict rejection - max_home_appliances is now an upper bound only; no demo appliance and no on/off behaviour - docs, openapi.json, CHANGELOG and optimize_result_2* fixtures updated; new tests/test_homeappliance.py covers the mandatory test matrix Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c59bf1b486
commit
67cf6f7d8a
@@ -362,7 +362,12 @@ as a cohesive unit for scheduling and availability checking.
|
||||
```
|
||||
<!-- pyml enable line-length -->
|
||||
|
||||
### Home Appliance devices base settings
|
||||
### Flexible consumer (home appliance) devices base settings
|
||||
|
||||
A consumer's load is defined **either** by an explicit power profile
|
||||
(``load_profile_power_w`` with an optional ``load_profile_interval_seconds``)
|
||||
**or** by the flat fallback ``consumption_wh`` + ``duration_h``. Exactly one
|
||||
of the two must be provided.
|
||||
|
||||
<!-- pyml disable line-length -->
|
||||
:::{table} devices::home_appliances::list
|
||||
@@ -371,10 +376,13 @@ as a cohesive unit for scheduling and availability checking.
|
||||
|
||||
| Name | Type | Read-Only | Default | Description |
|
||||
| ---- | ---- | --------- | ------- | ----------- |
|
||||
| consumption_wh | `int` | `rw` | `required` | Energy consumption [Wh]. |
|
||||
| consumption_wh | `Optional[int]` | `rw` | `None` | Flat fallback: total energy consumption of one run [Wh]. Used only when no load_profile_power_w is given. |
|
||||
| device_id | `str` | `rw` | `<unknown>` | ID of device |
|
||||
| duration_h | `int` | `rw` | `required` | Usage duration in hours [0 ... 24]. |
|
||||
| duration_h | `Optional[int]` | `rw` | `None` | Flat fallback: run duration in hours [0 ... 24]. Used only when no load_profile_power_w is given. |
|
||||
| load_profile_interval_seconds | `Optional[int]` | `rw` | `None` | Duration of one 'load_profile_power_w' step in seconds. Defaults to the configured optimization interval when a profile is given. |
|
||||
| load_profile_power_w | `Optional[list[float]]` | `rw` | `None` | Explicit load profile describing a single complete run as a sequence of non-negative power values in watts (e.g. [200.0, 2000.0, 1800.0, 100.0]). Each value covers 'load_profile_interval_seconds'. Mutually exclusive with consumption_wh/duration_h. |
|
||||
| measurement_keys | `Optional[list[str]]` | `ro` | `N/A` | Measurement keys for the home appliance stati that are measurements. |
|
||||
| schedule_mode | `<enum 'ConsumerScheduleMode'>` | `rw` | `ONCE` | Scheduling mode: ONCE (a single run within the horizon) or DAILY (one run per local calendar day with a feasible full run). |
|
||||
| time_windows | `Optional[akkudoktoreos.config.configabc.TimeWindowSequence]` | `rw` | `None` | Sequence of allowed time windows. Defaults to optimization general time window. |
|
||||
:::
|
||||
<!-- pyml enable line-length -->
|
||||
@@ -390,6 +398,9 @@ as a cohesive unit for scheduling and availability checking.
|
||||
"home_appliances": [
|
||||
{
|
||||
"device_id": "battery1",
|
||||
"load_profile_power_w": null,
|
||||
"load_profile_interval_seconds": null,
|
||||
"schedule_mode": "ONCE",
|
||||
"consumption_wh": 2000,
|
||||
"duration_h": 1,
|
||||
"time_windows": {
|
||||
@@ -421,6 +432,9 @@ as a cohesive unit for scheduling and availability checking.
|
||||
"home_appliances": [
|
||||
{
|
||||
"device_id": "battery1",
|
||||
"load_profile_power_w": null,
|
||||
"load_profile_interval_seconds": null,
|
||||
"schedule_mode": "ONCE",
|
||||
"consumption_wh": 2000,
|
||||
"duration_h": 1,
|
||||
"time_windows": {
|
||||
|
||||
@@ -257,13 +257,14 @@ The GENETIC algorithm supports 4 devices:
|
||||
- **electric_vehicle**: An electric vehicle, basically the battery of an electric vehicle. The
|
||||
The electrical vehicle is optional.
|
||||
- **battery**: A battery that can be charged by the inverter. The battery is mandatory.
|
||||
- **home_appliance**: A home appliance, like a washing machine or a dish washer. The home
|
||||
appliance is optional.
|
||||
- **home_appliance**: A flexible consumer, like a washing machine or a dish washer. Any number of
|
||||
home appliances can be configured; each is scheduled independently. Home appliances are optional.
|
||||
|
||||
:::{admonition} Warning
|
||||
:class: warning
|
||||
The GENETIC algorithm can only use the first inverter, electrical vehicle, battery, home appliance
|
||||
that is configured, even if more devices are configured.
|
||||
The GENETIC algorithm can only use the first inverter, electrical vehicle and battery that is
|
||||
configured, even if more devices are configured. Home appliances are the exception: all configured
|
||||
home appliances are scheduled.
|
||||
:::
|
||||
|
||||
#### Inverter simulation configuration
|
||||
|
||||
@@ -93,12 +93,15 @@ to `DISABLED` in the configuration.
|
||||
"initial_soc_percentage": 54,
|
||||
"min_soc_percentage": 0
|
||||
},
|
||||
"dishwasher": {
|
||||
"device_id": "dishwasher1",
|
||||
"consumption_wh": 2000,
|
||||
"duration_h": 3,
|
||||
"time_windows": null
|
||||
},
|
||||
"home_appliances": [
|
||||
{
|
||||
"device_id": "dishwasher1",
|
||||
"consumption_wh": 2000,
|
||||
"duration_h": 3,
|
||||
"schedule_mode": "ONCE",
|
||||
"time_windows": null
|
||||
}
|
||||
],
|
||||
"temperature_forecast": [
|
||||
18.3, 17.8, 16.9, 16.2, 15.6, 15.1, 14.6, 14.2, 14.3, 14.8, 15.7, 16.7, 17.4,
|
||||
18.0, 18.6, 19.2, 19.1, 18.7, 18.5, 17.7, 16.2, 14.6, 13.6, 13.0, 12.6, 12.2,
|
||||
|
||||
@@ -193,28 +193,52 @@ indicates no power transfer. Intermediate values scale the power proportionally.
|
||||
|
||||
## Home Appliance
|
||||
|
||||
The optimization algorithm supports one start of the home appliance within the optimization
|
||||
horizon.
|
||||
The optimization algorithm schedules any number of flexible consumers (home appliances). Each
|
||||
consumer has a unique `device_id` and is scheduled independently. The `schedule_mode` selects how
|
||||
often a consumer runs:
|
||||
|
||||
- `ONCE` — a single run somewhere within the optimization horizon ("fire and forget").
|
||||
- `DAILY` — one run per local calendar day that still has a feasible complete run.
|
||||
|
||||
### Home Appliance Simulation
|
||||
|
||||
Each consumer's load is described by the energy of a single complete run, resampled onto the
|
||||
optimization slot grid (hourly or 15-minute). Multiple consumers and multiple daily runs may
|
||||
overlap; their energy adds up.
|
||||
|
||||
### Home Appliance Configuration
|
||||
|
||||
Home appliance to run within the optimization horizon.
|
||||
A consumer's load is defined **either** by an explicit power profile or by the flat
|
||||
`consumption_wh` + `duration_h` fallback (exactly one of the two).
|
||||
|
||||
Two consumers, one defined by the flat fallback (runs once), one by an explicit 15-minute power
|
||||
profile that runs once per day:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"device_id": "dishwasher1",
|
||||
"consumption_wh": 2000,
|
||||
"duration_h": 3
|
||||
"duration_h": 3,
|
||||
"schedule_mode": "ONCE"
|
||||
},
|
||||
{
|
||||
"device_id": "washingmachine1",
|
||||
"load_profile_power_w": [200, 2000, 1800, 100],
|
||||
"load_profile_interval_seconds": 900,
|
||||
"schedule_mode": "DAILY"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Home appliance to run within a time window of 5 hours starting at 8:00 every day and another time
|
||||
window of 3 hours starting at 15:00 every day. See
|
||||
[Time Window Sequence Configuration](configtimewindow-page) for more information.
|
||||
- `load_profile_power_w`: non-negative power values in watts describing one complete run. Each value
|
||||
covers `load_profile_interval_seconds` (default: the configured optimization interval). The profile
|
||||
is resampled energy-preservingly onto the optimization slot grid.
|
||||
- `consumption_wh` / `duration_h`: flat fallback used when no `load_profile_power_w` is given.
|
||||
|
||||
A consumer may be restricted to run within a time window of 5 hours starting at 8:00 every day and
|
||||
another time window of 3 hours starting at 15:00 every day. The complete run must fit inside a
|
||||
single window. See [Time Window Sequence Configuration](configtimewindow-page) for more information.
|
||||
|
||||
```json
|
||||
[
|
||||
@@ -240,8 +264,8 @@ window of 3 hours starting at 15:00 every day. See
|
||||
|
||||
:::{admonition} Note
|
||||
:class: note
|
||||
The optimization algorithm always restricts to one start within the optimization horizon per
|
||||
energy management run.
|
||||
A `ONCE` consumer without any valid start (given its time windows and the horizon) is rejected. For
|
||||
`DAILY`, a calendar day without a feasible run simply gets no run for that day.
|
||||
:::
|
||||
|
||||
### Home Appliance Instructions
|
||||
|
||||
Reference in New Issue
Block a user