From 6c922e1fdb9c405a7f337075be16e1cf2becaaf9 Mon Sep 17 00:00:00 2001 From: Matthias Lohr Date: Wed, 23 Feb 2022 12:08:28 +0100 Subject: [PATCH] Add number platform to tolo integration (#66799) --- .coveragerc | 1 + homeassistant/components/tolo/__init__.py | 1 + homeassistant/components/tolo/const.py | 4 + homeassistant/components/tolo/number.py | 111 ++++++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 homeassistant/components/tolo/number.py diff --git a/.coveragerc b/.coveragerc index 1784bdad2f6..0d79bb02a4a 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1246,6 +1246,7 @@ omit = homeassistant/components/tolo/climate.py homeassistant/components/tolo/fan.py homeassistant/components/tolo/light.py + homeassistant/components/tolo/number.py homeassistant/components/tolo/select.py homeassistant/components/tolo/sensor.py homeassistant/components/tomato/device_tracker.py diff --git a/homeassistant/components/tolo/__init__.py b/homeassistant/components/tolo/__init__.py index 6e95089ccbe..6f17379dfbf 100644 --- a/homeassistant/components/tolo/__init__.py +++ b/homeassistant/components/tolo/__init__.py @@ -28,6 +28,7 @@ PLATFORMS = [ Platform.CLIMATE, Platform.FAN, Platform.LIGHT, + Platform.NUMBER, Platform.SELECT, Platform.SENSOR, ] diff --git a/homeassistant/components/tolo/const.py b/homeassistant/components/tolo/const.py index bfd700bb955..77bee92d521 100644 --- a/homeassistant/components/tolo/const.py +++ b/homeassistant/components/tolo/const.py @@ -11,3 +11,7 @@ DEFAULT_MIN_TEMP = 20 DEFAULT_MAX_HUMIDITY = 99 DEFAULT_MIN_HUMIDITY = 60 + +POWER_TIMER_MAX = 60 +SALT_BATH_TIMER_MAX = 60 +FAN_TIMER_MAX = 60 diff --git a/homeassistant/components/tolo/number.py b/homeassistant/components/tolo/number.py new file mode 100644 index 00000000000..85d80756020 --- /dev/null +++ b/homeassistant/components/tolo/number.py @@ -0,0 +1,111 @@ +"""TOLO Sauna number controls.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass +from typing import Any + +from tololib import ToloClient +from tololib.message_info import SettingsInfo + +from homeassistant.components.number import NumberEntity, NumberEntityDescription +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import TIME_MINUTES +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import ToloSaunaCoordinatorEntity, ToloSaunaUpdateCoordinator +from .const import DOMAIN, FAN_TIMER_MAX, POWER_TIMER_MAX, SALT_BATH_TIMER_MAX + + +@dataclass +class ToloNumberEntityDescriptionBase: + """Required values when describing TOLO Number entities.""" + + getter: Callable[[SettingsInfo], int | None] + setter: Callable[[ToloClient, int | None], Any] + + +@dataclass +class ToloNumberEntityDescription( + NumberEntityDescription, ToloNumberEntityDescriptionBase +): + """Class describing TOLO Number entities.""" + + entity_category = EntityCategory.CONFIG + min_value = 0 + step = 1 + + +NUMBERS = ( + ToloNumberEntityDescription( + key="power_timer", + icon="mdi:power-settings", + name="Power Timer", + unit_of_measurement=TIME_MINUTES, + max_value=POWER_TIMER_MAX, + getter=lambda settings: settings.power_timer, + setter=lambda client, value: client.set_power_timer(value), + ), + ToloNumberEntityDescription( + key="salt_bath_timer", + icon="mdi:shaker-outline", + name="Salt Bath Timer", + unit_of_measurement=TIME_MINUTES, + max_value=SALT_BATH_TIMER_MAX, + getter=lambda settings: settings.salt_bath_timer, + setter=lambda client, value: client.set_salt_bath_timer(value), + ), + ToloNumberEntityDescription( + key="fan_timer", + icon="mdi:fan-auto", + name="Fan Timer", + unit_of_measurement=TIME_MINUTES, + max_value=FAN_TIMER_MAX, + getter=lambda settings: settings.fan_timer, + setter=lambda client, value: client.set_fan_timer(value), + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up number controls for TOLO Sauna.""" + coordinator = hass.data[DOMAIN][entry.entry_id] + async_add_entities( + ToloNumberEntity(coordinator, entry, description) for description in NUMBERS + ) + + +class ToloNumberEntity(ToloSaunaCoordinatorEntity, NumberEntity): + """TOLO Number entity.""" + + entity_description: ToloNumberEntityDescription + + def __init__( + self, + coordinator: ToloSaunaUpdateCoordinator, + entry: ConfigEntry, + entity_description: ToloNumberEntityDescription, + ) -> None: + """Initialize TOLO Number entity.""" + super().__init__(coordinator, entry) + self.entity_description = entity_description + self._attr_unique_id = f"{entry.entry_id}_{entity_description.key}" + + @property + def value(self) -> float: + """Return the value of this TOLO Number entity.""" + return self.entity_description.getter(self.coordinator.data.settings) or 0 + + def set_value(self, value: float) -> None: + """Set the value of this TOLO Number entity.""" + int_value = int(value) + if int_value == 0: + self.entity_description.setter(self.coordinator.client, None) + return + self.entity_description.setter(self.coordinator.client, int_value)