Tags: frequenz-floss/frequenz-client-microgrid-python
Tags
# Frequenz Microgrid API Client Release Notes
## Summary
This release reintroduces sensor support that was temporarily removed in the v0.18.0 release. The new sensor API has been redesigned to fit the updated component and metrics model introduced in v0.18.0.
## New Features
- New `sensor` module (`frequenz.client.microgrid.sensor`) with sensor related types.
- New `MicrogridApiClient` methods
* `list_sensors()`: fetch sensor metadata.
* `receive_sensor_telemetry_stream()`: stream sensor telemetry data.
Example:
```python
import asyncio
from frequenz.client.microgrid import MicrogridApiClient
from frequenz.client.microgrid.metrics import Metric
URL = "grpc://[::1]:62060"
async def main() -> None:
print(f"Connecting to {URL}...")
async with MicrogridApiClient(URL) as client:
print("Listing available sensors...")
sensors = list(await client.list_sensors())
if not sensors:
print("No sensors found.")
return
print(f"Found {len(sensors)}: {sensors}.")
print()
sensor = sensors[0]
print(f"Streaming telemetry from sensor {sensor.id} ({sensor.name})...")
telemetry_stream = client.receive_sensor_telemetry_stream(
sensors[0].id, list(Metric)
)
async for telemetry in telemetry_stream:
print(f"\tReceived: {telemetry}")
asyncio.run(main())
```
## Upgrading (from v0.9)
### Sensor support restored with new API
Sensor support that was removed in v0.18.0 is now back, but with a redesigned API that aligns with the v0.18.0 component and metrics model.
#### `list_sensors()`
The method name remains the same, but the signature and return type have changed:
```python
# Old v0.9.1 API
sensors: Iterable[Sensor] = await client.list_sensors()
# New v0.18.2 API (same method name, different types)
from frequenz.client.common.microgrid.sensors import SensorId
from frequenz.client.microgrid.sensor import Sensor
sensors: Iterable[Sensor] = await client.list_sensors()
# You can also filter by sensor IDs
sensors = await client.list_sensors(sensors=[SensorId(1), SensorId(2)])
```
The `Sensor` class now provides a new attribute `microgrid_id: MicrogridId` and the `identity` property now returns a tuple `(SensorId, MicrogridId)` instead of just `SensorId`.
#### `stream_sensor_data()` → `receive_sensor_telemetry_stream()`
The streaming method has been renamed and its return type changed:
```python
# Old v0.9.1 API
from frequenz.client.microgrid.sensor import SensorDataSamples, SensorMetric
receiver: Receiver[SensorDataSamples] = client.stream_sensor_data(
sensor=SensorId(1),
metrics=[SensorMetric.TEMPERATURE, SensorMetric.HUMIDITY], # optional
)
async for samples in receiver:
# samples.metric_samples, samples.state_sample, etc.
...
# New v0.18.2 API
from frequenz.client.microgrid.sensor import SensorTelemetry
from frequenz.client.microgrid.metrics import Metric
receiver: Receiver[SensorTelemetry] = client.receive_sensor_telemetry_stream(
sensor=SensorId(1),
metrics=[Metric.TEMPERATURE, Metric.AC_VOLTAGE], # required
)
async for telemetry in receiver:
# telemetry.sensor_id: SensorId
# telemetry.metric_samples: Sequence[MetricSample]
# telemetry.state_snapshots: Sequence[SensorStateSnapshot]
for sample in telemetry.metric_samples:
print(f"{sample.metric}: {sample.value} at {sample.sampled_at}")
...
```
Key differences:
- **Method renamed**: `stream_sensor_data()` → `receive_sensor_telemetry_stream()`
- **Metrics parameter is now required**: You must specify which metrics to stream. The old API allowed `None` to stream all metrics.
- **Uses unified `Metric` enum**: The old `SensorMetric` enum is removed. Use `frequenz.client.microgrid.metrics.Metric` instead.
- **Return type changed**: `SensorDataSamples` → `SensorTelemetry`
- **State samples changed**: `SensorStateSample` → `SensorStateSnapshot` with different structure (see below)
#### Sensor state types
The sensor state types have been redesigned:
| Old v0.9.1 type | New v0.18.2 type |
|---------------------------|-------------------------------------------|
| `SensorMetric` | *Removed* — use `Metric` |
| `SensorStateCode` | `SensorStateCode` (different values) |
| `SensorErrorCode` | `SensorDiagnosticCode` |
| `SensorStateSample` | `SensorStateSnapshot` |
| `SensorMetricSample` | `MetricSample` |
| `SensorDataSamples` | `SensorTelemetry` |
The new `SensorStateSnapshot` structure:
```python
@DataClass(frozen=True, kw_only=True)
class SensorStateSnapshot:
origin_time: datetime # was `sampled_at`
states: Set[SensorStateCode | int] # was `frozenset`
warnings: Sequence[SensorDiagnostic] # new
errors: Sequence[SensorDiagnostic] # replaces error codes
```
The new `SensorDiagnostic` provides richer error/warning information:
```python
@DataClass(frozen=True, kw_only=True)
class SensorDiagnostic:
diagnostic_code: SensorDiagnosticCode | int
message: str | None
vendor_diagnostic_code: str | None
```
#### Import changes
Update your imports for sensor types:
```python
# Old v0.9.1
from frequenz.client.microgrid.sensor import (
Sensor,
SensorDataSamples,
SensorErrorCode,
SensorMetric,
SensorMetricSample,
SensorStateCode,
SensorStateSample,
)
# New v0.18.2
from frequenz.client.microgrid.sensor import (
Sensor,
SensorDiagnostic,
SensorDiagnosticCode,
SensorStateCode,
SensorStateSnapshot,
SensorTelemetry,
)
from frequenz.client.microgrid.metrics import Metric, MetricSample
from frequenz.client.common.microgrid.sensors import SensorId
```
# Frequenz Microgrid API Client Release Notes ## Summary This release adds a new `WindTurbine` component type. ## Upgrading - If you are using `match` and doing exhaustive matching on the `Component` types, you will get `mypy` errors and will need to handle the new `WindTurbine` type. ## New Features - Add `WindTurbine` component type.
# 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](https://github.com/frequenz-floss/frequenz-api-microgrid/releases) and [Common API releases](https://github.com/frequenz-floss/frequenz-api-common/releases). ## Upgrading The following notes are aimed at users upgrading from `frequenz-client-microgrid` `v0.9.1`. ### Dependencies and imports - **Dependencies**: - `frequenz-api-microgrid` is now required at `>= 0.18.0, < 0.19.0`. - `frequenz-api-common` is now required at `>= 0.8.0, < 1.0.0` and uses the `v1` namespace. - `frequenz-client-common` is now required at `>= 0.3.6, < 0.4.0` and 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 in `v0.9.1`, but they are now used more consistently): ```python 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 under `frequenz.client.microgrid` have been replaced with a richer component and metrics model: ```python 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: ```python components = await client.components() connections = await client.connections(starts={component_id}, ends=set()) ``` Now: - **List components**: ```python components = await client.list_components( components=[ComponentId(1), ComponentId(2)], categories=[ComponentCategory.INVERTER, ComponentCategory.BATTERY], ) ``` Notes: - `components` may contain `ComponentId` instances or `Component` objects. - `categories` may contain `ComponentCategory` enum values or raw integer category IDs. - Filters across `components` and `categories` are combined with `AND`; values inside each list are combined with `OR`. - **List connections**: ```python connections = await client.list_connections( sources=[ComponentId(1)], destinations=[ComponentId(2)], ) ``` Notes: - `sources` and `destinations` accept `ComponentId` or `Component` instances. - Filters across `sources` and `destinations` are combined with `AND`; values inside each list are combined with `OR`. - Connections now also use `.source` and `.destination` terminology instead of `.start` and `.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: ```python 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: ```python # 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 `ComponentId` or `Component` instances. ### 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`: ```python 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 `Metric` when adding bounds. - Bounds are represented as at most two ranges, matching `frequenz-api-common` `v1` (`Bounds` may 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: ```python 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`: ```python 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_bounds` and `system_{inclusion,exclusion}_bounds` are unified under `samples.metric[x].bounds`. - 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. - All metrics for a given component at a given time share the same `sampled_at` timestamp. - At most one `ComponentState` is included per `ComponentData`. 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 rich `MicrogridInfo` dataclass with ID, enterprise, location, delivery area, status, and timestamps. - Add a metrics model under `frequenz.client.microgrid.metrics` including the `Metric` enum, `Bounds`, and `MetricSample`/`AggregatedMetricValue`. - 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. - Add `WindTurbine` component type. ## Bug Fixes - Restore missing `Metric` enum 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).
# 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](https://github.com/frequenz-floss/frequenz-api-microgrid/releases) and [Common API releases](https://github.com/frequenz-floss/frequenz-api-common/releases). ## Upgrading The following notes are aimed at users upgrading from `frequenz-client-microgrid` `v0.9.1`. ### Dependencies and imports - **Dependencies**: - `frequenz-api-microgrid` is now required at `>= 0.18.0, < 0.19.0`. - `frequenz-api-common` is now required at `>= 0.8.0, < 1.0.0` and uses the `v1` namespace. - `frequenz-client-common` is now required at `>= 0.3.6, < 0.4.0` and 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 in `v0.9.1`, but they are now used more consistently): ```python 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 under `frequenz.client.microgrid` have been replaced with a richer component and metrics model: ```python 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: ```python components = await client.components() connections = await client.connections(starts={component_id}, ends=set()) ``` Now: - **List components**: ```python components = await client.list_components( components=[ComponentId(1), ComponentId(2)], categories=[ComponentCategory.INVERTER, ComponentCategory.BATTERY], ) ``` Notes: - `components` may contain `ComponentId` instances or `Component` objects. - `categories` may contain `ComponentCategory` enum values or raw integer category IDs. - Filters across `components` and `categories` are combined with `AND`; values inside each list are combined with `OR`. - **List connections**: ```python connections = await client.list_connections( sources=[ComponentId(1)], destinations=[ComponentId(2)], ) ``` Notes: - `sources` and `destinations` accept `ComponentId` or `Component` instances. - Filters across `sources` and `destinations` are combined with `AND`; values inside each list are combined with `OR`. - Connections now also use `.source` and `.destination` terminology instead of `.start` and `.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: ```python 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: ```python # 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 `ComponentId` or `Component` instances. ### 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`: ```python 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 `Metric` when adding bounds. - Bounds are represented as at most two ranges, matching `frequenz-api-common` `v1` (`Bounds` may 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: ```python 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`: ```python 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_bounds` and `system_{inclusion,exclusion}_bounds` are unified under `samples.metric[x].bounds`. - 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. - All metrics for a given component at a given time share the same `sampled_at` timestamp. - At most one `ComponentState` is included per `ComponentData`. 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 rich `MicrogridInfo` dataclass with ID, enterprise, location, delivery area, status, and timestamps. - Add a metrics model under `frequenz.client.microgrid.metrics` including the `Metric` enum, `Bounds`, and `MetricSample`/`AggregatedMetricValue`. - 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. ## Bug Fixes - Restore missing `Metric` enum 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).
# Frequenz Microgrid API Client Release Notes
## Summary
This release removes the `timezonefinder` dependency to significantly reduce package size by 66M+ and enable ARM platform support.
> [!WARNING]
> This is a **breaking change** shipped in a patch release because this feature has no known users.
## Upgrading
The `Location.timezone` field no longer performs automatic timezone lookup from latitude/longitude coordinates.
```python
# Automatic timezone lookup (no longer works)
location = Location(latitude=52.52, longitude=13.405)
print(location.timezone) # Previously: ZoneInfo('Europe/Berlin'), now None
```
If you need timezone lookup from coordinates, install [`timezonefinder`](https://pypi.org/project/timezonefinder/) separately and implement manual lookup:
```python
# Install: pip install timezonefinder
from timezonefinder import TimezoneFinder
from zoneinfo import ZoneInfo
from frequenz.client.microgrid import Location
tf = TimezoneFinder()
tz_name = tf.timezone_at(lat=52.52, lng=13.405)
timezone = ZoneInfo(tz_name) if tz_name else None
location = Location(latitude=52.52, longitude=13.405, timezone=timezone)
```
# Frequenz Microgrid API Client Release Notes
## Summary
This is a small release to allow for easier interoperability between different APIs.
## Upgrading
- Some minimum dependency versions are bumped, so you might need to update your dependencies as well.
- The IDs (`MicrogridId`, `ComponentId`, `SensorId`) are now imported from `frequenz-client-common`. Please add it to your dependencies if you haven't already, then you can replace your imports:
* `from frequenz.client.microgrid import MicrogridId` -> `from frequenz.client.common.microgrid import MicrogridId`
* `from frequenz.client.microgrid import ComponentId` -> `from frequenz.client.common.microgrid.components import ComponentId`
* `from frequenz.client.microgrid import SensorId` -> `from frequenz.client.common.microgrid.sensors import SensorId`
# Frequenz Microgrid API Client Release Notes ## Summary This release introduces sensors support and adds official support for Python 3.12. It also includes some bug fixes. ## Upgrading - Some minimum versions of dependencies have been bumped to support Python 3.12. You might also need to bump these dependencies in your project. ## New Features - The `MicrogridApiClient` can now list sensor retrieving their metadata (`list_sensors()`) and can stream sensor data (`stream_sensor_data()`). ## Bug Fixes - When retrieving the microgrid metadata using `metadata()`, if the location was empty in the protobuf message, a wrong location with long=0, lat=0 was used. Now the location will be properly set to `None` in that case. - The client now does some missing cleanup (stopping background tasks) when disconnecting (and when used as a context manager).
# Frequenz Microgrid API Client Release Notes ## Upgrading - Now component and microgrid IDs are wrapped in new classes: `ComponentId` and `MicrogridId` respectively. These classes provide type safety and prevent accidental errors by: - Making it impossible to mix up microgrid and component IDs (equality comparisons between different ID types always return false). - Preventing accidental math operations on IDs. - Providing clear string representations for debugging (MID42, CID42). - Ensuring proper hash behavior in collections. To migrate you just need to wrap your `int` IDs with the appropriate class: `0` -> `ComponentId(0)` / `MicrogridId(0)`.
# Frequenz Microgrid API Client Release Notes
## Upgrading
- `ApiClient`:
* The class was renamed to `MicrogridApiClient`.
* The `api` attribute was renamed to `stub`.
* The constructor parameter `channel_options` was renamed to `channels_defaults` to match the name used in `BaseApiClient`.
* The constructor now accepts a `connect` parameter, which is `True` by default. If set to `False`, the client will not connect to the server upon instantiation. You can connect later by calling the `connect()` method.
* The `frequenz-client-base` dependency was bumped to v0.8.0.
## New Features
- The client now inherits from `frequenz.client.base.BaseApiClient`, so it provides a few new features, like `disconnect()`ing or using it as a context manager. Please refer to the [`BaseApiClient` documentation](https://frequenz-floss.github.io/frequenz-client-base-python/latest/reference/frequenz/client/base/client/#frequenz.client.base.client.BaseApiClient) for more information on these features.
- The client now supports setting reactive power for components through the new `set_reactive_power` method.
PreviousNext