1 """Data update coordinator for AVM FRITZ!SmartHome devices."""
3 from __future__
import annotations
5 from dataclasses
import dataclass
6 from datetime
import timedelta
8 from pyfritzhome
import Fritzhome, FritzhomeDevice, LoginError
9 from pyfritzhome.devicetypes
import FritzhomeTemplate
10 from requests.exceptions
import ConnectionError
as RequestConnectionError, HTTPError
19 from .const
import DOMAIN, LOGGER
21 type FritzboxConfigEntry = ConfigEntry[FritzboxDataUpdateCoordinator]
26 """Data Type of FritzboxDataUpdateCoordinator's data."""
28 devices: dict[str, FritzhomeDevice]
29 templates: dict[str, FritzhomeTemplate]
33 """Fritzbox Smarthome device data update coordinator."""
35 config_entry: FritzboxConfigEntry
36 configuration_url: str
40 def __init__(self, hass: HomeAssistant, name: str) ->
None:
41 """Initialize the Fritzbox Smarthome device coordinator."""
55 """Set up the coordinator."""
60 password=self.
config_entryconfig_entry.data[CONF_PASSWORD],
64 await self.
hasshass.async_add_executor_job(self.
fritzfritz.login)
65 except RequestConnectionError
as err:
66 raise ConfigEntryNotReady
from err
67 except LoginError
as err:
68 raise ConfigEntryAuthFailed
from err
71 self.
fritzfritz.has_templates
73 LOGGER.debug(
"enable smarthome templates: %s", self.
has_templateshas_templates)
83 """Cleanup entity and device registry from removed devices."""
84 entity_reg = er.async_get(self.
hasshass)
85 for entity
in er.async_entries_for_config_entry(
88 if entity.unique_id.split(
"_")[0]
not in available_ains:
89 LOGGER.debug(
"Removing obsolete entity entry %s", entity.entity_id)
90 entity_reg.async_remove(entity.entity_id)
92 device_reg = dr.async_get(self.
hasshass)
93 identifiers = {(DOMAIN, ain)
for ain
in available_ains}
94 for device
in dr.async_entries_for_config_entry(
97 if not set(device.identifiers) & identifiers:
98 LOGGER.debug(
"Removing obsolete device entry %s", device.name)
99 device_reg.async_update_device(
100 device.id, remove_config_entry_id=self.
config_entryconfig_entry.entry_id
104 """Update all fritzbox device data."""
108 self.
fritzfritz.update_templates(ignore_removed=
False)
109 except RequestConnectionError
as ex:
110 raise UpdateFailed
from ex
114 self.
fritzfritz.login()
115 except LoginError
as ex:
116 raise ConfigEntryAuthFailed
from ex
119 self.
fritzfritz.update_templates(ignore_removed=
False)
121 devices = self.
fritzfritz.get_devices()
123 for device
in devices:
126 device.has_powermeter
128 and isinstance(device.voltage, int)
129 and device.voltage <= 0
130 and isinstance(device.power, int)
131 and device.power <= 0
132 and device.energy <= 0
134 LOGGER.debug(
"Assume device %s as unavailable", device.name)
135 device.present =
False
137 device_data[device.ain] = device
141 templates = self.
fritzfritz.get_templates()
142 for template
in templates:
143 template_data[template.ain] = template
151 """Fetch all device data."""
155 self.
datadatadata.devices.keys() - new_data.devices.keys()
156 or self.
datadatadata.templates.keys() - new_data.templates.keys()
159 list(new_data.devices) +
list(new_data.templates)
None __init__(self, HomeAssistant hass, str name)
None cleanup_removed_devices(self, list[str] available_ains)
FritzboxCoordinatorData _async_update_data(self)
FritzboxCoordinatorData _update_fritz_devices(self)
None async_config_entry_first_refresh(self)
None update_devices(HomeAssistant hass, ConfigEntry config_entry, dict[int, Roller] api)