Use runtime_data in foscam (#137646)

This commit is contained in:
epenet 2025-02-07 10:06:44 +01:00 committed by GitHub
parent 27cb88db1a
commit 5b8ef05bc2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 29 additions and 46 deletions

View File

@ -2,7 +2,6 @@
from libpyfoscam import FoscamCamera from libpyfoscam import FoscamCamera
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
CONF_HOST, CONF_HOST,
CONF_PASSWORD, CONF_PASSWORD,
@ -14,13 +13,13 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_registry import RegistryEntry, async_migrate_entries from homeassistant.helpers.entity_registry import RegistryEntry, async_migrate_entries
from .config_flow import DEFAULT_RTSP_PORT from .config_flow import DEFAULT_RTSP_PORT
from .const import CONF_RTSP_PORT, DOMAIN, LOGGER, SERVICE_PTZ, SERVICE_PTZ_PRESET from .const import CONF_RTSP_PORT, LOGGER
from .coordinator import FoscamCoordinator from .coordinator import FoscamConfigEntry, FoscamCoordinator
PLATFORMS = [Platform.CAMERA, Platform.SWITCH] PLATFORMS = [Platform.CAMERA, Platform.SWITCH]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: FoscamConfigEntry) -> bool:
"""Set up foscam from a config entry.""" """Set up foscam from a config entry."""
session = FoscamCamera( session = FoscamCamera(
@ -30,11 +29,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
entry.data[CONF_PASSWORD], entry.data[CONF_PASSWORD],
verbose=False, verbose=False,
) )
coordinator = FoscamCoordinator(hass, session) coordinator = FoscamCoordinator(hass, entry, session)
await coordinator.async_config_entry_first_refresh() await coordinator.async_config_entry_first_refresh()
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator entry.runtime_data = coordinator
# Migrate to correct unique IDs for switches # Migrate to correct unique IDs for switches
await async_migrate_entities(hass, entry) await async_migrate_entities(hass, entry)
@ -44,20 +43,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: FoscamConfigEntry) -> bool:
"""Unload a config entry.""" """Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)
if not hass.data[DOMAIN]:
hass.services.async_remove(domain=DOMAIN, service=SERVICE_PTZ)
hass.services.async_remove(domain=DOMAIN, service=SERVICE_PTZ_PRESET)
return unload_ok
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_migrate_entry(hass: HomeAssistant, entry: FoscamConfigEntry) -> bool:
"""Migrate old entry.""" """Migrate old entry."""
LOGGER.debug("Migrating from version %s", entry.version) LOGGER.debug("Migrating from version %s", entry.version)
@ -97,7 +88,7 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True return True
async def async_migrate_entities(hass: HomeAssistant, entry: ConfigEntry) -> None: async def async_migrate_entities(hass: HomeAssistant, entry: FoscamConfigEntry) -> None:
"""Migrate old entry.""" """Migrate old entry."""
@callback @callback

View File

@ -7,21 +7,13 @@ import asyncio
import voluptuous as vol import voluptuous as vol
from homeassistant.components.camera import Camera, CameraEntityFeature from homeassistant.components.camera import Camera, CameraEntityFeature
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv, entity_platform from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import ( from .const import CONF_RTSP_PORT, CONF_STREAM, LOGGER, SERVICE_PTZ, SERVICE_PTZ_PRESET
CONF_RTSP_PORT, from .coordinator import FoscamConfigEntry, FoscamCoordinator
CONF_STREAM,
DOMAIN,
LOGGER,
SERVICE_PTZ,
SERVICE_PTZ_PRESET,
)
from .coordinator import FoscamCoordinator
from .entity import FoscamEntity from .entity import FoscamEntity
DIR_UP = "up" DIR_UP = "up"
@ -56,7 +48,7 @@ PTZ_GOTO_PRESET_COMMAND = "ptz_goto_preset"
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: FoscamConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Add a Foscam IP camera from a config entry.""" """Add a Foscam IP camera from a config entry."""
@ -89,7 +81,7 @@ async def async_setup_entry(
"async_perform_ptz_preset", "async_perform_ptz_preset",
) )
coordinator: FoscamCoordinator = hass.data[DOMAIN][config_entry.entry_id] coordinator = config_entry.runtime_data
async_add_entities([HassFoscamCamera(coordinator, config_entry)]) async_add_entities([HassFoscamCamera(coordinator, config_entry)])
@ -103,7 +95,7 @@ class HassFoscamCamera(FoscamEntity, Camera):
def __init__( def __init__(
self, self,
coordinator: FoscamCoordinator, coordinator: FoscamCoordinator,
config_entry: ConfigEntry, config_entry: FoscamConfigEntry,
) -> None: ) -> None:
"""Initialize a Foscam camera.""" """Initialize a Foscam camera."""
super().__init__(coordinator, config_entry.entry_id) super().__init__(coordinator, config_entry.entry_id)

