mirror of https://github.com/home-assistant/core
135 lines
4.6 KiB
Python
135 lines
4.6 KiB
Python
"""Support for Huum wifi-enabled sauna."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Any
|
|
|
|
from huum.const import SaunaStatus
|
|
from huum.exceptions import SafetyException
|
|
from huum.huum import Huum
|
|
from huum.schemas import HuumStatusResponse
|
|
|
|
from homeassistant.components.climate import (
|
|
ClimateEntity,
|
|
ClimateEntityFeature,
|
|
HVACMode,
|
|
)
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers.device_registry import DeviceInfo
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from .const import DOMAIN
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
entry: ConfigEntry,
|
|
async_add_entities: AddEntitiesCallback,
|
|
) -> None:
|
|
"""Set up the Huum sauna with config flow."""
|
|
huum_handler = hass.data.setdefault(DOMAIN, {})[entry.entry_id]
|
|
|
|
async_add_entities([HuumDevice(huum_handler, entry.entry_id)], True)
|
|
|
|
|
|
class HuumDevice(ClimateEntity):
|
|
"""Representation of a heater."""
|
|
|
|
_attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF]
|
|
_attr_supported_features = (
|
|
ClimateEntityFeature.TARGET_TEMPERATURE
|
|
| ClimateEntityFeature.TURN_OFF
|
|
| ClimateEntityFeature.TURN_ON
|
|
)
|
|
_attr_target_temperature_step = PRECISION_WHOLE
|
|
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
|
_attr_max_temp = 110
|
|
_attr_min_temp = 40
|
|
_attr_has_entity_name = True
|
|
_attr_name = None
|
|
|
|
_target_temperature: int | None = None
|
|
_status: HuumStatusResponse | None = None
|
|
_enable_turn_on_off_backwards_compatibility = False
|
|
|
|
def __init__(self, huum_handler: Huum, unique_id: str) -> None:
|
|
"""Initialize the heater."""
|
|
self._attr_unique_id = unique_id
|
|
self._attr_device_info = DeviceInfo(
|
|
identifiers={(DOMAIN, unique_id)},
|
|
name="Huum sauna",
|
|
manufacturer="Huum",
|
|
)
|
|
|
|
self._huum_handler = huum_handler
|
|
|
|
@property
|
|
def hvac_mode(self) -> HVACMode:
|
|
"""Return hvac operation ie. heat, cool mode."""
|
|
if self._status and self._status.status == SaunaStatus.ONLINE_HEATING:
|
|
return HVACMode.HEAT
|
|
return HVACMode.OFF
|
|
|
|
@property
|
|
def icon(self) -> str:
|
|
"""Return nice icon for heater."""
|
|
if self.hvac_mode == HVACMode.HEAT:
|
|
return "mdi:radiator"
|
|
return "mdi:radiator-off"
|
|
|
|
@property
|
|
def current_temperature(self) -> int | None:
|
|
"""Return the current temperature."""
|
|
if (status := self._status) is not None:
|
|
return status.temperature
|
|
return None
|
|
|
|
@property
|
|
def target_temperature(self) -> int:
|
|
"""Return the temperature we try to reach."""
|
|
return self._target_temperature or int(self.min_temp)
|
|
|
|
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
|
"""Set hvac mode."""
|
|
if hvac_mode == HVACMode.HEAT:
|
|
await self._turn_on(self.target_temperature)
|
|
elif hvac_mode == HVACMode.OFF:
|
|
await self._huum_handler.turn_off()
|
|
|
|
async def async_set_temperature(self, **kwargs: Any) -> None:
|
|
"""Set new target temperature."""
|
|
temperature = kwargs.get(ATTR_TEMPERATURE)
|
|
if temperature is None:
|
|
return
|
|
self._target_temperature = temperature
|
|
|
|
if self.hvac_mode == HVACMode.HEAT:
|
|
await self._turn_on(temperature)
|
|
|
|
async def async_update(self) -> None:
|
|
"""Get the latest status data.
|
|
|
|
We get the latest status first from the status endpoints of the sauna.
|
|
If that data does not include the temperature, that means that the sauna
|
|
is off, we then call the off command which will in turn return the temperature.
|
|
This is a workaround for getting the temperature as the Huum API does not
|
|
return the target temperature of a sauna that is off, even if it can have
|
|
a target temperature at that time.
|
|
"""
|
|
self._status = await self._huum_handler.status_from_status_or_stop()
|
|
if self._target_temperature is None or self.hvac_mode == HVACMode.HEAT:
|
|
self._target_temperature = self._status.target_temperature
|
|
|
|
async def _turn_on(self, temperature: int) -> None:
|
|
try:
|
|
await self._huum_handler.turn_on(temperature)
|
|
except (ValueError, SafetyException) as err:
|
|
_LOGGER.error(str(err))
|
|
raise HomeAssistantError(f"Unable to turn on sauna: {err}") from err
|