"""Config flow to configure smhi component. First time the user creates the configuration and a valid location is set in the hass configuration yaml it will use that location and use it as default values. Additional locations can be added in config form. The input location will be checked by invoking the API. Exception will be thrown if the location is not supported by the API (Swedish locations only) """ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant import config_entries, data_entry_flow from homeassistant.const import (CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME) from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import aiohttp_client from homeassistant.util import slugify from .const import DOMAIN, HOME_LOCATION_NAME @callback def smhi_locations(hass: HomeAssistant): """Return configurations of SMHI component.""" return set((slugify(entry.data[CONF_NAME])) for entry in hass.config_entries.async_entries(DOMAIN)) @config_entries.HANDLERS.register(DOMAIN) class SmhiFlowHandler(data_entry_flow.FlowHandler): """Config flow for SMHI component.""" VERSION = 1 CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL def __init__(self) -> None: """Initialize SMHI forecast configuration flow.""" self._errors = {} async def async_step_user(self, user_input=None): """Handle a flow initialized by the user.""" self._errors = {} if user_input is not None: is_ok = await self._check_location( user_input[CONF_LONGITUDE], user_input[CONF_LATITUDE] ) if is_ok: name = slugify(user_input[CONF_NAME]) if not self._name_in_configuration_exists(name): return self.async_create_entry( title=user_input[CONF_NAME], data=user_input, ) self._errors[CONF_NAME] = 'name_exists' else: self._errors['base'] = 'wrong_location' # If hass config has the location set and # is a valid coordinate the default location # is set as default values in the form if not smhi_locations(self.hass): if await self._homeassistant_location_exists(): return await self._show_config_form( name=HOME_LOCATION_NAME, latitude=self.hass.config.latitude, longitude=self.hass.config.longitude ) return await self._show_config_form() async def _homeassistant_location_exists(self) -> bool: """Return true if default location is set and is valid.""" if self.hass.config.latitude != 0.0 and \ self.hass.config.longitude != 0.0: # Return true if valid location if await self._check_location( self.hass.config.longitude, self.hass.config.latitude): return True return False def _name_in_configuration_exists(self, name: str) -> bool: """Return True if name exists in configuration.""" if name in smhi_locations(self.hass): return True return False async def _show_config_form(self, name: str = None, latitude: str = None, longitude: str = None): """Show the configuration form to edit location data.""" return self.async_show_form( step_id='user', data_schema=vol.Schema({ vol.Required(CONF_NAME, default=name): str, vol.Required(CONF_LATITUDE, default=latitude): cv.latitude, vol.Required(CONF_LONGITUDE, default=longitude): cv.longitude }), errors=self._errors, ) async def _check_location(self, longitude: str, latitude: str) -> bool: """Return true if location is ok.""" from smhi.smhi_lib import Smhi, SmhiForecastException try: session = aiohttp_client.async_get_clientsession(self.hass) smhi_api = Smhi(longitude, latitude, session=session) await smhi_api.async_get_forecast() return True except SmhiForecastException: # The API will throw an exception if faulty location pass return False