View File

@ -6,11 +6,14 @@ from typing import Any
from libpyfoscam import FoscamCamera from libpyfoscam import FoscamCamera
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
from .const import DOMAIN, LOGGER from .const import DOMAIN, LOGGER
type FoscamConfigEntry = ConfigEntry[FoscamCoordinator]
class FoscamCoordinator(DataUpdateCoordinator[dict[str, Any]]): class FoscamCoordinator(DataUpdateCoordinator[dict[str, Any]]):
"""Foscam coordinator.""" """Foscam coordinator."""
@ -18,12 +21,14 @@ class FoscamCoordinator(DataUpdateCoordinator[dict[str, Any]]):
def __init__( def __init__(
self, self,
hass: HomeAssistant, hass: HomeAssistant,
entry: FoscamConfigEntry,
session: FoscamCamera, session: FoscamCamera,
) -> None: ) -> None:
"""Initialize my coordinator.""" """Initialize my coordinator."""
super().__init__( super().__init__(
hass, hass,
LOGGER, LOGGER,
config_entry=entry,
name=DOMAIN, name=DOMAIN,
update_interval=timedelta(seconds=30), update_interval=timedelta(seconds=30),
) )

View File

@ -5,24 +5,23 @@ from __future__ import annotations
from typing import Any from typing import Any
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import FoscamCoordinator from .const import LOGGER
from .const import DOMAIN, LOGGER from .coordinator import FoscamConfigEntry, FoscamCoordinator
from .entity import FoscamEntity from .entity import FoscamEntity
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: FoscamConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up foscam switch from a config entry.""" """Set up foscam switch from a config entry."""
coordinator: FoscamCoordinator = hass.data[DOMAIN][config_entry.entry_id] coordinator = config_entry.runtime_data
await coordinator.async_config_entry_first_refresh() await coordinator.async_config_entry_first_refresh()
@ -36,7 +35,7 @@ class FoscamSleepSwitch(FoscamEntity, SwitchEntity):
def __init__( def __init__(
self, self,
coordinator: FoscamCoordinator, coordinator: FoscamCoordinator,
config_entry: ConfigEntry, config_entry: FoscamConfigEntry,
) -> None: ) -> None:
"""Initialize a Foscam Sleep Switch.""" """Initialize a Foscam Sleep Switch."""
super().__init__(coordinator, config_entry.entry_id) super().__init__(coordinator, config_entry.entry_id)

View File

@ -2,7 +2,7 @@
from unittest.mock import patch from unittest.mock import patch
from homeassistant.components.foscam import DOMAIN, config_flow from homeassistant.components.foscam.const import DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
@ -18,9 +18,7 @@ async def test_unique_id_new_entry(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test unique ID for a newly added device is correct.""" """Test unique ID for a newly added device is correct."""
entry = MockConfigEntry( entry = MockConfigEntry(domain=DOMAIN, data=VALID_CONFIG, entry_id=ENTRY_ID)
domain=config_flow.DOMAIN, data=VALID_CONFIG, entry_id=ENTRY_ID
)
entry.add_to_hass(hass) entry.add_to_hass(hass)
with ( with (
@ -46,7 +44,7 @@ async def test_switch_unique_id_migration_ok(
) -> None: ) -> None:
"""Test that the unique ID for a sleep switch is migrated to the new format.""" """Test that the unique ID for a sleep switch is migrated to the new format."""
entry = MockConfigEntry( entry = MockConfigEntry(
domain=config_flow.DOMAIN, data=VALID_CONFIG, entry_id=ENTRY_ID, version=1 domain=DOMAIN, data=VALID_CONFIG, entry_id=ENTRY_ID, version=1
) )
entry.add_to_hass(hass) entry.add_to_hass(hass)
@ -57,7 +55,7 @@ async def test_switch_unique_id_migration_ok(
# Update config entry with version 2 # Update config entry with version 2
entry = MockConfigEntry( entry = MockConfigEntry(
domain=config_flow.DOMAIN, data=VALID_CONFIG, entry_id=ENTRY_ID, version=2 domain=DOMAIN, data=VALID_CONFIG, entry_id=ENTRY_ID, version=2
) )
entry.add_to_hass(hass) entry.add_to_hass(hass)
@ -84,9 +82,7 @@ async def test_unique_id_migration_not_needed(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test that the unique ID for a sleep switch is not executed if already in right format.""" """Test that the unique ID for a sleep switch is not executed if already in right format."""
entry = MockConfigEntry( entry = MockConfigEntry(domain=DOMAIN, data=VALID_CONFIG, entry_id=ENTRY_ID)
domain=config_flow.DOMAIN, data=VALID_CONFIG, entry_id=ENTRY_ID
)
entry.add_to_hass(hass) entry.add_to_hass(hass)
entity_registry.async_get_or_create( entity_registry.async_get_or_create(