Skip to content

Commit bb708b6

Browse files
committed
Add reactive power for inverters, meters and EV chargers
Signed-off-by: Leandro Lucarella <[email protected]>
1 parent c1f6059 commit bb708b6

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

src/frequenz/client/microgrid/_component.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,16 @@ class ComponentMetricId(Enum):
207207
ACTIVE_POWER_PHASE_3 = "active_power_phase_3"
208208
"""Active power in phase 3."""
209209

210+
REACTIVE_POWER = "reactive_power"
211+
"""Reactive power."""
212+
213+
REACTIVE_POWER_PHASE_1 = "reactive_power_phase_1"
214+
"""Reactive power in phase 1."""
215+
REACTIVE_POWER_PHASE_2 = "reactive_power_phase_2"
216+
"""Reactive power in phase 2."""
217+
REACTIVE_POWER_PHASE_3 = "reactive_power_phase_3"
218+
"""Reactive power in phase 3."""
219+
210220
CURRENT_PHASE_1 = "current_phase_1"
211221
"""Current in phase 1."""
212222
CURRENT_PHASE_2 = "current_phase_2"

src/frequenz/client/microgrid/_component_data.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,22 @@ class MeterData(ComponentData):
8787
* Negative means supply into the grid.
8888
"""
8989

90+
reactive_power: float
91+
"""The total reactive 3-phase AC power, in Volt-Ampere Reactive (VAr).
92+
93+
* Positive power means capacitive (current leading w.r.t. voltage).
94+
* Negative power means inductive (current lagging w.r.t. voltage).
95+
"""
96+
97+
reactive_power_per_phase: tuple[float, float, float]
98+
"""The per-phase AC reactive power, in Volt-Ampere Reactive (VAr).
99+
100+
The provided values are for phase 1, 2, and 3 respectively.
101+
102+
* Positive power means capacitive (current leading w.r.t. voltage).
103+
* Negative power means inductive (current lagging w.r.t. voltage).
104+
"""
105+
90106
current_per_phase: tuple[float, float, float]
91107
"""AC current in Amperes (A) for phase/line 1,2 and 3 respectively.
92108
@@ -123,6 +139,12 @@ def from_proto(cls, raw: PbComponentData) -> Self:
123139
raw.meter.data.ac.phase_2.power_active.value,
124140
raw.meter.data.ac.phase_3.power_active.value,
125141
),
142+
reactive_power=raw.meter.data.ac.power_reactive.value,
143+
reactive_power_per_phase=(
144+
raw.meter.data.ac.phase_1.power_reactive.value,
145+
raw.meter.data.ac.phase_2.power_reactive.value,
146+
raw.meter.data.ac.phase_3.power_reactive.value,
147+
),
126148
current_per_phase=(
127149
raw.meter.data.ac.phase_1.current.value,
128150
raw.meter.data.ac.phase_2.current.value,
@@ -270,6 +292,22 @@ class InverterData(ComponentData): # pylint: disable=too-many-instance-attribut
270292
* Negative means supply into the grid.
271293
"""
272294

295+
reactive_power: float
296+
"""The total reactive 3-phase AC power, in Volt-Ampere Reactive (VAr).
297+
298+
* Positive power means capacitive (current leading w.r.t. voltage).
299+
* Negative power means inductive (current lagging w.r.t. voltage).
300+
"""
301+
302+
reactive_power_per_phase: tuple[float, float, float]
303+
"""The per-phase AC reactive power, in Volt-Ampere Reactive (VAr).
304+
305+
The provided values are for phase 1, 2, and 3 respectively.
306+
307+
* Positive power means capacitive (current leading w.r.t. voltage).
308+
* Negative power means inductive (current lagging w.r.t. voltage).
309+
"""
310+
273311
current_per_phase: tuple[float, float, float]
274312
"""AC current in Amperes (A) for phase/line 1, 2 and 3 respectively.
275313
@@ -359,6 +397,12 @@ def from_proto(cls, raw: PbComponentData) -> Self:
359397
raw.inverter.data.ac.phase_2.power_active.value,
360398
raw.inverter.data.ac.phase_3.power_active.value,
361399
),
400+
reactive_power=raw.inverter.data.ac.power_reactive.value,
401+
reactive_power_per_phase=(
402+
raw.inverter.data.ac.phase_1.power_reactive.value,
403+
raw.inverter.data.ac.phase_2.power_reactive.value,
404+
raw.inverter.data.ac.phase_3.power_reactive.value,
405+
),
362406
current_per_phase=(
363407
raw.inverter.data.ac.phase_1.current.value,
364408
raw.inverter.data.ac.phase_2.current.value,
@@ -413,6 +457,22 @@ class EVChargerData(ComponentData): # pylint: disable=too-many-instance-attribu
413457
* Negative means supply into the grid.
414458
"""
415459

460+
reactive_power: float
461+
"""The total reactive 3-phase AC power, in Volt-Ampere Reactive (VAr).
462+
463+
* Positive power means capacitive (current leading w.r.t. voltage).
464+
* Negative power means inductive (current lagging w.r.t. voltage).
465+
"""
466+
467+
reactive_power_per_phase: tuple[float, float, float]
468+
"""The per-phase AC reactive power, in Volt-Ampere Reactive (VAr).
469+
470+
The provided values are for phase 1, 2, and 3 respectively.
471+
472+
* Positive power means capacitive (current leading w.r.t. voltage).
473+
* Negative power means inductive (current lagging w.r.t. voltage).
474+
"""
475+
416476
voltage_per_phase: tuple[float, float, float]
417477
"""The AC voltage in Volts (V) between the line and the neutral
418478
wire for phase/line 1,2 and 3 respectively.
@@ -491,6 +551,12 @@ def from_proto(cls, raw: PbComponentData) -> Self:
491551
raw.ev_charger.data.ac.phase_2.power_active.value,
492552
raw.ev_charger.data.ac.phase_3.power_active.value,
493553
),
554+
reactive_power=raw.ev_charger.data.ac.power_reactive.value,
555+
reactive_power_per_phase=(
556+
raw.ev_charger.data.ac.phase_1.power_reactive.value,
557+
raw.ev_charger.data.ac.phase_2.power_reactive.value,
558+
raw.ev_charger.data.ac.phase_3.power_reactive.value,
559+
),
494560
current_per_phase=(
495561
raw.ev_charger.data.ac.phase_1.current.value,
496562
raw.ev_charger.data.ac.phase_2.current.value,

tests/test_component_data.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,28 @@ def test_inverter_data() -> None:
5252
system_exclusion_bounds=Bounds(lower=-501.0, upper=501.0),
5353
system_inclusion_bounds=Bounds(lower=-51_000.0, upper=51_000.0),
5454
),
55+
power_reactive=Metric(
56+
value=200.3,
57+
system_exclusion_bounds=Bounds(lower=-502.0, upper=502.0),
58+
system_inclusion_bounds=Bounds(lower=-52_000.0, upper=52_000.0),
59+
),
5560
phase_1=AC.ACPhase(
5661
current=Metric(value=12.3),
5762
voltage=Metric(value=229.8),
5863
power_active=Metric(value=33.1),
64+
power_reactive=Metric(value=10.1),
5965
),
6066
phase_2=AC.ACPhase(
6167
current=Metric(value=23.4),
6268
voltage=Metric(value=230.0),
6369
power_active=Metric(value=33.3),
70+
power_reactive=Metric(value=10.2),
6471
),
6572
phase_3=AC.ACPhase(
6673
current=Metric(value=34.5),
6774
voltage=Metric(value=230.2),
6875
power_active=Metric(value=33.8),
76+
power_reactive=Metric(value=10.3),
6977
),
7078
),
7179
),
@@ -84,6 +92,8 @@ def test_inverter_data() -> None:
8492
assert inv_data.frequency == pytest.approx(50.1)
8593
assert inv_data.active_power == pytest.approx(100.2)
8694
assert inv_data.active_power_per_phase == pytest.approx((33.1, 33.3, 33.8))
95+
assert inv_data.reactive_power == pytest.approx(200.3)
96+
assert inv_data.reactive_power_per_phase == pytest.approx((10.1, 10.2, 10.3))
8797
assert inv_data.current_per_phase == pytest.approx((12.3, 23.4, 34.5))
8898
assert inv_data.voltage_per_phase == pytest.approx((229.8, 230.0, 230.2))
8999
assert inv_data.active_power_inclusion_lower_bound == pytest.approx(-51_000.0)

0 commit comments

Comments
 (0)