v0.18.0
Frequenz Microgrid API Client Release Notes
Summary
This release is a major breaking change. The client now targets the Microgrid API specification version 0.18.x and the v1 namespace in frequenz-api-common. Both upstream projects introduce large structural and naming changes to components, metrics, and telemetry, and this client has been refactored accordingly.
Existing code written for frequenz-client-microgrid v0.9.1 will not work without changes. Upgrading will typically require:
- Bumping dependencies to the new API and common libraries.
- Updating imports for components, metrics, and IDs.
- Migrating from the old ad-hoc component and sensor APIs to the new component/metrics model.
- Adapting to the new power-control and bounds APIs.
For a full overview of upstream changes, consult the Microgrid API releases and Common API releases.
Upgrading
The following notes are aimed at users upgrading from frequenz-client-microgrid v0.9.1.
Dependencies and imports
-
Dependencies:
frequenz-api-microgridis now required at>= 0.18.0, < 0.19.0.frequenz-api-commonis now required at>= 0.8.0, < 1.0.0and uses thev1namespace.frequenz-client-commonis now required at>= 0.3.6, < 0.4.0and provides ID and helper types used throughout the client.
Make sure you pin compatible versions in your own project when upgrading.
-
IDs and common types:
IDs come from
frequenz.client.common(this was already true inv0.9.1, but they are now used more consistently):from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId
-
Components and metrics:
The old component and data types (
Component,ComponentCategory,BatteryData,InverterData,ComponentState*, etc.) that used to live directly underfrequenz.client.microgridhave been replaced with a richer component and metrics model:from frequenz.client.microgrid import MicrogridApiClient from frequenz.client.microgrid import component, metrics # Example component types from frequenz.client.microgrid.component import ( Component, ComponentCategory, ComponentConnection, ComponentDataSamples, ComponentStateSample, GridConnectionPoint, Inverter, Battery, ) # Metrics and bounds from frequenz.client.microgrid.metrics import Metric, Bounds, MetricSample
Update your imports to use these new modules instead of the removed legacy types.
Metadata: metadata() → get_microgrid_info()
The old metadata() method has been replaced by get_microgrid_info() which returns a richer MicrogridInfo object.
Listing components and connections
In v0.9.1 you would often use:
components = await client.components()
connections = await client.connections(starts={component_id}, ends=set())Now:
-
List components:
components = await client.list_components( components=[ComponentId(1), ComponentId(2)], categories=[ComponentCategory.INVERTER, ComponentCategory.BATTERY], )
Notes:
componentsmay containComponentIdinstances orComponentobjects.categoriesmay containComponentCategoryenum values or raw integer category IDs.- Filters across
componentsandcategoriesare combined withAND; values inside each list are combined withOR.
-
List connections:
connections = await client.list_connections( sources=[ComponentId(1)], destinations=[ComponentId(2)], )
Notes:
sourcesanddestinationsacceptComponentIdorComponentinstances.- Filters across
sourcesanddestinationsare combined withAND; values inside each list are combined withOR. - Connections now also use
.sourceand.destinationterminology instead of.startand.end.
Sensors: list_sensors(), stream_sensor_data() → removed (temporary)
The old list_sensors() and stream_sensor_data() method has no direct equivalent. It will be reintroduced in a future release once sensor abstractions are reworked to fit the new component and metrics model.
Power control: set_power() / set_reactive_power() → set_component_power_active() / set_component_power_reactive()
In v0.9.1 you would typically set power using methods like:
await client.set_power(component_id, power_w)
await client.set_reactive_power(component_id, reactive_power_var)These methods have been replaced with lifetime-aware, metric-aligned calls:
# Active power in watts
expiry = await client.set_component_power_active(
component=ComponentId(1),
power_w=1_000.0,
request_lifetime=timedelta(seconds=30),
)
# Reactive power in volt-ampere reactive (var)
expiry = await client.set_component_power_reactive(
component=ComponentId(1),
power_var=500.0,
request_lifetime=timedelta(seconds=30),
)- Both methods accept either
ComponentIdorComponentinstances.
Bounds: set_bounds() → add_component_bounds()
In v0.9.1, power bounds were earlier set using methods like set_bounds(component_id, lower, upper).
Now the new API reflects the v0.18 metrics semantics: bounds are attached to metrics and transported as part of telemetry samples. Use add_component_bounds() together with Metric and Bounds:
await client.add_component_bounds(
component=ComponentId(1),
target=Metric.ACTIVE_POWER,
bounds=[Bounds(lower=-1_000.0, upper=1_000.0)],
)Notes:
- Bounds are now metric-specific: you must specify a
Metricwhen adding bounds. - Bounds are represented as at most two ranges, matching
frequenz-api-commonv1(Boundsmay contain up to two inclusive ranges).
Streaming telemetry: *_data() → receive_component_data_samples_stream()
The streaming model changed significantly.
In v0.9.1, you would use:
receiver = await client.meter_data(component_id)
async for sample in receiver:
# sample is a MeterData instance
...Now, telemetry is integrated around components and metrics using receive_component_data_samples_stream() and ComponentDataSamples:
receiver: Receiver[ComponentDataSamples] = (
await client.receive_component_data_samples_stream(
component=ComponentId(1),
metrics=[Metric.ACTIVE_POWER, Metric.REACTIVE_POWER],
)
)
async for samples in receiver:
# Each `samples` corresponds to a single component at a single timestamp.
# Metric values and bounds are attached per metric.The upstream Microgrid API v0.18 changes how samples are structured; important points from the upstream migration notes (see frequenz-api-microgrid discussion #278):
- Rated bounds moved into component metadata; telemetry samples now carry operational bounds per metric.
- Old
component_boundsandsystem_{inclusion,exclusion}_boundsare unified undersamples.metric[x].bounds. - Older voltage metrics like
VOLTAGE_PHASE_Amap toAC_VOLTAGE_PHASE_A_Nand similar; review metric names infrequenz.client.microgrid.metrics.Metricwhen porting code. - All metrics for a given component at a given time share the same
sampled_attimestamp. - At most one
ComponentStateis included perComponentData.
When migrating:
- Prefer requesting only the metrics you actually consume.
- Use the new bounds representation instead of any previously maintained client-side bounds fields.
- Replace sensor-centric streams with component-centric streams; each telemetry message now contains all requested metrics for a component.
New Features
- Add
get_microgrid_info()returning a richMicrogridInfodataclass with ID, enterprise, location, delivery area, status, and timestamps. - Add a metrics model under
frequenz.client.microgrid.metricsincluding theMetricenum,Bounds, andMetricSample/AggregatedMetricValue. - Add high-level methods on
MicrogridApiClientfor listing components and connections, adding component bounds, receiving component data samples streams, and controlling active/reactive power with lifetimes.
Bug Fixes
- Restore missing
Metricenum members to match the upstream common API definitions. - Remove an artificial timeout from the gRPC telemetry stream to avoid spurious cancellations under normal operation.
- Align error handling and validation with the updated API behavior (for example, validating lifetimes and power ranges before sending control requests).
What's Changed
- Initial upgrade to the API v0.17.x by @llucax in #94
- Add gRPC calls to control components by @llucax in #158
- Implement
ListComponentsby @llucax in #165 - Implement
ListConnectionsby @llucax in #167 - Clear release notes by @llucax in #177
- Rename objects returned by calls to
responseinternally by @llucax in #179 - Implement
ReceiveComponentDataStreamRequestby @llucax in #178 - Bump the patch group with 3 updates by @dependabot[bot] in #185
- Bump types-markdown from 3.8.0.20250708 to 3.8.0.20250809 by @dependabot[bot] in #187
- Bump mkdocstrings-python from 1.16.12 to 1.18.2 in the mkdocstrings group by @dependabot[bot] in #182
- Bump pydoclint from 0.6.6 to 0.6.11 by @dependabot[bot] in #183
- Bump setuptools-scm[toml] from 8.3.1 to 9.2.0 by @dependabot[bot] in #184
- Bump actions/checkout from 4 to 5 by @dependabot[bot] in #181
- Bump actions/download-artifact from 4 to 5 in the artifacts group by @dependabot[bot] in #180
- Bump types-protobuf from 6.30.2.20250703 to 6.30.2.20250822 by @dependabot[bot] in #186
- Merge v0.x.x into v0.18.x by @llucax in #189
- Upgrade the client to v0.18.x (v0.8.0 common) by @llucax in #190
- Bump pytest-asyncio from 1.1.0 to 1.2.0 by @dependabot[bot] in #195
- Bump the patch group with 3 updates by @dependabot[bot] in #192
- Bump pydoclint from 0.6.11 to 0.7.3 by @dependabot[bot] in #194
- Bump actions/labeler from 5.0.0 to 6.0.1 by @dependabot[bot] in #191
- Bump the minor group across 1 directory with 8 updates by @dependabot[bot] in #196
- Restore missing
Metricenum members by @llucax in #197 - Remove the timeout from the gRPC stream call by @llucax in #199
- Bump pydoclint from 0.7.3 to 0.7.6 by @dependabot[bot] in #205
- Add Dependabot auto-merge workflow by @Marenz in #198
- Bump actions/upload-artifact from 4 to 5 by @dependabot[bot] in #200
- Bump actions/download-artifact from 5 to 6 by @dependabot[bot] in #201
- Bump the patch group with 5 updates by @dependabot[bot] in #202
- Bump nox from 2025.5.1 to 2025.10.16 in the minor group by @dependabot[bot] in #203
- Bump pylint from 3.3.8 to 4.0.2 by @dependabot[bot] in #204
- Migrate to frequenz-floss dependabot-auto-approve action by @Marenz in #207
- Add pylint exception for too-many-branches by @llucax in #208
- Merge v0.18.x into v0.x.x by @llucax in #209
- Prepare for release v0.18.0 by @llucax in #210
Full Changelog: v0.9.1...v0.18.0