async def async_step_user(self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Handle the initial step.""" errors: dict[str, str] = {} if user_input is not None: verisure = Verisure(username=user_input[CONF_EMAIL], password=user_input[CONF_PASSWORD]) try: await self.hass.async_add_executor_job(verisure.login) except VerisureLoginError as ex: LOGGER.debug("Could not log in to Verisure, %s", ex) errors["base"] = "invalid_auth" except (VerisureError, VerisureResponseError) as ex: LOGGER.debug("Unexpected response from Verisure, %s", ex) errors["base"] = "unknown" else: self.email = user_input[CONF_EMAIL] self.password = user_input[CONF_PASSWORD] self.installations = { inst["giid"]: f"{inst['alias']} ({inst['street']})" for inst in verisure.installations } return await self.async_step_installation() return self.async_show_form( step_id="user", data_schema=vol.Schema({ vol.Required(CONF_EMAIL): str, vol.Required(CONF_PASSWORD): str, }), errors=errors, )
async def async_step_user(self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Handle the initial step.""" errors: dict[str, str] = {} if user_input is not None: self.email = user_input[CONF_EMAIL] self.password = user_input[CONF_PASSWORD] self.verisure = Verisure( username=self.email, password=self.password, cookieFileName=self.hass.config.path( STORAGE_DIR, f"verisure_{user_input[CONF_EMAIL]}"), ) try: await self.hass.async_add_executor_job(self.verisure.login) except VerisureLoginError as ex: if "Multifactor authentication enabled" in str(ex): try: await self.hass.async_add_executor_job( self.verisure.login_mfa) except ( VerisureLoginError, VerisureError, VerisureResponseError, ) as mfa_ex: LOGGER.debug( "Unexpected response from Verisure during MFA set up, %s", mfa_ex, ) errors["base"] = "unknown_mfa" else: return await self.async_step_mfa() else: LOGGER.debug("Could not log in to Verisure, %s", ex) errors["base"] = "invalid_auth" except (VerisureError, VerisureResponseError) as ex: LOGGER.debug("Unexpected response from Verisure, %s", ex) errors["base"] = "unknown" else: return await self.async_step_installation() return self.async_show_form( step_id="user", data_schema=vol.Schema({ vol.Required(CONF_EMAIL): str, vol.Required(CONF_PASSWORD): str, }), errors=errors, )
def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None: """Initialize the Verisure hub.""" self.imageseries = {} self.entry = entry self.verisure = Verisure( username=entry.data[CONF_EMAIL], password=entry.data[CONF_PASSWORD], cookieFileName=hass.config.path(STORAGE_DIR, f"verisure_{entry.entry_id}"), ) super().__init__(hass, LOGGER, name=DOMAIN, update_interval=DEFAULT_SCAN_INTERVAL)
async def async_step_reauth_confirm( self, user_input: dict[str, Any] | None = None ) -> dict[str, Any]: """Handle re-authentication with Verisure.""" errors: dict[str, str] = {} if user_input is not None: verisure = Verisure( username=user_input[CONF_EMAIL], password=user_input[CONF_PASSWORD] ) try: await self.hass.async_add_executor_job(verisure.login) except VerisureLoginError as ex: LOGGER.debug("Could not log in to Verisure, %s", ex) errors["base"] = "invalid_auth" except (VerisureError, VerisureResponseError) as ex: LOGGER.debug("Unexpected response from Verisure, %s", ex) errors["base"] = "unknown" else: data = self.entry.data.copy() self.hass.config_entries.async_update_entry( self.entry, data={ **data, CONF_EMAIL: user_input[CONF_EMAIL], CONF_PASSWORD: user_input[CONF_PASSWORD], }, ) self.hass.async_create_task( self.hass.config_entries.async_reload(self.entry.entry_id) ) return self.async_abort(reason="reauth_successful") return self.async_show_form( step_id="reauth_confirm", data_schema=vol.Schema( { vol.Required(CONF_EMAIL, default=self.entry.data[CONF_EMAIL]): str, vol.Required(CONF_PASSWORD): str, } ), errors=errors, )
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the Verisure integration.""" verisure = Verisure(config[DOMAIN][CONF_USERNAME], config[DOMAIN][CONF_PASSWORD]) coordinator = VerisureDataUpdateCoordinator(hass, session=verisure, domain_config=config[DOMAIN]) if not await hass.async_add_executor_job(coordinator.login): LOGGER.error("Login failed") return False hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, lambda event: coordinator.logout()) await coordinator.async_refresh() if not coordinator.last_update_success: LOGGER.error("Update failed") return False hass.data[DOMAIN] = coordinator for platform in PLATFORMS: hass.async_create_task( discovery.async_load_platform(hass, platform, DOMAIN, {}, config)) async def capture_smartcam(service): """Capture a new picture from a smartcam.""" device_id = service.data[ATTR_DEVICE_SERIAL] try: await hass.async_add_executor_job(coordinator.smartcam_capture, device_id) LOGGER.debug("Capturing new image from %s", ATTR_DEVICE_SERIAL) except VerisureError as ex: LOGGER.error("Could not capture image, %s", ex) hass.services.async_register(DOMAIN, SERVICE_CAPTURE_SMARTCAM, capture_smartcam, schema=DEVICE_SERIAL_SCHEMA) async def disable_autolock(service): """Disable autolock on a doorlock.""" device_id = service.data[ATTR_DEVICE_SERIAL] try: await hass.async_add_executor_job(coordinator.disable_autolock, device_id) LOGGER.debug("Disabling autolock on%s", ATTR_DEVICE_SERIAL) except VerisureError as ex: LOGGER.error("Could not disable autolock, %s", ex) hass.services.async_register(DOMAIN, SERVICE_DISABLE_AUTOLOCK, disable_autolock, schema=DEVICE_SERIAL_SCHEMA) async def enable_autolock(service): """Enable autolock on a doorlock.""" device_id = service.data[ATTR_DEVICE_SERIAL] try: await hass.async_add_executor_job(coordinator.enable_autolock, device_id) LOGGER.debug("Enabling autolock on %s", ATTR_DEVICE_SERIAL) except VerisureError as ex: LOGGER.error("Could not enable autolock, %s", ex) hass.services.async_register(DOMAIN, SERVICE_ENABLE_AUTOLOCK, enable_autolock, schema=DEVICE_SERIAL_SCHEMA) return True
async def async_step_reauth_confirm(self, user_input: dict[str, Any] | None = None) -> FlowResult: """Handle re-authentication with Verisure.""" errors: dict[str, str] = {} if user_input is not None: self.email = user_input[CONF_EMAIL] self.password = user_input[CONF_PASSWORD] self.verisure = Verisure( username=self.email, password=self.password, cookieFileName=self.hass.config.path( STORAGE_DIR, f"verisure-{user_input[CONF_EMAIL]}"), ) try: await self.hass.async_add_executor_job(self.verisure.login) except VerisureLoginError as ex: if "Multifactor authentication enabled" in str(ex): try: await self.hass.async_add_executor_job( self.verisure.login_mfa) except ( VerisureLoginError, VerisureError, VerisureResponseError, ) as mfa_ex: LOGGER.debug( "Unexpected response from Verisure during MFA set up, %s", mfa_ex, ) errors["base"] = "unknown_mfa" else: return await self.async_step_reauth_mfa() else: LOGGER.debug("Could not log in to Verisure, %s", ex) errors["base"] = "invalid_auth" except (VerisureError, VerisureResponseError) as ex: LOGGER.debug("Unexpected response from Verisure, %s", ex) errors["base"] = "unknown" else: data = self.entry.data.copy() self.hass.config_entries.async_update_entry( self.entry, data={ **data, CONF_EMAIL: user_input[CONF_EMAIL], CONF_PASSWORD: user_input[CONF_PASSWORD], }, ) self.hass.async_create_task( self.hass.config_entries.async_reload(self.entry.entry_id)) return self.async_abort(reason="reauth_successful") return self.async_show_form( step_id="reauth_confirm", data_schema=vol.Schema({ vol.Required(CONF_EMAIL, default=self.entry.data[CONF_EMAIL]): str, vol.Required(CONF_PASSWORD): str, }), errors=errors, )