Beispiel #1
0
class TestAreaClass(unittest.TestCase):
    def setUp(self):
        ConstSettings.BalancingSettings.ENABLE_BALANCING_MARKET = True
        DeviceRegistry.REGISTRY = {
            "H1 General Load": (33, 35),
            "H2 General Load": (33, 35),
            "H1 Storage1": (23, 25),
            "H1 Storage2": (23, 25),
        }

        self.strategy = MagicMock(spec=StorageStrategy)
        self.config = MagicMock(spec=SimulationConfig)
        self.config.slot_length = duration(minutes=15)
        self.config.tick_length = duration(seconds=15)
        self.config.ticks_per_slot = int(self.config.slot_length.seconds /
                                         self.config.tick_length.seconds)
        self.config.start_date = today(tz=constants.TIME_ZONE)
        GlobalConfig.sim_duration = duration(days=1)
        self.config.sim_duration = duration(days=1)
        self.config.grid_fee_type = 1
        self.config.end_date = self.config.start_date + self.config.sim_duration
        self.area = Area("test_area",
                         None,
                         None,
                         self.strategy,
                         self.config,
                         None,
                         grid_fee_percentage=1)
        self.area_child = Area("test_area_c",
                               None,
                               None,
                               self.strategy,
                               self.config,
                               None,
                               grid_fee_percentage=1)
        self.area_child.parent = self.area
        self.area.children = [self.area_child]
        self.area.grid_fee_percentage = 1
        self.dispatcher = AreaDispatcher(self.area)
        self.stats = AreaStats(self.area._markets, self.area)

    def tearDown(self):
        GlobalConfig.market_count = GlobalConfig.MARKET_COUNT
        constants.RETAIN_PAST_MARKET_STRATEGIES_STATE = False

    def test_respective_area_grid_fee_is_applied(self):
        self.config.grid_fee_type = 2
        self.area = Area(name="Street",
                         children=[Area(name="House")],
                         grid_fee_percentage=5,
                         config=self.config)
        self.area.parent = Area(name="GRID", config=self.config)
        self.area.config.market_count = 1
        self.area.activate()
        assert self.area.next_market.fee_class.grid_fee_rate == 0.05
        self.area.next_market.offer(1, 1, "test", "test")
        assert list(self.area.next_market.offers.values())[0].price == 1.05

    def test_markets_are_cycled_according_to_market_count(self):
        self.area._bc = None
        for i in range(2, 97):
            self.config.market_count = i
            self.config.grid_fee_type = ConstSettings.IAASettings.GRID_FEE_TYPE
            self.area.cycle_markets(False, False)
            assert len(self.area.all_markets) == i

    def test_delete_past_markets_instead_of_last(self):
        constants.RETAIN_PAST_MARKET_STRATEGIES_STATE = False
        self.area = Area(name="Street",
                         children=[Area(name="House")],
                         config=self.config,
                         grid_fee_percentage=5)
        self.area.config.market_count = 1
        self.area.activate()
        self.area._bc = None

        self.area.cycle_markets(False, False, False)
        assert len(self.area.past_markets) == 0

        current_time = today(tz=constants.TIME_ZONE).add(hours=1)
        self.area._markets.rotate_markets(current_time)
        assert len(self.area.past_markets) == 1

        self.area._markets.create_future_markets(current_time, True, self.area)
        current_time = today(tz=constants.TIME_ZONE).add(hours=2)
        self.area._markets.rotate_markets(current_time)
        assert len(self.area.past_markets) == 1
        assert (list(self.area.past_markets)[-1].time_slot == today(
            tz=constants.TIME_ZONE).add(hours=1))

    def test_keep_past_markets(self):
        constants.RETAIN_PAST_MARKET_STRATEGIES_STATE = True
        self.area = Area(name="Street",
                         children=[Area(name="House")],
                         config=self.config,
                         grid_fee_percentage=5)
        self.area.config.market_count = 1
        self.area.activate()
        self.area._bc = None

        self.area.cycle_markets(False, False, False)
        assert len(self.area.past_markets) == 0

        current_time = today(tz=constants.TIME_ZONE).add(hours=1)
        self.area._markets.rotate_markets(current_time)
        assert len(self.area.past_markets) == 1

        self.area._markets.create_future_markets(current_time, True, self.area)
        current_time = today(tz=constants.TIME_ZONE).add(hours=2)
        self.area._markets.rotate_markets(current_time)
        assert len(self.area.past_markets) == 2

    def test_market_with_most_expensive_offer(self):
        m1 = MagicMock(spec=Market)
        m1.in_sim_duration = True
        o1 = MagicMock(spec=Offer)
        o1.price = 12
        o1.energy = 1
        o1.energy_rate = 12
        m2 = MagicMock(spec=Market)
        m2.in_sim_duration = True
        o2 = MagicMock(spec=Offer)
        o2.price = 12
        o2.energy = 1
        o2.energy_rate = 12
        m3 = MagicMock(spec=Market)
        m3.in_sim_duration = True
        o3 = MagicMock(spec=Offer)
        o3.price = 12
        o3.energy = 1
        o3.energy_rate = 12
        markets = OrderedDict()
        td = today(tz=constants.TIME_ZONE)
        td1 = td + self.config.slot_length
        m1.time_slot = td1
        markets[m1.time_slot] = m1
        td2 = td1 + self.config.slot_length
        m2.time_slot = td2
        markets[m2.time_slot] = m2
        td3 = td2 + self.config.slot_length
        m3.time_slot = td3
        markets[m3.time_slot] = m3
        self.area._markets = MagicMock(spec=AreaMarkets)
        self.area._markets.markets = markets
        m1.sorted_offers = [o1, o1]
        m2.sorted_offers = [o2, o2]
        m3.sorted_offers = [o3, o3]
        assert self.area.market_with_most_expensive_offer is m1
        o1.energy_rate = 19
        o2.energy_rate = 20
        o3.energy_rate = 18
        assert self.area.market_with_most_expensive_offer is m2
        o1.energy_rate = 18
        o2.energy_rate = 19
        o3.energy_rate = 20
        assert self.area.market_with_most_expensive_offer is m3

    def test_cycle_markets(self):
        GlobalConfig.end_date = GlobalConfig.start_date + GlobalConfig.sim_duration
        self.area = Area(name="Street",
                         children=[Area(name="House")],
                         config=GlobalConfig,
                         grid_fee_percentage=1)
        self.area.parent = Area(name="GRID")
        self.area.config.market_count = 5
        self.area.activate()
        assert len(self.area.all_markets) == 5

        assert len(self.area.balancing_markets) == 5
        self.area.current_tick = 900
        self.area.cycle_markets()
        assert len(self.area.past_markets) == 1
        assert len(self.area.past_balancing_markets) == 1
        assert len(self.area.all_markets) == 5
        assert len(self.area.balancing_markets) == 5

    def test_get_restore_state_get_called_on_all_areas(self):
        strategy = MagicMock(spec=StorageStrategy)
        bat = Area(name="battery", strategy=strategy)

        house = Area(name="House", children=[bat])
        house.stats.get_state = MagicMock()
        house.stats.restore_state = MagicMock()
        area = Area(name="Street", children=[house])
        area.stats.get_state = MagicMock()
        area.stats.restore_state = MagicMock()
        area.parent = Area(name="GRID")

        area.get_state()
        area.stats.get_state.assert_called_once()
        area.restore_state({"current_tick": 200, "area_stats": None})
        area.stats.restore_state.assert_called_once()
        assert area.current_tick == 200

        house.get_state()
        house.stats.get_state.assert_called_once()
        house.restore_state({"current_tick": 2432, "area_stats": None})
        house.stats.restore_state.assert_called_once()
        assert house.current_tick == 2432

        bat.get_state()
        strategy.get_state.assert_called_once()
