Skip to content
Merged
36 changes: 21 additions & 15 deletions homeassistant/components/fritzbox/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import FritzBoxDeviceEntity
from .const import CONF_COORDINATOR, DOMAIN as FRITZBOX_DOMAIN
from .coordinator import FritzboxDataUpdateCoordinator
from .common import get_coordinator
from .model import FritzEntityDescriptionMixinBase


Expand Down Expand Up @@ -68,18 +67,25 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the FRITZ!SmartHome binary sensor from ConfigEntry."""
coordinator: FritzboxDataUpdateCoordinator = hass.data[FRITZBOX_DOMAIN][
entry.entry_id
][CONF_COORDINATOR]

async_add_entities(
[
FritzboxBinarySensor(coordinator, ain, description)
for ain, device in coordinator.data.devices.items()
for description in BINARY_SENSOR_TYPES
if description.suitable(device)
]
)
coordinator = get_coordinator(hass, entry.entry_id)

@callback
def _add_entities() -> None:
Comment thread
mib1185 marked this conversation as resolved.
"""Add devices."""
if not coordinator.new_devices:
return
async_add_entities(
[
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove the brackets to make it a generator expression instead of a list comprehension.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FritzboxBinarySensor(coordinator, ain, description)
for ain in coordinator.new_devices
for description in BINARY_SENSOR_TYPES
if description.suitable(coordinator.data.devices[ain])
]
Comment thread
mib1185 marked this conversation as resolved.
)

entry.async_on_unload(coordinator.async_add_listener(_add_entities))
Comment thread
mib1185 marked this conversation as resolved.

_add_entities()


class FritzboxBinarySensor(FritzBoxDeviceEntity, BinarySensorEntity):
Expand Down
28 changes: 18 additions & 10 deletions homeassistant/components/fritzbox/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,33 @@

from homeassistant.components.button import ButtonEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import FritzboxDataUpdateCoordinator, FritzBoxEntity
from .const import CONF_COORDINATOR, DOMAIN as FRITZBOX_DOMAIN
from . import FritzBoxEntity
from .common import get_coordinator
from .const import DOMAIN


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the FRITZ!SmartHome template from ConfigEntry."""
coordinator: FritzboxDataUpdateCoordinator = hass.data[FRITZBOX_DOMAIN][
entry.entry_id
][CONF_COORDINATOR]
coordinator = get_coordinator(hass, entry.entry_id)

@callback
def _add_entities() -> None:
"""Add templates."""
if not coordinator.new_templates:
return
async_add_entities(
[FritzBoxTemplate(coordinator, ain) for ain in coordinator.new_templates]
)

entry.async_on_unload(coordinator.async_add_listener(_add_entities))

async_add_entities(
[FritzBoxTemplate(coordinator, ain) for ain in coordinator.data.templates]
)
_add_entities()


