184 lines
6.0 KiB
Python
184 lines
6.0 KiB
Python
"""Support for humidifiers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from enum import StrEnum
|
|
from typing import Any, cast
|
|
|
|
from aiocomelit import ComelitSerialBridgeObject
|
|
from aiocomelit.const import CLIMATE
|
|
|
|
from homeassistant.components.humidifier import (
|
|
MODE_AUTO,
|
|
MODE_NORMAL,
|
|
HumidifierAction,
|
|
HumidifierDeviceClass,
|
|
HumidifierEntity,
|
|
HumidifierEntityFeature,
|
|
)
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
|
|
from .const import DOMAIN
|
|
from .coordinator import ComelitConfigEntry, ComelitSerialBridge
|
|
|
|
|
|
class HumidifierComelitMode(StrEnum):
|
|
"""Serial Bridge humidifier modes."""
|
|
|
|
AUTO = "A"
|
|
OFF = "O"
|
|
LOWER = "L"
|
|
UPPER = "U"
|
|
|
|
|
|
class HumidifierComelitCommand(StrEnum):
|
|
"""Serial Bridge humidifier commands."""
|
|
|
|
OFF = "off"
|
|
ON = "on"
|
|
MANUAL = "man"
|
|
SET = "set"
|
|
AUTO = "auto"
|
|
LOWER = "lower"
|
|
UPPER = "upper"
|
|
|
|
|
|
MODE_TO_ACTION: dict[str, HumidifierComelitCommand] = {
|
|
MODE_AUTO: HumidifierComelitCommand.AUTO,
|
|
MODE_NORMAL: HumidifierComelitCommand.MANUAL,
|
|
}
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
config_entry: ComelitConfigEntry,
|
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
|
) -> None:
|
|
"""Set up Comelit humidifiers."""
|
|
|
|
coordinator = cast(ComelitSerialBridge, config_entry.runtime_data)
|
|
|
|
entities: list[ComelitHumidifierEntity] = []
|
|
for device in coordinator.data[CLIMATE].values():
|
|
entities.append(
|
|
ComelitHumidifierEntity(
|
|
coordinator,
|
|
device,
|
|
config_entry.entry_id,
|
|
active_mode=HumidifierComelitMode.LOWER,
|
|
active_action=HumidifierAction.DRYING,
|
|
set_command=HumidifierComelitCommand.LOWER,
|
|
device_class=HumidifierDeviceClass.DEHUMIDIFIER,
|
|
)
|
|
)
|
|
entities.append(
|
|
ComelitHumidifierEntity(
|
|
coordinator,
|
|
device,
|
|
config_entry.entry_id,
|
|
active_mode=HumidifierComelitMode.UPPER,
|
|
active_action=HumidifierAction.HUMIDIFYING,
|
|
set_command=HumidifierComelitCommand.UPPER,
|
|
device_class=HumidifierDeviceClass.HUMIDIFIER,
|
|
),
|
|
)
|
|
|
|
async_add_entities(entities)
|
|
|
|
|
|
class ComelitHumidifierEntity(CoordinatorEntity[ComelitSerialBridge], HumidifierEntity):
|
|
"""Humidifier device."""
|
|
|
|
_attr_supported_features = HumidifierEntityFeature.MODES
|
|
_attr_available_modes = [MODE_NORMAL, MODE_AUTO]
|
|
_attr_min_humidity = 10
|
|
_attr_max_humidity = 90
|
|
_attr_has_entity_name = True
|
|
|
|
def __init__(
|
|
self,
|
|
coordinator: ComelitSerialBridge,
|
|
device: ComelitSerialBridgeObject,
|
|
config_entry_entry_id: str,
|
|
active_mode: HumidifierComelitMode,
|
|
active_action: HumidifierAction,
|
|
set_command: HumidifierComelitCommand,
|
|
device_class: HumidifierDeviceClass,
|
|
) -> None:
|
|
"""Init light entity."""
|
|
self._api = coordinator.api
|
|
self._device = device
|
|
super().__init__(coordinator)
|
|
# Use config_entry.entry_id as base for unique_id
|
|
# because no serial number or mac is available
|
|
self._attr_unique_id = f"{config_entry_entry_id}-{device.index}-{device_class}"
|
|
self._attr_device_info = coordinator.platform_device_info(device, device_class)
|
|
self._attr_device_class = device_class
|
|
self._attr_translation_key = device_class.value
|
|
self._active_mode = active_mode
|
|
self._active_action = active_action
|
|
self._set_command = set_command
|
|
|
|
@callback
|
|
def _handle_coordinator_update(self) -> None:
|
|
"""Handle updated data from the coordinator."""
|
|
device = self.coordinator.data[CLIMATE][self._device.index]
|
|
if not isinstance(device.val, list):
|
|
raise HomeAssistantError("Invalid clima data")
|
|
|
|
# CLIMATE has a 2 item tuple:
|
|
# - first for Clima
|
|
# - second for Humidifier
|
|
values = device.val[1]
|
|
|
|
_active = values[1]
|
|
_mode = values[2] # Values from API: "O", "L", "U"
|
|
_automatic = values[3] == HumidifierComelitMode.AUTO
|
|
|
|
self._attr_action = HumidifierAction.IDLE
|
|
if _mode == HumidifierComelitMode.OFF:
|
|
self._attr_action = HumidifierAction.OFF
|
|
if _active and _mode == self._active_mode:
|
|
self._attr_action = self._active_action
|
|
|
|
self._attr_current_humidity = values[0] / 10
|
|
self._attr_is_on = _mode == self._active_mode
|
|
self._attr_mode = MODE_AUTO if _automatic else MODE_NORMAL
|
|
self._attr_target_humidity = values[4] / 10
|
|
|
|
async def async_set_humidity(self, humidity: int) -> None:
|
|
"""Set new target humidity."""
|
|
if self.mode == HumidifierComelitMode.OFF:
|
|
raise ServiceValidationError(
|
|
translation_domain=DOMAIN,
|
|
translation_key="humidity_while_off",
|
|
)
|
|
|
|
await self.coordinator.api.set_humidity_status(
|
|
self._device.index, HumidifierComelitCommand.MANUAL
|
|
)
|
|
await self.coordinator.api.set_humidity_status(
|
|
self._device.index, HumidifierComelitCommand.SET, humidity
|
|
)
|
|
|
|
async def async_set_mode(self, mode: str) -> None:
|
|
"""Set humidifier mode."""
|
|
await self.coordinator.api.set_humidity_status(
|
|
self._device.index, MODE_TO_ACTION[mode]
|
|
)
|
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
|
"""Turn on."""
|
|
await self.coordinator.api.set_humidity_status(
|
|
self._device.index, self._set_command
|
|
)
|
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
|
"""Turn off."""
|
|
await self.coordinator.api.set_humidity_status(
|
|
self._device.index, HumidifierComelitCommand.OFF
|
|
)
|