Skip to content

Commit

Permalink
Fix reactive power retrieval (#927)
Browse files Browse the repository at this point in the history
The data sourcing actor needs to know about the new metric. This commit
exposes it, adds a trivial test and updates the release notes to do a
hotfix right after this is merged.
  • Loading branch information
llucax authored Apr 12, 2024
2 parents 57337df + d560032 commit cf75848
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 39 deletions.
40 changes: 1 addition & 39 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,5 @@
# Frequenz Python SDK Release Notes

## Summary

The most notable features for this release is the addition of the `PVPool` (exposed via `microgrid.pv_pool()`), which can be used to manage PV arrays as a single entity and the `EVChargerPool` (`microgrid.ev_charger_pool()`) learning to manage power for the whole pool (before it could only be used to control chargers individually).

Another notable change is the microgrid API client being moved to its own [repository](https://github.com/frequenz-floss/frequenz-client-microgrid-python/).

## Upgrading

- The SDK is now using the microgrid API client from [`frequenz-client-microgrid`](https://github.com/frequenz-floss/frequenz-client-microgrid-python/). You should update your code if you are using the microgrid API client directly.

- The minimum required `frequenz-channels` version is now [`v1.0.0-rc1`](https://github.com/frequenz-floss/frequenz-channels-python/releases/tag/v1.0.0-rc.1).

- The set of battery IDs managed by a battery pool are now available through `BatteryPool.component_ids`, and no longer through `BatteryPool.battery_ids`. This is done to have a consistent interface with other `*Pool`s.

- The `maxsize` parameter in calls to `BatteryPool.{soc/capacity/temperature}.new_receiver()` methods have now been renamed to `limit`, to be consistent with the channels repository.

- Support for per-component interaction in `EVChargerPool` has been removed. Please use the new `propose_power()` method to manage power for the whole pool. If you still need to manage power of chargers individually, you can create one pool per charger.

- PV power is now available from `microgrid.pv_pool().power`, and no longer from `microgrid.logical_meter().pv_power`.

## New Features

- `EVChargerPool`/`microgrid.ev_charger_pool()`: New `propose_power` and `power_status` methods have been added, similar to the `BatteryPool`. These method interface with the `PowerManager` and `PowerDistributor`, which currently uses a first-come-first-serve algorithm to distribute power to EVs.

- A PV pool (`PVPool`/`microgrid.pv_pool()`) was added, with `propose_power`, `power_status` and `power` methods similar to Battery and EV pools.

- The microgrid API client now exposes the reactive power for inverters, meters and EV chargers.

## Enhancements

- Warning messages are logged when multiple instances of `*Pool`s are created for the same set of batteries, with the same priority values.

- A warning message will now be logged if no relevant samples are found in a component for resampling.

## Bug Fixes

- A bug was fixed where the grid fuse was not created properly and would end up with a `max_current` with type `float` instead of `Current`.

- `BatteryPool.propose_discharge` now converts power values to the passive-sign convention. Earlier it was not doing this and that was causing it to charge instead of discharge.

- Fix a bug that was causing the power managing actor to crash and restart when cleaning up old proposals.
- Fix getting reactive power from meters, inverters and EV chargers.
30 changes: 30 additions & 0 deletions src/frequenz/sdk/actor/_data_sourcing/microgrid_api_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@
ComponentMetricId.VOLTAGE_PHASE_2: lambda msg: msg.voltage_per_phase[1],
ComponentMetricId.VOLTAGE_PHASE_3: lambda msg: msg.voltage_per_phase[2],
ComponentMetricId.FREQUENCY: lambda msg: msg.frequency,
ComponentMetricId.REACTIVE_POWER: lambda msg: msg.reactive_power,
ComponentMetricId.REACTIVE_POWER_PHASE_1: lambda msg: msg.reactive_power_per_phase[
0
],
ComponentMetricId.REACTIVE_POWER_PHASE_2: lambda msg: msg.reactive_power_per_phase[
1
],
ComponentMetricId.REACTIVE_POWER_PHASE_3: lambda msg: msg.reactive_power_per_phase[
2
],
}

_BatteryDataMethods: dict[ComponentMetricId, Callable[[BatteryData], float]] = {
Expand Down Expand Up @@ -84,6 +94,16 @@
ComponentMetricId.VOLTAGE_PHASE_2: lambda msg: msg.voltage_per_phase[1],
ComponentMetricId.VOLTAGE_PHASE_3: lambda msg: msg.voltage_per_phase[2],
ComponentMetricId.FREQUENCY: lambda msg: msg.frequency,
ComponentMetricId.REACTIVE_POWER: lambda msg: msg.reactive_power,
ComponentMetricId.REACTIVE_POWER_PHASE_1: lambda msg: msg.reactive_power_per_phase[
0
],
ComponentMetricId.REACTIVE_POWER_PHASE_2: lambda msg: msg.reactive_power_per_phase[
1
],
ComponentMetricId.REACTIVE_POWER_PHASE_3: lambda msg: msg.reactive_power_per_phase[
2
],
}

_EVChargerDataMethods: dict[ComponentMetricId, Callable[[EVChargerData], float]] = {
Expand All @@ -98,6 +118,16 @@
ComponentMetricId.VOLTAGE_PHASE_2: lambda msg: msg.voltage_per_phase[1],
ComponentMetricId.VOLTAGE_PHASE_3: lambda msg: msg.voltage_per_phase[2],
ComponentMetricId.FREQUENCY: lambda msg: msg.frequency,
ComponentMetricId.REACTIVE_POWER: lambda msg: msg.reactive_power,
ComponentMetricId.REACTIVE_POWER_PHASE_1: lambda msg: msg.reactive_power_per_phase[
0
],
ComponentMetricId.REACTIVE_POWER_PHASE_2: lambda msg: msg.reactive_power_per_phase[
1
],
ComponentMetricId.REACTIVE_POWER_PHASE_3: lambda msg: msg.reactive_power_per_phase[
2
],
}


Expand Down
8 changes: 8 additions & 0 deletions tests/actor/test_data_sourcing.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ async def test_data_sourcing_actor(self) -> None:
).new_receiver()
await req_sender.send(active_power_request)

reactive_power_request = ComponentMetricRequest(
"test-namespace", 4, ComponentMetricId.REACTIVE_POWER, None
)
reactive_power_recv = registry.get_or_create(
Sample[Quantity], reactive_power_request.get_channel_name()
).new_receiver()
await req_sender.send(reactive_power_request)

soc_request = ComponentMetricRequest(
"test-namespace", 9, ComponentMetricId.SOC, None
)
Expand Down

0 comments on commit cf75848

Please sign in to comment.