Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/gsye 689 #512

Merged
merged 13 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions gsy_framework/read_user_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ class InputProfileTypes(Enum):
ENERGY_KWH = 4


class LiveProfileTypes(Enum):
"""Enum for type of live data profiles"""
NO_LIVE_DATA = 0
FORECAST = 1
MEASUREMENT = 2


def _str_to_datetime(time_string, time_format) -> DateTime:
"""
Converts time_string into a pendulum (DateTime) object that either takes the global start date
Expand Down Expand Up @@ -325,6 +332,8 @@ def read_arbitrary_profile(profile_type: InputProfileTypes,
:param current_timestamp:
:return: a mapping from time to profile values
"""
if input_profile in [{}, None]:
return {}
profile = _read_from_different_sources_todict(input_profile,
current_timestamp=current_timestamp)
profile_time_list = list(profile.keys())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
]},
{"name": "power_profile", "type": ["null", "string"]},
{"name": "power_profile_uuid", "type": ["null", "string"]},
{"name": "power_measurement_uuid", "type": ["null", "string"]},
{"name": "capacity_kW", "type": ["null", "float"]},
{"name": "tilt", "type": ["null", "float"]},
{"name": "azimuth", "type": ["null", "float"]},
Expand Down Expand Up @@ -195,6 +196,7 @@
{"name": "energy_rate_decrease_per_update", "type": ["null", "float"]},
{"name": "power_profile", "type": ["null", "string"]},
{"name": "power_profile_uuid", "type": ["null", "string"]},
{"name": "power_measurement_uuid", "type": ["null", "string"]},
{"name": "update_interval", "type": ["null", "int"]},
{"name": "fit_to_limit", "type": ["null","boolean"]},
{"name": "capacity_kW", "type": ["null", "float"]},
Expand Down Expand Up @@ -227,6 +229,7 @@
{"name": "target_device_kpi", "type": ["null", "int"]},
{"name": "daily_load_profile", "type": ["null", "string"]},
{"name": "daily_load_profile_uuid", "type": ["null", "string"]},
{"name": "daily_load_measurement_uuid", "type": ["null", "string"]},
{"name": "use_market_maker_rate", "type": ["null", "boolean"]},
{"name": "forecast_stream_enabled", "type": ["null", "boolean"]},
{"name": "forecast_stream_id", "type": ["null", "string"]},
Expand Down Expand Up @@ -315,6 +318,7 @@
]},
{"name": "prosumption_kWh_profile", "type": ["null", "string"]},
{"name": "prosumption_kWh_profile_uuid", "type": ["null", "string"]},
{"name": "prosumption_kWh_measurement_uuid", "type": ["null", "string"]},
{"name": "use_market_maker_rate", "type": ["null", "boolean"]},
{"name": "allow_external_connection", "type": ["null", "boolean"]},
{"name": "display_type", "type": "string"},
Expand All @@ -338,6 +342,7 @@
]},
{"name": "consumption_kWh_profile", "type": ["null", "string"]},
{"name": "consumption_kWh_profile_uuid", "type": ["null", "string"]},
{"name": "consumption_kWh_measurement_uuid", "type": ["null", "string"]},
{"name": "use_market_maker_rate", "type": ["null", "boolean"]},
{"name": "allow_external_connection", "type": ["null", "boolean"]},
{"name": "display_type", "type": "string"},
Expand All @@ -363,6 +368,7 @@
]},
{"name": "smart_meter_profile", "type": ["null", "string"]},
{"name": "smart_meter_profile_uuid", "type": ["null", "string"]},
{"name": "smart_meter_measurement_uuid", "type": ["null", "string"]},
{"name": "final_buying_rate", "type": ["null", "float"]},
{"name": "initial_buying_rate", "type": ["null", "float"]},
{"name": "final_selling_rate", "type": ["null", "float"]},
Expand Down Expand Up @@ -398,9 +404,11 @@
{"name": "initial_temp_C", "type": "float"},
{"name": "external_temp_C_profile", "type": ["null", "string"]},
{"name": "external_temp_C_profile_uuid", "type": ["null", "string"]},
{"name": "external_temp_C_measurement_uuid", "type": ["null", "string"]},
{"name": "tank_volume_l", "type": "float"},
{"name": "consumption_kWh_profile", "type": ["null", "string"]},
{"name": "consumption_kWh_profile_uuid", "type": ["null", "string"]},
{"name": "consumption_kWh_measurement_uuid", "type": ["null", "string"]},
{"name": "source_type", "type": "int"},
{"name": "final_buying_rate", "type": ["null", "float"]},
{"name": "initial_buying_rate", "type": ["null", "float"]},
Expand Down
2 changes: 1 addition & 1 deletion gsy_framework/sim_results/scm/bills.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def update(self, area_result_dict, core_stats, current_market_slot):
if not area.get("children"):
continue

if "bills" not in core_stats[area["uuid"]]:
if "bills" not in core_stats[area["uuid"]] or not core_stats[area["uuid"]]["bills"]:
continue

