Feat: dynamic soc bounds defaults#2267
Open
BelhsanHmida wants to merge 8 commits into
Open
Conversation
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>
Contributor
There was a problem hiding this comment.
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/SensorReferenceto support adefaultfallback quantity and apply it when fetching belief series - Route dynamic
soc-min/soc-maxpayloads 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 on lines
+443
to
+446
| elif isinstance(value, tuple): | ||
| try: | ||
| return ur.Quantity.from_tuple(value).to(self.to_unit) | ||
| except Exception: |
Comment on lines
+455
to
+457
| raise FMValidationError( | ||
| f"Unsupported value type. `{type(value)}` was provided but only dict, list and str are supported." | ||
| ) |
Comment on lines
431
to
433
| def _deserialize( | ||
| self, value: dict[str, int] | list[dict] | str, attr, data, **kwargs | ||
| ) -> Sensor | list[dict] | ur.Quantity: |
Comment on lines
+1066
to
+1072
| default = fields.String( | ||
| load_default=None, | ||
| metadata=dict( | ||
| description="Fallback quantity to use when the referenced sensor has missing values.", | ||
| example="0 kWh", | ||
| ), | ||
| ) |
Comment on lines
+281
to
+285
| self.soc_min = VariableQuantityField( | ||
| to_unit="MWh", | ||
| default_src_unit=default_soc_unit, | ||
| timezone=self.timezone, | ||
| event_resolution=self.flooring_resolution, |
Comment on lines
126
to
129
| FlexMeasures' built-in storage scheduler no longer computes a fallback schedule for infeasible problems. | ||
| Instead, ``soc-minima`` and ``soc-maxima`` are relaxed by default through ``"relax-soc-constraints": true``, while ``soc-min``, ``soc-max`` and ``soc-targets`` remain hard constraints. | ||
| Instead, dynamic ``soc-min`` and ``soc-max`` boundaries, including the legacy aliases ``soc-minima`` and ``soc-maxima``, are relaxed by default through ``"relax-soc-constraints": true``. | ||
| Fixed ``soc-min`` / ``soc-max`` values and exact ``soc-targets`` remain hard constraints. | ||
| If hard constraints cannot be satisfied, the scheduling job fails and clients receive the failure reason when requesting the schedule. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
soc-minandsoc-maxthe canonical fields for fixed and dynamic storage SoC boundaries.soc-min/soc-maxvalues through sensor references and time-series specs.defaultfield to sensor references, so missing sensor values can be filled, e.g.{"sensor": 300, "default": "10 kWh"}.soc-minimaandsoc-maximasupported as legacy aliases for dynamicsoc-minandsoc-max, while marking them deprecated in docs/OpenAPI metadata.soc-minandsoc-minima, or both dynamicsoc-maxandsoc-maxima.soc-min/soc-max, including existing fixedsoc-minplus legacysoc-minimausage.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
Use a storage flex-model where
soc-minandsoc-maxare 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-minandsoc-maxare treated as dynamic SoC boundaries, and missing sensor values are filled with the provided default values.Further Improvements
soc-minima/soc-maxima.Related Items
Sign-off