Skip to content

Commit 0bb5338

Browse files
authored
Prepare for release v0.18.0 (#210)
2 parents 7a7e410 + 76b6ef2 commit 0bb5338

File tree

3 files changed

+201
-8
lines changed

3 files changed

+201
-8
lines changed

RELEASE_NOTES.md

Lines changed: 201 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,214 @@
22

33
## Summary
44

5-
This release is a major breaking change, as we jump to the API specification version 0.17.x, which introduces big and fundamental breaking changes. This also starts using the `v1` namespace in `frequenz-api-common`, which also introduces major breaking changes. It would be very hard to detail all the API changes here, please refer to the [Microgrid API releases](https://github.com/frequenz-floss/frequenz-api-microgrid/releases) and [Common API releases](https://github.com/frequenz-floss/frequenz-api-common/releases).
5+
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.
6+
7+
Existing code written for `frequenz-client-microgrid` `v0.9.1` will not work without changes. Upgrading will typically require:
8+
9+
- Bumping dependencies to the new API and common libraries.
10+
- Updating imports for components, metrics, and IDs.
11+
- Migrating from the old ad-hoc component and sensor APIs to the new component/metrics model.
12+
- Adapting to the new power-control and bounds APIs.
13+
14+
For a full overview of upstream changes, consult the [Microgrid API releases](https://github.com/frequenz-floss/frequenz-api-microgrid/releases) and [Common API releases](https://github.com/frequenz-floss/frequenz-api-common/releases).
615

716
## Upgrading
817

9-
- `MicrogridApiClient`:
18+
The following notes are aimed at users upgrading from `frequenz-client-microgrid` `v0.9.1`.
19+
20+
### Dependencies and imports
21+
22+
- **Dependencies**:
23+
24+
- `frequenz-api-microgrid` is now required at `>= 0.18.0, < 0.19.0`.
25+
- `frequenz-api-common` is now required at `>= 0.8.0, < 1.0.0` and uses the `v1` namespace.
26+
- `frequenz-client-common` is now required at `>= 0.3.6, < 0.4.0` and provides ID and helper types used throughout the client.
27+
28+
Make sure you pin compatible versions in your own project when upgrading.
29+
30+
- **IDs and common types**:
31+
32+
IDs come from `frequenz.client.common` (this was already true in `v0.9.1`, but they are now used more consistently):
33+
34+
```python
35+
from frequenz.client.common.microgrid import MicrogridId
36+
from frequenz.client.common.microgrid.components import ComponentId
37+
```
38+
39+
- **Components and metrics**:
40+
41+
The old component and data types (`Component`, `ComponentCategory`, `BatteryData`, `InverterData`, `ComponentState*`, etc.) that used to live directly under `frequenz.client.microgrid` have been replaced with a richer component and metrics model:
42+
43+
```python
44+
from frequenz.client.microgrid import MicrogridApiClient
45+
from frequenz.client.microgrid import component, metrics
46+
47+
# Example component types
48+
from frequenz.client.microgrid.component import (
49+
Component,
50+
ComponentCategory,
51+
ComponentConnection,
52+
ComponentDataSamples,
53+
ComponentStateSample,
54+
GridConnectionPoint,
55+
Inverter,
56+
Battery,
57+
)
58+
59+
# Metrics and bounds
60+
from frequenz.client.microgrid.metrics import Metric, Bounds, MetricSample
61+
```
62+
63+
Update your imports to use these new modules instead of the removed legacy types.
64+
65+
### Metadata: `metadata()``get_microgrid_info()`
66+
67+
The old `metadata()` method has been replaced by `get_microgrid_info()` which returns a richer `MicrogridInfo` object.
68+
69+
### Listing components and connections
70+
71+
In `v0.9.1` you would often use:
72+
73+
```python
74+
components = await client.components()
75+
connections = await client.connections(starts={component_id}, ends=set())
76+
```
77+
78+
Now:
79+
80+
- **List components**:
81+
82+
```python
83+
components = await client.list_components(
84+
components=[ComponentId(1), ComponentId(2)],
85+
categories=[ComponentCategory.INVERTER, ComponentCategory.BATTERY],
86+
)
87+
```
88+
89+
Notes:
90+
91+
- `components` may contain `ComponentId` instances or `Component` objects.
92+
- `categories` may contain `ComponentCategory` enum values or raw integer category IDs.
93+
- Filters across `components` and `categories` are combined with `AND`; values inside each list are combined with `OR`.
94+
95+
- **List connections**:
96+
97+
```python
98+
connections = await client.list_connections(
99+
sources=[ComponentId(1)],
100+
destinations=[ComponentId(2)],
101+
)
102+
```
103+
104+
Notes:
105+
106+
- `sources` and `destinations` accept `ComponentId` or `Component` instances.
107+
- Filters across `sources` and `destinations` are combined with `AND`; values inside each list are combined with `OR`.
108+
- Connections now also use `.source` and `.destination` terminology instead of `.start` and `.end`.
109+
110+
111+
### Sensors: `list_sensors()`, `stream_sensor_data()`*removed* (temporary)
112+
113+
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.
114+
115+
### Power control: `set_power()` / `set_reactive_power()``set_component_power_active()` / `set_component_power_reactive()`
116+
117+
In `v0.9.1` you would typically set power using methods like:
118+
119+
```python
120+
await client.set_power(component_id, power_w)
121+
await client.set_reactive_power(component_id, reactive_power_var)
122+
```
123+
124+
These methods have been replaced with lifetime-aware, metric-aligned calls:
125+
126+
```python
127+
# Active power in watts
128+
expiry = await client.set_component_power_active(
129+
component=ComponentId(1),
130+
power_w=1_000.0,
131+
request_lifetime=timedelta(seconds=30),
132+
)
133+
134+
# Reactive power in volt-ampere reactive (var)
135+
expiry = await client.set_component_power_reactive(
136+
component=ComponentId(1),
137+
power_var=500.0,
138+
request_lifetime=timedelta(seconds=30),
139+
)
140+
```
141+
142+
- Both methods accept either `ComponentId` or `Component` instances.
143+
144+
### Bounds: `set_bounds()``add_component_bounds()`
145+
146+
In `v0.9.1`, power bounds were earlier set using methods like `set_bounds(component_id, lower, upper)`.
147+
148+
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`:
149+
150+
```python
151+
await client.add_component_bounds(
152+
component=ComponentId(1),
153+
target=Metric.ACTIVE_POWER,
154+
bounds=[Bounds(lower=-1_000.0, upper=1_000.0)],
155+
)
156+
```
157+
158+
Notes:
159+
160+
- Bounds are now metric-specific: you must specify a `Metric` when adding bounds.
161+
- Bounds are represented as at most two ranges, matching `frequenz-api-common` `v1` (`Bounds` may contain up to two inclusive ranges).
162+
163+
### Streaming telemetry: `*_data()``receive_component_data_samples_stream()`
164+
165+
The streaming model changed significantly.
166+
167+
In `v0.9.1`, you would use:
168+
169+
```python
170+
receiver = await client.meter_data(component_id)
171+
async for sample in receiver:
172+
# sample is a MeterData instance
173+
...
174+
```
175+
176+
Now, telemetry is integrated around components and metrics using `receive_component_data_samples_stream()` and `ComponentDataSamples`:
177+
178+
```python
179+
receiver: Receiver[ComponentDataSamples] = (
180+
await client.receive_component_data_samples_stream(
181+
component=ComponentId(1),
182+
metrics=[Metric.ACTIVE_POWER, Metric.REACTIVE_POWER],
183+
)
184+
)
185+
186+
async for samples in receiver:
187+
# Each `samples` corresponds to a single component at a single timestamp.
188+
# Metric values and bounds are attached per metric.
189+
```
190+
191+
The upstream Microgrid API `v0.18` changes how samples are structured; important points from the upstream migration notes (see `frequenz-api-microgrid` discussion #278):
192+
193+
- Rated bounds moved into component metadata; telemetry samples now carry operational bounds per metric.
194+
- Old `component_bounds` and `system_{inclusion,exclusion}_bounds` are unified under `samples.metric[x].bounds`.
195+
- Older voltage metrics like `VOLTAGE_PHASE_A` map to `AC_VOLTAGE_PHASE_A_N` and similar; review metric names in `frequenz.client.microgrid.metrics.Metric` when porting code.
196+
- All metrics for a given component at a given time share the same `sampled_at` timestamp.
197+
- At most one `ComponentState` is included per `ComponentData`.
198+
199+
When migrating:
10200

11-
* The client now follows the v0.17 API names, so most methods changed names and signatures.
201+
- Prefer requesting only the metrics you actually consume.
202+
- Use the new bounds representation instead of any previously maintained client-side bounds fields.
203+
- Replace sensor-centric streams with component-centric streams; each telemetry message now contains all requested metrics for a component.
12204

13205
## New Features
14206

15-
<!-- Here goes the main new features and examples or instructions on how to use them -->
207+
- Add `get_microgrid_info()` returning a rich `MicrogridInfo` dataclass with ID, enterprise, location, delivery area, status, and timestamps.
208+
- Add a metrics model under `frequenz.client.microgrid.metrics` including the `Metric` enum, `Bounds`, and `MetricSample`/`AggregatedMetricValue`.
209+
- Add high-level methods on `MicrogridApiClient` for listing components and connections, adding component bounds, receiving component data samples streams, and controlling active/reactive power with lifetimes.
16210

17211
## Bug Fixes
18212

19-
<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
213+
- Restore missing `Metric` enum members to match the upstream common API definitions.
214+
- Remove an artificial timeout from the gRPC telemetry stream to avoid spurious cancellations under normal operation.
215+
- Align error handling and validation with the updated API behavior (for example, validating lifetimes and power ranges before sending control requests).

tests/client_test_cases/set_component_power_active/no_lifetime_case.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,3 @@ def assert_stub_method_call(stub_method: Any) -> None:
3232
def assert_client_result(result: Any) -> None: # noqa: D103
3333
"""Assert that the client result is None when no lifetime is provided."""
3434
assert result is None
35-
assert result is None

tests/client_test_cases/set_component_power_active/success_case.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,3 @@ def assert_stub_method_call(stub_method: Any) -> None:
3434
def assert_client_result(result: datetime) -> None:
3535
"""Assert that the client result matches the expected expiry time."""
3636
assert result == expiry_time
37-
"""Assert that the client result matches the expected expiry time."""
38-
assert result == expiry_time

0 commit comments

Comments
 (0)