mirror of https://github.com/home-assistant/core
128 lines
4.9 KiB
Python
128 lines
4.9 KiB
Python
"""Config flow for EHEIM Digital."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from aiohttp import ClientError
|
|
from eheimdigital.device import EheimDigitalDevice
|
|
from eheimdigital.hub import EheimDigitalHub
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.config_entries import SOURCE_USER, ConfigFlow, ConfigFlowResult
|
|
from homeassistant.const import CONF_HOST
|
|
from homeassistant.helpers import selector
|
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|
from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
|
|
|
|
from .const import DOMAIN, LOGGER
|
|
|
|
CONFIG_SCHEMA = vol.Schema(
|
|
{vol.Required(CONF_HOST, default="eheimdigital.local"): selector.TextSelector()}
|
|
)
|
|
|
|
|
|
class EheimDigitalConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
"""The EHEIM Digital config flow."""
|
|
|
|
def __init__(self) -> None:
|
|
"""Initialize the config flow."""
|
|
super().__init__()
|
|
self.data: dict[str, Any] = {}
|
|
self.main_device_added_event = asyncio.Event()
|
|
|
|
async def async_step_zeroconf(
|
|
self, discovery_info: ZeroconfServiceInfo
|
|
) -> ConfigFlowResult:
|
|
"""Handle zeroconf discovery."""
|
|
self.data[CONF_HOST] = host = discovery_info.host
|
|
|
|
self._async_abort_entries_match(self.data)
|
|
|
|
hub = EheimDigitalHub(
|
|
host=host,
|
|
session=async_get_clientsession(self.hass),
|
|
loop=self.hass.loop,
|
|
main_device_added_event=self.main_device_added_event,
|
|
)
|
|
try:
|
|
await hub.connect()
|
|
|
|
async with asyncio.timeout(2):
|
|
# This event gets triggered when the first message is received from
|
|
# the device, it contains the data necessary to create the main device.
|
|
# This removes the race condition where the main device is accessed
|
|
# before the response from the device is parsed.
|
|
await self.main_device_added_event.wait()
|
|
if TYPE_CHECKING:
|
|
# At this point the main device is always set
|
|
assert isinstance(hub.main, EheimDigitalDevice)
|
|
await hub.close()
|
|
except (ClientError, TimeoutError):
|
|
return self.async_abort(reason="cannot_connect")
|
|
except Exception: # noqa: BLE001
|
|
return self.async_abort(reason="unknown")
|
|
await self.async_set_unique_id(hub.main.mac_address)
|
|
self._abort_if_unique_id_configured(updates={CONF_HOST: host})
|
|
return await self.async_step_discovery_confirm()
|
|
|
|
async def async_step_discovery_confirm(
|
|
self, user_input: dict[str, Any] | None = None
|
|
) -> ConfigFlowResult:
|
|
"""Confirm discovery."""
|
|
if user_input is not None:
|
|
return self.async_create_entry(
|
|
title=self.data[CONF_HOST],
|
|
data={CONF_HOST: self.data[CONF_HOST]},
|
|
)
|
|
|
|
self._set_confirm_only()
|
|
return self.async_show_form(step_id="discovery_confirm")
|
|
|
|
async def async_step_user(
|
|
self, user_input: dict[str, Any] | None = None
|
|
) -> ConfigFlowResult:
|
|
"""Handle the user step."""
|
|
if user_input is None:
|
|
return self.async_show_form(step_id=SOURCE_USER, data_schema=CONFIG_SCHEMA)
|
|
|
|
self._async_abort_entries_match(user_input)
|
|
errors: dict[str, str] = {}
|
|
hub = EheimDigitalHub(
|
|
host=user_input[CONF_HOST],
|
|
session=async_get_clientsession(self.hass),
|
|
loop=self.hass.loop,
|
|
main_device_added_event=self.main_device_added_event,
|
|
)
|
|
|
|
try:
|
|
await hub.connect()
|
|
|
|
async with asyncio.timeout(2):
|
|
# This event gets triggered when the first message is received from
|
|
# the device, it contains the data necessary to create the main device.
|
|
# This removes the race condition where the main device is accessed
|
|
# before the response from the device is parsed.
|
|
await self.main_device_added_event.wait()
|
|
if TYPE_CHECKING:
|
|
# At this point the main device is always set
|
|
assert isinstance(hub.main, EheimDigitalDevice)
|
|
await self.async_set_unique_id(
|
|
hub.main.mac_address, raise_on_progress=False
|
|
)
|
|
await hub.close()
|
|
except (ClientError, TimeoutError):
|
|
errors["base"] = "cannot_connect"
|
|
except Exception: # noqa: BLE001
|
|
errors["base"] = "unknown"
|
|
LOGGER.exception("Unknown exception occurred")
|
|
else:
|
|
self._abort_if_unique_id_configured()
|
|
return self.async_create_entry(data=user_input, title=user_input[CONF_HOST])
|
|
return self.async_show_form(
|
|
step_id=SOURCE_USER,
|
|
data_schema=CONFIG_SCHEMA,
|
|
errors=errors,
|
|
)
|