@@ -489,3 +489,171 @@ async def test_case_4(self, mocks: Mocks, mocker: MockerFixture) -> None:
489489 result , power_distributing .Success
490490 ),
491491 )
492+
493+ async def test_case_5 ( # pylint: disable=too-many-statements
494+ self ,
495+ mocks : Mocks ,
496+ mocker : MockerFixture ,
497+ ) -> None :
498+ """Test case 5.
499+
500+ - four battery pools with same batteries, but different priorities.
501+ - two battery pools are in the shifting group, two are not.
502+ - all batteries are working.
503+ """
504+ set_power = typing .cast (
505+ AsyncMock , microgrid .connection_manager .get ().api_client .set_power
506+ )
507+
508+ await self ._patch_battery_pool_status (mocks , mocker )
509+ await self ._init_data_for_batteries (mocks )
510+ await self ._init_data_for_inverters (mocks )
511+
512+ battery_pool_4 = microgrid .battery_pool (priority = 4 , in_shifting_group = True )
513+ bounds_4_rx = battery_pool_4 .power_status .new_receiver ()
514+ battery_pool_3 = microgrid .battery_pool (priority = 3 , in_shifting_group = True )
515+ bounds_3_rx = battery_pool_3 .power_status .new_receiver ()
516+ battery_pool_2 = microgrid .battery_pool (priority = 2 )
517+ bounds_2_rx = battery_pool_2 .power_status .new_receiver ()
518+ battery_pool_1 = microgrid .battery_pool (priority = 1 )
519+ bounds_1_rx = battery_pool_1 .power_status .new_receiver ()
520+
521+ self ._assert_report (
522+ await bounds_4_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
523+ )
524+ self ._assert_report (
525+ await bounds_3_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
526+ )
527+ self ._assert_report (
528+ await bounds_2_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
529+ )
530+ self ._assert_report (
531+ await bounds_1_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
532+ )
533+
534+ # The target power of non-shifting battery pools should only be visible to other
535+ # non-shifting battery pools, and vice-versa.
536+ await battery_pool_2 .propose_power (
537+ Power .from_watts (200.0 ),
538+ bounds = timeseries .Bounds (
539+ Power .from_watts (- 1000.0 ), Power .from_watts (1500.0 )
540+ ),
541+ )
542+ self ._assert_report (
543+ await bounds_4_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
544+ )
545+ self ._assert_report (
546+ await bounds_3_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
547+ )
548+ self ._assert_report (
549+ await bounds_2_rx .receive (), power = 200.0 , lower = - 4000.0 , upper = 4000.0
550+ )
551+ self ._assert_report (
552+ await bounds_1_rx .receive (), power = 200.0 , lower = - 1000.0 , upper = 1500.0
553+ )
554+
555+ assert set_power .call_count == 4
556+ assert sorted (set_power .call_args_list ) == [
557+ mocker .call (inv_id , 50.0 ) for inv_id in mocks .microgrid .battery_inverter_ids
558+ ]
559+ set_power .reset_mock ()
560+
561+ # Set a power to the second non-shifting battery pool. This should also have
562+ # no effect on the shifting battery pools.
563+ await battery_pool_1 .propose_power (
564+ Power .from_watts (720.0 ),
565+ )
566+ self ._assert_report (
567+ await bounds_4_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
568+ )
569+ self ._assert_report (
570+ await bounds_3_rx .receive (), power = None , lower = - 4000.0 , upper = 4000.0
571+ )
572+ self ._assert_report (
573+ await bounds_2_rx .receive (), power = 720.0 , lower = - 4000.0 , upper = 4000.0
574+ )
575+ self ._assert_report (
576+ await bounds_1_rx .receive (), power = 720.0 , lower = - 1000.0 , upper = 1500.0
577+ )
578+
579+ for _ in range (5 ):
580+ await bounds_1_rx .receive ()
581+ await bounds_2_rx .receive ()
582+ await bounds_3_rx .receive ()
583+ bounds = await bounds_4_rx .receive ()
584+ if bounds .distribution_result is None or not isinstance (
585+ bounds .distribution_result , power_distributing .Success
586+ ):
587+ continue
588+ if bounds .distribution_result .succeeded_power == Power .from_watts (720.0 ):
589+ break
590+
591+ assert set_power .call_count == 4
592+ assert sorted (set_power .call_args_list ) == [
593+ mocker .call (inv_id , 720.0 / 4 )
594+ for inv_id in mocks .microgrid .battery_inverter_ids
595+ ]
596+ set_power .reset_mock ()
597+
598+ # Setting power to a shifting battery pool should shift the bounds seen by the
599+ # non-shifting battery pools. It would also shift the final target power sent
600+ # in the batteries.
601+ await battery_pool_3 .propose_power (
602+ Power .from_watts (- 1000.0 ),
603+ )
604+
605+ self ._assert_report (
606+ await bounds_4_rx .receive (), power = - 1000.0 , lower = - 4000.0 , upper = 4000.0
607+ )
608+ self ._assert_report (
609+ await bounds_3_rx .receive (), power = - 1000.0 , lower = - 4000.0 , upper = 4000.0
610+ )
611+ self ._assert_report (
612+ await bounds_2_rx .receive (), power = 720.0 , lower = - 3000.0 , upper = 5000.0
613+ )
614+ self ._assert_report (
615+ await bounds_1_rx .receive (), power = 720.0 , lower = - 1000.0 , upper = 1500.0
616+ )
617+
618+ for _ in range (5 ):
619+ await bounds_1_rx .receive ()
620+ await bounds_2_rx .receive ()
621+ await bounds_3_rx .receive ()
622+ bounds = await bounds_4_rx .receive ()
623+ if bounds .distribution_result is None or not isinstance (
624+ bounds .distribution_result , power_distributing .Success
625+ ):
626+ continue
627+ if bounds .distribution_result .succeeded_power == Power .from_watts (- 280.0 ):
628+ break
629+
630+ assert set_power .call_count == 4
631+ assert sorted (set_power .call_args_list ) == [
632+ mocker .call (inv_id , - 280.0 / 4 )
633+ for inv_id in mocks .microgrid .battery_inverter_ids
634+ ]
635+ set_power .reset_mock ()
636+
637+ # Creating a new non-shifting battery pool that's higher priority than the
638+ # shifting battery pools should still be shifted by the target power of the
639+ # shifting battery pools.
640+ battery_pool_5 = microgrid .battery_pool (priority = 5 )
641+ bounds_5_rx = battery_pool_5 .power_status .new_receiver ()
642+
643+ await battery_pool_5 .propose_power (None )
644+
645+ self ._assert_report (
646+ await bounds_5_rx .receive (), power = 720.0 , lower = - 3000.0 , upper = 5000.0
647+ )
648+ self ._assert_report (
649+ await bounds_4_rx .receive (), power = - 1000.0 , lower = - 4000.0 , upper = 4000.0
650+ )
651+ self ._assert_report (
652+ await bounds_3_rx .receive (), power = - 1000.0 , lower = - 4000.0 , upper = 4000.0
653+ )
654+ self ._assert_report (
655+ await bounds_2_rx .receive (), power = 720.0 , lower = - 3000.0 , upper = 5000.0
656+ )
657+ self ._assert_report (
658+ await bounds_1_rx .receive (), power = 720.0 , lower = - 1000.0 , upper = 1500.0
659+ )
0 commit comments