1
mirror of https://github.com/home-assistant/core synced 2024-08-28 03:36:46 +02:00
ha-core/homeassistant/components/roborock/number.py
Erik Montnemery 0c2485bc03
Freeze integration entity descriptions (#105984)
Co-authored-by: J. Nick Koston <nick@koston.org>
2023-12-18 16:28:13 -10:00

122 lines
4.1 KiB
Python

"""Support for Roborock number."""
import asyncio
from collections.abc import Callable, Coroutine
from dataclasses import dataclass
import logging
from typing import Any
from roborock.api import AttributeCache
from roborock.command_cache import CacheableAttribute
from roborock.exceptions import RoborockException
from homeassistant.components.number import NumberEntity, NumberEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE, EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import slugify
from .const import DOMAIN
from .coordinator import RoborockDataUpdateCoordinator
from .device import RoborockEntity
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True)
class RoborockNumberDescriptionMixin:
"""Define an entity description mixin for button entities."""
# Gets the status of the switch
cache_key: CacheableAttribute
# Sets the status of the switch
update_value: Callable[[AttributeCache, float], Coroutine[Any, Any, dict]]
@dataclass(frozen=True)
class RoborockNumberDescription(
NumberEntityDescription, RoborockNumberDescriptionMixin
):
"""Class to describe an Roborock number entity."""
NUMBER_DESCRIPTIONS: list[RoborockNumberDescription] = [
RoborockNumberDescription(
key="volume",
translation_key="volume",
icon="mdi:volume-source",
native_min_value=0,
native_max_value=100,
native_unit_of_measurement=PERCENTAGE,
cache_key=CacheableAttribute.sound_volume,
entity_category=EntityCategory.CONFIG,
update_value=lambda cache, value: cache.update_value([int(value)]),
)
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Roborock number platform."""
coordinators: dict[str, RoborockDataUpdateCoordinator] = hass.data[DOMAIN][
config_entry.entry_id
]
possible_entities: list[
tuple[RoborockDataUpdateCoordinator, RoborockNumberDescription]
] = [
(coordinator, description)
for coordinator in coordinators.values()
for description in NUMBER_DESCRIPTIONS
]
# We need to check if this function is supported by the device.
results = await asyncio.gather(
*(
coordinator.api.get_from_cache(description.cache_key)
for coordinator, description in possible_entities
),
return_exceptions=True,
)
valid_entities: list[RoborockNumberEntity] = []
for (coordinator, description), result in zip(possible_entities, results):
if result is None or isinstance(result, RoborockException):
_LOGGER.debug("Not adding entity because of %s", result)
else:
valid_entities.append(
RoborockNumberEntity(
f"{description.key}_{slugify(coordinator.roborock_device_info.device.duid)}",
coordinator,
description,
)
)
async_add_entities(valid_entities)
class RoborockNumberEntity(RoborockEntity, NumberEntity):
"""A class to let you set options on a Roborock vacuum where the potential options are fixed."""
entity_description: RoborockNumberDescription
def __init__(
self,
unique_id: str,
coordinator: RoborockDataUpdateCoordinator,
entity_description: RoborockNumberDescription,
) -> None:
"""Create a number entity."""
self.entity_description = entity_description
super().__init__(unique_id, coordinator.device_info, coordinator.api)
@property
def native_value(self) -> float | None:
"""Get native value."""
return self.get_cache(self.entity_description.cache_key).value
async def async_set_native_value(self, value: float) -> None:
"""Set number value."""
await self.entity_description.update_value(
self.get_cache(self.entity_description.cache_key), value
)