diff --git a/homeassistant/components/nest/climate_sdm.py b/homeassistant/components/nest/climate_sdm.py index 9171f066c19d680b87005f5540390e7c4f441080..57598e36ec958b367b874f6d85ea24f9641f7d88 100644 --- a/homeassistant/components/nest/climate_sdm.py +++ b/homeassistant/components/nest/climate_sdm.py @@ -46,7 +46,6 @@ THERMOSTAT_MODE_MAP = { "HEAT": HVAC_MODE_HEAT, "COOL": HVAC_MODE_COOL, "HEATCOOL": HVAC_MODE_HEAT_COOL, - "MANUAL_ECO": HVAC_MODE_AUTO, } THERMOSTAT_INV_MODE_MAP = {v: k for k, v in THERMOSTAT_MODE_MAP.items()} @@ -60,14 +59,6 @@ THERMOSTAT_HVAC_STATUS_MAP = { "COOLING": CURRENT_HVAC_COOL, } -# Mapping to determine the trait that supports the target temperatures -# based on the current HVAC mode -THERMOSTAT_SETPOINT_TRAIT_MAP = { - HVAC_MODE_COOL: ThermostatTemperatureSetpointTrait.NAME, - HVAC_MODE_HEAT: ThermostatTemperatureSetpointTrait.NAME, - HVAC_MODE_HEAT_COOL: ThermostatTemperatureSetpointTrait.NAME, - HVAC_MODE_AUTO: ThermostatEcoTrait.NAME, -} THERMOSTAT_RANGE_MODES = [HVAC_MODE_HEAT_COOL, HVAC_MODE_AUTO] PRESET_MODE_MAP = { @@ -170,7 +161,7 @@ class ThermostatEntity(ClimateEntity): @property def target_temperature_high(self): """Return the upper bound target temperature.""" - if self.hvac_mode not in THERMOSTAT_RANGE_MODES: + if self.hvac_mode != HVAC_MODE_HEAT_COOL: return None trait = self._target_temperature_trait if not trait: @@ -180,7 +171,7 @@ class ThermostatEntity(ClimateEntity): @property def target_temperature_low(self): """Return the lower bound target temperature.""" - if self.hvac_mode not in THERMOSTAT_RANGE_MODES: + if self.hvac_mode != HVAC_MODE_HEAT_COOL: return None trait = self._target_temperature_trait if not trait: @@ -192,20 +183,16 @@ class ThermostatEntity(ClimateEntity): """Return the correct trait with a target temp depending on mode.""" if not self.hvac_mode: return None - if self.hvac_mode not in THERMOSTAT_SETPOINT_TRAIT_MAP: - return None - trait_name = THERMOSTAT_SETPOINT_TRAIT_MAP[self.hvac_mode] - if trait_name not in self._device.traits: - return None - return self._device.traits[trait_name] + if self.preset_mode == PRESET_ECO: + if ThermostatEcoTrait.NAME in self._device.traits: + return self._device.traits[ThermostatEcoTrait.NAME] + if ThermostatTemperatureSetpointTrait.NAME in self._device.traits: + return self._device.traits[ThermostatTemperatureSetpointTrait.NAME] + return None @property def hvac_mode(self): """Return the current operation (e.g. heat, cool, idle).""" - if ThermostatEcoTrait.NAME in self._device.traits: - trait = self._device.traits[ThermostatEcoTrait.NAME] - if trait.mode == THERMOSTAT_ECO_MODE: - return HVAC_MODE_AUTO if ThermostatModeTrait.NAME in self._device.traits: trait = self._device.traits[ThermostatModeTrait.NAME] if trait.mode in THERMOSTAT_MODE_MAP: @@ -228,9 +215,6 @@ class ThermostatEntity(ClimateEntity): if ThermostatModeTrait.NAME in self._device.traits: trait = self._device.traits[ThermostatModeTrait.NAME] modes.extend(trait.available_modes) - if ThermostatEcoTrait.NAME in self._device.traits: - trait = self._device.traits[ThermostatEcoTrait.NAME] - modes.extend(trait.available_modes) return set(modes) @property @@ -274,7 +258,7 @@ class ThermostatEntity(ClimateEntity): def fan_modes(self): """Return the list of available fan modes.""" if FanTrait.NAME in self._device.traits: - return list(FAN_INV_MODE_MAP.keys()) + return list(FAN_INV_MODE_MAP) return [] @property @@ -285,7 +269,7 @@ class ThermostatEntity(ClimateEntity): def _get_supported_features(self): """Compute the bitmap of supported features from the current state.""" features = 0 - if HVAC_MODE_HEAT_COOL in self.hvac_modes or HVAC_MODE_AUTO in self.hvac_modes: + if HVAC_MODE_HEAT_COOL in self.hvac_modes: features |= SUPPORT_TARGET_TEMPERATURE_RANGE if HVAC_MODE_HEAT in self.hvac_modes or HVAC_MODE_COOL in self.hvac_modes: features |= SUPPORT_TARGET_TEMPERATURE @@ -320,11 +304,11 @@ class ThermostatEntity(ClimateEntity): trait = self._device.traits[ThermostatTemperatureSetpointTrait.NAME] if self.preset_mode == PRESET_ECO or self.hvac_mode == HVAC_MODE_HEAT_COOL: if low_temp and high_temp: - return await trait.set_range(low_temp, high_temp) + await trait.set_range(low_temp, high_temp) elif self.hvac_mode == HVAC_MODE_COOL and temp: - return await trait.set_cool(temp) + await trait.set_cool(temp) elif self.hvac_mode == HVAC_MODE_HEAT and temp: - return await trait.set_heat(temp) + await trait.set_heat(temp) async def async_set_preset_mode(self, preset_mode): """Set new target preset mode.""" diff --git a/tests/components/nest/climate_sdm_test.py b/tests/components/nest/climate_sdm_test.py index db5223b66811b9ed2209752fa4c077654802c24b..48efd32d859b852e202be6d3f2fd60e5b17f7062 100644 --- a/tests/components/nest/climate_sdm_test.py +++ b/tests/components/nest/climate_sdm_test.py @@ -23,7 +23,6 @@ from homeassistant.components.climate.const import ( CURRENT_HVAC_OFF, FAN_OFF, FAN_ON, - HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, @@ -267,7 +266,6 @@ async def test_thermostat_eco_off(hass): HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL, - HVAC_MODE_AUTO, HVAC_MODE_OFF, } assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] == 22.0 @@ -308,14 +306,13 @@ async def test_thermostat_eco_on(hass): assert len(hass.states.async_all()) == 1 thermostat = hass.states.get("climate.my_thermostat") assert thermostat is not None - assert thermostat.state == HVAC_MODE_AUTO + assert thermostat.state == HVAC_MODE_HEAT_COOL assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_COOL assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 29.9 assert set(thermostat.attributes[ATTR_HVAC_MODES]) == { HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL, - HVAC_MODE_AUTO, HVAC_MODE_OFF, } assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] == 21.0 @@ -325,6 +322,48 @@ async def test_thermostat_eco_on(hass): assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE] +async def test_thermostat_eco_heat_only(hass): + """Test a thermostat in eco mode that only supports heat.""" + await setup_climate( + hass, + { + "sdm.devices.traits.ThermostatHvac": { + "status": "OFF", + }, + "sdm.devices.traits.ThermostatMode": { + "availableModes": ["HEAT", "OFF"], + "mode": "HEAT", + }, + "sdm.devices.traits.ThermostatEco": { + "availableModes": ["MANUAL_ECO", "OFF"], + "mode": "MANUAL_ECO", + "heatCelsius": 21.0, + "coolCelsius": 29.0, + }, + "sdm.devices.traits.Temperature": { + "ambientTemperatureCelsius": 29.9, + }, + "sdm.devices.traits.ThermostatTemperatureSetpoint": {}, + }, + ) + + assert len(hass.states.async_all()) == 1 + thermostat = hass.states.get("climate.my_thermostat") + assert thermostat is not None + assert thermostat.state == HVAC_MODE_HEAT + assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF + assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 29.9 + assert set(thermostat.attributes[ATTR_HVAC_MODES]) == { + HVAC_MODE_HEAT, + HVAC_MODE_OFF, + } + assert thermostat.attributes[ATTR_TEMPERATURE] == 21.0 + assert ATTR_TARGET_TEMP_LOW not in thermostat.attributes + assert ATTR_TARGET_TEMP_HIGH not in thermostat.attributes + assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_ECO + assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE] + + class FakeAuth: """A fake implementation of the auth class that records requests.""" @@ -498,7 +537,7 @@ async def test_thermostat_set_eco_preset(hass): thermostat = hass.states.get("climate.my_thermostat") assert thermostat is not None - assert thermostat.state == HVAC_MODE_AUTO + assert thermostat.state == HVAC_MODE_OFF assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_ECO