class TestGlobalObjects(unittest.TestCase):

    def setUp(self):
        self.config = MagicMock(spec=SimulationConfig)
        self.config.slot_length = duration(minutes=15)
        self.config.tick_length = duration(seconds=15)
        self.config.ticks_per_slot = int(self.config.slot_length.seconds /
                                         self.config.tick_length.seconds)
        self.config.start_date = today(tz=TIME_ZONE)
        self.config.sim_duration = duration(days=1)
        self.config.grid_fee_type = 1
        self.config.end_date = self.config.start_date + self.config.sim_duration
        self.config.market_count = 1
        self.config.max_panel_power_W = 1000
        self.config.external_redis_communicator = \
            MagicMock(spec=ExternalConnectionCommunicator(True))
        self.storage = Area("Storage", strategy=StorageExternalStrategy(), config=self.config,
                            external_connection_available=True)
        self.load = Area("Load", strategy=LoadHoursExternalStrategy(avg_power_W=100),
                         config=self.config, external_connection_available=True)
        self.pv = Area("PV", strategy=PVExternalStrategy(), config=self.config,
                       external_connection_available=True)
        self.house_area = Area("House", children=[self.storage, self.load, self.pv],
                               config=self.config)
        self.grid_area = Area("Grid", children=[self.house_area], config=self.config)
        self.grid_area.activate()

    def test_global_objects_area_stats_tree_dict_general_structure(self):
        go = ExternalConnectionGlobalStatistics()
        go(self.grid_area, self.config.ticks_per_slot)
        self.grid_area.current_tick += 15
        self.house_area.current_tick += 15
        self.grid_area.cycle_markets(_trigger_event=True)

        go.update()

        expected_area_stats_tree_dict = {
            self.grid_area.uuid:
                {'last_market_bill': {'accumulated_trades': {}, 'external_trades': {}},
                 'last_market_stats': {'min_trade_rate': None, 'max_trade_rate': None,
                                       'avg_trade_rate': None, 'median_trade_rate': None,
                                       'total_traded_energy_kWh': None},
                 'last_market_fee': 0.0,
                 'current_market_fee': None,
                 'area_name': 'Grid',
                 'children': {
                     self.house_area.uuid: {
                         'last_market_bill': {'accumulated_trades': {},
                                              'external_trades': {}},
                         'last_market_stats': {'min_trade_rate': None,
                                               'max_trade_rate': None,
                                               'avg_trade_rate': None,
                                               'median_trade_rate': None,
                                               'total_traded_energy_kWh': None},
                         'last_market_fee': 0.0,
                         'current_market_fee': None,
                         'area_name': 'House',
                         'children': {
                             self.storage.uuid: {
                                  'asset_info': {'energy_to_sell': 0.0,
                                                 'energy_active_in_bids': 0,
                                                 'energy_to_buy': 1.08,
                                                 'energy_active_in_offers': 0,
                                                 'free_storage': 1.08,
                                                 'used_storage': 0.12,
                                                 'energy_traded': 0.0,
                                                 'total_cost': 0.0},
                                  'last_slot_asset_info': {'energy_traded': 0.0,
                                                           'total_cost': 0.0},
                                  'asset_bill': None,
                                  'area_name': 'Storage'},
                             self.load.uuid: {'asset_info': {
                                        'energy_requirement_kWh': 0.025,
                                        'energy_active_in_bids': 0.0,
                                        'energy_traded': 0.0,
                                        'total_cost': 0.0},
                                    'last_slot_asset_info': {
                                        'energy_traded': 0.0,
                                        'total_cost': 0.0},
                                    'asset_bill': None,
                                    'area_name': 'Load'},
                             self.pv.uuid: {'asset_info': {
                                      'available_energy_kWh': 0.0,
                                      'energy_active_in_offers': 0,
                                      'energy_traded': 0,
                                      'total_cost': 0},
                                  'last_slot_asset_info': {
                                         'energy_traded': 0,
                                         'total_cost': 0},
                                  'asset_bill': None,
                                  'area_name': 'PV'
                                  }}}}}}

        assert expected_area_stats_tree_dict == go.area_stats_tree_dict