ha-core/homeassistant/components/ukraine_alarm/config_flow.py

150 lines
4.8 KiB
Python

"""Config flow for Ukraine Alarm."""
from __future__ import annotations
import asyncio
import logging
import aiohttp
from uasiren.client import Client
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_NAME, CONF_REGION
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
class UkraineAlarmConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Config flow for Ukraine Alarm."""
VERSION = 1
def __init__(self):
"""Initialize a new UkraineAlarmConfigFlow."""
self.states = None
self.selected_region = None
async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
if len(self._async_current_entries()) == 5:
return self.async_abort(reason="max_regions")
if not self.states:
websession = async_get_clientsession(self.hass)
reason = None
unknown_err_msg = None
try:
regions = await Client(websession).get_regions()
except aiohttp.ClientResponseError as ex:
if ex.status == 429:
reason = "rate_limit"
else:
reason = "unknown"
unknown_err_msg = str(ex)
except aiohttp.ClientConnectionError:
reason = "cannot_connect"
except aiohttp.ClientError as ex:
reason = "unknown"
unknown_err_msg = str(ex)
except asyncio.TimeoutError:
reason = "timeout"
if not reason and not regions:
reason = "unknown"
unknown_err_msg = "no regions returned"
if unknown_err_msg:
_LOGGER.error("Failed to connect to the service: %s", unknown_err_msg)
if reason:
return self.async_abort(reason=reason)
self.states = regions["states"]
return await self._handle_pick_region("user", "district", user_input)
async def async_step_district(self, user_input=None):
"""Handle user-chosen district."""
return await self._handle_pick_region("district", "community", user_input)
async def async_step_community(self, user_input=None):
"""Handle user-chosen community."""
return await self._handle_pick_region("community", None, user_input, True)
async def _handle_pick_region(
self, step_id: str, next_step: str | None, user_input, last_step=False
):
"""Handle picking a (sub)region."""
if self.selected_region:
source = self.selected_region["regionChildIds"]
else:
source = self.states
if user_input is not None:
# Only offer to browse subchildren if picked region wasn't the previously picked one
if (
not self.selected_region
or user_input[CONF_REGION] != self.selected_region["regionId"]
):
self.selected_region = _find(source, user_input[CONF_REGION])
if next_step and self.selected_region["regionChildIds"]:
return await getattr(self, f"async_step_{next_step}")()
return await self._async_finish_flow()
regions = {}
if self.selected_region:
regions[self.selected_region["regionId"]] = self.selected_region[
"regionName"
]
regions.update(_make_regions_object(source))
schema = vol.Schema(
{
vol.Required(CONF_REGION): vol.In(regions),
}
)
return self.async_show_form(
step_id=step_id, data_schema=schema, last_step=last_step
)
async def _async_finish_flow(self):
"""Finish the setup."""
await self.async_set_unique_id(self.selected_region["regionId"])
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=self.selected_region["regionName"],
data={
CONF_REGION: self.selected_region["regionId"],
CONF_NAME: self.selected_region["regionName"],
},
)
def _find(regions, region_id):
return next((region for region in regions if region["regionId"] == region_id), None)
def _make_regions_object(regions):
regions_list = []
for region in regions:
regions_list.append(
{
"id": region["regionId"],
"name": region["regionName"],
}
)
regions_list = sorted(regions_list, key=lambda region: region["name"].lower())
regions_object = {}
for region in regions_list:
regions_object[region["id"]] = region["name"]
return regions_object