Skip to content

Commit

Permalink
fix: Fixed rate min/max/average calculations during BST
Browse files Browse the repository at this point in the history
  • Loading branch information
BottlecapDave committed Apr 13, 2024
1 parent 1ec383d commit fdccc5b
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ mode: single
variables:
octoplus_points_entity: !input octoplus_points_entity
message: >
{% if state_attr(saving_session_event_entity, 'redeemable_points') > 0 %}
{{ state_attr(saving_session_event_entity, 'redeemable_points') }} points have been automatically redeemed into account credit.
{% if state_attr(octoplus_points_entity, 'redeemable_points') > 0 %}
{{ state_attr(octoplus_points_entity, 'redeemable_points') }} points have been automatically redeemed into account credit.
{% endif %}
trigger:
- platform: numeric_state
Expand Down
20 changes: 10 additions & 10 deletions custom_components/octopus_energy/coordinators/gas_rates.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,16 @@ async def async_refresh_gas_rates_data(

return GasRatesCoordinatorResult(current, 1, new_rates)

result = None
if (existing_rates_result is not None):
result = GasRatesCoordinatorResult(existing_rates_result.last_retrieved, existing_rates_result.request_attempts + 1, existing_rates_result.rates)
_LOGGER.warning(f"Failed to retrieve new gas rates for {target_mprn}/{target_serial_number} - using cached rates. Next attempt at {result.next_refresh}")
else:
# We want to force into our fallback mode
result = GasRatesCoordinatorResult(current - timedelta(minutes=REFRESH_RATE_IN_MINUTES_RATES), 2, None)
_LOGGER.warning(f"Failed to retrieve new gas rates for {target_mprn}/{target_serial_number}. Next attempt at {result.next_refresh}")

return result
result = None
if (existing_rates_result is not None):
result = GasRatesCoordinatorResult(existing_rates_result.last_retrieved, existing_rates_result.request_attempts + 1, existing_rates_result.rates)
_LOGGER.warning(f"Failed to retrieve new gas rates for {target_mprn}/{target_serial_number} - using cached rates. Next attempt at {result.next_refresh}")
else:
# We want to force into our fallback mode
result = GasRatesCoordinatorResult(current - timedelta(minutes=REFRESH_RATE_IN_MINUTES_RATES), 2, None)
_LOGGER.warning(f"Failed to retrieve new gas rates for {target_mprn}/{target_serial_number}. Next attempt at {result.next_refresh}")

return result

return existing_rates_result

Expand Down
4 changes: 2 additions & 2 deletions custom_components/octopus_energy/electricity/current_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
)
from homeassistant.core import HomeAssistant, callback

from homeassistant.util.dt import (utcnow)
from homeassistant.util.dt import (now)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
)
Expand Down Expand Up @@ -96,7 +96,7 @@ def native_value(self):
def _handle_coordinator_update(self) -> None:
"""Retrieve the current rate for the sensor."""
# Find the current rate. We only need to do this every half an hour
current = utcnow()
current = now()
rates_result: ElectricityRatesCoordinatorResult = self.coordinator.data if self.coordinator is not None and self.coordinator.data is not None else None
if (rates_result is not None):
_LOGGER.debug(f"Updating OctopusEnergyElectricityCurrentRate for '{self._mpan}/{self._serial_number}'")
Expand Down
4 changes: 2 additions & 2 deletions custom_components/octopus_energy/electricity/next_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
)
from homeassistant.core import HomeAssistant, callback

from homeassistant.util.dt import (utcnow)
from homeassistant.util.dt import (now)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity
)
Expand Down Expand Up @@ -88,7 +88,7 @@ def native_value(self):
def _handle_coordinator_update(self) -> None:
"""Retrieve the next rate for the sensor."""
# Find the next rate. We only need to do this every half an hour
current = utcnow()
current = now()
rates_result: ElectricityRatesCoordinatorResult = self.coordinator.data if self.coordinator is not None and self.coordinator.data is not None else None
if (rates_result is not None):
_LOGGER.debug(f"Updating OctopusEnergyElectricityNextRate for '{self._mpan}/{self._serial_number}'")
Expand Down
4 changes: 2 additions & 2 deletions custom_components/octopus_energy/electricity/previous_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
)
from homeassistant.core import HomeAssistant, callback

from homeassistant.util.dt import (utcnow)
from homeassistant.util.dt import (now)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity
)
Expand Down Expand Up @@ -88,7 +88,7 @@ def native_value(self):
def _handle_coordinator_update(self) -> None:
"""Retrieve the previous rate."""
# Find the previous rate. We only need to do this every half an hour
current = utcnow()
current = now()
rates_result: ElectricityRatesCoordinatorResult = self.coordinator.data if self.coordinator is not None and self.coordinator.data is not None else None
if (rates_result is not None):
_LOGGER.debug(f"Updating OctopusEnergyElectricityPreviousRate for '{self._mpan}/{self._serial_number}'")
Expand Down
4 changes: 2 additions & 2 deletions custom_components/octopus_energy/gas/current_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
)
from homeassistant.core import HomeAssistant, callback

