diff --git a/.coveragerc b/.coveragerc index 390c098418e..d8d8bbdf80d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -854,6 +854,7 @@ omit = homeassistant/components/nad/media_player.py homeassistant/components/nanoleaf/__init__.py homeassistant/components/nanoleaf/button.py + homeassistant/components/nanoleaf/coordinator.py homeassistant/components/nanoleaf/entity.py homeassistant/components/nanoleaf/light.py homeassistant/components/neato/__init__.py diff --git a/homeassistant/components/nanoleaf/__init__.py b/homeassistant/components/nanoleaf/__init__.py index 9e368353774..c8211969f87 100644 --- a/homeassistant/components/nanoleaf/__init__.py +++ b/homeassistant/components/nanoleaf/__init__.py @@ -4,17 +4,9 @@ from __future__ import annotations import asyncio from dataclasses import dataclass -from datetime import timedelta import logging -from aionanoleaf import ( - EffectsEvent, - InvalidToken, - Nanoleaf, - StateEvent, - TouchEvent, - Unavailable, -) +from aionanoleaf import EffectsEvent, Nanoleaf, StateEvent, TouchEvent from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( @@ -25,12 +17,11 @@ from homeassistant.const import ( Platform, ) from homeassistant.core import HomeAssistant -from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.helpers import device_registry as dr from homeassistant.helpers.aiohttp_client import async_get_clientsession -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import DOMAIN, NANOLEAF_EVENT, TOUCH_GESTURE_TRIGGER_MAP, TOUCH_MODELS +from .coordinator import NanoleafCoordinator _LOGGER = logging.getLogger(__name__) @@ -42,7 +33,7 @@ class NanoleafEntryData: """Class for sharing data within the Nanoleaf integration.""" device: Nanoleaf - coordinator: DataUpdateCoordinator[None] + coordinator: NanoleafCoordinator event_listener: asyncio.Task @@ -52,22 +43,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async_get_clientsession(hass), entry.data[CONF_HOST], entry.data[CONF_TOKEN] ) - async def async_get_state() -> None: - """Get the state of the device.""" - try: - await nanoleaf.get_info() - except Unavailable as err: - raise UpdateFailed from err - except InvalidToken as err: - raise ConfigEntryAuthFailed from err - - coordinator = DataUpdateCoordinator( - hass, - _LOGGER, - name=entry.title, - update_interval=timedelta(minutes=1), - update_method=async_get_state, - ) + coordinator = NanoleafCoordinator(hass, nanoleaf) await coordinator.async_config_entry_first_refresh() diff --git a/homeassistant/components/nanoleaf/button.py b/homeassistant/components/nanoleaf/button.py index 950dc2a591a..dd0cc221fc2 100644 --- a/homeassistant/components/nanoleaf/button.py +++ b/homeassistant/components/nanoleaf/button.py @@ -1,15 +1,12 @@ """Support for Nanoleaf buttons.""" -from aionanoleaf import Nanoleaf - from homeassistant.components.button import ButtonDeviceClass, ButtonEntity from homeassistant.config_entries import ConfigEntry from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator -from . import NanoleafEntryData +from . import NanoleafCoordinator, NanoleafEntryData from .const import DOMAIN from .entity import NanoleafEntity @@ -19,9 +16,7 @@ async def async_setup_entry( ) -> None: """Set up the Nanoleaf button.""" entry_data: NanoleafEntryData = hass.data[DOMAIN][entry.entry_id] - async_add_entities( - [NanoleafIdentifyButton(entry_data.device, entry_data.coordinator)] - ) + async_add_entities([NanoleafIdentifyButton(entry_data.coordinator)]) class NanoleafIdentifyButton(NanoleafEntity, ButtonEntity): @@ -30,12 +25,10 @@ class NanoleafIdentifyButton(NanoleafEntity, ButtonEntity): _attr_entity_category = EntityCategory.CONFIG _attr_device_class = ButtonDeviceClass.IDENTIFY - def __init__( - self, nanoleaf: Nanoleaf, coordinator: DataUpdateCoordinator[None] - ) -> None: + def __init__(self, coordinator: NanoleafCoordinator) -> None: """Initialize the Nanoleaf button.""" - super().__init__(nanoleaf, coordinator) - self._attr_unique_id = f"{nanoleaf.serial_no}_identify" + super().__init__(coordinator) + self._attr_unique_id = f"{self._nanoleaf.serial_no}_identify" async def async_press(self) -> None: """Identify the Nanoleaf.""" diff --git a/homeassistant/components/nanoleaf/coordinator.py b/homeassistant/components/nanoleaf/coordinator.py new file mode 100644 index 00000000000..e080afc492e --- /dev/null +++ b/homeassistant/components/nanoleaf/coordinator.py @@ -0,0 +1,31 @@ +"""Define the Nanoleaf data coordinator.""" + +from datetime import timedelta +import logging + +from aionanoleaf import InvalidToken, Nanoleaf, Unavailable + +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryAuthFailed +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed + +_LOGGER = logging.getLogger(__name__) + + +class NanoleafCoordinator(DataUpdateCoordinator[None]): + """Class to manage fetching Nanoleaf data.""" + + def __init__(self, hass: HomeAssistant, nanoleaf: Nanoleaf) -> None: + """Initialize the Nanoleaf data coordinator.""" + super().__init__( + hass, _LOGGER, name="Nanoleaf", update_interval=timedelta(minutes=1) + ) + self.nanoleaf = nanoleaf + + async def _async_update_data(self) -> None: + try: + await self.nanoleaf.get_info() + except Unavailable as err: + raise UpdateFailed from err + except InvalidToken as err: + raise ConfigEntryAuthFailed from err diff --git a/homeassistant/components/nanoleaf/entity.py b/homeassistant/components/nanoleaf/entity.py index 73d635a46a1..ffe4a098022 100644 --- a/homeassistant/components/nanoleaf/entity.py +++ b/homeassistant/components/nanoleaf/entity.py @@ -1,27 +1,21 @@ """Base class for Nanoleaf entity.""" -from aionanoleaf import Nanoleaf - from homeassistant.helpers.device_registry import DeviceInfo -from homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, -) +from homeassistant.helpers.update_coordinator import CoordinatorEntity +from . import NanoleafCoordinator from .const import DOMAIN -class NanoleafEntity(CoordinatorEntity[DataUpdateCoordinator[None]]): +class NanoleafEntity(CoordinatorEntity[NanoleafCoordinator]): """Representation of a Nanoleaf entity.""" _attr_has_entity_name = True - def __init__( - self, nanoleaf: Nanoleaf, coordinator: DataUpdateCoordinator[None] - ) -> None: + def __init__(self, coordinator: NanoleafCoordinator) -> None: """Initialize a Nanoleaf entity.""" super().__init__(coordinator) - self._nanoleaf = nanoleaf + self._nanoleaf = nanoleaf = coordinator.nanoleaf self._attr_device_info = DeviceInfo( identifiers={(DOMAIN, nanoleaf.serial_no)}, manufacturer=nanoleaf.manufacturer, diff --git a/homeassistant/components/nanoleaf/light.py b/homeassistant/components/nanoleaf/light.py index b80048307bb..a02cb30754b 100644 --- a/homeassistant/components/nanoleaf/light.py +++ b/homeassistant/components/nanoleaf/light.py @@ -5,8 +5,6 @@ from __future__ import annotations import math from typing import Any -from aionanoleaf import Nanoleaf - from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, @@ -20,13 +18,12 @@ from homeassistant.components.light import ( from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.util.color import ( color_temperature_kelvin_to_mired as kelvin_to_mired, color_temperature_mired_to_kelvin as mired_to_kelvin, ) -from . import NanoleafEntryData +from . import NanoleafCoordinator, NanoleafEntryData from .const import DOMAIN from .entity import NanoleafEntity @@ -39,7 +36,7 @@ async def async_setup_entry( ) -> None: """Set up the Nanoleaf light.""" entry_data: NanoleafEntryData = hass.data[DOMAIN][entry.entry_id] - async_add_entities([NanoleafLight(entry_data.device, entry_data.coordinator)]) + async_add_entities([NanoleafLight(entry_data.coordinator)]) class NanoleafLight(NanoleafEntity, LightEntity): @@ -50,14 +47,14 @@ class NanoleafLight(NanoleafEntity, LightEntity): _attr_name = None _attr_translation_key = "light" - def __init__( - self, nanoleaf: Nanoleaf, coordinator: DataUpdateCoordinator[None] - ) -> None: + def __init__(self, coordinator: NanoleafCoordinator) -> None: """Initialize the Nanoleaf light.""" - super().__init__(nanoleaf, coordinator) - self._attr_unique_id = nanoleaf.serial_no - self._attr_min_mireds = math.ceil(1000000 / nanoleaf.color_temperature_max) - self._attr_max_mireds = kelvin_to_mired(nanoleaf.color_temperature_min) + super().__init__(coordinator) + self._attr_unique_id = self._nanoleaf.serial_no + self._attr_min_mireds = math.ceil( + 1000000 / self._nanoleaf.color_temperature_max + ) + self._attr_max_mireds = kelvin_to_mired(self._nanoleaf.color_temperature_min) @property def brightness(self) -> int: