"""Config flow for Tellduslive.""" import asyncio import logging import os import async_timeout import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_HOST from homeassistant.util.json import load_json from .const import ( APPLICATION_NAME, CLOUD_NAME, DOMAIN, KEY_SCAN_INTERVAL, KEY_SESSION, NOT_SO_PRIVATE_KEY, PUBLIC_KEY, SCAN_INTERVAL, TELLDUS_CONFIG_FILE) KEY_TOKEN = 'token' KEY_TOKEN_SECRET = 'token_secret' _LOGGER = logging.getLogger(__name__) @config_entries.HANDLERS.register('tellduslive') class FlowHandler(config_entries.ConfigFlow): """Handle a config flow.""" VERSION = 1 CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL def __init__(self): """Init config flow.""" self._hosts = [CLOUD_NAME] self._host = None self._session = None self._scan_interval = SCAN_INTERVAL def _get_auth_url(self): from tellduslive import Session self._session = Session( public_key=PUBLIC_KEY, private_key=NOT_SO_PRIVATE_KEY, host=self._host, application=APPLICATION_NAME, ) return self._session.authorize_url async def async_step_user(self, user_input=None): """Let user select host or cloud.""" if self.hass.config_entries.async_entries(DOMAIN): return self.async_abort(reason='already_setup') if user_input is not None or len(self._hosts) == 1: if user_input is not None and user_input[CONF_HOST] != CLOUD_NAME: self._host = user_input[CONF_HOST] return await self.async_step_auth() return self.async_show_form( step_id='user', data_schema=vol.Schema({ vol.Required(CONF_HOST): vol.In(list(self._hosts)) })) async def async_step_auth(self, user_input=None): """Handle the submitted configuration.""" errors = {} if user_input is not None: if await self.hass.async_add_executor_job( self._session.authorize): host = self._host or CLOUD_NAME if self._host: session = { CONF_HOST: host, KEY_TOKEN: self._session.access_token } else: session = { KEY_TOKEN: self._session.access_token, KEY_TOKEN_SECRET: self._session.access_token_secret } return self.async_create_entry( title=host, data={ CONF_HOST: host, KEY_SCAN_INTERVAL: self._scan_interval.seconds, KEY_SESSION: session, }) errors['base'] = 'auth_error' try: with async_timeout.timeout(10): auth_url = await self.hass.async_add_executor_job( self._get_auth_url) if not auth_url: return self.async_abort(reason='authorize_url_fail') except asyncio.TimeoutError: return self.async_abort(reason='authorize_url_timeout') except Exception: # pylint: disable=broad-except _LOGGER.exception("Unexpected error generating auth url") return self.async_abort(reason='authorize_url_fail') _LOGGER.debug('Got authorization URL %s', auth_url) return self.async_show_form( step_id='auth', errors=errors, description_placeholders={ 'app_name': APPLICATION_NAME, 'auth_url': auth_url, }, ) async def async_step_discovery(self, user_input): """Run when a Tellstick is discovered.""" from tellduslive import supports_local_api _LOGGER.info('Discovered tellstick device: %s', user_input) if supports_local_api(user_input[1]): _LOGGER.info('%s support local API', user_input[1]) self._hosts.append(user_input[0]) return await self.async_step_user() async def async_step_import(self, user_input): """Import a config entry.""" if self.hass.config_entries.async_entries(DOMAIN): return self.async_abort(reason='already_setup') self._scan_interval = user_input[KEY_SCAN_INTERVAL] if user_input[CONF_HOST] != DOMAIN: self._hosts.append(user_input[CONF_HOST]) if not await self.hass.async_add_executor_job( os.path.isfile, self.hass.config.path(TELLDUS_CONFIG_FILE)): return await self.async_step_user() conf = await self.hass.async_add_executor_job( load_json, self.hass.config.path(TELLDUS_CONFIG_FILE)) host = next(iter(conf)) if user_input[CONF_HOST] != host: return await self.async_step_user() host = CLOUD_NAME if host == 'tellduslive' else host return self.async_create_entry( title=host, data={ CONF_HOST: host, KEY_SCAN_INTERVAL: self._scan_interval.seconds, KEY_SESSION: next(iter(conf.values())), })