"""Config flow for HVV integration.""" import logging from pygti.auth import GTI_DEFAULT_HOST from pygti.exceptions import CannotConnect, InvalidAuth import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_HOST, CONF_OFFSET, CONF_PASSWORD, CONF_USERNAME from homeassistant.core import callback from homeassistant.helpers import aiohttp_client import homeassistant.helpers.config_validation as cv from .const import CONF_FILTER, CONF_REAL_TIME, CONF_STATION, DOMAIN from .hub import GTIHub _LOGGER = logging.getLogger(__name__) SCHEMA_STEP_USER = vol.Schema( { vol.Required(CONF_HOST, default=GTI_DEFAULT_HOST): str, vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str, } ) SCHEMA_STEP_STATION = vol.Schema({vol.Required(CONF_STATION): str}) SCHEMA_STEP_OPTIONS = vol.Schema( { vol.Required(CONF_FILTER): vol.In([]), vol.Required(CONF_OFFSET, default=0): cv.positive_int, vol.Optional(CONF_REAL_TIME, default=True): bool, } ) class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow for HVV.""" VERSION = 1 CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL def __init__(self): """Initialize component.""" self.hub = None self.data = None self.stations = {} async def async_step_user(self, user_input=None): """Handle the initial step.""" errors = {} if user_input is not None: session = aiohttp_client.async_get_clientsession(self.hass) self.hub = GTIHub( user_input[CONF_HOST], user_input[CONF_USERNAME], user_input[CONF_PASSWORD], session, ) try: response = await self.hub.authenticate() _LOGGER.debug("Init gti: %r", response) except CannotConnect: errors["base"] = "cannot_connect" except InvalidAuth: errors["base"] = "invalid_auth" if not errors: self.data = user_input return await self.async_step_station() return self.async_show_form( step_id="user", data_schema=SCHEMA_STEP_USER, errors=errors ) async def async_step_station(self, user_input=None): """Handle the step where the user inputs his/her station.""" if user_input is not None: errors = {} check_name = await self.hub.gti.checkName( {"theName": {"name": user_input[CONF_STATION]}, "maxList": 20} ) stations = check_name.get("results") self.stations = { f"{station.get('name')}": station for station in stations if station.get("type") == "STATION" } if not self.stations: errors["base"] = "no_results" return self.async_show_form( step_id="station", data_schema=SCHEMA_STEP_STATION, errors=errors ) # schema return await self.async_step_station_select() return self.async_show_form(step_id="station", data_schema=SCHEMA_STEP_STATION) async def async_step_station_select(self, user_input=None): """Handle the step where the user inputs his/her station.""" schema = vol.Schema({vol.Required(CONF_STATION): vol.In(list(self.stations))}) if user_input is None: return self.async_show_form(step_id="station_select", data_schema=schema) self.data.update({"station": self.stations[user_input[CONF_STATION]]}) title = self.data[CONF_STATION]["name"] return self.async_create_entry(title=title, data=self.data) @staticmethod @callback def async_get_options_flow(config_entry): """Get options flow.""" return OptionsFlowHandler(config_entry) class OptionsFlowHandler(config_entries.OptionsFlow): """Options flow handler.""" def __init__(self, config_entry): """Initialize HVV Departures options flow.""" self.config_entry = config_entry self.options = dict(config_entry.options) self.departure_filters = {} self.hub = None async def async_step_init(self, user_input=None): """Manage the options.""" errors = {} if not self.departure_filters: departure_list = {} self.hub = self.hass.data[DOMAIN][self.config_entry.entry_id] try: departure_list = await self.hub.gti.departureList( { "station": self.config_entry.data[CONF_STATION], "time": {"date": "heute", "time": "jetzt"}, "maxList": 5, "maxTimeOffset": 200, "useRealtime": True, "returnFilters": True, } ) except CannotConnect: errors["base"] = "cannot_connect" except InvalidAuth: errors["base"] = "invalid_auth" if not errors: self.departure_filters = { str(i): departure_filter for i, departure_filter in enumerate(departure_list.get("filter")) } if user_input is not None and not errors: options = { CONF_FILTER: [ self.departure_filters[x] for x in user_input[CONF_FILTER] ], CONF_OFFSET: user_input[CONF_OFFSET], CONF_REAL_TIME: user_input[CONF_REAL_TIME], } return self.async_create_entry(title="", data=options) if CONF_FILTER in self.config_entry.options: old_filter = [ i for (i, f) in self.departure_filters.items() if f in self.config_entry.options.get(CONF_FILTER) ] else: old_filter = [] return self.async_show_form( step_id="init", data_schema=vol.Schema( { vol.Optional(CONF_FILTER, default=old_filter): cv.multi_select( { key: f"{departure_filter['serviceName']}, {departure_filter['label']}" for key, departure_filter in self.departure_filters.items() } ), vol.Required( CONF_OFFSET, default=self.config_entry.options.get(CONF_OFFSET, 0), ): cv.positive_int, vol.Optional( CONF_REAL_TIME, default=self.config_entry.options.get(CONF_REAL_TIME, True), ): bool, } ), errors=errors, )