Try to avoid rate limiting in honeywell (#55304)

* Limit parallel update and sleep loop

* Use asyncio sleep instead

* Extract sleep to const for testing

* Make loop sleep 0 in test
pull/55969/head
RDFurman 2021-09-07 08:32:26 -06:00 committed by Paulus Schoutsen
parent 823c3735ce
commit 7f3adce675
3 changed files with 17 additions and 8 deletions

View File

@ -1,4 +1,5 @@
"""Support for Honeywell (US) Total Connect Comfort climate systems.""" """Support for Honeywell (US) Total Connect Comfort climate systems."""
import asyncio
from datetime import timedelta from datetime import timedelta
import somecomfort import somecomfort
@ -9,7 +10,8 @@ from homeassistant.util import Throttle
from .const import _LOGGER, CONF_DEV_ID, CONF_LOC_ID, DOMAIN from .const import _LOGGER, CONF_DEV_ID, CONF_LOC_ID, DOMAIN
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=180) UPDATE_LOOP_SLEEP_TIME = 5
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300)
PLATFORMS = ["climate"] PLATFORMS = ["climate"]
@ -42,7 +44,7 @@ async def async_setup_entry(hass, config):
return False return False
data = HoneywellData(hass, client, username, password, devices) data = HoneywellData(hass, client, username, password, devices)
await data.update() await data.async_update()
hass.data.setdefault(DOMAIN, {}) hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][config.entry_id] = data hass.data[DOMAIN][config.entry_id] = data
hass.config_entries.async_setup_platforms(config, PLATFORMS) hass.config_entries.async_setup_platforms(config, PLATFORMS)
@ -102,18 +104,19 @@ class HoneywellData:
self.devices = devices self.devices = devices
return True return True
def _refresh_devices(self): async def _refresh_devices(self):
"""Refresh each enabled device.""" """Refresh each enabled device."""
for device in self.devices: for device in self.devices:
device.refresh() await self._hass.async_add_executor_job(device.refresh)
await asyncio.sleep(UPDATE_LOOP_SLEEP_TIME)
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
async def update(self) -> None: async def async_update(self) -> None:
"""Update the state.""" """Update the state."""
retries = 3 retries = 3
while retries > 0: while retries > 0:
try: try:
await self._hass.async_add_executor_job(self._refresh_devices) await self._refresh_devices()
break break
except ( except (
somecomfort.client.APIRateLimited, somecomfort.client.APIRateLimited,
@ -124,7 +127,7 @@ class HoneywellData:
if retries == 0: if retries == 0:
raise exp raise exp
result = await self._hass.async_add_executor_job(self._retry()) result = await self._retry()
if not result: if not result:
raise exp raise exp

View File

@ -107,6 +107,8 @@ HW_FAN_MODE_TO_HA = {
"follow schedule": FAN_AUTO, "follow schedule": FAN_AUTO,
} }
PARALLEL_UPDATES = 1
async def async_setup_entry(hass, config, async_add_entities, discovery_info=None): async def async_setup_entry(hass, config, async_add_entities, discovery_info=None):
"""Set up the Honeywell thermostat.""" """Set up the Honeywell thermostat."""
@ -384,4 +386,4 @@ class HoneywellUSThermostat(ClimateEntity):
async def async_update(self): async def async_update(self):
"""Get the latest state from the service.""" """Get the latest state from the service."""
await self._data.update() await self._data.async_update()

View File

@ -1,11 +1,14 @@
"""Test honeywell setup process.""" """Test honeywell setup process."""
from unittest.mock import patch
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@patch("homeassistant.components.honeywell.UPDATE_LOOP_SLEEP_TIME", 0)
async def test_setup_entry(hass: HomeAssistant, config_entry: MockConfigEntry): async def test_setup_entry(hass: HomeAssistant, config_entry: MockConfigEntry):
"""Initialize the config entry.""" """Initialize the config entry."""
config_entry.add_to_hass(hass) config_entry.add_to_hass(hass)
@ -15,6 +18,7 @@ async def test_setup_entry(hass: HomeAssistant, config_entry: MockConfigEntry):
assert hass.states.async_entity_ids_count() == 1 assert hass.states.async_entity_ids_count() == 1
@patch("homeassistant.components.honeywell.UPDATE_LOOP_SLEEP_TIME", 0)
async def test_setup_multiple_thermostats( async def test_setup_multiple_thermostats(
hass: HomeAssistant, config_entry: MockConfigEntry, location, another_device hass: HomeAssistant, config_entry: MockConfigEntry, location, another_device
) -> None: ) -> None: