"""Config flow for Gogogate2.""" from __future__ import annotations import dataclasses import logging import re from typing import Any, Self from ismartgate.common import AbstractInfoResponse, ApiError from ismartgate.const import GogoGate2ApiErrorCode, ISmartGateApiErrorCode import voluptuous as vol from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.const import ( CONF_DEVICE, CONF_IP_ADDRESS, CONF_PASSWORD, CONF_USERNAME, ) from homeassistant.data_entry_flow import AbortFlow from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo from homeassistant.helpers.service_info.zeroconf import ( ATTR_PROPERTIES_ID, ZeroconfServiceInfo, ) from .common import get_api from .const import DEVICE_TYPE_GOGOGATE2, DEVICE_TYPE_ISMARTGATE, DOMAIN _LOGGER = logging.getLogger(__name__) DEVICE_NAMES = { DEVICE_TYPE_GOGOGATE2: "Gogogate2", DEVICE_TYPE_ISMARTGATE: "ismartgate", } class Gogogate2FlowHandler(ConfigFlow, domain=DOMAIN): """Gogogate2 config flow.""" VERSION = 1 def __init__(self) -> None: """Initialize the config flow.""" self._ip_address: str | None = None self._device_type: str | None = None async def async_step_homekit( self, discovery_info: ZeroconfServiceInfo ) -> ConfigFlowResult: """Handle homekit discovery.""" await self.async_set_unique_id(discovery_info.properties[ATTR_PROPERTIES_ID]) return await self._async_discovery_handler(discovery_info.host) async def async_step_dhcp( self, discovery_info: DhcpServiceInfo ) -> ConfigFlowResult: """Handle dhcp discovery.""" await self.async_set_unique_id(discovery_info.macaddress) return await self._async_discovery_handler(discovery_info.ip) async def _async_discovery_handler(self, ip_address: str) -> ConfigFlowResult: """Start the user flow from any discovery.""" self._abort_if_unique_id_configured({CONF_IP_ADDRESS: ip_address}) self._async_abort_entries_match({CONF_IP_ADDRESS: ip_address}) self._ip_address = ip_address if self.hass.config_entries.flow.async_has_matching_flow(self): raise AbortFlow("already_in_progress") self._device_type = DEVICE_TYPE_ISMARTGATE return await self.async_step_user() def is_matching(self, other_flow: Self) -> bool: """Return True if other_flow is matching this flow.""" return other_flow._ip_address == self._ip_address # noqa: SLF001 async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult: """Handle user initiated flow.""" user_input = user_input or {} errors = {} if user_input: api = get_api(self.hass, user_input) try: data: AbstractInfoResponse = await api.async_info() data_dict = dataclasses.asdict(data) title = data_dict.get( "gogogatename", data_dict.get("ismartgatename", "Cover") ) await self.async_set_unique_id(re.sub("\\..*$", "", data.remoteaccess)) return self.async_create_entry(title=title, data=user_input) except ApiError as api_error: device_type = user_input[CONF_DEVICE] is_invalid_auth = ( device_type == DEVICE_TYPE_GOGOGATE2 and api_error.code in ( GogoGate2ApiErrorCode.CREDENTIALS_NOT_SET, GogoGate2ApiErrorCode.CREDENTIALS_INCORRECT, ) ) or ( device_type == DEVICE_TYPE_ISMARTGATE and api_error.code in ( ISmartGateApiErrorCode.CREDENTIALS_NOT_SET, ISmartGateApiErrorCode.CREDENTIALS_INCORRECT, ) ) if is_invalid_auth: errors["base"] = "invalid_auth" else: errors["base"] = "cannot_connect" except Exception: _LOGGER.exception("Unexpected exception") errors["base"] = "cannot_connect" if self._ip_address and self._device_type: self.context["title_placeholders"] = { CONF_DEVICE: DEVICE_NAMES[self._device_type], CONF_IP_ADDRESS: self._ip_address, } return self.async_show_form( step_id="user", data_schema=vol.Schema( { vol.Required( CONF_DEVICE, default=self._device_type or user_input.get(CONF_DEVICE, DEVICE_TYPE_GOGOGATE2), ): vol.In((DEVICE_TYPE_GOGOGATE2, DEVICE_TYPE_ISMARTGATE)), vol.Required( CONF_IP_ADDRESS, default=user_input.get(CONF_IP_ADDRESS, self._ip_address), ): str, vol.Required( CONF_USERNAME, default=user_input.get(CONF_USERNAME, "") ): str, vol.Required( CONF_PASSWORD, default=user_input.get(CONF_PASSWORD, "") ): str, } ), errors=errors, )