2022-10-26 19:34:44 +00:00
|
|
|
"""UPnP/IGD coordinator."""
|
|
|
|
|
2024-06-29 17:11:22 +00:00
|
|
|
from collections import defaultdict
|
|
|
|
from collections.abc import Callable
|
2023-03-20 14:44:05 +00:00
|
|
|
from datetime import datetime, timedelta
|
2022-10-26 19:34:44 +00:00
|
|
|
|
|
|
|
from async_upnp_client.exceptions import UpnpCommunicationError
|
|
|
|
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from homeassistant.helpers.device_registry import DeviceEntry
|
|
|
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
|
|
|
|
|
|
|
from .const import LOGGER
|
|
|
|
from .device import Device
|
|
|
|
|
|
|
|
|
2023-03-20 14:44:05 +00:00
|
|
|
class UpnpDataUpdateCoordinator(
|
|
|
|
DataUpdateCoordinator[dict[str, str | datetime | int | float | None]]
|
|
|
|
):
|
2022-10-26 19:34:44 +00:00
|
|
|
"""Define an object to update data from UPNP device."""
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
hass: HomeAssistant,
|
|
|
|
device: Device,
|
|
|
|
device_entry: DeviceEntry,
|
|
|
|
update_interval: timedelta,
|
|
|
|
) -> None:
|
|
|
|
"""Initialize."""
|
|
|
|
self.device = device
|
|
|
|
self.device_entry = device_entry
|
2024-06-29 17:11:22 +00:00
|
|
|
self._features_by_entity_id: defaultdict[str, set[str]] = defaultdict(set)
|
2022-10-26 19:34:44 +00:00
|
|
|
|
|
|
|
super().__init__(
|
|
|
|
hass,
|
|
|
|
LOGGER,
|
|
|
|
name=device.name,
|
|
|
|
update_interval=update_interval,
|
|
|
|
)
|
|
|
|
|
2024-06-29 17:11:22 +00:00
|
|
|
def register_entity(self, key: str, entity_id: str) -> Callable[[], None]:
|
|
|
|
"""Register an entity."""
|
|
|
|
# self._entities.append(entity)
|
|
|
|
self._features_by_entity_id[key].add(entity_id)
|
|
|
|
|
|
|
|
def unregister_entity() -> None:
|
|
|
|
"""Unregister entity."""
|
|
|
|
self._features_by_entity_id[key].remove(entity_id)
|
|
|
|
|
|
|
|
if not self._features_by_entity_id[key]:
|
|
|
|
del self._features_by_entity_id[key]
|
|
|
|
|
|
|
|
return unregister_entity
|
|
|
|
|
|
|
|
@property
|
|
|
|
def _entity_description_keys(self) -> list[str] | None:
|
|
|
|
"""Return a list of entity description keys for which data is required."""
|
|
|
|
if not self._features_by_entity_id:
|
|
|
|
# Must be the first update, no entities attached/enabled yet.
|
|
|
|
return None
|
|
|
|
|
|
|
|
return list(self._features_by_entity_id.keys())
|
|
|
|
|
2023-03-20 14:44:05 +00:00
|
|
|
async def _async_update_data(
|
|
|
|
self,
|
|
|
|
) -> dict[str, str | datetime | int | float | None]:
|
2022-10-26 19:34:44 +00:00
|
|
|
"""Update data."""
|
|
|
|
try:
|
2024-06-29 17:11:22 +00:00
|
|
|
return await self.device.async_get_data(self._entity_description_keys)
|
2022-10-26 19:34:44 +00:00
|
|
|
except UpnpCommunicationError as exception:
|
|
|
|
LOGGER.debug(
|
|
|
|
"Caught exception when updating device: %s, exception: %s",
|
|
|
|
self.device,
|
|
|
|
exception,
|
|
|
|
)
|
|
|
|
raise UpdateFailed(
|
|
|
|
f"Unable to communicate with IGD at: {self.device.device_url}"
|
|
|
|
) from exception
|