Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
31f8281
refactor: update efficiency field and types in scheduling schemas
joshuaunity Apr 29, 2026
b599e43
test: add tests for efficiency sensors in DBFlexModelSchema
joshuaunity Apr 29, 2026
cf0edab
chore: add changelog entry
joshuaunity Apr 29, 2026
f0fc4c5
Update flexmeasures/data/schemas/scheduling/storage.py
joshuaunity Apr 29, 2026
7772bc2
Update flexmeasures/data/schemas/scheduling/storage.py
joshuaunity Apr 29, 2026
9c72835
Update flexmeasures/ui/static/openapi-specs.json
joshuaunity Apr 29, 2026
7a2925a
refactor: update EfficiencyField to inherit from QuantityField and ad…
joshuaunity Apr 29, 2026
9e00754
fix: restore openapi-specs.json version to 0.32.0
Copilot Apr 29, 2026
6ab9798
test: enhance DB storage flex-model schema tests for sensor references
joshuaunity Apr 29, 2026
85a2cb0
Merge branch 'feat/efficiencyfield-support-sensor' of github.com:Flex…
joshuaunity Apr 29, 2026
0ca0340
chore: udpated docstring
joshuaunity Apr 29, 2026
f5f8d50
feat: add warning for sensor resolution in storage efficiency info cards
joshuaunity May 4, 2026
3f57300
Merge branch 'main' into feat/efficiencyfield-support-sensor
joshuaunity May 5, 2026
057461e
Merge branch 'main' into feat/efficiencyfield-support-sensor
joshuaunity May 6, 2026
0efacb1
chore: resolving changelog conflicts
joshuaunity May 6, 2026
025bf3d
Update API version to 0.32.0
joshuaunity May 6, 2026
1a213b4
feat: update roundtrip efficiency field type and schema description
joshuaunity May 7, 2026
18d2369
Update API version to 0.32.0
joshuaunity May 7, 2026
40a055e
chore: refactored test cases
joshuaunity May 7, 2026
abe7c1e
Merge branch 'main' into feat/efficiencyfield-support-sensor
joshuaunity May 15, 2026
23c6ea0
fix: added support for string only field types
joshuaunity May 18, 2026
b0ff94a
chore: revert few changes
joshuaunity May 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion documentation/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ New features
-------------
* Added API and UI support for copying assets and their subtrees [see `PR #2017 <https://www.github.com/FlexMeasures/flexmeasures/pull/2017>`_ and `PR #2120 <https://www.github.com/FlexMeasures/flexmeasures/pull/2120>`_]
* Improve UX after deleting a child asset through the UI [see `PR #2119 <https://www.github.com/FlexMeasures/flexmeasures/pull/2119>`_]
* Improve source filtering in the sensor data GET endpoint by exposing the documented query parameters in Swagger and allowing filtering by the account linked to data sources [see `PR #2083 <https://www.github.com/FlexMeasures/flexmeasures/pull/2083>`_ and `PR #2151 <https://www.github.com/FlexMeasures/flexmeasures/pull/2151>`_]
Comment thread
joshuaunity marked this conversation as resolved.
* Improve source filtering in the sensor data GET endpoint by exposing the documented query parameters in Swagger and allowing filtering by the account linked to data sources [see `PR #2083 <https://www.github.com/FlexMeasures/flexmeasures/pull/2083>`_]
* Support sensor references for efficiency fields in storage flex-models [see `PR #2142 <https://www.github.com/FlexMeasures/flexmeasures/pull/2142>`_]
* Added a unified job status endpoint ``GET /api/v3_0/jobs/<uuid>`` to retrieve the current execution status and result message for any background job [see `PR #2141 <https://www.github.com/FlexMeasures/flexmeasures/pull/2141>`_]
* New ``GET /api/v3_0/sources`` endpoint to list accessible data sources and defined types, with ``only_latest=true`` by default to return only the most recent version per source [see `PR #2126 <https://www.github.com/FlexMeasures/flexmeasures/pull/2126>`_]
* Add support for filtering sensor data GET requests by ``source-type`` on ``/api/v3_0/sensors/<id>/data`` [see `PR #2127 <https://www.github.com/FlexMeasures/flexmeasures/pull/2127>`_]
Expand Down
6 changes: 3 additions & 3 deletions flexmeasures/data/models/forecasting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
from typing import Any

from flexmeasures.data.models.data_sources import DataGenerator
from flexmeasures.data.models.forecasting.custom_models.base_model import ( # noqa: F401
BaseModel,
)
Comment thread
joshuaunity marked this conversation as resolved.
from flexmeasures.data.schemas.forecasting import ForecasterConfigSchema


Expand Down Expand Up @@ -103,3 +100,6 @@ def _clean_parameters(self, parameters: dict) -> dict:
for field in fields_to_remove:
_parameters.pop(field, None)
return _parameters


