def __init__( self, hass: HomeAssistant, logger: Logger, username: str, password: str, panel_id: str, panel_pin: str, name: str, update_interval: timedelta, ) -> None: """Instantiate the object.""" self._client = Elmax(username=username, password=password) self._panel_id = panel_id self._panel_pin = panel_pin self._panel_entry = None self._state_by_endpoint = None super().__init__(hass=hass, logger=logger, name=name, update_interval=update_interval)
async def async_step_user(self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Handle a flow initialized by the user.""" # When invokes without parameters, show the login form. if user_input is None: return self.async_show_form(step_id="user", data_schema=LOGIN_FORM_SCHEMA) errors: dict[str, str] = {} username = user_input[CONF_ELMAX_USERNAME] password = user_input[CONF_ELMAX_PASSWORD] # Otherwise, it means we are handling now the "submission" of the user form. # In this case, let's try to log in to the Elmax cloud and retrieve the available panels. try: client = Elmax(username=username, password=password) await client.login() # If the login succeeded, retrieve the list of available panels and filter the online ones online_panels = [ x for x in await client.list_control_panels() if x.online ] # If no online panel was found, we display an error in the next UI. panels = list(online_panels) if len(panels) < 1: raise NoOnlinePanelsError() # Show the panel selection. # We want the user to choose the panel using the associated name, we set up a mapping # dictionary to handle that case. panel_names: dict[str, str] = {} username = client.get_authenticated_username() for panel in panels: _store_panel_by_name(panel=panel, username=username, panel_names=panel_names) self._client = client self._panel_names = panel_names schema = vol.Schema({ vol.Required(CONF_ELMAX_PANEL_NAME): vol.In(self._panel_names.keys()), vol.Required(CONF_ELMAX_PANEL_PIN, default="000000"): str, }) self._panels_schema = schema self._username = username self._password = password return self.async_show_form(step_id="panels", data_schema=schema, errors=errors) except ElmaxBadLoginError: _LOGGER.error("Wrong credentials or failed login") errors["base"] = "bad_auth" except NoOnlinePanelsError: _LOGGER.warning("No online device panel was found") errors["base"] = "no_panel_online" except ElmaxNetworkError: _LOGGER.exception("A network error occurred") errors["base"] = "network_error" # If an error occurred, show back the login form. return self.async_show_form(step_id="user", data_schema=LOGIN_FORM_SCHEMA, errors=errors)
async def _async_login(username: str, password: str) -> Elmax: """Log in to the Elmax cloud and return the http client.""" client = Elmax(username=username, password=password) await client.login() return client
async def async_step_reauth_confirm(self, user_input=None): """Handle reauthorization flow.""" errors = {} if user_input is not None: panel_pin = user_input.get(CONF_ELMAX_PANEL_PIN) password = user_input.get(CONF_ELMAX_PASSWORD) entry = await self.async_set_unique_id(self._reauth_panelid) # Handle authentication, make sure the panel we are re-authenticating against is listed among results # and verify its pin is correct. try: # Test login. client = Elmax(username=self._reauth_username, password=password) await client.login() # Make sure the panel we are authenticating to is still available. panels = [ p for p in await client.list_control_panels() if p.hash == self._reauth_panelid ] if len(panels) < 1: raise NoOnlinePanelsError() # Verify the pin is still valid.from await client.get_panel_status( control_panel_id=self._reauth_panelid, pin=panel_pin) # If it is, proceed with configuration update. self.hass.config_entries.async_update_entry( entry, data={ CONF_ELMAX_PANEL_ID: self._reauth_panelid, CONF_ELMAX_PANEL_PIN: panel_pin, CONF_ELMAX_USERNAME: self._reauth_username, CONF_ELMAX_PASSWORD: password, }, ) await self.hass.config_entries.async_reload(entry.entry_id) self._reauth_username = None self._reauth_panelid = None return self.async_abort(reason="reauth_successful") except ElmaxBadLoginError: _LOGGER.error( "Wrong credentials or failed login while re-authenticating" ) errors["base"] = "bad_auth" except NoOnlinePanelsError: _LOGGER.warning( "Panel ID %s is no longer associated to this user", self._reauth_panelid, ) errors["base"] = "reauth_panel_disappeared" except ElmaxBadPinError: errors["base"] = "invalid_pin" # We want the user to re-authenticate only for the given panel id using the same login. # We pin them to the UI, so the user realizes she must log in with the appropriate credentials # for the that specific panel. schema = vol.Schema({ vol.Required(CONF_ELMAX_USERNAME): self._reauth_username, vol.Required(CONF_ELMAX_PASSWORD): str, vol.Required(CONF_ELMAX_PANEL_ID): self._reauth_panelid, vol.Required(CONF_ELMAX_PANEL_PIN): str, }) return self.async_show_form(step_id="reauth_confirm", data_schema=schema, errors=errors)