mirror of https://github.com/home-assistant/core
145 lines
5.4 KiB
Python
145 lines
5.4 KiB
Python
"""EHEIM Digital climate."""
|
|
|
|
from typing import Any
|
|
|
|
from eheimdigital.device import EheimDigitalDevice
|
|
from eheimdigital.heater import EheimDigitalHeater
|
|
from eheimdigital.types import EheimDigitalClientError, HeaterMode, HeaterUnit
|
|
|
|
from homeassistant.components.climate import (
|
|
PRESET_NONE,
|
|
ClimateEntity,
|
|
ClimateEntityFeature,
|
|
HVACAction,
|
|
HVACMode,
|
|
)
|
|
from homeassistant.const import (
|
|
ATTR_TEMPERATURE,
|
|
PRECISION_HALVES,
|
|
PRECISION_TENTHS,
|
|
UnitOfTemperature,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
|
|
|
from .const import HEATER_BIO_MODE, HEATER_PRESET_TO_HEATER_MODE, HEATER_SMART_MODE
|
|
from .coordinator import EheimDigitalConfigEntry, EheimDigitalUpdateCoordinator
|
|
from .entity import EheimDigitalEntity
|
|
|
|
# Coordinator is used to centralize the data updates
|
|
PARALLEL_UPDATES = 0
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
entry: EheimDigitalConfigEntry,
|
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
|
) -> None:
|
|
"""Set up the callbacks for the coordinator so climate entities can be added as devices are found."""
|
|
coordinator = entry.runtime_data
|
|
|
|
def async_setup_device_entities(
|
|
device_address: dict[str, EheimDigitalDevice],
|
|
) -> None:
|
|
"""Set up the climate entities for one or multiple devices."""
|
|
entities: list[EheimDigitalHeaterClimate] = []
|
|
for device in device_address.values():
|
|
if isinstance(device, EheimDigitalHeater):
|
|
entities.append(EheimDigitalHeaterClimate(coordinator, device))
|
|
coordinator.known_devices.add(device.mac_address)
|
|
|
|
async_add_entities(entities)
|
|
|
|
coordinator.add_platform_callback(async_setup_device_entities)
|
|
|
|
async_setup_device_entities(coordinator.hub.devices)
|
|
|
|
|
|
class EheimDigitalHeaterClimate(EheimDigitalEntity[EheimDigitalHeater], ClimateEntity):
|
|
"""Represent an EHEIM Digital heater."""
|
|
|
|
_attr_hvac_modes = [HVACMode.OFF, HVACMode.AUTO]
|
|
_attr_hvac_mode = HVACMode.OFF
|
|
_attr_precision = PRECISION_TENTHS
|
|
_attr_supported_features = (
|
|
ClimateEntityFeature.TARGET_TEMPERATURE
|
|
| ClimateEntityFeature.TURN_ON
|
|
| ClimateEntityFeature.TURN_OFF
|
|
| ClimateEntityFeature.PRESET_MODE
|
|
)
|
|
_attr_target_temperature_step = PRECISION_HALVES
|
|
_attr_preset_modes = [PRESET_NONE, HEATER_BIO_MODE, HEATER_SMART_MODE]
|
|
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
|
_attr_preset_mode = PRESET_NONE
|
|
_attr_translation_key = "heater"
|
|
_attr_name = None
|
|
|
|
def __init__(
|
|
self, coordinator: EheimDigitalUpdateCoordinator, device: EheimDigitalHeater
|
|
) -> None:
|
|
"""Initialize an EHEIM Digital thermocontrol climate entity."""
|
|
super().__init__(coordinator, device)
|
|
self._attr_unique_id = self._device_address
|
|
self._async_update_attrs()
|
|
|
|
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
|
"""Set the preset mode."""
|
|
try:
|
|
if preset_mode in HEATER_PRESET_TO_HEATER_MODE:
|
|
await self._device.set_operation_mode(
|
|
HEATER_PRESET_TO_HEATER_MODE[preset_mode]
|
|
)
|
|
except EheimDigitalClientError as err:
|
|
raise HomeAssistantError from err
|
|
|
|
async def async_set_temperature(self, **kwargs: Any) -> None:
|
|
"""Set a new temperature."""
|
|
try:
|
|
if ATTR_TEMPERATURE in kwargs:
|
|
await self._device.set_target_temperature(kwargs[ATTR_TEMPERATURE])
|
|
except EheimDigitalClientError as err:
|
|
raise HomeAssistantError from err
|
|
|
|
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
|
"""Set the heating mode."""
|
|
try:
|
|
match hvac_mode:
|
|
case HVACMode.OFF:
|
|
await self._device.set_active(active=False)
|
|
case HVACMode.AUTO:
|
|
await self._device.set_active(active=True)
|
|
except EheimDigitalClientError as err:
|
|
raise HomeAssistantError from err
|
|
|
|
def _async_update_attrs(self) -> None:
|
|
if self._device.temperature_unit == HeaterUnit.CELSIUS:
|
|
self._attr_min_temp = 18
|
|
self._attr_max_temp = 32
|
|
self._attr_temperature_unit = UnitOfTemperature.CELSIUS
|
|
elif self._device.temperature_unit == HeaterUnit.FAHRENHEIT:
|
|
self._attr_min_temp = 64
|
|
self._attr_max_temp = 90
|
|
self._attr_temperature_unit = UnitOfTemperature.FAHRENHEIT
|
|
|
|
self._attr_current_temperature = self._device.current_temperature
|
|
self._attr_target_temperature = self._device.target_temperature
|
|
|
|
if self._device.is_heating:
|
|
self._attr_hvac_action = HVACAction.HEATING
|
|
self._attr_hvac_mode = HVACMode.AUTO
|
|
elif self._device.is_active:
|
|
self._attr_hvac_action = HVACAction.IDLE
|
|
self._attr_hvac_mode = HVACMode.AUTO
|
|
else:
|
|
self._attr_hvac_action = HVACAction.OFF
|
|
self._attr_hvac_mode = HVACMode.OFF
|
|
|
|
match self._device.operation_mode:
|
|
case HeaterMode.MANUAL:
|
|
self._attr_preset_mode = PRESET_NONE
|
|
case HeaterMode.BIO:
|
|
self._attr_preset_mode = HEATER_BIO_MODE
|
|
case HeaterMode.SMART:
|
|
self._attr_preset_mode = HEATER_SMART_MODE
|