From 58b36514ad7dca801e31d28e4c3786a9b5f36d21 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:54:15 +0100 Subject: [PATCH] Address late feedback in SFR Box coordinator (#85039) * Address late feedback in SFR Box coordinator * One more --- 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 | 16 ++++----- 4 files changed, 61 insertions(+), 32 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 43dfdcf627a..2b4ab0f8c1b 100644 --- a/homeassistant/components/sfr_box/__init__.py +++ b/homeassistant/components/sfr_box/__init__.py @@ -1,31 +1,39 @@ """SFR Box.""" from __future__ import annotations +import asyncio + from sfrbox_api.bridge import SFRBox -from sfrbox_api.exceptions import SFRBoxError 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 - hass.data.setdefault(DOMAIN, {}) + 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) + 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, @@ -36,11 +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] = { - "box": box, - "dsl_coordinator": DslDataUpdateCoordinator(hass, box), - } - await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) return True diff --git a/homeassistant/components/sfr_box/coordinator.py b/homeassistant/components/sfr_box/coordinator.py index 6c10e133a0e..739fc2a770b 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 00000000000..242a248309c --- /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 daa8771fbb1..a178e08d508 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 ( @@ -20,7 +19,8 @@ from homeassistant.helpers.typing import StateType from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import DOMAIN -from .coordinator import DslDataUpdateCoordinator +from .coordinator import SFRDataUpdateCoordinator +from .models import DomainData @dataclass @@ -156,18 +156,16 @@ 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) + async_add_entities(entities) -class SFRBoxSensor(CoordinatorEntity[DslDataUpdateCoordinator], SensorEntity): +class SFRBoxSensor(CoordinatorEntity[SFRDataUpdateCoordinator[DslInfo]], SensorEntity): """SFR Box sensor.""" entity_description: SFRBoxSensorEntityDescription @@ -175,7 +173,7 @@ class SFRBoxSensor(CoordinatorEntity[DslDataUpdateCoordinator], SensorEntity): def __init__( self, - coordinator: DslDataUpdateCoordinator, + coordinator: SFRDataUpdateCoordinator[DslInfo], description: SFRBoxSensorEntityDescription, system_info: SystemInfo, ) -> None: