core/homeassistant/components/smartthings/number.py

220 lines
7.5 KiB
Python

"""Support for number entities through the SmartThings cloud API."""
from __future__ import annotations
from pysmartthings import Attribute, Capability, Command, SmartThings
from homeassistant.components.number import NumberDeviceClass, NumberEntity, NumberMode
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import FullDevice, SmartThingsConfigEntry
from .const import MAIN, UNIT_MAP
from .entity import SmartThingsEntity
async def async_setup_entry(
hass: HomeAssistant,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add number entities for a config entry."""
entry_data = entry.runtime_data
entities: list[NumberEntity] = [
SmartThingsWasherRinseCyclesNumberEntity(entry_data.client, device)
for device in entry_data.devices.values()
if Capability.CUSTOM_WASHER_RINSE_CYCLES in device.status[MAIN]
]
entities.extend(
SmartThingsHoodNumberEntity(entry_data.client, device)
for device in entry_data.devices.values()
if (
(hood_component := device.status.get("hood")) is not None
and Capability.SAMSUNG_CE_HOOD_FAN_SPEED in hood_component
and Capability.SAMSUNG_CE_CONNECTION_STATE not in hood_component
)
)
entities.extend(
SmartThingsRefrigeratorTemperatureNumberEntity(
entry_data.client, device, component
)
for device in entry_data.devices.values()
for component in device.status
if component in ("cooler", "freezer")
and Capability.THERMOSTAT_COOLING_SETPOINT in device.status[component]
)
async_add_entities(entities)
class SmartThingsWasherRinseCyclesNumberEntity(SmartThingsEntity, NumberEntity):
"""Define a SmartThings number."""
_attr_translation_key = "washer_rinse_cycles"
_attr_native_step = 1.0
_attr_mode = NumberMode.BOX
_attr_entity_category = EntityCategory.CONFIG
def __init__(self, client: SmartThings, device: FullDevice) -> None:
"""Initialize the instance."""
super().__init__(client, device, {Capability.CUSTOM_WASHER_RINSE_CYCLES})
self._attr_unique_id = f"{device.device.device_id}_{MAIN}_{Capability.CUSTOM_WASHER_RINSE_CYCLES}_{Attribute.WASHER_RINSE_CYCLES}_{Attribute.WASHER_RINSE_CYCLES}"
@property
def options(self) -> list[int]:
"""Return the list of options."""
values = self.get_attribute_value(
Capability.CUSTOM_WASHER_RINSE_CYCLES,
Attribute.SUPPORTED_WASHER_RINSE_CYCLES,
)
return [int(value) for value in values] if values else []
@property
def native_value(self) -> float | None:
"""Return the current value."""
return int(
self.get_attribute_value(
Capability.CUSTOM_WASHER_RINSE_CYCLES, Attribute.WASHER_RINSE_CYCLES
)
)
@property
def native_min_value(self) -> float:
"""Return the minimum value."""
return min(self.options)
@property
def native_max_value(self) -> float:
"""Return the maximum value."""
return max(self.options)
async def async_set_native_value(self, value: float) -> None:
"""Set the value."""
await self.execute_device_command(
Capability.CUSTOM_WASHER_RINSE_CYCLES,
Command.SET_WASHER_RINSE_CYCLES,
str(int(value)),
)
class SmartThingsHoodNumberEntity(SmartThingsEntity, NumberEntity):
"""Define a SmartThings number."""
_attr_translation_key = "hood_fan_speed"
_attr_native_step = 1.0
_attr_mode = NumberMode.SLIDER
_attr_entity_category = EntityCategory.CONFIG
def __init__(self, client: SmartThings, device: FullDevice) -> None:
"""Initialize the instance."""
super().__init__(
client, device, {Capability.SAMSUNG_CE_HOOD_FAN_SPEED}, component="hood"
)
self._attr_unique_id = f"{device.device.device_id}_hood_{Capability.SAMSUNG_CE_HOOD_FAN_SPEED}_{Attribute.HOOD_FAN_SPEED}_{Attribute.HOOD_FAN_SPEED}"
@property
def options(self) -> list[int]:
"""Return the list of options."""
min_value = self.get_attribute_value(
Capability.SAMSUNG_CE_HOOD_FAN_SPEED,
Attribute.SETTABLE_MIN_FAN_SPEED,
)
max_value = self.get_attribute_value(
Capability.SAMSUNG_CE_HOOD_FAN_SPEED,
Attribute.SETTABLE_MAX_FAN_SPEED,
)
return list(range(min_value, max_value + 1))
@property
def native_value(self) -> int:
"""Return the current value."""
return int(
self.get_attribute_value(
Capability.SAMSUNG_CE_HOOD_FAN_SPEED, Attribute.HOOD_FAN_SPEED
)
)
@property
def native_min_value(self) -> float:
"""Return the minimum value."""
return min(self.options)
@property
def native_max_value(self) -> float:
"""Return the maximum value."""
return max(self.options)
async def async_set_native_value(self, value: float) -> None:
"""Set the value."""
await self.execute_device_command(
Capability.SAMSUNG_CE_HOOD_FAN_SPEED,
Command.SET_HOOD_FAN_SPEED,
int(value),
)
class SmartThingsRefrigeratorTemperatureNumberEntity(SmartThingsEntity, NumberEntity):
"""Define a SmartThings number."""
_attr_entity_category = EntityCategory.CONFIG
_attr_device_class = NumberDeviceClass.TEMPERATURE
def __init__(self, client: SmartThings, device: FullDevice, component: str) -> None:
"""Initialize the instance."""
super().__init__(
client,
device,
{Capability.THERMOSTAT_COOLING_SETPOINT},
component=component,
)
self._attr_unique_id = f"{device.device.device_id}_{component}_{Capability.THERMOSTAT_COOLING_SETPOINT}_{Attribute.COOLING_SETPOINT}_{Attribute.COOLING_SETPOINT}"
unit = self._internal_state[Capability.THERMOSTAT_COOLING_SETPOINT][
Attribute.COOLING_SETPOINT
].unit
assert unit is not None
self._attr_native_unit_of_measurement = UNIT_MAP[unit]
self._attr_translation_key = {
"cooler": "cooler_temperature",
"freezer": "freezer_temperature",
}[component]
@property
def range(self) -> dict[str, int]:
"""Return the list of options."""
return self.get_attribute_value(
Capability.THERMOSTAT_COOLING_SETPOINT,
Attribute.COOLING_SETPOINT_RANGE,
)
@property
def native_value(self) -> int:
"""Return the current value."""
return int(
self.get_attribute_value(
Capability.THERMOSTAT_COOLING_SETPOINT, Attribute.COOLING_SETPOINT
)
)
@property
def native_min_value(self) -> float:
"""Return the minimum value."""
return self.range["minimum"]
@property
def native_max_value(self) -> float:
"""Return the maximum value."""
return self.range["maximum"]
@property
def native_step(self) -> float:
"""Return the step value."""
return self.range["step"]
async def async_set_native_value(self, value: float) -> None:
"""Set the value."""
await self.execute_device_command(
Capability.THERMOSTAT_COOLING_SETPOINT,
Command.SET_COOLING_SETPOINT,
int(value),
)