"""Config flow for Electra Air Conditioner integration.""" from __future__ import annotations import logging from typing import Any from electrasmart.api import STATUS_SUCCESS, Attributes, ElectraAPI, ElectraApiError from electrasmart.api.utils import generate_imei import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_TOKEN from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers.aiohttp_client import async_get_clientsession from .const import CONF_IMEI, CONF_OTP, CONF_PHONE_NUMBER, DOMAIN _LOGGER = logging.getLogger(__name__) class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow for Electra Air Conditioner.""" VERSION = 1 def __init__(self) -> None: """Device settings.""" self._phone_number: str | None = None self._description_placeholders = None self._otp: str | None = None self._imei: str | None = None self._token: str | None = None self._api: ElectraAPI | None = None async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Handle the initial step.""" if not self._api: self._api = ElectraAPI(async_get_clientsession(self.hass)) errors: dict[str, Any] = {} if user_input is None: return self._show_setup_form(user_input, errors, "user") return await self._validate_phone_number(user_input) def _show_setup_form( self, user_input: dict[str, str] | None = None, errors: dict[str, str] | None = None, step_id: str = "user", ) -> FlowResult: """Show the setup form to the user.""" if user_input is None: user_input = {} if step_id == "user": schema = { vol.Required( CONF_PHONE_NUMBER, default=user_input.get(CONF_PHONE_NUMBER, "") ): str } else: schema = {vol.Required(CONF_OTP, default=user_input.get(CONF_OTP, "")): str} return self.async_show_form( step_id=step_id, data_schema=vol.Schema(schema), errors=errors or {}, description_placeholders=self._description_placeholders, ) async def _validate_phone_number(self, user_input: dict[str, str]) -> FlowResult: """Check if config is valid and create entry if so.""" self._phone_number = user_input[CONF_PHONE_NUMBER] self._imei = generate_imei() # Check if already configured if self.unique_id is None: await self.async_set_unique_id(self._phone_number) self._abort_if_unique_id_configured() assert isinstance(self._api, ElectraAPI) try: resp = await self._api.generate_new_token(self._phone_number, self._imei) except ElectraApiError as exp: _LOGGER.error("Failed to connect to API: %s", exp) return self._show_setup_form(user_input, {"base": "cannot_connect"}, "user") if resp[Attributes.STATUS] == STATUS_SUCCESS: if resp[Attributes.DATA][Attributes.RES] != STATUS_SUCCESS: return self._show_setup_form( user_input, {CONF_PHONE_NUMBER: "invalid_phone_number"}, "user" ) return await self.async_step_one_time_password() async def _validate_one_time_password( self, user_input: dict[str, str] ) -> FlowResult: self._otp = user_input[CONF_OTP] assert isinstance(self._api, ElectraAPI) assert isinstance(self._imei, str) assert isinstance(self._phone_number, str) assert isinstance(self._otp, str) try: resp = await self._api.validate_one_time_password( self._otp, self._imei, self._phone_number ) except ElectraApiError as exp: _LOGGER.error("Failed to connect to API: %s", exp) return self._show_setup_form( user_input, {"base": "cannot_connect"}, CONF_OTP ) if resp[Attributes.DATA][Attributes.RES] == STATUS_SUCCESS: self._token = resp[Attributes.DATA][Attributes.TOKEN] data = { CONF_TOKEN: self._token, CONF_IMEI: self._imei, CONF_PHONE_NUMBER: self._phone_number, } return self.async_create_entry(title=self._phone_number, data=data) return self._show_setup_form(user_input, {CONF_OTP: "invalid_auth"}, CONF_OTP) async def async_step_one_time_password( self, user_input: dict[str, Any] | None = None, errors: dict[str, str] | None = None, ) -> FlowResult: """Ask the verification code to the user.""" if errors is None: errors = {} if user_input is None: return await self._show_otp_form(errors) return await self._validate_one_time_password(user_input) async def _show_otp_form( self, errors: dict[str, str] | None = None, ) -> FlowResult: """Show the verification_code form to the user.""" return self.async_show_form( step_id=CONF_OTP, data_schema=vol.Schema({vol.Required(CONF_OTP): str}), errors=errors or {}, )