Improve SRP Energy coordinator (#99010)

* Improve SRP Energy coordinator

* Use time instead of asyncio
This commit is contained in:
Joost Lekkerkerker 2023-08-25 11:19:40 +02:00 committed by GitHub
parent 11c5e3534a
commit da9fc495ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 32 deletions

View file

@ -4,7 +4,6 @@ from __future__ import annotations
import asyncio import asyncio
from datetime import timedelta from datetime import timedelta
from requests.exceptions import ConnectionError as ConnectError, HTTPError, Timeout
from srpenergy.client import SrpEnergyClient from srpenergy.client import SrpEnergyClient
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -14,6 +13,8 @@ from homeassistant.util import dt as dt_util
from .const import DOMAIN, LOGGER, MIN_TIME_BETWEEN_UPDATES, PHOENIX_TIME_ZONE from .const import DOMAIN, LOGGER, MIN_TIME_BETWEEN_UPDATES, PHOENIX_TIME_ZONE
TIMEOUT = 10
class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]): class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]):
"""A srp_energy Data Update Coordinator.""" """A srp_energy Data Update Coordinator."""
@ -40,19 +41,20 @@ class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]):
so entities can quickly look up their data. so entities can quickly look up their data.
""" """
LOGGER.debug("async_update_data enter") LOGGER.debug("async_update_data enter")
try:
# Fetch srp_energy data # Fetch srp_energy data
phx_time_zone = dt_util.get_time_zone(PHOENIX_TIME_ZONE) phx_time_zone = dt_util.get_time_zone(PHOENIX_TIME_ZONE)
end_date = dt_util.now(phx_time_zone) end_date = dt_util.now(phx_time_zone)
start_date = end_date - timedelta(days=1) start_date = end_date - timedelta(days=1)
try:
async with asyncio.timeout(10): async with asyncio.timeout(TIMEOUT):
hourly_usage = await self.hass.async_add_executor_job( hourly_usage = await self.hass.async_add_executor_job(
self._client.usage, self._client.usage,
start_date, start_date,
end_date, end_date,
self._is_time_of_use, self._is_time_of_use,
) )
except (ValueError, TypeError) as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err
LOGGER.debug( LOGGER.debug(
"async_update_data: Received %s record(s) from %s to %s", "async_update_data: Received %s record(s) from %s to %s",
@ -71,7 +73,3 @@ class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]):
) )
return previous_daily_usage return previous_daily_usage
except TimeoutError as timeout_err:
raise UpdateFailed("Timeout communicating with API") from timeout_err
except (ConnectError, HTTPError, Timeout, ValueError, TypeError) as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err

View file

@ -1,7 +1,7 @@
"""Tests for the srp_energy sensor platform.""" """Tests for the srp_energy sensor platform."""
import time
from unittest.mock import patch from unittest.mock import patch
import pytest
from requests.models import HTTPError from requests.models import HTTPError
from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass
@ -46,10 +46,8 @@ async def test_srp_entity(hass: HomeAssistant, init_integration) -> None:
assert usage_state.attributes.get(ATTR_ICON) == "mdi:flash" assert usage_state.attributes.get(ATTR_ICON) == "mdi:flash"
@pytest.mark.parametrize("error", [TimeoutError, HTTPError])
async def test_srp_entity_update_failed( async def test_srp_entity_update_failed(
hass: HomeAssistant, hass: HomeAssistant,
error: Exception,
mock_config_entry: MockConfigEntry, mock_config_entry: MockConfigEntry,
) -> None: ) -> None:
"""Test the SrpEntity.""" """Test the SrpEntity."""
@ -59,7 +57,30 @@ async def test_srp_entity_update_failed(
) as srp_energy_mock: ) as srp_energy_mock:
client = srp_energy_mock.return_value client = srp_energy_mock.return_value
client.validate.return_value = True client.validate.return_value = True
client.usage.side_effect = error client.usage.side_effect = HTTPError
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
usage_state = hass.states.get("sensor.home_energy_usage")
assert usage_state is None
async def test_srp_entity_timeout(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the SrpEntity timing out."""
with patch(
"homeassistant.components.srp_energy.SrpEnergyClient", autospec=True
) as srp_energy_mock, patch(
"homeassistant.components.srp_energy.coordinator.TIMEOUT", 0
):
client = srp_energy_mock.return_value
client.validate.return_value = True
client.usage = lambda _, __, ___: time.sleep(1)
mock_config_entry.add_to_hass(hass) mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id) await hass.config_entries.async_setup(mock_config_entry.entry_id)