core/homeassistant/components/miele/light.py

142 lines
4.3 KiB
Python

"""Platform for Miele light entity."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
import logging
from typing import Any, Final
import aiohttp
from homeassistant.components.light import (
ColorMode,
LightEntity,
LightEntityDescription,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from .const import AMBIENT_LIGHT, DOMAIN, LIGHT, LIGHT_OFF, LIGHT_ON, MieleAppliance
from .coordinator import MieleConfigEntry
from .entity import MieleDevice, MieleEntity
PARALLEL_UPDATES = 1
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True, kw_only=True)
class MieleLightDescription(LightEntityDescription):
"""Class describing Miele light entities."""
value_fn: Callable[[MieleDevice], StateType]
light_type: str
@dataclass
class MieleLightDefinition:
"""Class for defining light entities."""
types: tuple[MieleAppliance, ...]
description: MieleLightDescription
LIGHT_TYPES: Final[tuple[MieleLightDefinition, ...]] = (
MieleLightDefinition(
types=(
MieleAppliance.OVEN,
MieleAppliance.OVEN_MICROWAVE,
MieleAppliance.STEAM_OVEN,
MieleAppliance.MICROWAVE,
MieleAppliance.COFFEE_SYSTEM,
MieleAppliance.HOOD,
MieleAppliance.STEAM_OVEN_COMBI,
MieleAppliance.WINE_CABINET,
MieleAppliance.WINE_CONDITIONING_UNIT,
MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
MieleAppliance.STEAM_OVEN_MICRO,
MieleAppliance.WINE_CABINET_FREEZER,
MieleAppliance.STEAM_OVEN_MK2,
),
description=MieleLightDescription(
key="light",
value_fn=lambda value: value.state_light,
light_type=LIGHT,
translation_key="light",
),
),
MieleLightDefinition(
types=(MieleAppliance.HOOD,),
description=MieleLightDescription(
key="ambient_light",
value_fn=lambda value: value.state_ambient_light,
light_type=AMBIENT_LIGHT,
translation_key="ambient_light",
),
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: MieleConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the light platform."""
coordinator = config_entry.runtime_data
added_devices: set[str] = set()
def _async_add_new_devices() -> None:
nonlocal added_devices
new_devices_set, current_devices = coordinator.async_add_devices(added_devices)
added_devices = current_devices
async_add_entities(
MieleLight(coordinator, device_id, definition.description)
for device_id, device in coordinator.data.devices.items()
for definition in LIGHT_TYPES
if device_id in new_devices_set and device.device_type in definition.types
)
config_entry.async_on_unload(coordinator.async_add_listener(_async_add_new_devices))
_async_add_new_devices()
class MieleLight(MieleEntity, LightEntity):
"""Representation of a Light."""
entity_description: MieleLightDescription
_attr_color_mode = ColorMode.ONOFF
_attr_supported_color_modes = {ColorMode.ONOFF}
@property
def is_on(self) -> bool:
"""Return current on/off state."""
return self.entity_description.value_fn(self.device) == LIGHT_ON
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the light."""
await self.async_turn_light(LIGHT_ON)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
await self.async_turn_light(LIGHT_OFF)
async def async_turn_light(self, mode: int) -> None:
"""Set light to mode."""
try:
await self.api.send_action(
self._device_id, {self.entity_description.light_type: mode}
)
except aiohttp.ClientError as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="set_state_error",
translation_placeholders={
"entity": self.entity_id,
},
) from err