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
This commit is contained in:
Fredrik Erlandsson 2019-02-06 00:20:23 +01:00 committed by Paulus Schoutsen
parent ca17d4395a
commit c76a61ad16
2 changed files with 36 additions and 31 deletions

View File

@ -5,27 +5,26 @@ For more details about this component, please refer to the documentation at
https://home-assistant.io/components/tellduslive/ https://home-assistant.io/components/tellduslive/
""" """
import asyncio import asyncio
from datetime import timedelta
from functools import partial from functools import partial
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_UPDATE_INTERVAL 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.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 . import config_flow # noqa pylint_disable=unused-import
from .const import ( from .const import (
CONF_HOST, DOMAIN, KEY_HOST, KEY_SCAN_INTERVAL, CONF_HOST, DOMAIN, KEY_HOST, KEY_SCAN_INTERVAL, KEY_SESSION,
KEY_SESSION, MIN_UPDATE_INTERVAL, NOT_SO_PRIVATE_KEY, PUBLIC_KEY, MIN_UPDATE_INTERVAL, NOT_SO_PRIVATE_KEY, PUBLIC_KEY, SCAN_INTERVAL,
SCAN_INTERVAL, SIGNAL_UPDATE_ENTITY, TELLDUS_DISCOVERY_NEW) SIGNAL_UPDATE_ENTITY, TELLDUS_DISCOVERY_NEW)
APPLICATION_NAME = 'Home Assistant' APPLICATION_NAME = 'Home Assistant'
REQUIREMENTS = ['tellduslive==0.10.8'] REQUIREMENTS = ['tellduslive==0.10.10']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -45,6 +44,7 @@ CONFIG_SCHEMA = vol.Schema(
DATA_CONFIG_ENTRY_LOCK = 'tellduslive_config_entry_lock' DATA_CONFIG_ENTRY_LOCK = 'tellduslive_config_entry_lock'
CONFIG_ENTRY_IS_SETUP = 'telldus_config_entry_is_setup' CONFIG_ENTRY_IS_SETUP = 'telldus_config_entry_is_setup'
NEW_CLIENT_TASK = 'telldus_new_client_task'
INTERVAL_TRACKER = '{}_INTERVAL'.format(DOMAIN) 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[DATA_CONFIG_ENTRY_LOCK] = asyncio.Lock()
hass.data[CONFIG_ENTRY_IS_SETUP] = set() hass.data[CONFIG_ENTRY_IS_SETUP] = set()
hass.data[NEW_CLIENT_TASK] = hass.loop.create_task(
client = TelldusLiveClient(hass, entry, session) async_new_client(hass, session, entry))
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)
return True 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.""" """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() dev_reg = await hass.helpers.device_registry.async_get_registry()
for hub in await client.async_get_hubs(): for hub in await client.async_get_hubs():
_LOGGER.debug("Connected hub %s", hub['name']) _LOGGER.debug("Connected hub %s", hub['name'])
dev_reg.async_get_or_create( dev_reg.async_get_or_create(
config_entry_id=entry_id, config_entry_id=entry.entry_id,
identifiers={(DOMAIN, hub['id'])}, identifiers={(DOMAIN, hub['id'])},
manufacturer='Telldus', manufacturer='Telldus',
name=hub['name'], name=hub['name'],
model=hub['type'], model=hub['type'],
sw_version=hub['version'], sw_version=hub['version'],
) )
await client.update()
async def async_setup(hass, config): async def async_setup(hass, config):
@ -118,6 +115,8 @@ async def async_setup(hass, config):
async def async_unload_entry(hass, config_entry): async def async_unload_entry(hass, config_entry):
"""Unload a 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 = hass.data.pop(INTERVAL_TRACKER)
interval_tracker() interval_tracker()
await asyncio.wait([ await asyncio.wait([
@ -132,7 +131,7 @@ async def async_unload_entry(hass, config_entry):
class TelldusLiveClient: class TelldusLiveClient:
"""Get the latest data and update the states.""" """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.""" """Initialize the Tellus data object."""
self._known_devices = set() self._known_devices = set()
self._device_infos = {} self._device_infos = {}
@ -140,6 +139,7 @@ class TelldusLiveClient:
self._hass = hass self._hass = hass
self._config_entry = config_entry self._config_entry = config_entry
self._client = session self._client = session
self._interval = interval
async def async_get_hubs(self): async def async_get_hubs(self):
"""Return hubs registered for the user.""" """Return hubs registered for the user."""
@ -195,16 +195,21 @@ class TelldusLiveClient:
async def update(self, *args): async def update(self, *args):
"""Periodically poll the servers for current state.""" """Periodically poll the servers for current state."""
if not await self._hass.async_add_executor_job(self._client.update): try:
_LOGGER.warning('Failed request') if not await self._hass.async_add_executor_job(
self._client.update):
dev_ids = {dev.device_id for dev in self._client.devices} _LOGGER.warning('Failed request')
new_devices = dev_ids - self._known_devices return
# just await each discover as `gather` use up all HTTPAdapter pools dev_ids = {dev.device_id for dev in self._client.devices}
for d_id in new_devices: new_devices = dev_ids - self._known_devices
await self._discover(d_id) # just await each discover as `gather` use up all HTTPAdapter pools
self._known_devices |= new_devices for d_id in new_devices:
async_dispatcher_send(self._hass, SIGNAL_UPDATE_ENTITY) 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): def device(self, device_id):
"""Return device representation.""" """Return device representation."""

View File

@ -1628,7 +1628,7 @@ tellcore-net==0.4
tellcore-py==1.1.2 tellcore-py==1.1.2
# homeassistant.components.tellduslive # homeassistant.components.tellduslive
tellduslive==0.10.8 tellduslive==0.10.10
# homeassistant.components.media_player.lg_soundbar # homeassistant.components.media_player.lg_soundbar
temescal==0.1 temescal==0.1