From c76a61ad1663e18351fa75ba0f88c02e48b662aa Mon Sep 17 00:00:00 2001 From: Fredrik Erlandsson Date: Wed, 6 Feb 2019 00:20:23 +0100 Subject: [PATCH] Fix tellduslive responsiveness (#20603) * use async_call_later for update * no need to timeout * fixes * move init tasks to hass.loop * version bump of tellduslive * fixes for @MartinHjelmare * fixes task cancel * don't return from new client --- .../components/tellduslive/__init__.py | 65 ++++++++++--------- requirements_all.txt | 2 +- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/tellduslive/__init__.py b/homeassistant/components/tellduslive/__init__.py index d9cd1be59da..2a57a78ee9e 100644 --- a/homeassistant/components/tellduslive/__init__.py +++ b/homeassistant/components/tellduslive/__init__.py @@ -5,27 +5,26 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/components/tellduslive/ """ import asyncio -from datetime import timedelta from functools import partial import logging import voluptuous as vol from homeassistant import config_entries -import homeassistant.helpers.config_validation as cv from homeassistant.const import CONF_UPDATE_INTERVAL +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.dispatcher import async_dispatcher_send -from homeassistant.helpers.event import async_track_time_interval +from homeassistant.helpers.event import async_call_later from . import config_flow # noqa pylint_disable=unused-import from .const import ( - CONF_HOST, DOMAIN, KEY_HOST, KEY_SCAN_INTERVAL, - KEY_SESSION, MIN_UPDATE_INTERVAL, NOT_SO_PRIVATE_KEY, PUBLIC_KEY, - SCAN_INTERVAL, SIGNAL_UPDATE_ENTITY, TELLDUS_DISCOVERY_NEW) + CONF_HOST, DOMAIN, KEY_HOST, KEY_SCAN_INTERVAL, KEY_SESSION, + MIN_UPDATE_INTERVAL, NOT_SO_PRIVATE_KEY, PUBLIC_KEY, SCAN_INTERVAL, + SIGNAL_UPDATE_ENTITY, TELLDUS_DISCOVERY_NEW) APPLICATION_NAME = 'Home Assistant' -REQUIREMENTS = ['tellduslive==0.10.8'] +REQUIREMENTS = ['tellduslive==0.10.10'] _LOGGER = logging.getLogger(__name__) @@ -45,6 +44,7 @@ CONFIG_SCHEMA = vol.Schema( DATA_CONFIG_ENTRY_LOCK = 'tellduslive_config_entry_lock' CONFIG_ENTRY_IS_SETUP = 'telldus_config_entry_is_setup' +NEW_CLIENT_TASK = 'telldus_new_client_task' INTERVAL_TRACKER = '{}_INTERVAL'.format(DOMAIN) @@ -71,33 +71,30 @@ async def async_setup_entry(hass, entry): hass.data[DATA_CONFIG_ENTRY_LOCK] = asyncio.Lock() hass.data[CONFIG_ENTRY_IS_SETUP] = set() - - client = TelldusLiveClient(hass, entry, session) - hass.data[DOMAIN] = client - await async_add_hubs(hass, client, entry.entry_id) - hass.async_create_task(client.update()) - - interval = timedelta(seconds=entry.data[KEY_SCAN_INTERVAL]) - _LOGGER.debug('Update interval %s', interval) - hass.data[INTERVAL_TRACKER] = async_track_time_interval( - hass, client.update, interval) + hass.data[NEW_CLIENT_TASK] = hass.loop.create_task( + async_new_client(hass, session, entry)) return True -async def async_add_hubs(hass, client, entry_id): +async def async_new_client(hass, session, entry): """Add the hubs associated with the current client to device_registry.""" + interval = entry.data[KEY_SCAN_INTERVAL] + _LOGGER.debug('Update interval %s seconds.', interval) + client = TelldusLiveClient(hass, entry, session, interval) + hass.data[DOMAIN] = client dev_reg = await hass.helpers.device_registry.async_get_registry() for hub in await client.async_get_hubs(): _LOGGER.debug("Connected hub %s", hub['name']) dev_reg.async_get_or_create( - config_entry_id=entry_id, + config_entry_id=entry.entry_id, identifiers={(DOMAIN, hub['id'])}, manufacturer='Telldus', name=hub['name'], model=hub['type'], sw_version=hub['version'], ) + await client.update() async def async_setup(hass, config): @@ -118,6 +115,8 @@ async def async_setup(hass, config): async def async_unload_entry(hass, config_entry): """Unload a config entry.""" + if not hass.data[NEW_CLIENT_TASK].done(): + hass.data[NEW_CLIENT_TASK].cancel() interval_tracker = hass.data.pop(INTERVAL_TRACKER) interval_tracker() await asyncio.wait([ @@ -132,7 +131,7 @@ async def async_unload_entry(hass, config_entry): class TelldusLiveClient: """Get the latest data and update the states.""" - def __init__(self, hass, config_entry, session): + def __init__(self, hass, config_entry, session, interval): """Initialize the Tellus data object.""" self._known_devices = set() self._device_infos = {} @@ -140,6 +139,7 @@ class TelldusLiveClient: self._hass = hass self._config_entry = config_entry self._client = session + self._interval = interval async def async_get_hubs(self): """Return hubs registered for the user.""" @@ -195,16 +195,21 @@ class TelldusLiveClient: async def update(self, *args): """Periodically poll the servers for current state.""" - if not await self._hass.async_add_executor_job(self._client.update): - _LOGGER.warning('Failed request') - - dev_ids = {dev.device_id for dev in self._client.devices} - new_devices = dev_ids - self._known_devices - # just await each discover as `gather` use up all HTTPAdapter pools - for d_id in new_devices: - await self._discover(d_id) - self._known_devices |= new_devices - async_dispatcher_send(self._hass, SIGNAL_UPDATE_ENTITY) + try: + if not await self._hass.async_add_executor_job( + self._client.update): + _LOGGER.warning('Failed request') + return + dev_ids = {dev.device_id for dev in self._client.devices} + new_devices = dev_ids - self._known_devices + # just await each discover as `gather` use up all HTTPAdapter pools + for d_id in new_devices: + await self._discover(d_id) + self._known_devices |= new_devices + async_dispatcher_send(self._hass, SIGNAL_UPDATE_ENTITY) + finally: + self._hass.data[INTERVAL_TRACKER] = async_call_later( + self._hass, self._interval, self.update) def device(self, device_id): """Return device representation.""" diff --git a/requirements_all.txt b/requirements_all.txt index 35019f74408..ed107f224c8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1628,7 +1628,7 @@ tellcore-net==0.4 tellcore-py==1.1.2 # homeassistant.components.tellduslive -tellduslive==0.10.8 +tellduslive==0.10.10 # homeassistant.components.media_player.lg_soundbar temescal==0.1