if area["uuid"] not in self.bills_redis_results:
Expand Down
2 changes: 1 addition & 1 deletion gsy_framework/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def generate_market_slot_list(start_timestamp=None):
No input arguments, required input is only handled by a preconfigured GlobalConfig
@return: List with market slot datetimes
"""
time_span = (duration(days=PROFILE_EXPANSION_DAYS)
time_span = (GlobalConfig.slot_length
if GlobalConfig.is_canary_network()
else min(GlobalConfig.sim_duration, duration(days=PROFILE_EXPANSION_DAYS)))
time_span += duration(hours=ConstSettings.FutureMarketSettings.FUTURE_MARKET_DURATION_HOURS)
Expand Down
6 changes: 5 additions & 1 deletion gsy_framework/validators/profile_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ class ProfileValidator:
def __init__(
self, profile: Dict[DateTime, float], start_time: Optional[DateTime] = None,
end_time: Optional[DateTime] = None, slot_length: Optional[timedelta] = None):
assert len(profile) > 0, "profile is empty"

self.profile = OrderedDict(profile)
if not self.profile:
return
self.start_time = start_time if start_time else self._profile_start_time
self.end_time = end_time if end_time else self._profile_end_time
self.slot_length: timedelta = slot_length

def validate(self):
"""Validate if profile corresponds to the start_time, end_time and slot_length setting."""
if not self.profile:
return
if self.slot_length:
self._validate_slot_length()
else:
Expand Down
27 changes: 16 additions & 11 deletions tests/test_read_user_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import pytest
from pendulum import datetime, duration, today

from gsy_framework.constants_limits import PROFILE_EXPANSION_DAYS, TIME_ZONE, GlobalConfig
from gsy_framework.constants_limits import TIME_ZONE, GlobalConfig
from gsy_framework.enums import ConfigurationType
from gsy_framework.read_user_profile import (
InputProfileTypes, _fill_gaps_in_profile, _generate_slot_based_zero_values_dict_from_profile,
Expand Down Expand Up @@ -122,16 +122,8 @@ def test_read_profile_for_player():
def test_read_arbitrary_profile_returns_correct_profile_in_canary_network(
set_is_canary_network):
set_is_canary_network(True)
market_maker_rate = 30
GlobalConfig.sim_duration = duration(hours=3)
expected_last_time_slot = today(tz=TIME_ZONE).add(days=PROFILE_EXPANSION_DAYS - 1,
hours=23, minutes=45)
mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY, market_maker_rate)
assert list(mmr.keys())[-1] == expected_last_time_slot
GlobalConfig.sim_duration = duration(hours=30)
expected_last_time_slot = today(tz=TIME_ZONE).add(days=PROFILE_EXPANSION_DAYS - 1,
hours=23, minutes=45)
mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY, market_maker_rate)
expected_last_time_slot = today(tz=TIME_ZONE)
mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY, 30)
assert list(mmr.keys())[-1] == expected_last_time_slot

@staticmethod
Expand Down Expand Up @@ -192,3 +184,16 @@ def test_resample_energy_profile_performs_correctly_for_equal_resolutions():
duration(hours=4),
datetime(2021, 1, 25, 0, 0))
assert result_profile == input_profile

@staticmethod
def test_read_arbitrary_profile_returns_early_for_empty_profiles():
original_slot_length = GlobalConfig.slot_length
original_sim_duration = GlobalConfig.sim_duration
GlobalConfig.slot_length = duration(hours=1)
GlobalConfig.sim_duration = duration(hours=4)
assert read_arbitrary_profile(InputProfileTypes.POWER_W, {}) == {}
assert read_arbitrary_profile(InputProfileTypes.POWER_W, None) == {}
assert len(read_arbitrary_profile(InputProfileTypes.POWER_W, 0)) == 4
assert set(read_arbitrary_profile(InputProfileTypes.POWER_W, 0).values()) == {0}
GlobalConfig.slot_length = original_slot_length
GlobalConfig.sim_duration = original_sim_duration
14 changes: 14 additions & 0 deletions tests/test_validators/test_profile_validator.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from copy import copy
from unittest.mock import Mock

import pytest

Expand All @@ -8,6 +9,7 @@


class TestProfileValidator:
# pylint: disable=protected-access

@staticmethod
@pytest.mark.parametrize("input_profile, end_time", [
Expand Down Expand Up @@ -87,3 +89,15 @@ def test_profile_validator_fails_if_gap_in_profile_no_slot_length(input_profile)
del profile[gap_time]
with pytest.raises(AssertionError):
ProfileValidator(profile=profile).validate()

@staticmethod
def test_profile_validator_returns_early_if_empty_profile():
validator = ProfileValidator(profile={})
validator._validate_slot_length = Mock()
validator._get_and_validate_time_diffs = Mock()
validator._validate_start_end_date = Mock()
validator.slot_length = Mock()
assert validator.validate() is None
validator._validate_slot_length.assert_not_called()
validator._get_and_validate_time_diffs.assert_not_called()
validator._validate_start_end_date.assert_not_called()
Loading