Skip to content

Commit d422e0d

Browse files
Improve producer power formula
Signed-off-by: Matthias Wende <[email protected]>
1 parent 1517b4f commit d422e0d

File tree

1 file changed

+32
-27
lines changed

1 file changed

+32
-27
lines changed

src/frequenz/sdk/timeseries/_formula_engine/_formula_generators/_producer_power_formula.py

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55

66
from __future__ import annotations
77

8+
import logging
9+
810
from ....microgrid import connection_manager
911
from ....microgrid.component import ComponentCategory, ComponentMetricId
1012
from ..._quantities import Power
1113
from .._formula_engine import FormulaEngine
1214
from ._formula_generator import NON_EXISTING_COMPONENT_ID, FormulaGenerator
1315

16+
_logger = logging.getLogger(__name__)
17+
1418

1519
class ProducerPowerFormula(FormulaGenerator[Power]):
1620
"""Formula generator from component graph for calculating the Producer Power.
@@ -34,36 +38,37 @@ def generate(self) -> FormulaEngine[Power]:
3438
builder = self._get_builder(
3539
"producer_power", ComponentMetricId.ACTIVE_POWER, Power.from_watts
3640
)
41+
3742
component_graph = connection_manager.get().component_graph
38-
grid_successors = self._get_grid_component_successors()
39-
40-
if len(grid_successors) == 1:
41-
grid_meter = next(iter(grid_successors))
42-
if grid_meter.category != ComponentCategory.METER:
43-
raise RuntimeError(
44-
"Only grid successor in the component graph is not a meter."
45-
)
46-
grid_successors = component_graph.successors(grid_meter.component_id)
47-
48-
first_iteration = True
49-
for successor in iter(grid_successors):
50-
# if in the future we support additional producers, we need to add them here
51-
if component_graph.is_chp_chain(successor) or component_graph.is_pv_chain(
52-
successor
53-
):
54-
if not first_iteration:
55-
builder.push_oper("+")
56-
57-
first_iteration = False
58-
59-
builder.push_component_metric(
60-
successor.component_id,
61-
nones_are_zeros=successor.category != ComponentCategory.METER,
62-
)
63-
64-
if first_iteration:
43+
# if in the future we support additional producers, we need to add them to the lambda
44+
producer_components = component_graph.dfs(
45+
self._get_grid_component(),
46+
set(),
47+
lambda component: component_graph.is_pv_chain(component)
48+
or component_graph.is_chp_chain(component),
49+
)
50+
51+
if not producer_components:
52+
_logger.warning(
53+
"Unable to find any producer components in the component graph. "
54+
"Subscribing to the resampling actor with a non-existing "
55+
"component id, so that `0` values are sent from the formula."
56+
)
57+
# If there are no producer components, we have to send 0 values at the same
58+
# frequency as the other streams. So we subscribe with a non-existing
59+
# component id, just to get a `None` message at the resampling interval.
6560
builder.push_component_metric(
6661
NON_EXISTING_COMPONENT_ID, nones_are_zeros=True
6762
)
63+
return builder.build()
64+
65+
for idx, component in enumerate(producer_components):
66+
if idx > 0:
67+
builder.push_oper("+")
68+
69+
builder.push_component_metric(
70+
component.component_id,
71+
nones_are_zeros=component.category != ComponentCategory.METER,
72+
)
6873

6974
return builder.build()

0 commit comments

Comments
 (0)