Skip to content

Commit fb61bb3

Browse files
committed
Add a formula generator for PV power
Signed-off-by: Sahas Subramanian <[email protected]>
1 parent facc381 commit fb61bb3

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

src/frequenz/sdk/timeseries/logical_meter/_formula_generators/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,22 @@
1010
FormulaGenerator,
1111
)
1212
from ._grid_power_formula import GridPowerFormula
13+
from ._pv_power_formula import PVPowerFormula
1314

1415
__all__ = [
16+
#
17+
# Base class
18+
#
19+
"FormulaGenerator",
20+
#
21+
# Formula generators
22+
#
1523
"GridPowerFormula",
1624
"BatteryPowerFormula",
25+
"PVPowerFormula",
26+
#
27+
# Exceptions
28+
#
1729
"ComponentNotFound",
18-
"FormulaGenerator",
1930
"FormulaGenerationError",
2031
]
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# License: MIT
2+
# Copyright © 2022 Frequenz Energy-as-a-Service GmbH
3+
4+
"""Formula generator for PV Power, from the component graph."""
5+
6+
from .....sdk import microgrid
7+
from ....microgrid.component import ComponentCategory, ComponentMetricId, InverterType
8+
from .._formula_engine import FormulaEngine
9+
from ._formula_generator import ComponentNotFound, FormulaGenerator
10+
11+
12+
class PVPowerFormula(FormulaGenerator):
13+
"""Creates a formula engine for calculating the PV power production."""
14+
15+
async def generate(self) -> FormulaEngine:
16+
"""Make a formula for the PV power production of a microgrid.
17+
18+
Returns:
19+
A formula engine that will calculate PV power production values.
20+
21+
Raises:
22+
ComponentNotFound: if there are no PV inverters in the component graph.
23+
"""
24+
builder = self._get_builder(ComponentMetricId.ACTIVE_POWER)
25+
26+
component_graph = microgrid.get().component_graph
27+
pv_inverters = list(
28+
comp
29+
for comp in component_graph.components()
30+
if comp.category == ComponentCategory.INVERTER
31+
and comp.type == InverterType.SOLAR
32+
)
33+
34+
if not pv_inverters:
35+
raise ComponentNotFound(
36+
"Unable to find any PV inverters in the component graph."
37+
)
38+
39+
for idx, comp in enumerate(pv_inverters):
40+
if idx > 0:
41+
builder.push_oper("+")
42+
43+
await builder.push_component_metric(comp.component_id, nones_are_zeros=True)
44+
45+
return builder.build()

src/frequenz/sdk/timeseries/logical_meter/_logical_meter.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@
1717
from ...microgrid.component import ComponentMetricId
1818
from .. import Sample
1919
from ._formula_engine import FormulaEngine
20-
from ._formula_generators import BatteryPowerFormula, FormulaGenerator, GridPowerFormula
20+
from ._formula_generators import (
21+
BatteryPowerFormula,
22+
FormulaGenerator,
23+
GridPowerFormula,
24+
PVPowerFormula,
25+
)
2126
from ._resampled_formula_builder import ResampledFormulaBuilder
2227

2328
logger = logging.Logger(__name__)
@@ -170,3 +175,15 @@ async def battery_power(self) -> Receiver[Sample]:
170175
171176
"""
172177
return await self._get_formula_stream("battery_power", BatteryPowerFormula)
178+
179+
async def pv_power(self) -> Receiver[Sample]:
180+
"""Fetch the PV power production in the microgrid.
181+
182+
If a formula engine to calculate PV power production is not
183+
already running, it will be started. Else, we'll just get a new
184+
receiver to the already existing data stream.
185+
186+
Returns:
187+
A *new* receiver that will stream PV power production values.
188+
"""
189+
return await self._get_formula_stream("pv_power", PVPowerFormula)

0 commit comments

Comments
 (0)