# End of module.
Comment thread
joshuaunity marked this conversation as resolved.
Outdated
12 changes: 6 additions & 6 deletions flexmeasures/data/schemas/scheduling/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,26 +667,26 @@ def _to_currency_per_mwh(price_unit: str) -> str:
"default": None,
"description": rst_to_openapi(metadata.CHARGING_EFFICIENCY.description),
"types": {
"backend": "typeFive",
"ui": "Fixed value only.",
"backend": "typeThree",
"ui": "One fixed value or a dynamic signal (via a sensor).",
},
"example-units": EXAMPLE_UNIT_TYPES["efficiency"],
},
"discharging-efficiency": {
"default": None,
"description": rst_to_openapi(metadata.DISCHARGING_EFFICIENCY.description),
"types": {
"backend": "typeFive",
"ui": "Fixed value only.",
"backend": "typeThree",
"ui": "One fixed value or a dynamic signal (via a sensor).",
},
"example-units": EXAMPLE_UNIT_TYPES["efficiency"],
},
"storage-efficiency": {
"default": None,
"description": rst_to_openapi(metadata.STORAGE_EFFICIENCY.description),
"types": {
"backend": "typeFive",
"ui": "Fixed value only.",
"backend": "typeThree",
"ui": "One fixed value or a dynamic signal (via a sensor).",
},
Comment thread
Flix6x marked this conversation as resolved.
"example-units": EXAMPLE_UNIT_TYPES["efficiency"],
},
Expand Down
6 changes: 4 additions & 2 deletions flexmeasures/data/schemas/scheduling/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@


class EfficiencyField(QuantityField):
Comment thread
joshuaunity marked this conversation as resolved.
"""Field that deserializes to a Quantity with % units. Must be greater than 0% and less than or equal to 100%.
"""Field that deserializes to a Quantity with % units.
Fixed values must be greater than 0% and less than or equal to 100%.

Examples:

Expand Down Expand Up @@ -455,7 +456,8 @@ class DBStorageFlexModelSchema(Schema):
metadata={"deprecated field": "discharging-efficiency"},
)

storage_efficiency = EfficiencyField(
storage_efficiency = VariableQuantityField(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there no associated change to the openapi-specs.json?

@joshuaunity joshuaunity May 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, I don't think they should, as the flex-config schema isn't directly placed on the API's themselves, rather they are used under the hood.

"%",
data_key="storage-efficiency",
required=False,
metadata={"deprecated field": "storage_efficiency"},
Expand Down
35 changes: 34 additions & 1 deletion flexmeasures/data/schemas/tests/test_scheduling.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,15 +782,48 @@ def test_get_variable_quantity_unit(
{"soc-usage": ["3500 kW", {"sensor": "power-sensor"}]},
False,
),
(
{"roundtrip-efficiency": "90%"},
False,
),
(
{"roundtrip-efficiency": "12 MW"},
{"roundtrip-efficiency": "Cannot convert value `12 MW` to '%'"},
),
(
{"storage-efficiency": {"sensor": "efficiency-sensor"}},
False,
),
(
{"storage-efficiency": {"sensor": "power-sensor"}},
{"storage-efficiency": "Cannot convert MW to %"},
),
Comment thread
joshuaunity marked this conversation as resolved.
],
)
def test_db_flex_model_schema(db, app, setup_dummy_sensors, flex_model, fails):
def test_db_flex_model_schema(
Comment thread
joshuaunity marked this conversation as resolved.
db, app, setup_dummy_sensors, setup_efficiency_sensors, flex_model, fails
):
"""Validate DBStorageFlexModelSchema for accepted and rejected flex-model inputs.

Input under test:
- ``flex_model`` payloads with fixed quantities, sensor references, and list fields
(for example ``soc-min``, ``soc-minima``, ``soc-gain``,
``roundtrip-efficiency``, ``storage-efficiency``).
- Sensor placeholders in parametrized payloads are replaced with fixture-backed
sensor IDs before schema loading.

Expected outcomes:
- When ``fails`` is ``False``, schema loading succeeds.
- When ``fails`` is a field-to-message mapping, schema loading raises
``ValidationError`` and contains the expected field-specific error message(s).
"""
schema = DBStorageFlexModelSchema()

sensors = {
"energy-sensor": setup_dummy_sensors[0],
"price-sensor": setup_dummy_sensors[1],
"power-sensor": setup_dummy_sensors[3],
"efficiency-sensor": setup_efficiency_sensors,
}

for field_name, field_value in flex_model.items():
Expand Down
16 changes: 15 additions & 1 deletion flexmeasures/ui/templates/assets/asset_properties.html
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,10 @@ <h5 class="modal-title pe-2">Edit {{ asset.name }}'s flex-model</h5>
validTypes = [Array];
} else if (type === "typeFive") {
validTypes = [String];
} else {
// Raise error for unsupported type
showToast(`Unsupported type for field "${key}" in flex model schema.`, "error");
console.error(`Unsupported type "${type}" for field "${key}" in flex model schema.`);
}
FlexModelFieldValidTypes[key] = validTypes;
}
Expand Down Expand Up @@ -671,14 +675,24 @@ <h5 class="modal-title pe-2">Edit {{ asset.name }}'s flex-model</h5>

async function renderSelectInfoCards(modelKey, allowedUnits = []) {
if (modelKey) {
const storageEfficiencyWarning = modelKey === "storage-efficiency"
? `
<div class="pt-2 text-danger">
<span class="fw-bold">Warning:</span> If you use a sensor, ensure its resolution matches the scheduling resolution. Currently there is no resampling using sensor resolution for this field.
</div>
`
: "";

flexInfoContainer.innerHTML = `
<div>
<div class="alert alert-info" role="alert">
<b> About ${getFlexFieldTitle(modelKey)}
<strong>About ${getFlexFieldTitle(modelKey)}</strong>
<div class="pt-2 fw-normal">
${schemaSpecs[modelKey]["description"] || "No description available."}
</div>

${storageEfficiencyWarning}

<div class="pt-2 fw-bold">
Possible types: <span class="fw-normal"> ${schemaSpecs[modelKey]["types"]["ui"] || "No types available."} </span> <br/>
Example units: <span class="fw-normal"> ${schemaSpecs[modelKey]["example-units"].join(", ")} </span>
Expand Down
Loading