1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00
ha-core/homeassistant/components/dyson/climate.py
2021-04-09 09:58:27 -07:00

318 lines
10 KiB
Python

"""Support for Dyson Pure Hot+Cool link fan."""
import logging
from libpurecool.const import (
AutoMode,
FanPower,
FanSpeed,
FanState,
FocusMode,
HeatMode,
HeatState,
HeatTarget,
)
from libpurecool.dyson_pure_hotcool import DysonPureHotCool
from libpurecool.dyson_pure_hotcool_link import DysonPureHotCoolLink
from libpurecool.dyson_pure_state import DysonPureHotCoolState
from libpurecool.dyson_pure_state_v2 import DysonPureHotCoolV2State
from homeassistant.components.climate import ClimateEntity
from homeassistant.components.climate.const import (
CURRENT_HVAC_COOL,
CURRENT_HVAC_HEAT,
CURRENT_HVAC_IDLE,
CURRENT_HVAC_OFF,
FAN_AUTO,
FAN_DIFFUSE,
FAN_FOCUS,
FAN_HIGH,
FAN_LOW,
FAN_MEDIUM,
FAN_OFF,
HVAC_MODE_COOL,
HVAC_MODE_HEAT,
HVAC_MODE_OFF,
SUPPORT_FAN_MODE,
SUPPORT_TARGET_TEMPERATURE,
)
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
from . import DYSON_DEVICES, DysonEntity
_LOGGER = logging.getLogger(__name__)
SUPPORT_FAN = [FAN_FOCUS, FAN_DIFFUSE]
SUPPORT_FAN_PCOOL = [FAN_OFF, FAN_AUTO, FAN_LOW, FAN_MEDIUM, FAN_HIGH]
SUPPORT_HVAC = [HVAC_MODE_COOL, HVAC_MODE_HEAT]
SUPPORT_HVAC_PCOOL = [HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF]
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE
DYSON_KNOWN_CLIMATE_DEVICES = "dyson_known_climate_devices"
SPEED_MAP = {
FanSpeed.FAN_SPEED_1.value: FAN_LOW,
FanSpeed.FAN_SPEED_2.value: FAN_LOW,
FanSpeed.FAN_SPEED_3.value: FAN_LOW,
FanSpeed.FAN_SPEED_4.value: FAN_LOW,
FanSpeed.FAN_SPEED_AUTO.value: FAN_AUTO,
FanSpeed.FAN_SPEED_5.value: FAN_MEDIUM,
FanSpeed.FAN_SPEED_6.value: FAN_MEDIUM,
FanSpeed.FAN_SPEED_7.value: FAN_MEDIUM,
FanSpeed.FAN_SPEED_8.value: FAN_HIGH,
FanSpeed.FAN_SPEED_9.value: FAN_HIGH,
FanSpeed.FAN_SPEED_10.value: FAN_HIGH,
}
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Dyson fan components."""
if discovery_info is None:
return
known_devices = hass.data.setdefault(DYSON_KNOWN_CLIMATE_DEVICES, set())
# Get Dyson Devices from parent component
new_entities = []
for device in hass.data[DYSON_DEVICES]:
if device.serial not in known_devices:
if isinstance(device, DysonPureHotCool):
dyson_entity = DysonPureHotCoolEntity(device)
new_entities.append(dyson_entity)
known_devices.add(device.serial)
elif isinstance(device, DysonPureHotCoolLink):
dyson_entity = DysonPureHotCoolLinkEntity(device)
new_entities.append(dyson_entity)
known_devices.add(device.serial)
add_entities(new_entities)
class DysonClimateEntity(DysonEntity, ClimateEntity):
"""Representation of a Dyson climate fan."""
@property
def supported_features(self):
"""Return the list of supported features."""
return SUPPORT_FLAGS
@property
def temperature_unit(self):
"""Return the unit of measurement."""
return TEMP_CELSIUS
@property
def current_temperature(self):
"""Return the current temperature."""
if (
self._device.environmental_state
and self._device.environmental_state.temperature
):
temperature_kelvin = self._device.environmental_state.temperature
return float(f"{temperature_kelvin - 273:.1f}")
return None
@property
def target_temperature(self):
"""Return the target temperature."""
heat_target = int(self._device.state.heat_target) / 10
return int(heat_target - 273)
@property
def current_humidity(self):
"""Return the current humidity."""
# Humidity equaling to 0 means invalid value so we don't check for None here
# https://github.com/home-assistant/core/pull/45172#discussion_r559069756
if (
self._device.environmental_state
and self._device.environmental_state.humidity
):
return self._device.environmental_state.humidity
return None
@property
def min_temp(self):
"""Return the minimum temperature."""
return 1
@property
def max_temp(self):
"""Return the maximum temperature."""
return 37
def set_temperature(self, **kwargs):
"""Set new target temperature."""
target_temp = kwargs.get(ATTR_TEMPERATURE)
if target_temp is None:
_LOGGER.error("Missing target temperature %s", kwargs)
return
target_temp = int(target_temp)
_LOGGER.debug("Set %s temperature %s", self.name, target_temp)
# Limit the target temperature into acceptable range.
target_temp = min(self.max_temp, target_temp)
target_temp = max(self.min_temp, target_temp)
self.set_heat_target(HeatTarget.celsius(target_temp))
def set_heat_target(self, heat_target):
"""Set heating target temperature."""
class DysonPureHotCoolLinkEntity(DysonClimateEntity):
"""Representation of a Dyson climate fan."""
def __init__(self, device):
"""Initialize the fan."""
super().__init__(device, DysonPureHotCoolState)
@property
def hvac_mode(self):
"""Return hvac operation ie. heat, cool mode.
Need to be one of HVAC_MODE_*.
"""
if self._device.state.heat_mode == HeatMode.HEAT_ON.value:
return HVAC_MODE_HEAT
return HVAC_MODE_COOL
@property
def hvac_modes(self):
"""Return the list of available hvac operation modes.
Need to be a subset of HVAC_MODES.
"""
return SUPPORT_HVAC
@property
def hvac_action(self):
"""Return the current running hvac operation if supported.
Need to be one of CURRENT_HVAC_*.
"""
if self._device.state.heat_mode == HeatMode.HEAT_ON.value:
if self._device.state.heat_state == HeatState.HEAT_STATE_ON.value:
return CURRENT_HVAC_HEAT
return CURRENT_HVAC_IDLE
return CURRENT_HVAC_COOL
@property
def fan_mode(self):
"""Return the fan setting."""
if self._device.state.focus_mode == FocusMode.FOCUS_ON.value:
return FAN_FOCUS
return FAN_DIFFUSE
@property
def fan_modes(self):
"""Return the list of available fan modes."""
return SUPPORT_FAN
def set_heat_target(self, heat_target):
"""Set heating target temperature."""
self._device.set_configuration(
heat_target=heat_target, heat_mode=HeatMode.HEAT_ON
)
def set_fan_mode(self, fan_mode):
"""Set new fan mode."""
_LOGGER.debug("Set %s focus mode %s", self.name, fan_mode)
if fan_mode == FAN_FOCUS:
self._device.set_configuration(focus_mode=FocusMode.FOCUS_ON)
elif fan_mode == FAN_DIFFUSE:
self._device.set_configuration(focus_mode=FocusMode.FOCUS_OFF)
def set_hvac_mode(self, hvac_mode):
"""Set new target hvac mode."""
_LOGGER.debug("Set %s heat mode %s", self.name, hvac_mode)
if hvac_mode == HVAC_MODE_HEAT:
self._device.set_configuration(heat_mode=HeatMode.HEAT_ON)
elif hvac_mode == HVAC_MODE_COOL:
self._device.set_configuration(heat_mode=HeatMode.HEAT_OFF)
class DysonPureHotCoolEntity(DysonClimateEntity):
"""Representation of a Dyson climate hot+cool fan."""
def __init__(self, device):
"""Initialize the fan."""
super().__init__(device, DysonPureHotCoolV2State)
@property
def hvac_mode(self):
"""Return hvac operation ie. heat, cool mode.
Need to be one of HVAC_MODE_*.
"""
if self._device.state.fan_power == FanPower.POWER_OFF.value:
return HVAC_MODE_OFF
if self._device.state.heat_mode == HeatMode.HEAT_ON.value:
return HVAC_MODE_HEAT
return HVAC_MODE_COOL
@property
def hvac_modes(self):
"""Return the list of available hvac operation modes.
Need to be a subset of HVAC_MODES.
"""
return SUPPORT_HVAC_PCOOL
@property
def hvac_action(self):
"""Return the current running hvac operation if supported.
Need to be one of CURRENT_HVAC_*.
"""
if self._device.state.fan_power == FanPower.POWER_OFF.value:
return CURRENT_HVAC_OFF
if self._device.state.heat_mode == HeatMode.HEAT_ON.value:
if self._device.state.heat_state == HeatState.HEAT_STATE_ON.value:
return CURRENT_HVAC_HEAT
return CURRENT_HVAC_IDLE
return CURRENT_HVAC_COOL
@property
def fan_mode(self):
"""Return the fan setting."""
if (
self._device.state.auto_mode != AutoMode.AUTO_ON.value
and self._device.state.fan_state == FanState.FAN_OFF.value
):
return FAN_OFF
return SPEED_MAP[self._device.state.speed]
@property
def fan_modes(self):
"""Return the list of available fan modes."""
return SUPPORT_FAN_PCOOL
def set_heat_target(self, heat_target):
"""Set heating target temperature."""
self._device.set_heat_target(heat_target)
def set_fan_mode(self, fan_mode):
"""Set new fan mode."""
_LOGGER.debug("Set %s focus mode %s", self.name, fan_mode)
if fan_mode == FAN_OFF:
self._device.turn_off()
elif fan_mode == FAN_LOW:
self._device.set_fan_speed(FanSpeed.FAN_SPEED_4)
elif fan_mode == FAN_MEDIUM:
self._device.set_fan_speed(FanSpeed.FAN_SPEED_7)
elif fan_mode == FAN_HIGH:
self._device.set_fan_speed(FanSpeed.FAN_SPEED_10)
elif fan_mode == FAN_AUTO:
self._device.enable_auto_mode()
def set_hvac_mode(self, hvac_mode):
"""Set new target hvac mode."""
_LOGGER.debug("Set %s heat mode %s", self.name, hvac_mode)
if hvac_mode == HVAC_MODE_OFF:
self._device.turn_off()
elif self._device.state.fan_power == FanPower.POWER_OFF.value:
self._device.turn_on()
if hvac_mode == HVAC_MODE_HEAT:
self._device.enable_heat_mode()
elif hvac_mode == HVAC_MODE_COOL:
self._device.disable_heat_mode()