class FritzBoxTemplate(FritzBoxEntity, ButtonEntity):
Expand All @@ -37,7 +45,7 @@ def device_info(self) -> DeviceInfo:
"""Return device specific attributes."""
return DeviceInfo(
name=self.data.name,
identifiers={(FRITZBOX_DOMAIN, self.ain)},
identifiers={(DOMAIN, self.ain)},
configuration_url=self.coordinator.configuration_url,
manufacturer="AVM",
model="SmartHome Template",
Expand Down
36 changes: 21 additions & 15 deletions homeassistant/components/fritzbox/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@
PRECISION_HALVES,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import FritzboxDataUpdateCoordinator, FritzBoxDeviceEntity
from . import FritzBoxDeviceEntity
from .common import get_coordinator
from .const import (
ATTR_STATE_BATTERY_LOW,
ATTR_STATE_HOLIDAY_MODE,
ATTR_STATE_SUMMER_MODE,
ATTR_STATE_WINDOW_OPEN,
CONF_COORDINATOR,
DOMAIN as FRITZBOX_DOMAIN,
)
from .model import ClimateExtraAttributes

Expand All @@ -50,17 +49,24 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the FRITZ!SmartHome thermostat from ConfigEntry."""
coordinator: FritzboxDataUpdateCoordinator = hass.data[FRITZBOX_DOMAIN][
entry.entry_id
][CONF_COORDINATOR]

async_add_entities(
[
FritzboxThermostat(coordinator, ain)
for ain, device in coordinator.data.devices.items()
if device.has_thermostat
]
)
coordinator = get_coordinator(hass, entry.entry_id)

@callback
def _add_entities() -> None:
"""Add devices."""
if not coordinator.new_devices:
return
async_add_entities(
[
FritzboxThermostat(coordinator, ain)
for ain in coordinator.new_devices
if coordinator.data.devices[ain].has_thermostat
]
)

entry.async_on_unload(coordinator.async_add_listener(_add_entities))

_add_entities()


class FritzboxThermostat(FritzBoxDeviceEntity, ClimateEntity):
Expand Down
16 changes: 16 additions & 0 deletions homeassistant/components/fritzbox/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Common functions for fritzbox integration."""

from homeassistant.core import HomeAssistant

from .const import CONF_COORDINATOR, DOMAIN
from .coordinator import FritzboxDataUpdateCoordinator


def get_coordinator(
hass: HomeAssistant, config_entry_id: str
) -> FritzboxDataUpdateCoordinator:
"""Get coordinator for given config entry id."""
coordinator: FritzboxDataUpdateCoordinator = hass.data[DOMAIN][config_entry_id][
CONF_COORDINATOR
]
return coordinator
7 changes: 7 additions & 0 deletions homeassistant/components/fritzbox/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def __init__(
self.fritz: Fritzhome = hass.data[DOMAIN][self.entry.entry_id][CONF_CONNECTIONS]
self.configuration_url = self.fritz.get_prefixed_host()
self.has_templates = has_templates
self.new_devices: set[str] = set()
self.new_templates: set[str] = set()

super().__init__(
hass,
Expand All @@ -45,6 +47,8 @@ def __init__(
update_interval=timedelta(seconds=30),
)

self.data = FritzboxCoordinatorData({}, {})

def _update_fritz_devices(self) -> FritzboxCoordinatorData:
"""Update all fritzbox device data."""
try:
Expand Down Expand Up @@ -87,6 +91,9 @@ def _update_fritz_devices(self) -> FritzboxCoordinatorData:
for template in templates:
template_data[template.ain] = template

self.new_devices = device_data.keys() - self.data.devices.keys()
self.new_templates = template_data.keys() - self.data.templates.keys()

Comment thread
mib1185 marked this conversation as resolved.
return FritzboxCoordinatorData(devices=device_data, templates=template_data)

async def _async_update_data(self) -> FritzboxCoordinatorData:
Expand Down
33 changes: 21 additions & 12 deletions homeassistant/components/fritzbox/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,35 @@
CoverEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import FritzboxDataUpdateCoordinator, FritzBoxDeviceEntity
from .const import CONF_COORDINATOR, DOMAIN as FRITZBOX_DOMAIN
from . import FritzBoxDeviceEntity
from .common import get_coordinator


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the FRITZ!SmartHome cover from ConfigEntry."""
coordinator: FritzboxDataUpdateCoordinator = hass.data[FRITZBOX_DOMAIN][
entry.entry_id
][CONF_COORDINATOR]

async_add_entities(
FritzboxCover(coordinator, ain)
for ain, device in coordinator.data.devices.items()
if device.has_blind
)
coordinator = get_coordinator(hass, entry.entry_id)

@callback
def _add_entities() -> None:
"""Add devices."""
if not coordinator.new_devices:
return
async_add_entities(
[
FritzboxCover(coordinator, ain)
for ain in coordinator.new_devices
if coordinator.data.devices[ain].has_blind
]
)

entry.async_on_unload(coordinator.async_add_listener(_add_entities))

_add_entities()


class FritzboxCover(FritzBoxDeviceEntity, CoverEntity):
Expand Down
53 changes: 23 additions & 30 deletions homeassistant/components/fritzbox/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,12 @@
LightEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import FritzboxDataUpdateCoordinator, FritzBoxDeviceEntity
from .const import (
COLOR_MODE,
COLOR_TEMP_MODE,
CONF_COORDINATOR,
DOMAIN as FRITZBOX_DOMAIN,
LOGGER,
)
from .common import get_coordinator
from .const import COLOR_MODE, COLOR_TEMP_MODE, LOGGER

SUPPORTED_COLOR_MODES = {ColorMode.COLOR_TEMP, ColorMode.HS}

Expand All @@ -32,31 +27,29 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the FRITZ!SmartHome light from ConfigEntry."""
entities: list[FritzboxLight] = []
coordinator: FritzboxDataUpdateCoordinator = hass.data[FRITZBOX_DOMAIN][
entry.entry_id
][CONF_COORDINATOR]

for ain, device in coordinator.data.devices.items():
if not device.has_lightbulb:
continue

supported_color_temps = await hass.async_add_executor_job(
device.get_color_temps
coordinator = get_coordinator(hass, entry.entry_id)

@callback
def _add_entities() -> None:
"""Add devices."""
if not coordinator.new_devices:
return
async_add_entities(
[
FritzboxLight(
coordinator,
ain,
device.get_colors(),
device.get_color_temps(),
)
for ain in coordinator.new_devices
if (device := coordinator.data.devices[ain]).has_lightbulb
]
)

supported_colors = await hass.async_add_executor_job(device.get_colors)

entities.append(
FritzboxLight(
coordinator,
ain,
supported_colors,
supported_color_temps,
)
)
entry.async_on_unload(coordinator.async_add_listener(_add_entities))

async_add_entities(entities)
_add_entities()


class FritzboxLight(FritzBoxDeviceEntity, LightEntity):
Expand Down
33 changes: 21 additions & 12 deletions homeassistant/components/fritzbox/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
UnitOfPower,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.util.dt import utc_from_timestamp

from . import FritzBoxDeviceEntity
from .const import CONF_COORDINATOR, DOMAIN as FRITZBOX_DOMAIN
from .common import get_coordinator
from .model import FritzEntityDescriptionMixinBase


Expand Down Expand Up @@ -212,16 +212,25 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the FRITZ!SmartHome sensor from ConfigEntry."""
coordinator = hass.data[FRITZBOX_DOMAIN][entry.entry_id][CONF_COORDINATOR]

async_add_entities(
[
FritzBoxSensor(coordinator, ain, description)
for ain, device in coordinator.data.devices.items()
for description in SENSOR_TYPES
if description.suitable(device)
]
)
coordinator = get_coordinator(hass, entry.entry_id)

@callback
def _add_entities() -> None:
"""Add devices."""
if not coordinator.new_devices:
return
async_add_entities(
[
FritzBoxSensor(coordinator, ain, description)
for ain in coordinator.new_devices
for description in SENSOR_TYPES
if description.suitable(coordinator.data.devices[ain])
]
)

entry.async_on_unload(coordinator.async_add_listener(_add_entities))

_add_entities()


class FritzBoxSensor(FritzBoxDeviceEntity, SensorEntity):
Expand Down
Loading