Use runtime_data in blink (#129072)

This commit is contained in:
epenet 2024-10-24 14:32:48 +02:00 committed by GitHub
parent add8db0186
commit bf7d292884
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 45 additions and 43 deletions

View File

@ -2,6 +2,7 @@
from copy import deepcopy from copy import deepcopy
import logging import logging
from typing import Any
from aiohttp import ClientError from aiohttp import ClientError
from blinkpy.auth import Auth from blinkpy.auth import Auth
@ -9,7 +10,7 @@ from blinkpy.blinkpy import Blink
import voluptuous as vol import voluptuous as vol
from homeassistant.components import persistent_notification from homeassistant.components import persistent_notification
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntry from homeassistant.config_entries import SOURCE_REAUTH
from homeassistant.const import ( from homeassistant.const import (
CONF_FILE_PATH, CONF_FILE_PATH,
CONF_FILENAME, CONF_FILENAME,
@ -24,7 +25,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from .const import DEFAULT_SCAN_INTERVAL, DOMAIN, PLATFORMS from .const import DEFAULT_SCAN_INTERVAL, DOMAIN, PLATFORMS
from .coordinator import BlinkUpdateCoordinator from .coordinator import BlinkConfigEntry, BlinkUpdateCoordinator
from .services import setup_services from .services import setup_services
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -40,7 +41,7 @@ SERVICE_SAVE_RECENT_CLIPS_SCHEMA = vol.Schema(
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
async def _reauth_flow_wrapper(hass, data): async def _reauth_flow_wrapper(hass: HomeAssistant, data: dict[str, Any]) -> None:
"""Reauth flow wrapper.""" """Reauth flow wrapper."""
hass.add_job( hass.add_job(
hass.config_entries.flow.async_init( hass.config_entries.flow.async_init(
@ -57,7 +58,7 @@ async def _reauth_flow_wrapper(hass, data):
) )
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_migrate_entry(hass: HomeAssistant, entry: BlinkConfigEntry) -> bool:
"""Handle migration of a previous version config entry.""" """Handle migration of a previous version config entry."""
_LOGGER.debug("Migrating from version %s", entry.version) _LOGGER.debug("Migrating from version %s", entry.version)
data = {**entry.data} data = {**entry.data}
@ -79,10 +80,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
return True return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: BlinkConfigEntry) -> bool:
"""Set up Blink via config entry.""" """Set up Blink via config entry."""
hass.data.setdefault(DOMAIN, {})
_async_import_options_from_data_if_missing(hass, entry) _async_import_options_from_data_if_missing(hass, entry)
session = async_get_clientsession(hass) session = async_get_clientsession(hass)
blink = Blink(session=session) blink = Blink(session=session)
@ -104,7 +103,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
raise ConfigEntryNotReady raise ConfigEntryNotReady
await coordinator.async_config_entry_first_refresh() await coordinator.async_config_entry_first_refresh()
hass.data[DOMAIN][entry.entry_id] = coordinator
entry.runtime_data = coordinator
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
@ -113,7 +113,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
@callback @callback
def _async_import_options_from_data_if_missing( def _async_import_options_from_data_if_missing(
hass: HomeAssistant, entry: ConfigEntry hass: HomeAssistant, entry: BlinkConfigEntry
) -> None: ) -> None:
options = dict(entry.options) options = dict(entry.options)
if CONF_SCAN_INTERVAL not in entry.options: if CONF_SCAN_INTERVAL not in entry.options:
@ -123,8 +123,6 @@ def _async_import_options_from_data_if_missing(
hass.config_entries.async_update_entry(entry, options=options) hass.config_entries.async_update_entry(entry, options=options)
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: BlinkConfigEntry) -> bool:
"""Unload Blink entry.""" """Unload Blink entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok

View File

@ -11,7 +11,6 @@ from homeassistant.components.alarm_control_panel import (
AlarmControlPanelEntityFeature, AlarmControlPanelEntityFeature,
AlarmControlPanelState, AlarmControlPanelState,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ATTRIBUTION from homeassistant.const import ATTR_ATTRIBUTION
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
@ -20,16 +19,18 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DEFAULT_ATTRIBUTION, DEFAULT_BRAND, DOMAIN from .const import DEFAULT_ATTRIBUTION, DEFAULT_BRAND, DOMAIN
from .coordinator import BlinkUpdateCoordinator from .coordinator import BlinkConfigEntry, BlinkUpdateCoordinator
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, config: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
config_entry: BlinkConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the Blink Alarm Control Panels.""" """Set up the Blink Alarm Control Panels."""
coordinator: BlinkUpdateCoordinator = hass.data[DOMAIN][config.entry_id] coordinator = config_entry.runtime_data
sync_modules = [] sync_modules = []
for sync_name, sync_module in coordinator.api.sync.items(): for sync_name, sync_module in coordinator.api.sync.items():

View File

@ -9,7 +9,6 @@ from homeassistant.components.binary_sensor import (
BinarySensorEntity, BinarySensorEntity,
BinarySensorEntityDescription, BinarySensorEntityDescription,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
@ -23,7 +22,7 @@ from .const import (
TYPE_CAMERA_ARMED, TYPE_CAMERA_ARMED,
TYPE_MOTION_DETECTED, TYPE_MOTION_DETECTED,
) )
from .coordinator import BlinkUpdateCoordinator from .coordinator import BlinkConfigEntry, BlinkUpdateCoordinator
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -47,11 +46,13 @@ BINARY_SENSORS_TYPES: tuple[BinarySensorEntityDescription, ...] = (
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, config: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
config_entry: BlinkConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the blink binary sensors.""" """Set up the blink binary sensors."""
coordinator: BlinkUpdateCoordinator = hass.data[DOMAIN][config.entry_id] coordinator = config_entry.runtime_data
entities = [ entities = [
BlinkBinarySensor(coordinator, camera, description) BlinkBinarySensor(coordinator, camera, description)

View File

@ -10,7 +10,6 @@ from requests.exceptions import ChunkedEncodingError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.camera import Camera from homeassistant.components.camera import Camera
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_FILE_PATH, CONF_FILENAME from homeassistant.const import CONF_FILE_PATH, CONF_FILENAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
@ -28,7 +27,7 @@ from .const import (
SERVICE_SAVE_VIDEO, SERVICE_SAVE_VIDEO,
SERVICE_TRIGGER, SERVICE_TRIGGER,
) )
from .coordinator import BlinkUpdateCoordinator from .coordinator import BlinkConfigEntry, BlinkUpdateCoordinator
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -38,11 +37,13 @@ PARALLEL_UPDATES = 1
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, config: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
config_entry: BlinkConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up a Blink Camera.""" """Set up a Blink Camera."""
coordinator: BlinkUpdateCoordinator = hass.data[DOMAIN][config.entry_id] coordinator = config_entry.runtime_data
entities = [ entities = [
BlinkCamera(coordinator, name, camera) BlinkCamera(coordinator, name, camera)
for name, camera in coordinator.api.cameras.items() for name, camera in coordinator.api.cameras.items()

View File

@ -8,6 +8,7 @@ from typing import Any
from blinkpy.blinkpy import Blink from blinkpy.blinkpy import Blink
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
@ -16,6 +17,8 @@ from .const import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = 300 SCAN_INTERVAL = 300
type BlinkConfigEntry = ConfigEntry[BlinkUpdateCoordinator]
class BlinkUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]): class BlinkUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
"""BlinkUpdateCoordinator - In charge of downloading the data for a site.""" """BlinkUpdateCoordinator - In charge of downloading the data for a site."""

View File

@ -4,24 +4,21 @@ from __future__ import annotations
from typing import Any from typing import Any
from blinkpy.blinkpy import Blink
from homeassistant.components.diagnostics import async_redact_data from homeassistant.components.diagnostics import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .const import DOMAIN from .coordinator import BlinkConfigEntry
TO_REDACT = {"serial", "macaddress", "username", "password", "token", "unique_id"} TO_REDACT = {"serial", "macaddress", "username", "password", "token", "unique_id"}
async def async_get_config_entry_diagnostics( async def async_get_config_entry_diagnostics(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: BlinkConfigEntry,
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Return diagnostics for a config entry.""" """Return diagnostics for a config entry."""
api: Blink = hass.data[DOMAIN][config_entry.entry_id].api api = config_entry.runtime_data.api
data = { data = {
camera.name: dict(camera.attributes.items()) camera.name: dict(camera.attributes.items())

View File

@ -10,7 +10,6 @@ from homeassistant.components.sensor import (
SensorEntityDescription, SensorEntityDescription,
SensorStateClass, SensorStateClass,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory, UnitOfTemperature from homeassistant.const import EntityCategory, UnitOfTemperature
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
@ -18,7 +17,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DEFAULT_BRAND, DOMAIN, TYPE_TEMPERATURE, TYPE_WIFI_STRENGTH from .const import DEFAULT_BRAND, DOMAIN, TYPE_TEMPERATURE, TYPE_WIFI_STRENGTH
from .coordinator import BlinkUpdateCoordinator from .coordinator import BlinkConfigEntry, BlinkUpdateCoordinator
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -40,11 +39,13 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, config: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
config_entry: BlinkConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Initialize a Blink sensor.""" """Initialize a Blink sensor."""
coordinator: BlinkUpdateCoordinator = hass.data[DOMAIN][config.entry_id] coordinator = config_entry.runtime_data
entities = [ entities = [
BlinkSensor(coordinator, camera, description) BlinkSensor(coordinator, camera, description)
for camera in coordinator.api.cameras for camera in coordinator.api.cameras

View File

@ -11,6 +11,7 @@ from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from .const import ATTR_CONFIG_ENTRY_ID, DOMAIN, SERVICE_SEND_PIN from .const import ATTR_CONFIG_ENTRY_ID, DOMAIN, SERVICE_SEND_PIN
from .coordinator import BlinkConfigEntry
SERVICE_UPDATE_SCHEMA = vol.Schema( SERVICE_UPDATE_SCHEMA = vol.Schema(
{ {
@ -30,6 +31,7 @@ def setup_services(hass: HomeAssistant) -> None:
async def send_pin(call: ServiceCall): async def send_pin(call: ServiceCall):
"""Call blink to send new pin.""" """Call blink to send new pin."""
config_entry: BlinkConfigEntry | None
for entry_id in call.data[ATTR_CONFIG_ENTRY_ID]: for entry_id in call.data[ATTR_CONFIG_ENTRY_ID]:
if not (config_entry := hass.config_entries.async_get_entry(entry_id)): if not (config_entry := hass.config_entries.async_get_entry(entry_id)):
raise ServiceValidationError( raise ServiceValidationError(
@ -43,7 +45,7 @@ def setup_services(hass: HomeAssistant) -> None:
translation_key="not_loaded", translation_key="not_loaded",
translation_placeholders={"target": config_entry.title}, translation_placeholders={"target": config_entry.title},
) )
coordinator = hass.data[DOMAIN][entry_id] coordinator = config_entry.runtime_data
await coordinator.api.auth.send_auth_key( await coordinator.api.auth.send_auth_key(
coordinator.api, coordinator.api,
call.data[CONF_PIN], call.data[CONF_PIN],

View File

@ -9,7 +9,6 @@ from homeassistant.components.switch import (
SwitchEntity, SwitchEntity,
SwitchEntityDescription, SwitchEntityDescription,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
@ -17,7 +16,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DEFAULT_BRAND, DOMAIN, TYPE_CAMERA_ARMED from .const import DEFAULT_BRAND, DOMAIN, TYPE_CAMERA_ARMED
from .coordinator import BlinkUpdateCoordinator from .coordinator import BlinkConfigEntry, BlinkUpdateCoordinator
SWITCH_TYPES: tuple[SwitchEntityDescription, ...] = ( SWITCH_TYPES: tuple[SwitchEntityDescription, ...] = (
SwitchEntityDescription( SwitchEntityDescription(
@ -30,11 +29,11 @@ SWITCH_TYPES: tuple[SwitchEntityDescription, ...] = (
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config: ConfigEntry, config_entry: BlinkConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the Blink switches.""" """Set up the Blink switches."""
coordinator: BlinkUpdateCoordinator = hass.data[DOMAIN][config.entry_id] coordinator = config_entry.runtime_data
async_add_entities( async_add_entities(
BlinkSwitch(coordinator, camera, description) BlinkSwitch(coordinator, camera, description)

View File

@ -66,18 +66,17 @@ async def test_setup_not_ready_authkey_required(
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR
async def test_unload_entry_multiple( async def test_unload_entry(
hass: HomeAssistant, hass: HomeAssistant,
mock_blink_api: MagicMock, mock_blink_api: MagicMock,
mock_blink_auth_api: MagicMock, mock_blink_auth_api: MagicMock,
mock_config_entry: MockConfigEntry, mock_config_entry: MockConfigEntry,
) -> None: ) -> None:
"""Test being able to unload one of 2 entries.""" """Test unload doesn't un-register services."""
mock_config_entry.add_to_hass(hass) mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id) assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
hass.data[DOMAIN]["dummy"] = {1: 2}
assert mock_config_entry.state is ConfigEntryState.LOADED assert mock_config_entry.state is ConfigEntryState.LOADED
assert await hass.config_entries.async_unload(mock_config_entry.entry_id) assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED assert mock_config_entry.state is ConfigEntryState.NOT_LOADED