"""Support for Blink Home Camera System.""" from copy import deepcopy import logging from typing import Any from blinkpy.auth import Auth from blinkpy.blinkpy import Blink from homeassistant.components import persistent_notification from homeassistant.const import CONF_SCAN_INTERVAL from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import config_validation as cv from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.typing import ConfigType from .const import DEFAULT_SCAN_INTERVAL, DOMAIN, PLATFORMS from .coordinator import BlinkConfigEntry, BlinkUpdateCoordinator from .services import async_setup_services _LOGGER = logging.getLogger(__name__) CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) async def _reauth_flow_wrapper( hass: HomeAssistant, entry: BlinkConfigEntry, data: dict[str, Any] ) -> None: """Reauth flow wrapper.""" entry.async_start_reauth(hass, data=data) persistent_notification.async_create( hass, ( "Blink configuration migrated to a new version. Please go to the" " integrations page to re-configure (such as sending a new 2FA key)." ), "Blink Migration", ) async def async_migrate_entry(hass: HomeAssistant, entry: BlinkConfigEntry) -> bool: """Handle migration of a previous version config entry.""" _LOGGER.debug("Migrating from version %s", entry.version) data = {**entry.data} if entry.version == 1: data.pop("login_response", None) await _reauth_flow_wrapper(hass, entry, data) return False if entry.version == 2: await _reauth_flow_wrapper(hass, entry, data) return False if entry.version == 3: # Migrate device_id to hardware_id for blinkpy 0.25.x OAuth2 compatibility if "device_id" in data: data["hardware_id"] = data.pop("device_id") hass.config_entries.async_update_entry(entry, data=data, version=4) return True return True async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up Blink.""" async_setup_services(hass) return True async def async_setup_entry(hass: HomeAssistant, entry: BlinkConfigEntry) -> bool: """Set up Blink via config entry.""" _async_import_options_from_data_if_missing(hass, entry) session = async_get_clientsession(hass) blink = Blink(session=session) auth_data = deepcopy(dict(entry.data)) blink.auth = Auth( auth_data, no_prompt=True, session=session, callback=lambda: _async_update_entry_data(hass, entry, blink), ) blink.refresh_rate = entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) coordinator = BlinkUpdateCoordinator(hass, entry, blink) await coordinator.async_config_entry_first_refresh() entry.runtime_data = coordinator await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) return True @callback def _async_update_entry_data( hass: HomeAssistant, entry: BlinkConfigEntry, blink: Blink ) -> None: """Update the config entry data after token refresh.""" hass.config_entries.async_update_entry(entry, data=blink.auth.login_attributes) @callback def _async_import_options_from_data_if_missing( hass: HomeAssistant, entry: BlinkConfigEntry ) -> None: options = dict(entry.options) if CONF_SCAN_INTERVAL not in entry.options: options[CONF_SCAN_INTERVAL] = entry.data.get( CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL ) hass.config_entries.async_update_entry(entry, options=options) async def async_unload_entry(hass: HomeAssistant, entry: BlinkConfigEntry) -> bool: """Unload Blink entry.""" return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)