@@ -109,7 +109,11 @@ async def _patch_battery_pool_status(
109109 )
110110 )
111111
112- async def _init_data_for_batteries (self , mocks : Mocks ) -> None :
112+ async def _init_data_for_batteries (
113+ self , mocks : Mocks , * , exclusion_bounds : tuple [float , float ] | None = None
114+ ) -> None :
115+ excl_lower = exclusion_bounds [0 ] if exclusion_bounds else 0.0
116+ excl_upper = exclusion_bounds [1 ] if exclusion_bounds else 0.0
113117 now = datetime .now (tz = timezone .utc )
114118 for battery_id in mocks .microgrid .battery_ids :
115119 mocks .streamer .start_streaming (
@@ -119,8 +123,8 @@ async def _init_data_for_batteries(self, mocks: Mocks) -> None:
119123 soc = 50.0 ,
120124 soc_lower_bound = 10.0 ,
121125 soc_upper_bound = 90.0 ,
122- power_exclusion_lower_bound = 0.0 ,
123- power_exclusion_upper_bound = 0.0 ,
126+ power_exclusion_lower_bound = excl_lower ,
127+ power_exclusion_upper_bound = excl_upper ,
124128 power_inclusion_lower_bound = - 1000.0 ,
125129 power_inclusion_upper_bound = 1000.0 ,
126130 capacity = 2000.0 ,
@@ -368,3 +372,113 @@ async def test_case_3(self, mocks: Mocks, mocker: MockerFixture) -> None:
368372 assert sorted (set_power .call_args_list ) == [
369373 mocker .call (inv_id , 0.0 ) for inv_id in mocks .microgrid .battery_inverter_ids
370374 ]
375+
376+ async def test_case_4 (self , mocks : Mocks , mocker : MockerFixture ) -> None :
377+ """Test case 4.
378+
379+ - single battery pool with all batteries.
380+ - all batteries are working, but have exclusion bounds.
381+ """
382+ set_power = typing .cast (
383+ AsyncMock , microgrid .connection_manager .get ().api_client .set_power
384+ )
385+ await self ._patch_battery_pool_status (mocks , mocker )
386+ await self ._init_data_for_batteries (mocks , exclusion_bounds = (- 100.0 , 100.0 ))
387+ await self ._init_data_for_inverters (mocks )
388+
389+ battery_pool = microgrid .battery_pool ()
390+ bounds_rx = battery_pool .power_status .new_receiver ()
391+
392+ self ._assert_report (
393+ await bounds_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
394+ )
395+
396+ await battery_pool .propose_power (Power .from_watts (1000.0 ))
397+
398+ self ._assert_report (
399+ await bounds_rx .receive (), power = 1000.0 , lower = - 4000.0 , upper = 4000.0
400+ )
401+ assert set_power .call_count == 4
402+ assert sorted (set_power .call_args_list ) == [
403+ mocker .call (inv_id , 250.0 )
404+ for inv_id in mocks .microgrid .battery_inverter_ids
405+ ]
406+ self ._assert_report (
407+ await bounds_rx .receive (),
408+ power = 1000.0 ,
409+ lower = - 4000.0 ,
410+ upper = 4000.0 ,
411+ expected_result_pred = lambda result : isinstance (
412+ result , power_distributing .Success
413+ ),
414+ )
415+
416+ set_power .reset_mock ()
417+
418+ # Non-zero power but within the exclusion bounds should get adjusted to nearest
419+ # available power.
420+ await battery_pool .propose_power (Power .from_watts (50.0 ))
421+
422+ self ._assert_report (
423+ await bounds_rx .receive (), power = 400.0 , lower = - 4000.0 , upper = 4000.0
424+ )
425+ assert set_power .call_count == 4
426+ assert sorted (set_power .call_args_list ) == [
427+ mocker .call (inv_id , 100.0 )
428+ for inv_id in mocks .microgrid .battery_inverter_ids
429+ ]
430+ self ._assert_report (
431+ await bounds_rx .receive (),
432+ power = 400.0 ,
433+ lower = - 4000.0 ,
434+ upper = 4000.0 ,
435+ expected_result_pred = lambda result : isinstance (
436+ result , power_distributing .Success
437+ ),
438+ )
439+
440+ set_power .reset_mock ()
441+
442+ # Zero power should be allowed, even if there are exclusion bounds.
443+ await battery_pool .propose_power (Power .from_watts (0.0 ))
444+
445+ self ._assert_report (
446+ await bounds_rx .receive (), power = 0.0 , lower = - 4000.0 , upper = 4000.0
447+ )
448+ assert set_power .call_count == 4
449+ assert sorted (set_power .call_args_list ) == [
450+ mocker .call (inv_id , 0.0 ) for inv_id in mocks .microgrid .battery_inverter_ids
451+ ]
452+ self ._assert_report (
453+ await bounds_rx .receive (),
454+ power = 0.0 ,
455+ lower = - 4000.0 ,
456+ upper = 4000.0 ,
457+ expected_result_pred = lambda result : isinstance (
458+ result , power_distributing .Success
459+ ),
460+ )
461+
462+ set_power .reset_mock ()
463+
464+ # Non-zero power but within the exclusion bounds should get adjusted to nearest
465+ # available power.
466+ await battery_pool .propose_power (Power .from_watts (- 150.0 ))
467+
468+ self ._assert_report (
469+ await bounds_rx .receive (), power = - 400.0 , lower = - 4000.0 , upper = 4000.0
470+ )
471+ assert set_power .call_count == 4
472+ assert sorted (set_power .call_args_list ) == [
473+ mocker .call (inv_id , - 100.0 )
474+ for inv_id in mocks .microgrid .battery_inverter_ids
475+ ]
476+ self ._assert_report (
477+ await bounds_rx .receive (),
478+ power = - 400.0 ,
479+ lower = - 4000.0 ,
480+ upper = 4000.0 ,
481+ expected_result_pred = lambda result : isinstance (
482+ result , power_distributing .Success
483+ ),
484+ )
0 commit comments