Skip to content

Commit f10dfc6

Browse files
committed
Add tests for battery_pool.temperature
Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 3ae0941 commit f10dfc6

File tree

1 file changed

+131
-1
lines changed

1 file changed

+131
-1
lines changed

tests/timeseries/_battery_pool/test_battery_pool.py

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Copyright © 2023 Frequenz Energy-as-a-Service GmbH
33

44
"""Tests for battery pool."""
5+
56
from __future__ import annotations
67

78
import asyncio
@@ -25,7 +26,7 @@
2526
from frequenz.sdk.actor import ResamplerConfig
2627
from frequenz.sdk.actor.power_distributing import BatteryStatus
2728
from frequenz.sdk.microgrid.component import ComponentCategory
28-
from frequenz.sdk.timeseries import Energy, Percentage, Power, Sample
29+
from frequenz.sdk.timeseries import Energy, Percentage, Power, Sample, Temperature
2930
from frequenz.sdk.timeseries.battery_pool import BatteryPool, Bound, PowerMetrics
3031
from frequenz.sdk.timeseries.battery_pool._metric_calculator import (
3132
battery_inverter_mapping,
@@ -45,6 +46,8 @@
4546
# pylint doesn't understand fixtures. It thinks it is redefined name.
4647
# pylint: disable=redefined-outer-name
4748

49+
# pylint: disable=too-many-lines
50+
4851

4952
@pytest.fixture()
5053
def event_loop() -> Iterator[async_solipsism.EventLoop]:
@@ -337,6 +340,24 @@ async def test_battery_pool_power_bounds(setup_batteries_pool: SetupArgs) -> Non
337340
await run_power_bounds_test(setup_batteries_pool)
338341

339342

343+
async def test_all_batteries_temperature(setup_all_batteries: SetupArgs) -> None:
344+
"""Test temperature for battery pool with all components in the microgrid.
345+
346+
Args:
347+
setup_all_batteries: Fixture that creates needed microgrid tools.
348+
"""
349+
await run_temperature_test(setup_all_batteries)
350+
351+
352+
async def test_battery_pool_temperature(setup_batteries_pool: SetupArgs) -> None:
353+
"""Test temperature for battery pool with subset of components in the microgrid.
354+
355+
Args:
356+
setup_all_batteries: Fixture that creates needed microgrid tools.
357+
"""
358+
await run_temperature_test(setup_batteries_pool)
359+
360+
340361
def assert_dataclass(arg: Any) -> None:
341362
"""Raise assert error if argument is not dataclass.
342363
@@ -981,3 +1002,112 @@ async def run_power_bounds_test( # pylint: disable=too-many-locals
9811002
streamer.start_streaming(latest_data, sampling_rate=0.1)
9821003
msg = await asyncio.wait_for(receiver.receive(), timeout=waiting_time_sec)
9831004
compare_messages(msg, PowerMetrics(now, Bound(-100, 0), Bound(0, 100)), 0.2)
1005+
1006+
1007+
async def run_temperature_test( # pylint: disable=too-many-locals
1008+
setup_args: SetupArgs,
1009+
) -> None:
1010+
"""Test if temperature metric is working as expected."""
1011+
battery_pool = setup_args.battery_pool
1012+
mock_microgrid = setup_args.mock_microgrid
1013+
streamer = setup_args.streamer
1014+
battery_status_sender = setup_args.battery_status_sender
1015+
1016+
all_batteries = get_components(mock_microgrid, ComponentCategory.BATTERY)
1017+
await battery_status_sender.send(
1018+
BatteryStatus(working=all_batteries, uncertain=set())
1019+
)
1020+
bat_inv_map = battery_inverter_mapping(all_batteries)
1021+
1022+
for battery_id, inverter_id in bat_inv_map.items():
1023+
# Sampling rate choose to reflect real application.
1024+
streamer.start_streaming(
1025+
BatteryDataWrapper(
1026+
component_id=battery_id,
1027+
timestamp=datetime.now(tz=timezone.utc),
1028+
temperature=25.0,
1029+
),
1030+
sampling_rate=0.05,
1031+
)
1032+
streamer.start_streaming(
1033+
InverterDataWrapper(
1034+
component_id=inverter_id,
1035+
timestamp=datetime.now(tz=timezone.utc),
1036+
),
1037+
sampling_rate=0.1,
1038+
)
1039+
1040+
receiver = battery_pool.temperature.new_receiver()
1041+
1042+
msg = await asyncio.wait_for(
1043+
receiver.receive(), timeout=WAIT_FOR_COMPONENT_DATA_SEC + 0.2
1044+
)
1045+
now = datetime.now(tz=timezone.utc)
1046+
expected = Sample(now, value=Temperature.from_celsius(25.0))
1047+
compare_messages(msg, expected, WAIT_FOR_COMPONENT_DATA_SEC + 0.2)
1048+
1049+
batteries_in_pool = list(battery_pool.battery_ids)
1050+
bat_0, bat_1 = batteries_in_pool
1051+
scenarios: list[Scenario[Sample[Temperature]]] = [
1052+
Scenario(
1053+
bat_0,
1054+
{"temperature": 30.0},
1055+
Sample(now, value=Temperature.from_celsius(27.5)),
1056+
),
1057+
Scenario(
1058+
bat_1,
1059+
{"temperature": 20.0},
1060+
Sample(now, value=Temperature.from_celsius(25.0)),
1061+
),
1062+
Scenario(
1063+
bat_0,
1064+
{"temperature": math.nan},
1065+
Sample(now, value=Temperature.from_celsius(20.0)),
1066+
),
1067+
Scenario(
1068+
bat_1,
1069+
{"temperature": math.nan},
1070+
None,
1071+
),
1072+
Scenario(
1073+
bat_0,
1074+
{"temperature": 30.0},
1075+
Sample(now, value=Temperature.from_celsius(30.0)),
1076+
),
1077+
Scenario(
1078+
bat_1,
1079+
{"temperature": 15.0},
1080+
Sample(now, value=Temperature.from_celsius(22.5)),
1081+
),
1082+
]
1083+
1084+
waiting_time_sec = setup_args.min_update_interval + 0.02
1085+
await run_scenarios(scenarios, streamer, receiver, waiting_time_sec)
1086+
1087+
await run_test_battery_status_channel(
1088+
battery_status_sender=battery_status_sender,
1089+
battery_pool_metric_receiver=receiver,
1090+
all_batteries=all_batteries,
1091+
batteries_in_pool=batteries_in_pool,
1092+
waiting_time_sec=waiting_time_sec,
1093+
all_pool_result=Sample(now, Temperature.from_celsius(22.5)),
1094+
only_first_battery_result=Sample(now, Temperature.from_celsius(30.0)),
1095+
)
1096+
1097+
# one battery stops sending data.
1098+
await streamer.stop_streaming(bat_1)
1099+
await asyncio.sleep(MAX_BATTERY_DATA_AGE_SEC + 0.2)
1100+
msg = await asyncio.wait_for(receiver.receive(), timeout=waiting_time_sec)
1101+
compare_messages(msg, Sample(now, Temperature.from_celsius(30.0)), 0.2)
1102+
1103+
# All batteries stopped sending data.
1104+
await streamer.stop_streaming(bat_0)
1105+
await asyncio.sleep(MAX_BATTERY_DATA_AGE_SEC + 0.2)
1106+
msg = await asyncio.wait_for(receiver.receive(), timeout=waiting_time_sec)
1107+
assert msg is None
1108+
1109+
# one battery started sending data.
1110+
latest_data = streamer.get_current_component_data(bat_1)
1111+
streamer.start_streaming(latest_data, sampling_rate=0.1)
1112+
msg = await asyncio.wait_for(receiver.receive(), timeout=waiting_time_sec)
1113+
compare_messages(msg, Sample(now, Temperature.from_celsius(15.0)), 0.2)

0 commit comments

Comments
 (0)