Skip to content

Feat: dynamic soc bounds defaults#2267

Open
BelhsanHmida wants to merge 15 commits into
feat/retire-fallback-schedulerfrom
feat/dynamic-soc-bounds-defaults
Open

Feat: dynamic soc bounds defaults#2267
BelhsanHmida wants to merge 15 commits into
feat/retire-fallback-schedulerfrom
feat/dynamic-soc-bounds-defaults

Conversation

@BelhsanHmida

@BelhsanHmida BelhsanHmida commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Description

  • Make soc-min and soc-max the canonical fields for fixed and dynamic storage SoC boundaries.
  • Allow dynamic soc-min / soc-max values through sensor references and time-series specs.
  • Add a generic default field to sensor references, so missing sensor values can be filled, e.g. {"sensor": 300, "default": "10 kWh"}.
  • Keep soc-minima and soc-maxima supported as legacy aliases for dynamic soc-min and soc-max, while marking them deprecated in docs/OpenAPI metadata.
  • Reject ambiguous payloads that define both dynamic soc-min and soc-minima, or both dynamic soc-max and soc-maxima.
  • Preserve backwards compatibility for fixed soc-min / soc-max, including existing fixed soc-min plus legacy soc-minima usage.
  • Update API examples, scheduling docs, UI schema text, and regenerated OpenAPI specs.
  • Add changelog entry

Look & Feel

N/A

Example API flex-model shape:

{
  "soc-at-start": "12 kWh",
  "soc-min": {
    "sensor": 300,
    "default": "10 kWh"
  },
  "soc-max": {
    "sensor": 301,
    "default": "25 kWh"
  },
  "power-capacity": "5 kW"
}

How to test

  • pytest:
uv run pytest \
  flexmeasures/data/schemas/tests/test_sensor.py \
  flexmeasures/data/schemas/tests/test_scheduling.py \
  flexmeasures/data/models/planning/tests/test_utils_fresh_db.py \
  flexmeasures/data/models/planning/tests/test_solver.py \
  • Manual API-style check:
    Use a storage flex-model where soc-min and soc-max are dynamic sensor references with defaults:
{
  "flex-model": {
    "soc-at-start": "12 kWh",
    "soc-min": {
      "sensor": 300,
      "default": "10 kWh"
    },
    "soc-max": {
      "sensor": 301,
      "default": "25 kWh"
    },
    "power-capacity": "5 kW"
  }
}

Expected behavior: soc-min and soc-max are treated as dynamic SoC boundaries, and missing sensor values are filled with the provided default values.

Further Improvements

  • Decide whether to add runtime deprecation warnings for soc-minima / soc-maxima.
  • Handle recurring SoC limits separately in Recurring SoC limits #2255.

Related Items


Sign-off

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on code under GPL or other license that is incompatible with FlexMeasures

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
@BelhsanHmida BelhsanHmida self-assigned this Jul 6, 2026
@BelhsanHmida BelhsanHmida changed the base branch from main to feat/retire-fallback-scheduler July 6, 2026 01:18
@BelhsanHmida BelhsanHmida requested a review from Copilot July 6, 2026 07:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates FlexMeasures’ storage flex-model schema to make soc-min / soc-max the canonical fields for both fixed and dynamic SoC boundaries, adds a default fallback to sensor references for filling missing values, and keeps soc-minima / soc-maxima as deprecated legacy aliases (including OpenAPI + docs updates).

Changes:

  • Extend VariableQuantityField / SensorReference to support a default fallback quantity and apply it when fetching belief series
  • Route dynamic soc-min / soc-max payloads to the internal dynamic-boundary handling while rejecting ambiguous combinations with legacy aliases
  • Update tests, docs, and regenerated OpenAPI specs/examples to reflect the new canonical behavior and deprecations

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
flexmeasures/ui/static/openapi-specs.json Regenerated OpenAPI specs/examples for canonical soc-min / soc-max, default fallback, and deprecated aliases
flexmeasures/data/schemas/tests/test_sensor.py Add tests for deserializing/serializing sensor references with default
flexmeasures/data/schemas/tests/test_scheduling.py Add schema tests for soc-min / soc-max dynamic sensor refs with default, plus mutual exclusivity cases
flexmeasures/data/schemas/sensors.py Implement default handling in VariableQuantityField + SensorReference and update time series schema examples
flexmeasures/data/schemas/scheduling/storage.py Switch soc_min / soc_max to VariableQuantityField, deprecate legacy metadata, and map dynamic canonical fields to legacy dynamic keys post-load
flexmeasures/data/schemas/scheduling/metadata.py Update field descriptions/examples to document canonical dynamic behavior and mark legacy aliases deprecated
flexmeasures/data/schemas/scheduling/init.py Update UI schema text for SoC boundaries and legacy alias labeling
flexmeasures/data/models/planning/utils.py Apply SensorReference.default to fill missing values in queried belief series
flexmeasures/data/models/planning/tests/test_utils_fresh_db.py Add integration test ensuring default fills missing belief slots
flexmeasures/data/models/planning/tests/test_solver.py Extend solver tests to cover canonical dynamic soc-min / soc-max and time-series cases
flexmeasures/data/models/planning/storage.py Update internal comment to reflect new deserialization routing for dynamic soc-max
flexmeasures/api/v3_0/sensors.py Update API example payload to use canonical soc-min sensor reference with default
flexmeasures/api/v3_0/assets.py Update API example payload to use canonical soc-min for time-series specs
documentation/features/scheduling.rst Update scheduling docs to describe dynamic soc-min / soc-max relaxation behavior and legacy aliases
documentation/api/introduction.rst Update API introduction note on default relaxation behavior for dynamic SoC boundaries

Comment thread flexmeasures/data/schemas/sensors.py Outdated
Comment thread flexmeasures/data/schemas/sensors.py
Comment thread flexmeasures/data/schemas/sensors.py Outdated
Comment thread flexmeasures/data/schemas/sensors.py
Comment thread flexmeasures/data/schemas/scheduling/storage.py Outdated
Comment thread documentation/api/introduction.rst
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
@BelhsanHmida

Copy link
Copy Markdown
Contributor Author

A couple of follow-up questions:

  1. I implemented default on the generic sensor reference schema rather than special-casing it for soc-min / soc-max. This means other fields that accept sensor references could also use default now. Is that an acceptable API shape, or should fallback defaults be restricted to dynamic SoC bounds only?

  2. Fixed scalar soc-min / soc-max remain hard physical limits, while dynamic soc-min / soc-max are mapped to the existing relaxed soc-minima / soc-maxima scheduler path. Is that the distinction we want?

  3. I kept fixed soc-min / soc-max together with legacy soc-minima / soc-maxima valid for backwards compatibility. Should we keep allowing that, or should it eventually warn/reject?

  4. I treat default: null the same as omitting default. Is that acceptable?

  5. I marked soc-minima and soc-maxima as deprecated in docs/OpenAPI metadata, but did not add runtime deprecation warnings when users still send them. Is metadata-only deprecation enough for this PR, or should we also emit runtime warnings for legacy soc-minima / soc-maxima usage?

@BelhsanHmida BelhsanHmida requested a review from Flix6x July 8, 2026 01:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make soc-minima and soc-maxima the default, simplifying usage

2 participants