hass-core/homeassistant/components/gogogate2/config_flow.py
epenet 97c04d2e67
Use dataclass properties in gogogate2 discovery (#60607)
Co-authored-by: epenet <epenet@users.noreply.github.com>
2021-11-30 06:15:23 -10:00

138 lines
5 KiB
Python

"""Config flow for Gogogate2."""
import dataclasses
import re
from ismartgate.common import AbstractInfoResponse, ApiError
from ismartgate.const import GogoGate2ApiErrorCode, ISmartGateApiErrorCode
import voluptuous as vol
from homeassistant import data_entry_flow
from homeassistant.components import dhcp, zeroconf
from homeassistant.config_entries import ConfigFlow
from homeassistant.const import (
CONF_DEVICE,
CONF_IP_ADDRESS,
CONF_PASSWORD,
CONF_USERNAME,
)
from .common import get_api
from .const import DEVICE_TYPE_GOGOGATE2, DEVICE_TYPE_ISMARTGATE, DOMAIN
DEVICE_NAMES = {
DEVICE_TYPE_GOGOGATE2: "Gogogate2",
DEVICE_TYPE_ISMARTGATE: "ismartgate",
}
class Gogogate2FlowHandler(ConfigFlow, domain=DOMAIN):
"""Gogogate2 config flow."""
VERSION = 1
def __init__(self):
"""Initialize the config flow."""
self._ip_address = None
self._device_type = None
async def async_step_homekit(
self, discovery_info: zeroconf.ZeroconfServiceInfo
) -> data_entry_flow.FlowResult:
"""Handle homekit discovery."""
await self.async_set_unique_id(
discovery_info.properties[zeroconf.ATTR_PROPERTIES_ID]
)
return await self._async_discovery_handler(discovery_info.host)
async def async_step_dhcp(
self, discovery_info: dhcp.DhcpServiceInfo
) -> data_entry_flow.FlowResult:
"""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):
"""Start the user flow from any discovery."""
self.context[CONF_IP_ADDRESS] = ip_address
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
for progress in self._async_in_progress():
if progress.get("context", {}).get(CONF_IP_ADDRESS) == self._ip_address:
raise data_entry_flow.AbortFlow("already_in_progress")
self._device_type = DEVICE_TYPE_ISMARTGATE
return await self.async_step_user()
async def async_step_user(self, user_input: dict = None):
"""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: # pylint: disable=broad-except
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,
)