167 lines
5.8 KiB
Python
167 lines
5.8 KiB
Python
"""Config Flow for Hive."""
|
|
|
|
from apyhiveapi import Auth
|
|
from apyhiveapi.helper.hive_exceptions import (
|
|
HiveApiError,
|
|
HiveInvalid2FACode,
|
|
HiveInvalidPassword,
|
|
HiveInvalidUsername,
|
|
)
|
|
import voluptuous as vol
|
|
|
|
from homeassistant import config_entries
|
|
from homeassistant.const import CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME
|
|
from homeassistant.core import callback
|
|
|
|
from .const import CONF_CODE, CONFIG_ENTRY_VERSION, DOMAIN
|
|
|
|
|
|
class HiveFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|
"""Handle a Hive config flow."""
|
|
|
|
VERSION = CONFIG_ENTRY_VERSION
|
|
|
|
def __init__(self):
|
|
"""Initialize the config flow."""
|
|
self.hive_auth = None
|
|
self.data = {}
|
|
self.tokens = {}
|
|
self.entry = None
|
|
|
|
async def async_step_user(self, user_input=None):
|
|
"""Prompt user input. Create or edit entry."""
|
|
errors = {}
|
|
# Login to Hive with user data.
|
|
if user_input is not None:
|
|
self.data.update(user_input)
|
|
self.hive_auth = Auth(
|
|
username=self.data[CONF_USERNAME], password=self.data[CONF_PASSWORD]
|
|
)
|
|
|
|
# Get user from existing entry and abort if already setup
|
|
self.entry = await self.async_set_unique_id(self.data[CONF_USERNAME])
|
|
if self.context["source"] != config_entries.SOURCE_REAUTH:
|
|
self._abort_if_unique_id_configured()
|
|
|
|
# Login to the Hive.
|
|
try:
|
|
self.tokens = await self.hive_auth.login()
|
|
except HiveInvalidUsername:
|
|
errors["base"] = "invalid_username"
|
|
except HiveInvalidPassword:
|
|
errors["base"] = "invalid_password"
|
|
except HiveApiError:
|
|
errors["base"] = "no_internet_available"
|
|
|
|
if self.tokens.get("ChallengeName") == "SMS_MFA":
|
|
# Complete SMS 2FA.
|
|
return await self.async_step_2fa()
|
|
|
|
if not errors:
|
|
# Complete the entry setup.
|
|
try:
|
|
return await self.async_setup_hive_entry()
|
|
except UnknownHiveError:
|
|
errors["base"] = "unknown"
|
|
|
|
# Show User Input form.
|
|
schema = vol.Schema(
|
|
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
|
|
)
|
|
return self.async_show_form(step_id="user", data_schema=schema, errors=errors)
|
|
|
|
async def async_step_2fa(self, user_input=None):
|
|
"""Handle 2fa step."""
|
|
errors = {}
|
|
|
|
if user_input and user_input["2fa"] == "0000":
|
|
self.tokens = await self.hive_auth.login()
|
|
elif user_input:
|
|
try:
|
|
self.tokens = await self.hive_auth.sms_2fa(
|
|
user_input["2fa"], self.tokens
|
|
)
|
|
except HiveInvalid2FACode:
|
|
errors["base"] = "invalid_code"
|
|
except HiveApiError:
|
|
errors["base"] = "no_internet_available"
|
|
|
|
if not errors:
|
|
try:
|
|
return await self.async_setup_hive_entry()
|
|
except UnknownHiveError:
|
|
errors["base"] = "unknown"
|
|
|
|
schema = vol.Schema({vol.Required(CONF_CODE): str})
|
|
return self.async_show_form(step_id="2fa", data_schema=schema, errors=errors)
|
|
|
|
async def async_setup_hive_entry(self):
|
|
"""Finish setup and create the config entry."""
|
|
|
|
if "AuthenticationResult" not in self.tokens:
|
|
raise UnknownHiveError
|
|
|
|
# Setup the config entry
|
|
self.data["tokens"] = self.tokens
|
|
if self.context["source"] == config_entries.SOURCE_REAUTH:
|
|
self.hass.config_entries.async_update_entry(
|
|
self.entry, title=self.data["username"], data=self.data
|
|
)
|
|
await self.hass.config_entries.async_reload(self.entry.entry_id)
|
|
return self.async_abort(reason="reauth_successful")
|
|
return self.async_create_entry(title=self.data["username"], data=self.data)
|
|
|
|
async def async_step_reauth(self, user_input=None):
|
|
"""Re Authenticate a user."""
|
|
data = {
|
|
CONF_USERNAME: user_input[CONF_USERNAME],
|
|
CONF_PASSWORD: user_input[CONF_PASSWORD],
|
|
}
|
|
return await self.async_step_user(data)
|
|
|
|
async def async_step_import(self, user_input=None):
|
|
"""Import user."""
|
|
return await self.async_step_user(user_input)
|
|
|
|
@staticmethod
|
|
@callback
|
|
def async_get_options_flow(config_entry):
|
|
"""Hive options callback."""
|
|
return HiveOptionsFlowHandler(config_entry)
|
|
|
|
|
|
class HiveOptionsFlowHandler(config_entries.OptionsFlow):
|
|
"""Config flow options for Hive."""
|
|
|
|
def __init__(self, config_entry):
|
|
"""Initialize Hive options flow."""
|
|
self.hive = None
|
|
self.config_entry = config_entry
|
|
self.interval = config_entry.options.get(CONF_SCAN_INTERVAL, 120)
|
|
|
|
async def async_step_init(self, user_input=None):
|
|
"""Manage the options."""
|
|
return await self.async_step_user()
|
|
|
|
async def async_step_user(self, user_input=None):
|
|
"""Handle a flow initialized by the user."""
|
|
self.hive = self.hass.data["hive"][self.config_entry.entry_id]
|
|
errors = {}
|
|
if user_input is not None:
|
|
new_interval = user_input.get(CONF_SCAN_INTERVAL)
|
|
await self.hive.updateInterval(new_interval)
|
|
return self.async_create_entry(title="", data=user_input)
|
|
|
|
schema = vol.Schema(
|
|
{
|
|
vol.Optional(CONF_SCAN_INTERVAL, default=self.interval): vol.All(
|
|
vol.Coerce(int), vol.Range(min=30)
|
|
)
|
|
}
|
|
)
|
|
return self.async_show_form(step_id="user", data_schema=schema, errors=errors)
|
|
|
|
|
|
class UnknownHiveError(Exception):
|
|
"""Catch unknown hive error."""
|