diff --git a/homeassistant/components/tile/__init__.py b/homeassistant/components/tile/__init__.py index f9a08b65067..72aed11b4fe 100644 --- a/homeassistant/components/tile/__init__.py +++ b/homeassistant/components/tile/__init__.py @@ -3,11 +3,9 @@ from __future__ import annotations from dataclasses import dataclass -from datetime import timedelta -from functools import partial from pytile import async_login -from pytile.errors import InvalidAuthError, SessionExpiredError, TileError +from pytile.errors import InvalidAuthError, TileError from pytile.tile import Tile from homeassistant.config_entries import ConfigEntry @@ -15,16 +13,15 @@ from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers import aiohttp_client -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.util.async_ import gather_with_limited_concurrency -from .const import DOMAIN, LOGGER +from .const import DOMAIN +from .coordinator import TileCoordinator PLATFORMS = [Platform.DEVICE_TRACKER] DEVICE_TYPES = ["PHONE", "TILE"] DEFAULT_INIT_TASK_LIMIT = 2 -DEFAULT_UPDATE_INTERVAL = timedelta(minutes=2) CONF_SHOW_INACTIVE = "show_inactive" @@ -33,7 +30,7 @@ CONF_SHOW_INACTIVE = "show_inactive" class TileData: """Define an object to be stored in `hass.data`.""" - coordinators: dict[str, DataUpdateCoordinator[None]] + coordinators: dict[str, TileCoordinator] tiles: dict[str, Tile] @@ -56,30 +53,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: except TileError as err: raise ConfigEntryNotReady("Error during integration setup") from err - async def async_update_tile(tile: Tile) -> None: - """Update the Tile.""" - try: - await tile.async_update() - except InvalidAuthError as err: - raise ConfigEntryAuthFailed("Invalid credentials") from err - except SessionExpiredError: - LOGGER.debug("Tile session expired; creating a new one") - await client.async_init() - except TileError as err: - raise UpdateFailed(f"Error while retrieving data: {err}") from err - - coordinators: dict[str, DataUpdateCoordinator[None]] = {} + coordinators: dict[str, TileCoordinator] = {} coordinator_init_tasks = [] for tile_uuid, tile in tiles.items(): - coordinator = coordinators[tile_uuid] = DataUpdateCoordinator( - hass, - LOGGER, - config_entry=entry, - name=tile.name, - update_interval=DEFAULT_UPDATE_INTERVAL, - update_method=partial(async_update_tile, tile), - ) + coordinator = coordinators[tile_uuid] = TileCoordinator(hass, client, tile) coordinator_init_tasks.append(coordinator.async_refresh()) await gather_with_limited_concurrency( diff --git a/homeassistant/components/tile/coordinator.py b/homeassistant/components/tile/coordinator.py new file mode 100644 index 00000000000..e9565210a3e --- /dev/null +++ b/homeassistant/components/tile/coordinator.py @@ -0,0 +1,40 @@ +"""Update coordinator for Tile.""" + +from datetime import timedelta + +from pytile.api import API +from pytile.errors import InvalidAuthError, SessionExpiredError, TileError +from pytile.tile import Tile + +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryAuthFailed +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed + +from .const import LOGGER + + +class TileCoordinator(DataUpdateCoordinator[None]): + """Define an object to coordinate Tile data retrieval.""" + + def __init__(self, hass: HomeAssistant, client: API, tile: Tile) -> None: + """Initialize.""" + super().__init__( + hass, + LOGGER, + name=tile.name, + update_interval=timedelta(minutes=2), + ) + self.tile = tile + self.client = client + + async def _async_update_data(self) -> None: + """Update data via library.""" + try: + await self.tile.async_update() + except InvalidAuthError as err: + raise ConfigEntryAuthFailed("Invalid credentials") from err + except SessionExpiredError: + LOGGER.debug("Tile session expired; creating a new one") + await self.client.async_init() + except TileError as err: + raise UpdateFailed(f"Error while retrieving data: {err}") from err diff --git a/homeassistant/components/tile/device_tracker.py b/homeassistant/components/tile/device_tracker.py index 71abbbef2c7..150bad3d843 100644 --- a/homeassistant/components/tile/device_tracker.py +++ b/homeassistant/components/tile/device_tracker.py @@ -4,8 +4,6 @@ from __future__ import annotations import logging -from pytile.tile import Tile - from homeassistant.components.device_tracker import AsyncSeeCallback, TrackerEntity from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME @@ -13,13 +11,10 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType -from homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, -) +from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.util.dt import as_utc -from . import TileData +from . import TileCoordinator, TileData from .const import DOMAIN _LOGGER = logging.getLogger(__name__) @@ -43,7 +38,7 @@ async def async_setup_entry( async_add_entities( [ - TileDeviceTracker(entry, data.coordinators[tile_uuid], tile) + TileDeviceTracker(entry, data.coordinators[tile_uuid]) for tile_uuid, tile in data.tiles.items() ] ) @@ -75,23 +70,21 @@ async def async_setup_scanner( return True -class TileDeviceTracker(CoordinatorEntity[DataUpdateCoordinator[None]], TrackerEntity): +class TileDeviceTracker(CoordinatorEntity[TileCoordinator], TrackerEntity): """Representation of a network infrastructure device.""" _attr_has_entity_name = True _attr_name = None _attr_translation_key = "tile" - def __init__( - self, entry: ConfigEntry, coordinator: DataUpdateCoordinator[None], tile: Tile - ) -> None: + def __init__(self, entry: ConfigEntry, coordinator: TileCoordinator) -> None: """Initialize.""" super().__init__(coordinator) self._attr_extra_state_attributes = {} - self._attr_unique_id = f"{entry.data[CONF_USERNAME]}_{tile.uuid}" + self._tile = coordinator.tile + self._attr_unique_id = f"{entry.data[CONF_USERNAME]}_{self._tile.uuid}" self._entry = entry - self._tile = tile @property def available(self) -> bool: