From 6a1993482e21de85b7ff6c21665295a1c22e635d Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 3 Jan 2023 07:15:13 +0000 Subject: [PATCH 1/2] Address late feedback in SFR Box coordinator --- homeassistant/components/sfr_box/__init__.py | 33 +++++++++++-------- .../components/sfr_box/coordinator.py | 30 ++++++++++++----- homeassistant/components/sfr_box/models.py | 14 ++++++++ homeassistant/components/sfr_box/sensor.py | 14 ++++---- 4 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 homeassistant/components/sfr_box/models.py diff --git a/homeassistant/components/sfr_box/__init__.py b/homeassistant/components/sfr_box/__init__.py index 43dfdcf627a128..246e99fb7cda4d 100644 --- a/homeassistant/components/sfr_box/__init__.py +++ b/homeassistant/components/sfr_box/__init__.py @@ -1,29 +1,39 @@ """SFR Box.""" from __future__ import annotations +import asyncio + from sfrbox_api.bridge import SFRBox -from sfrbox_api.exceptions import SFRBoxError +from sfrbox_api.models import SystemInfo from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST from homeassistant.core import HomeAssistant -from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import device_registry as dr from homeassistant.helpers.httpx_client import get_async_client from .const import DOMAIN, PLATFORMS -from .coordinator import DslDataUpdateCoordinator +from .coordinator import SFRDataUpdateCoordinator +from .models import DomainData async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up SFR box as config entry.""" box = SFRBox(ip=entry.data[CONF_HOST], client=get_async_client(hass)) - try: - system_info = await box.system_get_info() - except SFRBoxError as err: - raise ConfigEntryNotReady( - f"Unable to connect to {entry.data[CONF_HOST]}" - ) from err + data = DomainData( + dsl=SFRDataUpdateCoordinator(hass, box, "dsl", lambda b: b.dsl_get_info()), + system=SFRDataUpdateCoordinator( + hass, box, "system", lambda b: b.system_get_info() + ), + ) + tasks = [ + data.dsl.async_config_entry_first_refresh(), + data.system.async_config_entry_first_refresh(), + ] + await asyncio.gather(*tasks) + + system_info: SystemInfo = data.system.data + hass.data.setdefault(DOMAIN, {}) device_registry = dr.async_get(hass) @@ -36,10 +46,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: configuration_url=f"http://{entry.data[CONF_HOST]}", ) - hass.data[DOMAIN][entry.entry_id] = { - "box": box, - "dsl_coordinator": DslDataUpdateCoordinator(hass, box), - } + hass.data[DOMAIN][entry.entry_id] = data await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) diff --git a/homeassistant/components/sfr_box/coordinator.py b/homeassistant/components/sfr_box/coordinator.py index 6c10e133a0e9dc..739fc2a770bec6 100644 --- a/homeassistant/components/sfr_box/coordinator.py +++ b/homeassistant/components/sfr_box/coordinator.py @@ -1,25 +1,39 @@ """SFR Box coordinator.""" +from collections.abc import Callable, Coroutine from datetime import timedelta import logging +from typing import Any, TypeVar from sfrbox_api.bridge import SFRBox -from sfrbox_api.models import DslInfo +from sfrbox_api.exceptions import SFRBoxError from homeassistant.core import HomeAssistant -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed _LOGGER = logging.getLogger(__name__) _SCAN_INTERVAL = timedelta(minutes=1) +_T = TypeVar("_T") -class DslDataUpdateCoordinator(DataUpdateCoordinator[DslInfo]): + +class SFRDataUpdateCoordinator(DataUpdateCoordinator[_T]): """Coordinator to manage data updates.""" - def __init__(self, hass: HomeAssistant, box: SFRBox) -> None: + def __init__( + self, + hass: HomeAssistant, + box: SFRBox, + name: str, + method: Callable[[SFRBox], Coroutine[Any, Any, _T]], + ) -> None: """Initialize coordinator.""" - self._box = box - super().__init__(hass, _LOGGER, name="dsl", update_interval=_SCAN_INTERVAL) + self.box = box + self._method = method + super().__init__(hass, _LOGGER, name=name, update_interval=_SCAN_INTERVAL) - async def _async_update_data(self) -> DslInfo: + async def _async_update_data(self) -> _T: """Update data.""" - return await self._box.dsl_get_info() + try: + return await self._method(self.box) + except SFRBoxError as err: + raise UpdateFailed() from err diff --git a/homeassistant/components/sfr_box/models.py b/homeassistant/components/sfr_box/models.py new file mode 100644 index 00000000000000..242a248309c8fa --- /dev/null +++ b/homeassistant/components/sfr_box/models.py @@ -0,0 +1,14 @@ +"""SFR Box models.""" +from dataclasses import dataclass + +from sfrbox_api.models import DslInfo, SystemInfo + +from .coordinator import SFRDataUpdateCoordinator + + +@dataclass +class DomainData: + """Domain data for SFR Box.""" + + dsl: SFRDataUpdateCoordinator[DslInfo] + system: SFRDataUpdateCoordinator[SystemInfo] diff --git a/homeassistant/components/sfr_box/sensor.py b/homeassistant/components/sfr_box/sensor.py index 36440e7e0bf028..16a4a58011c3fe 100644 --- a/homeassistant/components/sfr_box/sensor.py +++ b/homeassistant/components/sfr_box/sensor.py @@ -2,7 +2,6 @@ from collections.abc import Callable from dataclasses import dataclass -from sfrbox_api.bridge import SFRBox from sfrbox_api.models import DslInfo, SystemInfo from homeassistant.components.sensor import ( @@ -19,7 +18,8 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import DOMAIN -from .coordinator import DslDataUpdateCoordinator +from .coordinator import SFRDataUpdateCoordinator +from .models import DomainData @dataclass @@ -148,25 +148,23 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up the sensors.""" - data = hass.data[DOMAIN][entry.entry_id] - box: SFRBox = data["box"] - system_info = await box.system_get_info() + data: DomainData = hass.data[DOMAIN][entry.entry_id] entities = [ - SFRBoxSensor(data["dsl_coordinator"], description, system_info) + SFRBoxSensor(data.dsl, description, data.system.data) for description in SENSOR_TYPES ] async_add_entities(entities, True) -class SFRBoxSensor(CoordinatorEntity[DslDataUpdateCoordinator], SensorEntity): +class SFRBoxSensor(CoordinatorEntity[SFRDataUpdateCoordinator[DslInfo]], SensorEntity): """SFR Box sensor.""" entity_description: SFRBoxSensorEntityDescription def __init__( self, - coordinator: DslDataUpdateCoordinator, + coordinator: SFRDataUpdateCoordinator[DslInfo], description: SFRBoxSensorEntityDescription, system_info: SystemInfo, ) -> None: From 3e05375427825f42e55bd56d8fb628521c61a5b1 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 3 Jan 2023 07:27:33 +0000 Subject: [PATCH 2/2] One more --- homeassistant/components/sfr_box/__init__.py | 8 ++------ homeassistant/components/sfr_box/sensor.py | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/sfr_box/__init__.py b/homeassistant/components/sfr_box/__init__.py index 246e99fb7cda4d..2b4ab0f8c1b70d 100644 --- a/homeassistant/components/sfr_box/__init__.py +++ b/homeassistant/components/sfr_box/__init__.py @@ -4,7 +4,6 @@ import asyncio from sfrbox_api.bridge import SFRBox -from sfrbox_api.models import SystemInfo from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST @@ -32,10 +31,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: ] await asyncio.gather(*tasks) - system_info: SystemInfo = data.system.data - - hass.data.setdefault(DOMAIN, {}) + hass.data.setdefault(DOMAIN, {})[entry.entry_id] = data + system_info = data.system.data device_registry = dr.async_get(hass) device_registry.async_get_or_create( config_entry_id=entry.entry_id, @@ -46,8 +44,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: configuration_url=f"http://{entry.data[CONF_HOST]}", ) - hass.data[DOMAIN][entry.entry_id] = data - await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) return True diff --git a/homeassistant/components/sfr_box/sensor.py b/homeassistant/components/sfr_box/sensor.py index 16a4a58011c3fe..685478fa3c8a81 100644 --- a/homeassistant/components/sfr_box/sensor.py +++ b/homeassistant/components/sfr_box/sensor.py @@ -154,7 +154,7 @@ async def async_setup_entry( SFRBoxSensor(data.dsl, description, data.system.data) for description in SENSOR_TYPES ] - async_add_entities(entities, True) + async_add_entities(entities) class SFRBoxSensor(CoordinatorEntity[SFRDataUpdateCoordinator[DslInfo]], SensorEntity):