Skip to content

Commit 6637d7f

Browse files
authored
Some EV charger pool cleanup and fixes (#919)
2 parents 9fd4865 + 4e96e28 commit 6637d7f

File tree

3 files changed

+16
-21
lines changed

3 files changed

+16
-21
lines changed

src/frequenz/sdk/actor/power_distributing/_component_managers/_ev_charger_manager/_ev_charger_manager.py

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import grpc
1212
from frequenz.channels import Broadcast, Sender, merge, select, selected_from
13-
from frequenz.channels.timer import SkipMissedAndDrift, Timer
1413
from frequenz.client.microgrid import ApiClient, ComponentCategory, EVChargerData
1514
from typing_extensions import override
1615

@@ -20,8 +19,6 @@
2019
from ....._internal._math import is_close_to_zero
2120
from .....timeseries import Power, Sample3Phase, Voltage
2221
from ..._component_pool_status_tracker import ComponentPoolStatusTracker
23-
24-
# from .._component_pool_status_tracker import ComponentPoolStatusTracker
2522
from ..._component_status import ComponentPoolStatus, EVChargerStatusTracker
2623
from ...request import Request
2724
from ...result import PartialFailure, Result, Success
@@ -32,7 +29,6 @@
3229
_logger = logging.getLogger(__name__)
3330

3431
_DEFAULT_API_REQUEST_TIMEOUT = timedelta(seconds=5.0)
35-
_TGT_POWER_RESEND_INTERVAL = timedelta(seconds=5.0)
3632

3733

3834
class EVChargerManager(ComponentManager):
@@ -79,7 +75,9 @@ def component_ids(self) -> collections.abc.Set[int]:
7975
@override
8076
async def start(self) -> None:
8177
"""Start the ev charger data manager."""
82-
self._task = asyncio.create_task(self._run_forever())
78+
# Need to start a task only if there are EV chargers in the component graph.
79+
if self._ev_charger_ids:
80+
self._task = asyncio.create_task(self._run_forever())
8381

8482
@override
8583
async def distribute_power(self, request: Request) -> None:
@@ -88,7 +86,8 @@ async def distribute_power(self, request: Request) -> None:
8886
Args:
8987
request: Request to get the distribution for.
9088
"""
91-
await self._target_power_tx.send(request)
89+
if self._ev_charger_ids:
90+
await self._target_power_tx.send(request)
9291

9392
@override
9493
async def stop(self) -> None:
@@ -222,10 +221,8 @@ async def _run(self) -> None: # pylint: disable=too-many-locals
222221
)
223222
target_power_rx = self._target_power_channel.new_receiver()
224223
api_request_timeout = _DEFAULT_API_REQUEST_TIMEOUT
225-
resend_timer = Timer(_TGT_POWER_RESEND_INTERVAL, SkipMissedAndDrift())
226224
latest_target_powers: dict[int, Power] = {}
227-
async for selected in select(ev_charger_data_rx, target_power_rx, resend_timer):
228-
resending = False
225+
async for selected in select(ev_charger_data_rx, target_power_rx):
229226
target_power_changes = {}
230227
now = datetime.now(tz=timezone.utc)
231228

@@ -276,21 +273,14 @@ async def _run(self) -> None: # pylint: disable=too-many-locals
276273
diff_power = allocated_power - self._target_power
277274
target_power_changes = self._deallocate_unused_power(diff_power)
278275

279-
elif selected_from(selected, resend_timer):
280-
target_power_changes = latest_target_powers
281-
resending = True
282-
283276
if target_power_changes:
284277
_logger.debug("Setting power to EV chargers: %s", target_power_changes)
285278
else:
286279
continue
287-
if not resending:
288-
for component_id, power in target_power_changes.items():
289-
self._evc_states.get(component_id).update_last_allocation(
290-
power, now
291-
)
280+
for component_id, power in target_power_changes.items():
281+
self._evc_states.get(component_id).update_last_allocation(power, now)
292282

293-
latest_target_powers.update(target_power_changes)
283+
latest_target_powers.update(target_power_changes)
294284
result = await self._set_api_power(
295285
api, target_power_changes, api_request_timeout
296286
)

src/frequenz/sdk/timeseries/ev_charger_pool/_ev_charger_pool.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,14 @@ async def propose_power(
115115
actors with a higher priority. If None, the power bounds will be set to
116116
the maximum power of the batteries in the pool. This is currently and
117117
experimental feature.
118+
119+
Raises:
120+
EVChargerPoolError: If a discharge power for EV chargers is requested.
118121
"""
122+
if power is not None and power < Power.zero():
123+
raise EVChargerPoolError(
124+
"Discharging from EV chargers is currently not supported."
125+
)
119126
await self._ev_charger_pool.power_manager_requests_sender.send(
120127
_power_managing.Proposal(
121128
source_id=self._source_id,

tests/timeseries/_ev_charger_pool/test_ev_charger_pool_control_methods.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,6 @@ async def _init_ev_chargers(self, mocks: _Mocks) -> None:
163163
0.05,
164164
)
165165

166-
await asyncio.sleep(1)
167-
168166
def _assert_report( # pylint: disable=too-many-arguments
169167
self,
170168
report: EVChargerPoolReport,

0 commit comments

Comments
 (0)