"""Config flow for SiteSage Emonitor integration.""" import logging from aioemonitor import Emonitor import aiohttp import voluptuous as vol from homeassistant import config_entries, core from homeassistant.components import dhcp from homeassistant.const import CONF_HOST, CONF_NAME from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import aiohttp_client from homeassistant.helpers.device_registry import format_mac from . import name_short_mac from .const import DOMAIN _LOGGER = logging.getLogger(__name__) async def fetch_mac_and_title(hass: core.HomeAssistant, host): """Validate the user input allows us to connect.""" session = aiohttp_client.async_get_clientsession(hass) emonitor = Emonitor(host, session) status = await emonitor.async_get_status() mac_address = status.network.mac_address return {"title": name_short_mac(mac_address[-6:]), "mac_address": mac_address} class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow for SiteSage Emonitor.""" VERSION = 1 def __init__(self): """Initialize Emonitor ConfigFlow.""" self.discovered_ip = None self.discovered_info = None async def async_step_user(self, user_input=None): """Handle the initial step.""" errors = {} if user_input is not None: try: info = await fetch_mac_and_title(self.hass, user_input[CONF_HOST]) except aiohttp.ClientError: errors[CONF_HOST] = "cannot_connect" except Exception: # pylint: disable=broad-except _LOGGER.exception("Unexpected exception") errors["base"] = "unknown" else: await self.async_set_unique_id( format_mac(info["mac_address"]), raise_on_progress=False ) self._abort_if_unique_id_configured() return self.async_create_entry(title=info["title"], data=user_input) return self.async_show_form( step_id="user", data_schema=vol.Schema( {vol.Required("host", default=self.discovered_ip): str} ), errors=errors, ) async def async_step_dhcp(self, discovery_info: dhcp.DhcpServiceInfo) -> FlowResult: """Handle dhcp discovery.""" self.discovered_ip = discovery_info.ip await self.async_set_unique_id(format_mac(discovery_info.macaddress)) self._abort_if_unique_id_configured(updates={CONF_HOST: self.discovered_ip}) name = name_short_mac(short_mac(discovery_info.macaddress)) self.context["title_placeholders"] = {"name": name} try: self.discovered_info = await fetch_mac_and_title( self.hass, self.discovered_ip ) except Exception as ex: # pylint: disable=broad-except _LOGGER.debug( "Unable to fetch status, falling back to manual entry", exc_info=ex ) return await self.async_step_user() return await self.async_step_confirm() async def async_step_confirm(self, user_input=None): """Attempt to confirm.""" if user_input is not None: return self.async_create_entry( title=self.discovered_info["title"], data={CONF_HOST: self.discovered_ip}, ) self._set_confirm_only() self.context["title_placeholders"] = {"name": self.discovered_info["title"]} return self.async_show_form( step_id="confirm", description_placeholders={ CONF_HOST: self.discovered_ip, CONF_NAME: self.discovered_info["title"], }, ) def short_mac(mac): """Short version of the mac.""" return "".join(mac.split(":")[3:]).upper()