mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add DataUpdateCoordinator to Nanoleaf (#65950)
This commit is contained in:
parent
275d4b9770
commit
b1dcf7e0d8
@ -3,15 +3,17 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from aionanoleaf import EffectsEvent, InvalidToken, Nanoleaf, StateEvent, Unavailable
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_TOKEN, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
@ -23,6 +25,7 @@ class NanoleafEntryData:
|
||||
"""Class for sharing data within the Nanoleaf integration."""
|
||||
|
||||
device: Nanoleaf
|
||||
coordinator: DataUpdateCoordinator
|
||||
event_listener: asyncio.Task
|
||||
|
||||
|
||||
@ -31,26 +34,39 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
nanoleaf = Nanoleaf(
|
||||
async_get_clientsession(hass), entry.data[CONF_HOST], entry.data[CONF_TOKEN]
|
||||
)
|
||||
try:
|
||||
await nanoleaf.get_info()
|
||||
except Unavailable as err:
|
||||
raise ConfigEntryNotReady from err
|
||||
except InvalidToken as err:
|
||||
raise ConfigEntryAuthFailed from err
|
||||
|
||||
async def _callback_update_light_state(event: StateEvent | EffectsEvent) -> None:
|
||||
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,
|
||||
logging.getLogger(__name__),
|
||||
name=entry.title,
|
||||
update_interval=timedelta(minutes=1),
|
||||
update_method=async_get_state,
|
||||
)
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
async def update_light_state_callback(event: StateEvent | EffectsEvent) -> None:
|
||||
"""Receive state and effect event."""
|
||||
async_dispatcher_send(hass, f"{DOMAIN}_update_light_{nanoleaf.serial_no}")
|
||||
coordinator.async_set_updated_data(None)
|
||||
|
||||
event_listener = asyncio.create_task(
|
||||
nanoleaf.listen_events(
|
||||
state_callback=_callback_update_light_state,
|
||||
effects_callback=_callback_update_light_state,
|
||||
state_callback=update_light_state_callback,
|
||||
effects_callback=update_light_state_callback,
|
||||
)
|
||||
)
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = NanoleafEntryData(
|
||||
nanoleaf, event_listener
|
||||
nanoleaf, coordinator, event_listener
|
||||
)
|
||||
|
||||
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
|
||||
|
@ -7,6 +7,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from . import NanoleafEntryData
|
||||
from .const import DOMAIN
|
||||
@ -18,15 +19,17 @@ 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)])
|
||||
async_add_entities(
|
||||
[NanoleafIdentifyButton(entry_data.device, entry_data.coordinator)]
|
||||
)
|
||||
|
||||
|
||||
class NanoleafIdentifyButton(NanoleafEntity, ButtonEntity):
|
||||
"""Representation of a Nanoleaf identify button."""
|
||||
|
||||
def __init__(self, nanoleaf: Nanoleaf) -> None:
|
||||
def __init__(self, nanoleaf: Nanoleaf, coordinator: DataUpdateCoordinator) -> None:
|
||||
"""Initialize the Nanoleaf button."""
|
||||
super().__init__(nanoleaf)
|
||||
super().__init__(nanoleaf, coordinator)
|
||||
self._attr_unique_id = f"{nanoleaf.serial_no}_identify"
|
||||
self._attr_name = f"Identify {nanoleaf.name}"
|
||||
self._attr_icon = "mdi:magnify"
|
||||
|
@ -2,16 +2,21 @@
|
||||
|
||||
from aionanoleaf import Nanoleaf
|
||||
|
||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
)
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
class NanoleafEntity(Entity):
|
||||
class NanoleafEntity(CoordinatorEntity):
|
||||
"""Representation of a Nanoleaf entity."""
|
||||
|
||||
def __init__(self, nanoleaf: Nanoleaf) -> None:
|
||||
def __init__(self, nanoleaf: Nanoleaf, coordinator: DataUpdateCoordinator) -> None:
|
||||
"""Initialize an Nanoleaf entity."""
|
||||
super().__init__(coordinator)
|
||||
self._nanoleaf = nanoleaf
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, nanoleaf.serial_no)},
|
||||
|
@ -1,12 +1,11 @@
|
||||
"""Support for Nanoleaf Lights."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
import math
|
||||
from typing import Any
|
||||
|
||||
from aionanoleaf import Nanoleaf, Unavailable
|
||||
from aionanoleaf import Nanoleaf
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.light import (
|
||||
@ -25,11 +24,11 @@ from homeassistant.components.light import (
|
||||
)
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TOKEN
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
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,
|
||||
@ -52,8 +51,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SCAN_INTERVAL = timedelta(minutes=5)
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
@ -82,15 +79,15 @@ 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)])
|
||||
async_add_entities([NanoleafLight(entry_data.device, entry_data.coordinator)])
|
||||
|
||||
|
||||
class NanoleafLight(NanoleafEntity, LightEntity):
|
||||
"""Representation of a Nanoleaf Light."""
|
||||
|
||||
def __init__(self, nanoleaf: Nanoleaf) -> None:
|
||||
def __init__(self, nanoleaf: Nanoleaf, coordinator: DataUpdateCoordinator) -> None:
|
||||
"""Initialize the Nanoleaf light."""
|
||||
super().__init__(nanoleaf)
|
||||
super().__init__(nanoleaf, coordinator)
|
||||
self._attr_unique_id = nanoleaf.serial_no
|
||||
self._attr_name = nanoleaf.name
|
||||
self._attr_min_mireds = math.ceil(1000000 / nanoleaf.color_temperature_max)
|
||||
@ -186,35 +183,3 @@ class NanoleafLight(NanoleafEntity, LightEntity):
|
||||
"""Instruct the light to turn off."""
|
||||
transition: float | None = kwargs.get(ATTR_TRANSITION)
|
||||
await self._nanoleaf.turn_off(None if transition is None else int(transition))
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Fetch new state data for this light."""
|
||||
try:
|
||||
await self._nanoleaf.get_info()
|
||||
except Unavailable:
|
||||
if self.available:
|
||||
_LOGGER.warning("Could not connect to %s", self.name)
|
||||
self._attr_available = False
|
||||
return
|
||||
if not self.available:
|
||||
_LOGGER.info("Fetching %s data recovered", self.name)
|
||||
self._attr_available = True
|
||||
|
||||
@callback
|
||||
def async_handle_update(self) -> None:
|
||||
"""Handle state update."""
|
||||
self.async_write_ha_state()
|
||||
if not self.available:
|
||||
_LOGGER.info("Connection to %s recovered", self.name)
|
||||
self._attr_available = True
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Handle entity being added to Home Assistant."""
|
||||
await super().async_added_to_hass()
|
||||
self.async_on_remove(
|
||||
async_dispatcher_connect(
|
||||
self.hass,
|
||||
f"{DOMAIN}_update_light_{self._nanoleaf.serial_no}",
|
||||
self.async_handle_update,
|
||||
)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user