"""Config flow to configure SMHI component.""" from __future__ import annotations from typing import Any from smhi.smhi_lib import Smhi, SmhiForecastException import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import aiohttp_client import homeassistant.helpers.config_validation as cv from homeassistant.util import slugify from .const import DOMAIN, HOME_LOCATION_NAME @callback def smhi_locations(hass: HomeAssistant) -> set[str]: """Return configurations of SMHI component.""" return { slugify(entry.data[CONF_NAME]) for entry in hass.config_entries.async_entries(DOMAIN) } class SmhiFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): """Config flow for SMHI component.""" VERSION = 1 def __init__(self) -> None: """Initialize SMHI forecast configuration flow.""" self._errors: dict[str, str] = {} async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> FlowResult: """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) and 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.""" # Return true if valid location return ( self.hass.config.latitude != 0.0 and self.hass.config.longitude != 0.0 and await self._check_location( self.hass.config.longitude, self.hass.config.latitude ) ) def _name_in_configuration_exists(self, name: str) -> bool: """Return True if name exists in configuration.""" return name in smhi_locations(self.hass) async def _show_config_form( self, name: str | None = None, latitude: float | None = None, longitude: float | None = None, ) -> FlowResult: """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: float, latitude: float) -> bool: """Return true if location is ok.""" 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