Skip to content

Commit aad64ed

Browse files
authored
Update DataSourcingActor to accept current requests for inverters (#759)
In some component configurations, it might be necessary to use current readings from inverters to calculate grid current.
2 parents 300544d + fa90c12 commit aad64ed

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,4 @@ This version ships an experimental version of the **Power Manager**, adds prelim
7171
- Fix rendering of diagrams in the documentation.
7272
- The `__getitem__` magic of the `MovingWindow` is fixed to support the same functionality that the `window` method provides.
7373
- Fixes incorrect implementation of single element access in `__getitem__` magic of `MovingWindow`.
74+
- Fix incorrect grid current calculations in locations where the calculations depended on current measurements from an inverter.

src/frequenz/sdk/actor/_data_sourcing/microgrid_api_source.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@
6969
ComponentMetricId.ACTIVE_POWER_INCLUSION_UPPER_BOUND: lambda msg: (
7070
msg.active_power_inclusion_upper_bound
7171
),
72+
ComponentMetricId.CURRENT_PHASE_1: lambda msg: msg.current_per_phase[0],
73+
ComponentMetricId.CURRENT_PHASE_2: lambda msg: msg.current_per_phase[1],
74+
ComponentMetricId.CURRENT_PHASE_3: lambda msg: msg.current_per_phase[2],
7275
ComponentMetricId.FREQUENCY: lambda msg: msg.frequency,
7376
}
7477

@@ -152,7 +155,9 @@ async def _check_battery_request(
152155
"""
153156
for metric in requests:
154157
if metric not in _BatteryDataMethods:
155-
raise ValueError(f"Unknown metric {metric} for Battery id {comp_id}")
158+
err = f"Unknown metric {metric} for Battery id {comp_id}"
159+
logging.error(err)
160+
raise ValueError(err)
156161
if comp_id not in self.comp_data_receivers:
157162
self.comp_data_receivers[
158163
comp_id
@@ -175,7 +180,9 @@ async def _check_ev_charger_request(
175180
"""
176181
for metric in requests:
177182
if metric not in _EVChargerDataMethods:
178-
raise ValueError(f"Unknown metric {metric} for EvCharger id {comp_id}")
183+
err = f"Unknown metric {metric} for EvCharger id {comp_id}"
184+
logging.error(err)
185+
raise ValueError(err)
179186
if comp_id not in self.comp_data_receivers:
180187
self.comp_data_receivers[
181188
comp_id
@@ -198,7 +205,9 @@ async def _check_inverter_request(
198205
"""
199206
for metric in requests:
200207
if metric not in _InverterDataMethods:
201-
raise ValueError(f"Unknown metric {metric} for Inverter id {comp_id}")
208+
err = f"Unknown metric {metric} for Inverter id {comp_id}"
209+
logging.error(err)
210+
raise ValueError(err)
202211
if comp_id not in self.comp_data_receivers:
203212
self.comp_data_receivers[
204213
comp_id
@@ -221,7 +230,9 @@ async def _check_meter_request(
221230
"""
222231
for metric in requests:
223232
if metric not in _MeterDataMethods:
224-
raise ValueError(f"Unknown metric {metric} for Meter id {comp_id}")
233+
err = f"Unknown metric {metric} for Meter id {comp_id}"
234+
logging.error(err)
235+
raise ValueError(err)
225236
if comp_id not in self.comp_data_receivers:
226237
self.comp_data_receivers[
227238
comp_id
@@ -257,7 +268,9 @@ async def _check_requested_component_and_metrics(
257268
elif category == ComponentCategory.METER:
258269
await self._check_meter_request(comp_id, requests)
259270
else:
260-
raise ValueError(f"Unknown component category {category}")
271+
err = f"Unknown component category {category}"
272+
logging.error(err)
273+
raise ValueError(err)
261274

262275
def _get_data_extraction_method(
263276
self, category: ComponentCategory, metric: ComponentMetricId
@@ -283,7 +296,9 @@ def _get_data_extraction_method(
283296
return _MeterDataMethods[metric]
284297
if category == ComponentCategory.EV_CHARGER:
285298
return _EVChargerDataMethods[metric]
286-
raise ValueError(f"Unknown component category {category}")
299+
err = f"Unknown component category {category}"
300+
logging.error(err)
301+
raise ValueError(err)
287302

288303
def _get_metric_senders(
289304
self,

src/frequenz/sdk/microgrid/component/_component_data.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,12 @@ class InverterData(ComponentData):
231231
-ve current means supply into the grid.
232232
"""
233233

234+
current_per_phase: tuple[float, float, float]
235+
"""AC current in Amperes (A) for phase/line 1, 2 and 3 respectively.
236+
+ve current means consumption, away from the grid.
237+
-ve current means supply into the grid.
238+
"""
239+
234240
# pylint: disable=line-too-long
235241
active_power_inclusion_lower_bound: float
236242
"""Lower inclusion bound for inverter power in watts.
@@ -301,6 +307,11 @@ def from_proto(cls, raw: microgrid_pb.ComponentData) -> InverterData:
301307
component_id=raw.id,
302308
timestamp=raw.ts.ToDatetime(tzinfo=timezone.utc),
303309
active_power=raw.inverter.data.ac.power_active.value,
310+
current_per_phase=(
311+
raw.meter.data.ac.phase_1.current.value,
312+
raw.meter.data.ac.phase_2.current.value,
313+
raw.meter.data.ac.phase_3.current.value,
314+
),
304315
active_power_inclusion_lower_bound=raw_power.system_inclusion_bounds.lower,
305316
active_power_exclusion_lower_bound=raw_power.system_exclusion_bounds.lower,
306317
active_power_inclusion_upper_bound=raw_power.system_inclusion_bounds.upper,

tests/utils/component_data_wrapper.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ def __init__( # pylint: disable=too-many-arguments
101101
component_id: int,
102102
timestamp: datetime,
103103
active_power: float = math.nan,
104+
current_per_phase: tuple[float, float, float] | None = None,
104105
active_power_inclusion_lower_bound: float = math.nan,
105106
active_power_exclusion_lower_bound: float = math.nan,
106107
active_power_inclusion_upper_bound: float = math.nan,
@@ -120,6 +121,11 @@ def __init__( # pylint: disable=too-many-arguments
120121
component_id=component_id,
121122
timestamp=timestamp,
122123
active_power=active_power,
124+
current_per_phase=(
125+
current_per_phase
126+
if current_per_phase
127+
else (math.nan, math.nan, math.nan)
128+
),
123129
active_power_inclusion_lower_bound=active_power_inclusion_lower_bound,
124130
active_power_exclusion_lower_bound=active_power_exclusion_lower_bound,
125131
active_power_inclusion_upper_bound=active_power_inclusion_upper_bound,

0 commit comments

Comments
 (0)