Files

155 lines
5.4 KiB
Python

"""Config flow for Gogogate2."""
import dataclasses
import logging
import re
from typing import Any, Self, override
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
@override
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)
@override
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()
@override
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
@override
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,
)