from homeassistant.util.dt import (utcnow)
from homeassistant.util.dt import (now)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
)
Expand Down Expand Up @@ -89,7 +89,7 @@ def native_value(self):
@callback
def _handle_coordinator_update(self) -> None:
"""Retrieve the current rate for the sensor."""
current = utcnow()
current = now()
rates_result: GasRatesCoordinatorResult = self.coordinator.data if self.coordinator is not None and self.coordinator.data is not None else None
if (rates_result is not None):
_LOGGER.debug(f"Updating OctopusEnergyGasCurrentRate for '{self._mprn}/{self._serial_number}'")
Expand Down
4 changes: 2 additions & 2 deletions custom_components/octopus_energy/gas/next_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
)
from homeassistant.core import HomeAssistant, callback

from homeassistant.util.dt import (utcnow)
from homeassistant.util.dt import (now)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
)
Expand Down Expand Up @@ -85,7 +85,7 @@ def native_value(self):
@callback
def _handle_coordinator_update(self) -> None:
"""Retrieve the next rate for the sensor."""
current = utcnow()
current = now()
rates_result: GasRatesCoordinatorResult = self.coordinator.data if self.coordinator is not None and self.coordinator.data is not None else None
if (rates_result is not None):
_LOGGER.debug(f"Updating OctopusEnergyGasNextRate for '{self._mprn}/{self._serial_number}'")
Expand Down
4 changes: 2 additions & 2 deletions custom_components/octopus_energy/gas/previous_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
)
from homeassistant.core import HomeAssistant, callback

from homeassistant.util.dt import (utcnow)
from homeassistant.util.dt import (now)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
)
Expand Down Expand Up @@ -85,7 +85,7 @@ def native_value(self):
@callback
def _handle_coordinator_update(self) -> None:
"""Retrieve the previous rate for the sensor."""
current = utcnow()
current = now()
rates_result: GasRatesCoordinatorResult = self.coordinator.data if self.coordinator is not None and self.coordinator.data is not None else None
if (rates_result is not None):
_LOGGER.debug(f"Updating OctopusEnergyGasPreviousRate for '{self._mprn}/{self._serial_number}'")
Expand Down
30 changes: 22 additions & 8 deletions tests/unit/coordinators/test_async_refresh_gas_rates_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,17 @@ def fire_event(name, metadata):
assert len(actual_fired_events.keys()) == 0

@pytest.mark.asyncio
async def test_when_next_refresh_is_in_the_past_then_existing_gas_rates_returned():
current = datetime.strptime("2023-07-14T10:30:01+01:00", "%Y-%m-%dT%H:%M:%S%z")
expected_rates = create_rate_data(period_from, period_to, [1, 2])
async def test_when_next_refresh_is_in_the_past_then_rates_retrieved():
expected_period_from = (current - timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0)
expected_period_to = (current + timedelta(days=2)).replace(hour=0, minute=0, second=0, microsecond=0)
expected_rates = create_rate_data(expected_period_from, expected_period_to, [1, 2])
mock_api_called = False
requested_period_from = None
requested_period_to = None
async def async_mocked_get_gas_rates(*args, **kwargs):
nonlocal mock_api_called
nonlocal requested_period_from, requested_period_to, mock_api_called

requested_client, requested_tariff_code, requested_period_from, requested_period_to = args
mock_api_called = True
return expected_rates

Expand All @@ -165,7 +170,8 @@ def fire_event(name, metadata):
return None

account_info = get_account_info()
existing_rates = GasRatesCoordinatorResult(current - timedelta(minutes=4, seconds=59), 1, create_rate_data(period_from, period_to, [2, 4]))
expected_retrieved_rates = GasRatesCoordinatorResult(current, 1, expected_rates)
existing_rates = GasRatesCoordinatorResult(current - timedelta(days=4), 1, create_rate_data(period_from, period_to, [2, 4]))

with mock.patch.multiple(OctopusEnergyApiClient, async_get_gas_rates=async_mocked_get_gas_rates):
client = OctopusEnergyApiClient("NOT_REAL")
Expand All @@ -179,9 +185,17 @@ def fire_event(name, metadata):
fire_event
)

assert retrieved_rates == existing_rates
assert mock_api_called == False
assert len(actual_fired_events.keys()) == 0
assert retrieved_rates is not None
assert retrieved_rates.last_retrieved == expected_retrieved_rates.last_retrieved
assert retrieved_rates.rates == expected_retrieved_rates.rates
assert mock_api_called == True
assert requested_period_from == expected_period_from
assert requested_period_to == expected_period_to

assert len(actual_fired_events.keys()) == 3
assert_raised_events(actual_fired_events, EVENT_GAS_PREVIOUS_DAY_RATES, requested_period_from, requested_period_from + timedelta(days=1))
assert_raised_events(actual_fired_events, EVENT_GAS_CURRENT_DAY_RATES, requested_period_from + timedelta(days=1), requested_period_from + timedelta(days=2))
assert_raised_events(actual_fired_events, EVENT_GAS_NEXT_DAY_RATES, requested_period_from + timedelta(days=2), requested_period_from + timedelta(days=3))

@pytest.mark.asyncio
@pytest.mark.parametrize("existing_rates",[
Expand Down

0 comments on commit fdccc5b

Please sign in to comment.