Define intermediate power constraints via DB flex-models on the asset tree - #2277
Merged
Flix6x merged 1 commit intoJul 10, 2026
Merged
Conversation
… asset tree
Extend the storage flex-model's group field to also accept {"asset": <id>},
so a group can be identified by an asset-keyed flex-model entry - the form
that DB-stored flex-models naturally produce. This makes intermediate power
constraints fully definable via an asset tree with stored flex-models, with
an empty flex-model in the scheduling trigger.
- Asset-referenced group entries define no power sensor of their own; the
group's scheduled aggregate power is saved via the entry's consumption
and/or production output sensors, following the usual output-sensor
conventions (full profile on a single sensor; clip-split when both given).
- Sensor-referenced groups keep saving the aggregate to the group power
sensor, and may now also define output sensors.
- The UI asset flex-model editor recommends the parent asset when editing a
child's group field (one-click suggestion), and hints in both the parent's
and children's editors when the parent's flex-model defines power-capacity.
- New tutorial: toy example for intermediate power constraints, driven
entirely by DB-stored flex-models.
Bug fixes uncovered along the way:
- AssetTriggerSchema.check_flex_model_sensors raised KeyError on asset-only
flex-model entries.
- The freeze_server_now test fixture leaked its server_now monkeypatch into
all subsequently run tests in the same process, causing order-dependent
duplicate-key failures when scheduling jobs saved beliefs with identical
(frozen) belief times.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX
Signed-off-by: F.N. Claessen <claessen@seita.nl>
Documentation build overview
11 files changed ·
|
Flix6x
added a commit
that referenced
this pull request
Jul 18, 2026
…el group field) (#2276) * feat: support intermediate power constraints on groups of devices Add a new `group` field to the storage flex-model, letting device entries reference a power sensor that represents a group of devices (e.g. a hybrid inverter shared by a battery and PV). The group sensor's own flex-model entry constrains the group's aggregate power: - power-capacity: hard constraint (both directions) - consumption-capacity / production-capacity: soft constraints, enforced via breach commitments with default breach prices (10000 <currency>/kW) The group's scheduled aggregate power is saved to the group sensor. Nested groups are supported (cycles rejected); groups require multi-device flex-models and members must share a commodity. Implemented on top of the existing device-group solver machinery (ems_constraint_groups from the multi-commodity work, and grouped FlowCommitments from PR #1934); no changes to the optimizer itself. Also fixes a latent device-index misalignment in MetaStorageScheduler._prepare, where per-device lists were built from the full flex-model list (including stock-only entries) instead of the filtered device models. Closes #2092 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX * docs: cite PR #2276 in changelog entry Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX * feat: support intermediate power constraints on groups of devices Add a new `group` field to the storage flex-model, letting device entries reference a power sensor that represents a group of devices (e.g. a hybrid inverter shared by a battery and PV). The group sensor's own flex-model entry constrains the group's aggregate power: - power-capacity: hard constraint (both directions) - consumption-capacity / production-capacity: soft constraints, enforced via breach commitments with default breach prices (10000 <currency>/kW) The group's scheduled aggregate power is saved to the group sensor. Nested groups are supported (cycles rejected); groups require multi-device flex-models and members must share a commodity. Implemented on top of the existing device-group solver machinery (ems_constraint_groups from the multi-commodity work, and grouped FlowCommitments from PR #1934); no changes to the optimizer itself. Also fixes a latent device-index misalignment in MetaStorageScheduler._prepare, where per-device lists were built from the full flex-model list (including stock-only entries) instead of the filtered device models. Closes #2092 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX Signed-off-by: F.N. Claessen <claessen@seita.nl> * docs: cite PR #2276 in changelog entry Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX Signed-off-by: F.N. Claessen <claessen@seita.nl> * fix: add group field to UI flex-model schema The UI-DB flex-model schema parity test requires every DBStorageFlexModelSchema field to have UI support. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX Signed-off-by: F.N. Claessen <claessen@seita.nl> * feat: define intermediate power constraints via DB flex-models on the asset tree (#2277) Extend the storage flex-model's group field to also accept {"asset": <id>}, so a group can be identified by an asset-keyed flex-model entry - the form that DB-stored flex-models naturally produce. This makes intermediate power constraints fully definable via an asset tree with stored flex-models, with an empty flex-model in the scheduling trigger. - Asset-referenced group entries define no power sensor of their own; the group's scheduled aggregate power is saved via the entry's consumption and/or production output sensors, following the usual output-sensor conventions (full profile on a single sensor; clip-split when both given). - Sensor-referenced groups keep saving the aggregate to the group power sensor, and may now also define output sensors. - The UI asset flex-model editor recommends the parent asset when editing a child's group field (one-click suggestion), and hints in both the parent's and children's editors when the parent's flex-model defines power-capacity. - New tutorial: toy example for intermediate power constraints, driven entirely by DB-stored flex-models. Bug fixes uncovered along the way: - AssetTriggerSchema.check_flex_model_sensors raised KeyError on asset-only flex-model entries. - The freeze_server_now test fixture leaked its server_now monkeypatch into all subsequently run tests in the same process, causing order-dependent duplicate-key failures when scheduling jobs saved beliefs with identical (frozen) belief times. Claude-Session: https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX Signed-off-by: F.N. Claessen <claessen@seita.nl> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * docs: keep the group-constraints tutorial audience-appropriate Remove references to code modules, tests and GitHub issues from the tutorial; tutorials address FlexMeasures users, not developers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX Signed-off-by: F.N. Claessen <claessen@seita.nl> * fix: address review on the group field (XSS, error path, schema base) - asset_properties.html: HTML-escape the parent asset name before it is inserted into innerHTML in the group hint (it is user-controlled -> XSS). - storage.py: attach the "group must reference a power sensor" ValidationError to the `group` field, not `sensor`. - GroupReferenceSchema now inherits from SharedSensorReferenceSchema instead of SensorReferenceSchema, so it accepts only `sensor`/`asset` (a group is a device-group identifier, not a belief-query reference) and no longer exposes the source-* filter fields; regenerate openapi-specs.json accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016MLCUiSdXDqDBmg8GbYp1B Signed-off-by: F.N. Claessen <claessen@seita.nl> * docs: the model computes group schedules, it does not save them Reword _add_group_schedules' docstring: the scheduling model assembles and returns each group's aggregate power schedule; persistence is the data service's responsibility. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016MLCUiSdXDqDBmg8GbYp1B Signed-off-by: F.N. Claessen <claessen@seita.nl> --------- Signed-off-by: F.N. Claessen <claessen@seita.nl> Signed-off-by: F.N. Claessen <felix@seita.nl> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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
Follow-up to #2276, making intermediate power constraints fully definable via DB-stored flex-models on an asset tree — trigger the parent asset with an empty flex-model and everything comes from the tree.
What's new
group: {"asset": <id>}: the group field now also accepts an asset reference. DB flex-models are asset-keyed (get_flex_model()never emitssensor), so this is the form an asset tree naturally produces. Sensor references keep working.consumptionand/orproductionoutput sensors and the group's aggregate power is saved there, following the standard conventions (consumption only → full profile consumption-positive; production only → full profile production-positive on save; both → clip-split into positive parts on each). Sensor-referenced groups still save to the group power sensor and may also define output sensors.groupfield (one-click "Use parent asset as group"), and shows hints in both the parent's and children's editors when the parent's flex-model defines apower-capacity.Bug fixes uncovered
AssetTriggerSchema.check_flex_model_sensorsraisedKeyErroron any asset-only flex-model entry.freeze_server_nowtest fixture leaked itsserver_nowmonkeypatch into all subsequently run tests in the same process (its teardown restored nothing), causing order-dependent duplicate-key failures whenever scheduling jobs later saved beliefs with identical frozen belief times. Fixed at the source inconftest.py.Tests
test_pure_db_tree_group_constraint) that stores all flex-models as asset attributes and schedules withflex_model=[]through the realcollect_flex_configpath.🤖 Generated with Claude Code
https://claude.ai/code/session_01TAad46Ayg86DHpL6nY54sX