Files

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

203 lines
6.7 KiB
Python
Raw Permalink Normal View History

2022-01-17 09:41:18 -05:00
"""CoolMasterNet platform to control of CoolMasterNet Climate Devices."""
2019-02-10 20:34:39 +02:00
import logging
2022-08-19 13:02:46 +02:00
from typing import Any
2019-02-10 20:34:39 +02:00
from pycoolmasternet_async import SWING_MODES
from homeassistant.components.climate import (
FAN_AUTO,
FAN_HIGH,
FAN_LOW,
FAN_MEDIUM,
ClimateEntity,
ClimateEntityFeature,
HVACMode,
)
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
2025-01-24 08:58:35 +01:00
from .const import CONF_SUPPORTED_MODES
from .coordinator import CoolmasterConfigEntry, CoolmasterDataUpdateCoordinator
from .entity import CoolmasterEntity
2019-02-10 20:34:39 +02:00
CM_TO_HA_STATE = {
2022-04-25 13:18:34 +02:00
"heat": HVACMode.HEAT,
"cool": HVACMode.COOL,
"auto": HVACMode.HEAT_COOL,
"dry": HVACMode.DRY,
"fan": HVACMode.FAN_ONLY,
2019-02-10 20:34:39 +02:00
}
HA_STATE_TO_CM = {value: key for key, value in CM_TO_HA_STATE.items()}
CM_TO_HA_FAN = {
"low": FAN_LOW,
"med": FAN_MEDIUM,
"high": FAN_HIGH,
"auto": FAN_AUTO,
}
HA_FAN_TO_CM = {value: key for key, value in CM_TO_HA_FAN.items()}
FAN_MODES = list(CM_TO_HA_FAN.values())
2019-02-10 20:34:39 +02:00
_LOGGER = logging.getLogger(__name__)
2022-01-03 13:26:32 +01:00
async def async_setup_entry(
hass: HomeAssistant,
2025-01-24 08:58:35 +01:00
config_entry: CoolmasterConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
2022-01-03 13:26:32 +01:00
) -> None:
2019-02-10 20:34:39 +02:00
"""Set up the CoolMasterNet climate platform."""
2025-01-24 08:58:35 +01:00
coordinator = config_entry.runtime_data
supported_modes: list[str] = config_entry.data[CONF_SUPPORTED_MODES]
async_add_entities(
2025-01-24 08:58:35 +01:00
CoolmasterClimate(
coordinator, unit_id, [HVACMode(mode) for mode in supported_modes]
)
for unit_id in coordinator.data
)
2019-02-10 20:34:39 +02:00
class CoolmasterClimate(CoolmasterEntity, ClimateEntity):
2019-02-10 20:34:39 +02:00
"""Representation of a coolmaster climate device."""
_attr_name = None
# TODO(2026.7.0): When support for unknown fan speeds is removed, delete this variable.
# Holds unknown fan speeds we have already warned about.
warned_unknown_fan_speeds: set[str] = set()
2025-01-24 08:58:35 +01:00
def __init__(
self,
coordinator: CoolmasterDataUpdateCoordinator,
unit_id: str,
supported_modes: list[HVACMode],
) -> None:
2019-02-10 20:34:39 +02:00
"""Initialize the climate device."""
2025-01-24 08:58:35 +01:00
super().__init__(coordinator, unit_id)
self._attr_hvac_modes = supported_modes
self._attr_unique_id = unit_id
2019-02-10 20:34:39 +02:00
@property
def supported_features(self) -> ClimateEntityFeature:
"""Return the list of supported features."""
supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
if self.swing_mode:
supported_features |= ClimateEntityFeature.SWING_MODE
return supported_features
2019-02-10 20:34:39 +02:00
@property
2022-08-19 13:02:46 +02:00
def temperature_unit(self) -> str:
2019-02-10 20:34:39 +02:00
"""Return the unit of measurement."""
if self._unit.temperature_unit == "celsius":
return UnitOfTemperature.CELSIUS
return UnitOfTemperature.FAHRENHEIT
2019-02-10 20:34:39 +02:00
@property
def current_temperature(self) -> float:
2019-02-10 20:34:39 +02:00
"""Return the current temperature."""
return self._unit.temperature
2019-02-10 20:34:39 +02:00
@property
def target_temperature(self) -> float:
2019-02-10 20:34:39 +02:00
"""Return the temperature we are trying to reach."""
return self._unit.thermostat
2019-02-10 20:34:39 +02:00
@property
def hvac_mode(self) -> HVACMode:
2019-07-08 14:00:24 +02:00
"""Return hvac target hvac state."""
mode = self._unit.mode
2021-10-17 19:56:00 +02:00
if not self._unit.is_on:
2022-04-25 13:18:34 +02:00
return HVACMode.OFF
return CM_TO_HA_STATE[mode]
2019-02-10 20:34:39 +02:00
@property
def fan_mode(self) -> str:
2019-02-10 20:34:39 +02:00
"""Return the fan setting."""
# Normalize to lowercase for lookup, and pass unknown lowercase values through.
fan_speed_lower = self._unit.fan_speed.lower()
if fan_speed_lower not in CM_TO_HA_FAN:
# TODO(2026.7.0): Stop supporting unknown fan speeds.
if fan_speed_lower not in CoolmasterClimate.warned_unknown_fan_speeds:
CoolmasterClimate.warned_unknown_fan_speeds.add(fan_speed_lower)
_LOGGER.warning(
"Detected unknown fan speed value from HVAC unit: %s. "
"Support for unknown fan speeds will be removed in 2026.7.0",
fan_speed_lower,
)
return fan_speed_lower
return CM_TO_HA_FAN[fan_speed_lower]
2019-02-10 20:34:39 +02:00
@property
def fan_modes(self) -> list[str]:
2019-02-10 20:34:39 +02:00
"""Return the list of available fan modes."""
return FAN_MODES
@property
def swing_mode(self) -> str | None:
"""Return the swing mode setting."""
return self._unit.swing
@property
def swing_modes(self) -> list[str] | None:
"""Return swing modes if supported."""
return SWING_MODES if self.swing_mode is not None else None
2022-08-19 13:02:46 +02:00
async def async_set_temperature(self, **kwargs: Any) -> None:
2019-02-10 20:34:39 +02:00
"""Set new target temperatures."""
2021-10-18 15:54:38 +02:00
if (temp := kwargs.get(ATTR_TEMPERATURE)) is not None:
2019-02-10 20:34:39 +02:00
_LOGGER.debug("Setting temp of %s to %s", self.unique_id, str(temp))
self._unit = await self._unit.set_thermostat(temp)
self.async_write_ha_state()
2019-02-10 20:34:39 +02:00
2022-08-19 13:02:46 +02:00
async def async_set_fan_mode(self, fan_mode: str) -> None:
2019-02-10 20:34:39 +02:00
"""Set new fan mode."""
_LOGGER.debug("Setting fan mode of %s to %s", self.unique_id, fan_mode)
self._unit = await self._unit.set_fan_speed(HA_FAN_TO_CM[fan_mode])
self.async_write_ha_state()
2019-02-10 20:34:39 +02:00
async def async_set_swing_mode(self, swing_mode: str) -> None:
"""Set new swing mode."""
_LOGGER.debug("Setting swing mode of %s to %s", self.unique_id, swing_mode)
try:
self._unit = await self._unit.set_swing(swing_mode)
except ValueError as error:
raise HomeAssistantError(error) from error
self.async_write_ha_state()
2022-08-19 13:02:46 +02:00
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
2019-02-10 20:34:39 +02:00
"""Set new operation mode."""
_LOGGER.debug("Setting operation mode of %s to %s", self.unique_id, hvac_mode)
2022-04-25 13:18:34 +02:00
if hvac_mode == HVACMode.OFF:
await self.async_turn_off()
2019-07-08 14:00:24 +02:00
else:
self._unit = await self._unit.set_mode(HA_STATE_TO_CM[hvac_mode])
await self.async_turn_on()
2019-07-12 18:40:29 +03:00
2022-08-19 13:02:46 +02:00
async def async_turn_on(self) -> None:
2019-07-12 18:40:29 +03:00
"""Turn on."""
_LOGGER.debug("Turning %s on", self.unique_id)
self._unit = await self._unit.turn_on()
self.async_write_ha_state()
2019-07-12 18:40:29 +03:00
2022-08-19 13:02:46 +02:00
async def async_turn_off(self) -> None:
2019-07-12 18:40:29 +03:00
"""Turn off."""
_LOGGER.debug("Turning %s off", self.unique_id)
self._unit = await self._unit.turn_off()
self.async_write_ha_state()