255 lines
7.9 KiB
Python
255 lines
7.9 KiB
Python
"""Adds climate entity for each air conditioner appliance."""
|
|
|
|
import logging
|
|
from typing import Final
|
|
|
|
from homeassistant.components.climate import ClimateEntity
|
|
from homeassistant.components.climate.const import (
|
|
ATTR_FAN_MODE,
|
|
ATTR_HVAC_MODE,
|
|
ATTR_SWING_MODE,
|
|
FAN_AUTO,
|
|
FAN_HIGH,
|
|
FAN_LOW,
|
|
FAN_MEDIUM,
|
|
PRESET_BOOST,
|
|
PRESET_ECO,
|
|
PRESET_NONE,
|
|
PRESET_SLEEP,
|
|
PRESET_AWAY,
|
|
PRESET_COMFORT,
|
|
ClimateEntityFeature,
|
|
SWING_BOTH,
|
|
SWING_HORIZONTAL,
|
|
SWING_OFF,
|
|
SWING_VERTICAL,
|
|
HVACAction,
|
|
HVACMode,
|
|
)
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_HALVES, UnitOfTemperature
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from custom_components.midea_dehumidifier_lan.appliance_coordinator import (
|
|
ApplianceEntity,
|
|
)
|
|
from custom_components.midea_dehumidifier_lan.const import (
|
|
ATTR_RUNNING,
|
|
DOMAIN,
|
|
MAX_TARGET_TEMPERATURE,
|
|
MIN_TARGET_TEMPERATURE,
|
|
)
|
|
from custom_components.midea_dehumidifier_lan.hub import Hub
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
FAN_SILENT = "Silent"
|
|
FAN_FULL = "Full"
|
|
|
|
HVAC_MODES: Final = [
|
|
HVACMode.OFF,
|
|
HVACMode.AUTO,
|
|
HVACMode.COOL,
|
|
HVACMode.HEAT,
|
|
HVACMode.DRY,
|
|
HVACMode.FAN_ONLY,
|
|
]
|
|
FAN_MODES: Final = [
|
|
FAN_SILENT,
|
|
FAN_LOW,
|
|
FAN_MEDIUM,
|
|
FAN_HIGH,
|
|
FAN_FULL,
|
|
FAN_AUTO,
|
|
]
|
|
|
|
SWING_MODES: Final = [SWING_OFF, SWING_HORIZONTAL, SWING_VERTICAL, SWING_BOTH]
|
|
|
|
PRESET_MODES: Final = [PRESET_NONE, PRESET_ECO, PRESET_BOOST, PRESET_SLEEP, PRESET_AWAY, PRESET_COMFORT]
|
|
|
|
_FAN_SPEEDS = {
|
|
FAN_AUTO: 102,
|
|
FAN_FULL: 100,
|
|
FAN_HIGH: 80,
|
|
FAN_MEDIUM: 60,
|
|
FAN_LOW: 40,
|
|
FAN_SILENT: 20,
|
|
}
|
|
|
|
_MODES_TO_MIDEA = {
|
|
HVACMode.AUTO: 1,
|
|
HVACMode.COOL: 2,
|
|
HVACMode.DRY: 3,
|
|
HVACMode.HEAT: 4,
|
|
HVACMode.FAN_ONLY: 5,
|
|
}
|
|
|
|
_MIDEA_TO_MODES = {
|
|
1: HVACMode.AUTO,
|
|
2: HVACMode.COOL,
|
|
3: HVACMode.DRY,
|
|
4: HVACMode.HEAT,
|
|
5: HVACMode.FAN_ONLY,
|
|
}
|
|
|
|
_HVAC_ACTIONS = {
|
|
HVACMode.OFF: HVACAction.OFF,
|
|
HVACMode.AUTO: None,
|
|
HVACMode.COOL: HVACAction.COOLING,
|
|
HVACMode.DRY: HVACAction.DRYING,
|
|
HVACMode.HEAT: HVACAction.HEATING,
|
|
HVACMode.FAN_ONLY: HVACAction.FAN,
|
|
}
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
config_entry: ConfigEntry,
|
|
async_add_entities: AddEntitiesCallback,
|
|
) -> None:
|
|
"""Sets up air conditioner entites"""
|
|
hub: Hub = hass.data[DOMAIN][config_entry.entry_id]
|
|
|
|
async_add_entities(
|
|
AirConditionerEntity(c) for c in hub.coordinators if c.is_climate()
|
|
)
|
|
|
|
|
|
class AirConditionerEntity(ApplianceEntity, ClimateEntity):
|
|
"""Climate entity for Midea air conditioner"""
|
|
|
|
_attr_hvac_modes = HVAC_MODES
|
|
_attr_fan_modes = FAN_MODES
|
|
_attr_preset_modes = PRESET_MODES
|
|
_attr_swing_modes = SWING_MODES
|
|
_attr_max_temp = MAX_TARGET_TEMPERATURE
|
|
_attr_min_temp = MIN_TARGET_TEMPERATURE
|
|
_attr_precision = PRECISION_HALVES
|
|
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
|
|
|
_attr_supported_features = (
|
|
ClimateEntityFeature.TARGET_TEMPERATURE
|
|
| ClimateEntityFeature.FAN_MODE
|
|
| ClimateEntityFeature.SWING_MODE
|
|
| ClimateEntityFeature.PRESET_MODE
|
|
| ClimateEntityFeature.TURN_ON
|
|
| ClimateEntityFeature.TURN_OFF
|
|
)
|
|
|
|
_name_suffix = ""
|
|
_add_extra_attrs = True
|
|
|
|
def on_update(self) -> None:
|
|
aircon = self.airconditioner()
|
|
self._attr_current_temperature = aircon.indoor_temperature
|
|
self._attr_target_temperature = aircon.target_temperature
|
|
self._attr_fan_mode = self._fan_mode()
|
|
self._attr_preset_mode = self._preset_mode()
|
|
self._attr_swing_mode = self._swing_mode()
|
|
self._attr_hvac_mode = self._hvac_mode()
|
|
self._attr_hvac_action = _HVAC_ACTIONS.get(self._attr_hvac_mode)
|
|
super().on_update()
|
|
|
|
def _fan_mode(self) -> str:
|
|
fan_speed = self.airconditioner().fan_speed
|
|
for mode, mode_speed in _FAN_SPEEDS.items():
|
|
if fan_speed <= mode_speed:
|
|
return mode
|
|
return FAN_AUTO
|
|
|
|
def _preset_mode(self) -> str:
|
|
if self.airconditioner().turbo:
|
|
return PRESET_BOOST
|
|
if self.airconditioner().eco_mode:
|
|
return PRESET_ECO
|
|
if self.airconditioner().comfort_sleep:
|
|
return PRESET_SLEEP
|
|
if self.airconditioner().frost_protect:
|
|
return PRESET_AWAY
|
|
if self.airconditioner().comfort_mode:
|
|
return PRESET_COMFORT
|
|
return PRESET_NONE
|
|
|
|
def _swing_mode(self) -> str:
|
|
if self.airconditioner().vertical_swing:
|
|
if self.airconditioner().horizontal_swing:
|
|
return SWING_BOTH
|
|
return SWING_VERTICAL
|
|
if self.airconditioner().horizontal_swing:
|
|
return SWING_HORIZONTAL
|
|
return SWING_OFF
|
|
|
|
def _hvac_mode(self) -> str:
|
|
if not self.airconditioner().running:
|
|
return HVACMode.OFF
|
|
|
|
curr_mode = self.airconditioner().mode
|
|
mode = _MIDEA_TO_MODES.get(curr_mode)
|
|
if mode is None:
|
|
mode = HVACMode.AUTO
|
|
_LOGGER.warning("Unknown mode %d, reporting %s", curr_mode, mode)
|
|
|
|
return mode
|
|
|
|
def turn_on(self, **kwargs) -> None: # pylint: disable=unused-argument
|
|
"""Turn the entity on."""
|
|
self.apply(ATTR_RUNNING, True)
|
|
|
|
def turn_off(self, **kwargs) -> None: # pylint: disable=unused-argument
|
|
"""Turn the entity off."""
|
|
self.apply(ATTR_RUNNING, False)
|
|
|
|
def set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
|
"""Set new target hvac mode."""
|
|
if hvac_mode == HVACMode.OFF:
|
|
self.turn_off()
|
|
return
|
|
midea_mode = _MODES_TO_MIDEA.get(hvac_mode)
|
|
if midea_mode is None:
|
|
_LOGGER.warning("Unsupported climate mode %s", hvac_mode)
|
|
return
|
|
# Make sure we are running
|
|
if not self.airconditioner().running:
|
|
self.turn_on()
|
|
self.apply("mode", midea_mode)
|
|
|
|
def set_temperature(self, **kwargs) -> None:
|
|
"""Set new target temperature."""
|
|
if kwargs.get(ATTR_TEMPERATURE):
|
|
self.apply("target_temperature", kwargs.get(ATTR_TEMPERATURE))
|
|
if kwargs.get(ATTR_HVAC_MODE):
|
|
self.set_hvac_mode(kwargs.get(ATTR_HVAC_MODE))
|
|
if kwargs.get(ATTR_SWING_MODE):
|
|
self.set_swing_mode(kwargs.get(ATTR_SWING_MODE))
|
|
if kwargs.get(ATTR_FAN_MODE):
|
|
self.set_fan_mode(kwargs.get(ATTR_FAN_MODE))
|
|
|
|
def set_swing_mode(self, swing_mode: str) -> None:
|
|
if swing_mode == SWING_VERTICAL:
|
|
self.apply(vertical_swing=True, horizontal_swing=False)
|
|
elif swing_mode == SWING_HORIZONTAL:
|
|
self.apply(vertical_swing=False, horizontal_swing=True)
|
|
elif swing_mode == SWING_BOTH:
|
|
self.apply(vertical_swing=True, horizontal_swing=True)
|
|
else:
|
|
self.apply(vertical_swing=False, horizontal_swing=False)
|
|
|
|
def set_fan_mode(self, fan_mode: str) -> None:
|
|
self.apply(fan_speed=_FAN_SPEEDS.get(fan_mode, 20))
|
|
|
|
def set_preset_mode(self, preset_mode: str) -> None:
|
|
if preset_mode == PRESET_BOOST:
|
|
self.apply(turbo=True, eco_mode=False, comfort_sleep=False, frost_protect=False, comfort_mode=False)
|
|
elif preset_mode == PRESET_ECO:
|
|
self.apply(turbo=False, eco_mode=True, comfort_sleep=False, frost_protect=False, comfort_mode=False)
|
|
elif preset_mode == PRESET_SLEEP:
|
|
self.apply(turbo=False, eco_mode=False, comfort_sleep=True, frost_protect=False, comfort_mode=False)
|
|
elif preset_mode == PRESET_AWAY:
|
|
self.apply(turbo=False, eco_mode=False, comfort_sleep=False, frost_protect=True, comfort_mode=False)
|
|
elif preset_mode == PRESET_SLEEP:
|
|
self.apply(turbo=False, eco_mode=False, comfort_sleep=False, frost_protect=False, comfort_mode=True)
|
|
else:
|
|
self.apply(turbo=False, eco_mode=False, comfort_sleep=False, frost_protect=False, comfort_mode=False)
|