mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Use climate enums in nest (#70723)
This commit is contained in:
parent
7cbe56dcdf
commit
76dd82f8e5
@ -14,25 +14,18 @@ from google_nest_sdm.thermostat_traits import (
|
|||||||
ThermostatTemperatureSetpointTrait,
|
ThermostatTemperatureSetpointTrait,
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.components.climate import ClimateEntity, ClimateEntityFeature
|
from homeassistant.components.climate import ClimateEntity
|
||||||
from homeassistant.components.climate.const import (
|
from homeassistant.components.climate.const import (
|
||||||
ATTR_HVAC_MODE,
|
ATTR_HVAC_MODE,
|
||||||
ATTR_TARGET_TEMP_HIGH,
|
ATTR_TARGET_TEMP_HIGH,
|
||||||
ATTR_TARGET_TEMP_LOW,
|
ATTR_TARGET_TEMP_LOW,
|
||||||
CURRENT_HVAC_COOL,
|
|
||||||
CURRENT_HVAC_HEAT,
|
|
||||||
CURRENT_HVAC_IDLE,
|
|
||||||
CURRENT_HVAC_OFF,
|
|
||||||
FAN_OFF,
|
FAN_OFF,
|
||||||
FAN_ON,
|
FAN_ON,
|
||||||
HVAC_MODE_AUTO,
|
|
||||||
HVAC_MODE_COOL,
|
|
||||||
HVAC_MODE_FAN_ONLY,
|
|
||||||
HVAC_MODE_HEAT,
|
|
||||||
HVAC_MODE_HEAT_COOL,
|
|
||||||
HVAC_MODE_OFF,
|
|
||||||
PRESET_ECO,
|
PRESET_ECO,
|
||||||
PRESET_NONE,
|
PRESET_NONE,
|
||||||
|
ClimateEntityFeature,
|
||||||
|
HVACAction,
|
||||||
|
HVACMode,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
|
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
|
||||||
@ -45,11 +38,11 @@ from .const import DATA_SUBSCRIBER, DOMAIN
|
|||||||
from .device_info import NestDeviceInfo
|
from .device_info import NestDeviceInfo
|
||||||
|
|
||||||
# Mapping for sdm.devices.traits.ThermostatMode mode field
|
# Mapping for sdm.devices.traits.ThermostatMode mode field
|
||||||
THERMOSTAT_MODE_MAP: dict[str, str] = {
|
THERMOSTAT_MODE_MAP: dict[str, HVACMode] = {
|
||||||
"OFF": HVAC_MODE_OFF,
|
"OFF": HVACMode.OFF,
|
||||||
"HEAT": HVAC_MODE_HEAT,
|
"HEAT": HVACMode.HEAT,
|
||||||
"COOL": HVAC_MODE_COOL,
|
"COOL": HVACMode.COOL,
|
||||||
"HEATCOOL": HVAC_MODE_HEAT_COOL,
|
"HEATCOOL": HVACMode.HEAT_COOL,
|
||||||
}
|
}
|
||||||
THERMOSTAT_INV_MODE_MAP = {v: k for k, v in THERMOSTAT_MODE_MAP.items()}
|
THERMOSTAT_INV_MODE_MAP = {v: k for k, v in THERMOSTAT_MODE_MAP.items()}
|
||||||
|
|
||||||
@ -58,12 +51,12 @@ THERMOSTAT_ECO_MODE = "MANUAL_ECO"
|
|||||||
|
|
||||||
# Mapping for sdm.devices.traits.ThermostatHvac status field
|
# Mapping for sdm.devices.traits.ThermostatHvac status field
|
||||||
THERMOSTAT_HVAC_STATUS_MAP = {
|
THERMOSTAT_HVAC_STATUS_MAP = {
|
||||||
"OFF": CURRENT_HVAC_OFF,
|
"OFF": HVACAction.OFF,
|
||||||
"HEATING": CURRENT_HVAC_HEAT,
|
"HEATING": HVACAction.HEATING,
|
||||||
"COOLING": CURRENT_HVAC_COOL,
|
"COOLING": HVACAction.COOLING,
|
||||||
}
|
}
|
||||||
|
|
||||||
THERMOSTAT_RANGE_MODES = [HVAC_MODE_HEAT_COOL, HVAC_MODE_AUTO]
|
THERMOSTAT_RANGE_MODES = [HVACMode.HEAT_COOL, HVACMode.AUTO]
|
||||||
|
|
||||||
PRESET_MODE_MAP = {
|
PRESET_MODE_MAP = {
|
||||||
"MANUAL_ECO": PRESET_ECO,
|
"MANUAL_ECO": PRESET_ECO,
|
||||||
@ -153,16 +146,16 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
"""Return the temperature currently set to be reached."""
|
"""Return the temperature currently set to be reached."""
|
||||||
if not (trait := self._target_temperature_trait):
|
if not (trait := self._target_temperature_trait):
|
||||||
return None
|
return None
|
||||||
if self.hvac_mode == HVAC_MODE_HEAT:
|
if self.hvac_mode == HVACMode.HEAT:
|
||||||
return trait.heat_celsius
|
return trait.heat_celsius
|
||||||
if self.hvac_mode == HVAC_MODE_COOL:
|
if self.hvac_mode == HVACMode.COOL:
|
||||||
return trait.cool_celsius
|
return trait.cool_celsius
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_temperature_high(self) -> float | None:
|
def target_temperature_high(self) -> float | None:
|
||||||
"""Return the upper bound target temperature."""
|
"""Return the upper bound target temperature."""
|
||||||
if self.hvac_mode != HVAC_MODE_HEAT_COOL:
|
if self.hvac_mode != HVACMode.HEAT_COOL:
|
||||||
return None
|
return None
|
||||||
if not (trait := self._target_temperature_trait):
|
if not (trait := self._target_temperature_trait):
|
||||||
return None
|
return None
|
||||||
@ -171,7 +164,7 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
@property
|
@property
|
||||||
def target_temperature_low(self) -> float | None:
|
def target_temperature_low(self) -> float | None:
|
||||||
"""Return the lower bound target temperature."""
|
"""Return the lower bound target temperature."""
|
||||||
if self.hvac_mode != HVAC_MODE_HEAT_COOL:
|
if self.hvac_mode != HVACMode.HEAT_COOL:
|
||||||
return None
|
return None
|
||||||
if not (trait := self._target_temperature_trait):
|
if not (trait := self._target_temperature_trait):
|
||||||
return None
|
return None
|
||||||
@ -197,26 +190,26 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_mode(self) -> str:
|
def hvac_mode(self) -> HVACMode:
|
||||||
"""Return the current operation (e.g. heat, cool, idle)."""
|
"""Return the current operation (e.g. heat, cool, idle)."""
|
||||||
hvac_mode = HVAC_MODE_OFF
|
hvac_mode = HVACMode.OFF
|
||||||
if ThermostatModeTrait.NAME in self._device.traits:
|
if ThermostatModeTrait.NAME in self._device.traits:
|
||||||
trait = self._device.traits[ThermostatModeTrait.NAME]
|
trait = self._device.traits[ThermostatModeTrait.NAME]
|
||||||
if trait.mode in THERMOSTAT_MODE_MAP:
|
if trait.mode in THERMOSTAT_MODE_MAP:
|
||||||
hvac_mode = THERMOSTAT_MODE_MAP[trait.mode]
|
hvac_mode = THERMOSTAT_MODE_MAP[trait.mode]
|
||||||
if hvac_mode == HVAC_MODE_OFF and self.fan_mode == FAN_ON:
|
if hvac_mode == HVACMode.OFF and self.fan_mode == FAN_ON:
|
||||||
hvac_mode = HVAC_MODE_FAN_ONLY
|
hvac_mode = HVACMode.FAN_ONLY
|
||||||
return hvac_mode
|
return hvac_mode
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_modes(self) -> list[str]:
|
def hvac_modes(self) -> list[HVACMode]:
|
||||||
"""List of available operation modes."""
|
"""List of available operation modes."""
|
||||||
supported_modes = []
|
supported_modes = []
|
||||||
for mode in self._get_device_hvac_modes:
|
for mode in self._get_device_hvac_modes:
|
||||||
if mode in THERMOSTAT_MODE_MAP:
|
if mode in THERMOSTAT_MODE_MAP:
|
||||||
supported_modes.append(THERMOSTAT_MODE_MAP[mode])
|
supported_modes.append(THERMOSTAT_MODE_MAP[mode])
|
||||||
if self.supported_features & ClimateEntityFeature.FAN_MODE:
|
if self.supported_features & ClimateEntityFeature.FAN_MODE:
|
||||||
supported_modes.append(HVAC_MODE_FAN_ONLY)
|
supported_modes.append(HVACMode.FAN_ONLY)
|
||||||
return supported_modes
|
return supported_modes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -229,14 +222,12 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
return set(modes)
|
return set(modes)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_action(self) -> str | None:
|
def hvac_action(self) -> HVACAction | None:
|
||||||
"""Return the current HVAC action (heating, cooling)."""
|
"""Return the current HVAC action (heating, cooling)."""
|
||||||
trait = self._device.traits[ThermostatHvacTrait.NAME]
|
trait = self._device.traits[ThermostatHvacTrait.NAME]
|
||||||
if trait.status == "OFF" and self.hvac_mode != HVAC_MODE_OFF:
|
if trait.status == "OFF" and self.hvac_mode != HVACMode.OFF:
|
||||||
return CURRENT_HVAC_IDLE
|
return HVACAction.IDLE
|
||||||
if trait.status in THERMOSTAT_HVAC_STATUS_MAP:
|
return THERMOSTAT_HVAC_STATUS_MAP.get(trait.status)
|
||||||
return THERMOSTAT_HVAC_STATUS_MAP[trait.status]
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_mode(self) -> str:
|
def preset_mode(self) -> str:
|
||||||
@ -281,9 +272,9 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
def _get_supported_features(self) -> int:
|
def _get_supported_features(self) -> int:
|
||||||
"""Compute the bitmap of supported features from the current state."""
|
"""Compute the bitmap of supported features from the current state."""
|
||||||
features = 0
|
features = 0
|
||||||
if HVAC_MODE_HEAT_COOL in self.hvac_modes:
|
if HVACMode.HEAT_COOL in self.hvac_modes:
|
||||||
features |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
features |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||||
if HVAC_MODE_HEAT in self.hvac_modes or HVAC_MODE_COOL in self.hvac_modes:
|
if HVACMode.HEAT in self.hvac_modes or HVACMode.COOL in self.hvac_modes:
|
||||||
features |= ClimateEntityFeature.TARGET_TEMPERATURE
|
features |= ClimateEntityFeature.TARGET_TEMPERATURE
|
||||||
if ThermostatEcoTrait.NAME in self._device.traits:
|
if ThermostatEcoTrait.NAME in self._device.traits:
|
||||||
features |= ClimateEntityFeature.PRESET_MODE
|
features |= ClimateEntityFeature.PRESET_MODE
|
||||||
@ -294,14 +285,14 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
features |= ClimateEntityFeature.FAN_MODE
|
features |= ClimateEntityFeature.FAN_MODE
|
||||||
return features
|
return features
|
||||||
|
|
||||||
async def async_set_hvac_mode(self, hvac_mode: str) -> None:
|
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||||
"""Set new target hvac mode."""
|
"""Set new target hvac mode."""
|
||||||
if hvac_mode not in self.hvac_modes:
|
if hvac_mode not in self.hvac_modes:
|
||||||
raise ValueError(f"Unsupported hvac_mode '{hvac_mode}'")
|
raise ValueError(f"Unsupported hvac_mode '{hvac_mode}'")
|
||||||
if hvac_mode == HVAC_MODE_FAN_ONLY:
|
if hvac_mode == HVACMode.FAN_ONLY:
|
||||||
# Turn the fan on but also turn off the hvac if it is on
|
# Turn the fan on but also turn off the hvac if it is on
|
||||||
await self.async_set_fan_mode(FAN_ON)
|
await self.async_set_fan_mode(FAN_ON)
|
||||||
hvac_mode = HVAC_MODE_OFF
|
hvac_mode = HVACMode.OFF
|
||||||
api_mode = THERMOSTAT_INV_MODE_MAP[hvac_mode]
|
api_mode = THERMOSTAT_INV_MODE_MAP[hvac_mode]
|
||||||
trait = self._device.traits[ThermostatModeTrait.NAME]
|
trait = self._device.traits[ThermostatModeTrait.NAME]
|
||||||
await trait.set_mode(api_mode)
|
await trait.set_mode(api_mode)
|
||||||
@ -318,12 +309,12 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
if ThermostatTemperatureSetpointTrait.NAME not in self._device.traits:
|
if ThermostatTemperatureSetpointTrait.NAME not in self._device.traits:
|
||||||
return
|
return
|
||||||
trait = self._device.traits[ThermostatTemperatureSetpointTrait.NAME]
|
trait = self._device.traits[ThermostatTemperatureSetpointTrait.NAME]
|
||||||
if self.preset_mode == PRESET_ECO or hvac_mode == HVAC_MODE_HEAT_COOL:
|
if self.preset_mode == PRESET_ECO or hvac_mode == HVACMode.HEAT_COOL:
|
||||||
if low_temp and high_temp:
|
if low_temp and high_temp:
|
||||||
await trait.set_range(low_temp, high_temp)
|
await trait.set_range(low_temp, high_temp)
|
||||||
elif hvac_mode == HVAC_MODE_COOL and temp:
|
elif hvac_mode == HVACMode.COOL and temp:
|
||||||
await trait.set_cool(temp)
|
await trait.set_cool(temp)
|
||||||
elif hvac_mode == HVAC_MODE_HEAT and temp:
|
elif hvac_mode == HVACMode.HEAT and temp:
|
||||||
await trait.set_heat(temp)
|
await trait.set_heat(temp)
|
||||||
|
|
||||||
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||||
|
@ -6,26 +6,18 @@ import logging
|
|||||||
from nest.nest import APIError
|
from nest.nest import APIError
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.climate import (
|
from homeassistant.components.climate import PLATFORM_SCHEMA, ClimateEntity
|
||||||
PLATFORM_SCHEMA,
|
|
||||||
ClimateEntity,
|
|
||||||
ClimateEntityFeature,
|
|
||||||
)
|
|
||||||
from homeassistant.components.climate.const import (
|
from homeassistant.components.climate.const import (
|
||||||
ATTR_TARGET_TEMP_HIGH,
|
ATTR_TARGET_TEMP_HIGH,
|
||||||
ATTR_TARGET_TEMP_LOW,
|
ATTR_TARGET_TEMP_LOW,
|
||||||
CURRENT_HVAC_COOL,
|
|
||||||
CURRENT_HVAC_HEAT,
|
|
||||||
CURRENT_HVAC_IDLE,
|
|
||||||
FAN_AUTO,
|
FAN_AUTO,
|
||||||
FAN_ON,
|
FAN_ON,
|
||||||
HVAC_MODE_AUTO,
|
|
||||||
HVAC_MODE_COOL,
|
|
||||||
HVAC_MODE_HEAT,
|
|
||||||
HVAC_MODE_OFF,
|
|
||||||
PRESET_AWAY,
|
PRESET_AWAY,
|
||||||
PRESET_ECO,
|
PRESET_ECO,
|
||||||
PRESET_NONE,
|
PRESET_NONE,
|
||||||
|
ClimateEntityFeature,
|
||||||
|
HVACAction,
|
||||||
|
HVACMode,
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_TEMPERATURE,
|
ATTR_TEMPERATURE,
|
||||||
@ -51,18 +43,18 @@ NEST_MODE_COOL = "cool"
|
|||||||
NEST_MODE_OFF = "off"
|
NEST_MODE_OFF = "off"
|
||||||
|
|
||||||
MODE_HASS_TO_NEST = {
|
MODE_HASS_TO_NEST = {
|
||||||
HVAC_MODE_AUTO: NEST_MODE_HEAT_COOL,
|
HVACMode.AUTO: NEST_MODE_HEAT_COOL,
|
||||||
HVAC_MODE_HEAT: NEST_MODE_HEAT,
|
HVACMode.HEAT: NEST_MODE_HEAT,
|
||||||
HVAC_MODE_COOL: NEST_MODE_COOL,
|
HVACMode.COOL: NEST_MODE_COOL,
|
||||||
HVAC_MODE_OFF: NEST_MODE_OFF,
|
HVACMode.OFF: NEST_MODE_OFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
MODE_NEST_TO_HASS = {v: k for k, v in MODE_HASS_TO_NEST.items()}
|
MODE_NEST_TO_HASS = {v: k for k, v in MODE_HASS_TO_NEST.items()}
|
||||||
|
|
||||||
ACTION_NEST_TO_HASS = {
|
ACTION_NEST_TO_HASS = {
|
||||||
"off": CURRENT_HVAC_IDLE,
|
"off": HVACAction.IDLE,
|
||||||
"heating": CURRENT_HVAC_HEAT,
|
"heating": HVACAction.HEATING,
|
||||||
"cooling": CURRENT_HVAC_COOL,
|
"cooling": HVACAction.COOLING,
|
||||||
}
|
}
|
||||||
|
|
||||||
PRESET_AWAY_AND_ECO = "Away and Eco"
|
PRESET_AWAY_AND_ECO = "Away and Eco"
|
||||||
@ -110,17 +102,17 @@ class NestThermostat(ClimateEntity):
|
|||||||
self._operation_list = []
|
self._operation_list = []
|
||||||
|
|
||||||
if self.device.can_heat and self.device.can_cool:
|
if self.device.can_heat and self.device.can_cool:
|
||||||
self._operation_list.append(HVAC_MODE_AUTO)
|
self._operation_list.append(HVACMode.AUTO)
|
||||||
self._support_flags |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
self._support_flags |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||||
|
|
||||||
# Add supported nest thermostat features
|
# Add supported nest thermostat features
|
||||||
if self.device.can_heat:
|
if self.device.can_heat:
|
||||||
self._operation_list.append(HVAC_MODE_HEAT)
|
self._operation_list.append(HVACMode.HEAT)
|
||||||
|
|
||||||
if self.device.can_cool:
|
if self.device.can_cool:
|
||||||
self._operation_list.append(HVAC_MODE_COOL)
|
self._operation_list.append(HVACMode.COOL)
|
||||||
|
|
||||||
self._operation_list.append(HVAC_MODE_OFF)
|
self._operation_list.append(HVACMode.OFF)
|
||||||
|
|
||||||
# feature of device
|
# feature of device
|
||||||
self._has_fan = self.device.has_fan
|
self._has_fan = self.device.has_fan
|
||||||
@ -197,7 +189,7 @@ class NestThermostat(ClimateEntity):
|
|||||||
return self._temperature
|
return self._temperature
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_mode(self):
|
def hvac_mode(self) -> HVACMode:
|
||||||
"""Return current operation ie. heat, cool, idle."""
|
"""Return current operation ie. heat, cool, idle."""
|
||||||
if self._mode == NEST_MODE_ECO:
|
if self._mode == NEST_MODE_ECO:
|
||||||
if self.device.previous_mode in MODE_NEST_TO_HASS:
|
if self.device.previous_mode in MODE_NEST_TO_HASS:
|
||||||
@ -209,7 +201,7 @@ class NestThermostat(ClimateEntity):
|
|||||||
return MODE_NEST_TO_HASS[self._mode]
|
return MODE_NEST_TO_HASS[self._mode]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_action(self):
|
def hvac_action(self) -> HVACAction:
|
||||||
"""Return the current hvac action."""
|
"""Return the current hvac action."""
|
||||||
return ACTION_NEST_TO_HASS[self._action]
|
return ACTION_NEST_TO_HASS[self._action]
|
||||||
|
|
||||||
@ -259,12 +251,12 @@ class NestThermostat(ClimateEntity):
|
|||||||
# restore target temperature
|
# restore target temperature
|
||||||
self.schedule_update_ha_state(True)
|
self.schedule_update_ha_state(True)
|
||||||
|
|
||||||
def set_hvac_mode(self, hvac_mode):
|
def set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||||
"""Set operation mode."""
|
"""Set operation mode."""
|
||||||
self.device.mode = MODE_HASS_TO_NEST[hvac_mode]
|
self.device.mode = MODE_HASS_TO_NEST[hvac_mode]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_modes(self):
|
def hvac_modes(self) -> list[HVACMode]:
|
||||||
"""List of available operation modes."""
|
"""List of available operation modes."""
|
||||||
return self._operation_list
|
return self._operation_list
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user