core/homeassistant/components/melcloud/config_flow.py

83 lines
2.8 KiB
Python

"""Config flow for the MELCloud platform."""
from __future__ import annotations
import asyncio
from http import HTTPStatus
from aiohttp import ClientError, ClientResponseError
from async_timeout import timeout
import pymelcloud
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN
class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow."""
VERSION = 1
async def _create_entry(self, username: str, token: str):
"""Register new entry."""
await self.async_set_unique_id(username)
self._abort_if_unique_id_configured({CONF_TOKEN: token})
return self.async_create_entry(
title=username, data={CONF_USERNAME: username, CONF_TOKEN: token}
)
async def _create_client(
self,
username: str,
*,
password: str | None = None,
token: str | None = None,
):
"""Create client."""
if password is None and token is None:
raise ValueError(
"Invalid internal state. Called without either password or token"
)
try:
async with timeout(10):
if (acquired_token := token) is None:
acquired_token = await pymelcloud.login(
username,
password,
async_get_clientsession(self.hass),
)
await pymelcloud.get_devices(
acquired_token,
async_get_clientsession(self.hass),
)
except ClientResponseError as err:
if err.status in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN):
return self.async_abort(reason="invalid_auth")
return self.async_abort(reason="cannot_connect")
except (asyncio.TimeoutError, ClientError):
return self.async_abort(reason="cannot_connect")
return await self._create_entry(username, acquired_token)
async def async_step_user(self, user_input=None):
"""User initiated config flow."""
if user_input is None:
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
),
)
username = user_input[CONF_USERNAME]
return await self._create_client(username, password=user_input[CONF_PASSWORD])
async def async_step_import(self, user_input):
"""Import a config entry."""
return await self._create_client(
user_input[CONF_USERNAME], token=user_input[CONF_TOKEN]
)