diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4563c5576..0c94034b2 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -46,6 +46,10 @@ - The `ComponentGraph.components()` parameters `component_id` and `component_category` were renamed to `component_ids` and `component_categories`, respectively. +- The `GridFrequency.component` propery was renamed to `GridFrequency.source` + +- The `microgrid.frequency()` method no longer supports passing the `component` parameter. Instead the best component is automatically selected. + ## New Features diff --git a/src/frequenz/sdk/microgrid/_data_pipeline.py b/src/frequenz/sdk/microgrid/_data_pipeline.py index 720587c22..1b46ca3a5 100644 --- a/src/frequenz/sdk/microgrid/_data_pipeline.py +++ b/src/frequenz/sdk/microgrid/_data_pipeline.py @@ -19,7 +19,6 @@ from frequenz.channels import Broadcast, Sender from ..actor._actor import Actor -from ..microgrid.component import Component from ..timeseries._base_types import PoolType from ..timeseries._grid_frequency import GridFrequency from ..timeseries.grid import Grid @@ -119,29 +118,21 @@ def __init__( self._grid: Grid | None = None self._ev_charger_pools: dict[frozenset[int], EVChargerPool] = {} self._battery_pools: dict[frozenset[int], BatteryPoolReferenceStore] = {} - self._frequency_pool: dict[int, GridFrequency] = {} + self._frequency_instance: GridFrequency | None = None - def frequency(self, component: Component | None = None) -> GridFrequency: + def frequency(self) -> GridFrequency: """Fetch the grid frequency for the microgrid. - Args: - component: The component to use when fetching the grid frequency. If None, - the component will be fetched from the registry. - Returns: - A GridFrequency instance. + The GridFrequency instance. """ - if component is None: - component = GridFrequency.find_frequency_component() + if self._frequency_instance is None: + self._frequency_instance = GridFrequency( + self._data_sourcing_request_sender(), + self._channel_registry, + ) - if component.component_id in self._frequency_pool: - return self._frequency_pool[component.component_id] - - grid_frequency = GridFrequency( - self._data_sourcing_request_sender(), self._channel_registry, component - ) - self._frequency_pool[component.component_id] = grid_frequency - return grid_frequency + return self._frequency_instance def logical_meter(self) -> LogicalMeter: """Return the logical meter instance. @@ -409,17 +400,13 @@ async def initialize(resampler_config: ResamplerConfig) -> None: _DATA_PIPELINE = _DataPipeline(resampler_config) -def frequency(component: Component | None = None) -> GridFrequency: +def frequency() -> GridFrequency: """Return the grid frequency. - Args: - component: Optional component to get the frequency for. If not specified, - the frequency of the grid is returned. - Returns: The grid frequency. """ - return _get().frequency(component) + return _get().frequency() def logical_meter() -> LogicalMeter: diff --git a/src/frequenz/sdk/timeseries/_grid_frequency.py b/src/frequenz/sdk/timeseries/_grid_frequency.py index 805b6aea2..96ac30285 100644 --- a/src/frequenz/sdk/timeseries/_grid_frequency.py +++ b/src/frequenz/sdk/timeseries/_grid_frequency.py @@ -49,32 +49,32 @@ def __init__( self, data_sourcing_request_sender: Sender[ComponentMetricRequest], channel_registry: ChannelRegistry, - component: Component, + source: Component | None = None, ): """Initialize the grid frequency formula generator. Args: data_sourcing_request_sender: The sender to use for requests. channel_registry: The channel registry to use for the grid frequency. - component: The component to use for the grid frequency receiver. If not - provided, the first component that is either a meter, inverter or EV - charger will be used. + source: The source component to use to receive the grid frequency. """ self._request_sender = data_sourcing_request_sender self._channel_registry = channel_registry - self._component = component - self._component_metric_request = create_request(component.component_id) + self._source_component = source or GridFrequency.find_frequency_source() + self._component_metric_request = create_request( + self._source_component.component_id + ) self._task: None | asyncio.Task[None] = None @property - def component(self) -> Component: - """The component that is used for grid frequency. + def source(self) -> Component: + """The component that is used to fetch the grid frequency. Returns: The component that is used for grid frequency. """ - return self._component + return self._source_component def new_receiver(self) -> Receiver[Sample[Frequency]]: """Create a receiver for grid frequency. @@ -89,22 +89,23 @@ def new_receiver(self) -> Receiver[Sample[Frequency]]: if not self._task: self._task = asyncio.create_task(self._send_request()) else: - _logger.info("Grid frequency request already sent: %s", self._component) + _logger.info( + "Grid frequency request already sent: %s", self._source_component + ) return receiver async def _send_request(self) -> None: """Send the request for grid frequency.""" - _logger.info("Sending request for grid frequency: %s", self._component) await self._request_sender.send(self._component_metric_request) - _logger.info("Sent request for grid frequency: %s", self._component) + _logger.debug("Sent request for grid frequency: %s", self._source_component) @staticmethod - def find_frequency_component() -> Component: - """Find the component that will be used for grid frequency. + def find_frequency_source() -> Component: + """Find the source component that will be used for grid frequency. - Uses the first meter it can find to gather the frequency. If no meter is - available, it will use the first inverter, then EV charger. + Will use the first meter it can find to gather the frequency. + If no meter is available, the first inverter will be used and finally the first EV charger. Returns: The component that will be used for grid frequency.