diff --git a/homeassistant/components/zwave_js/climate.py b/homeassistant/components/zwave_js/climate.py index 07119d365e0..e2bd69a1436 100644 --- a/homeassistant/components/zwave_js/climate.py +++ b/homeassistant/components/zwave_js/climate.py @@ -201,13 +201,25 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity): if self._fan_mode: self._attr_supported_features |= ClimateEntityFeature.FAN_MODE - def _setpoint_value(self, setpoint_type: ThermostatSetpointType) -> ZwaveValue: - """Optionally return a ZwaveValue for a setpoint.""" + def _setpoint_value_or_raise( + self, setpoint_type: ThermostatSetpointType + ) -> ZwaveValue: + """Return a ZwaveValue for a setpoint or raise if not available.""" if (val := self._setpoint_values[setpoint_type]) is None: raise ValueError("Value requested is not available") return val + def _setpoint_temperature( + self, setpoint_type: ThermostatSetpointType + ) -> float | None: + """Optionally return the temperature value of a setpoint.""" + try: + temp = self._setpoint_value_or_raise(setpoint_type) + except (IndexError, ValueError): + return None + return get_value_of_zwave_value(temp) + def _set_modes_and_presets(self) -> None: """Convert Z-Wave Thermostat modes into Home Assistant modes and presets.""" all_modes: dict[HVACMode, int | None] = {} @@ -290,36 +302,44 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity): @property def target_temperature(self) -> float | None: """Return the temperature we try to reach.""" - if self._current_mode and self._current_mode.value is None: + if ( + self._current_mode and self._current_mode.value is None + ) or not self._current_mode_setpoint_enums: # guard missing value return None - try: - temp = self._setpoint_value(self._current_mode_setpoint_enums[0]) - except (IndexError, ValueError): + if len(self._current_mode_setpoint_enums) > 1: + # current mode has a temperature range return None - return get_value_of_zwave_value(temp) + + return self._setpoint_temperature(self._current_mode_setpoint_enums[0]) @property def target_temperature_high(self) -> float | None: """Return the highbound target temperature we try to reach.""" - if self._current_mode and self._current_mode.value is None: + if ( + self._current_mode and self._current_mode.value is None + ) or not self._current_mode_setpoint_enums: # guard missing value return None - try: - temp = self._setpoint_value(self._current_mode_setpoint_enums[1]) - except (IndexError, ValueError): + if len(self._current_mode_setpoint_enums) < 2: + # current mode has a single temperature return None - return get_value_of_zwave_value(temp) + + return self._setpoint_temperature(self._current_mode_setpoint_enums[1]) @property def target_temperature_low(self) -> float | None: """Return the lowbound target temperature we try to reach.""" - if self._current_mode and self._current_mode.value is None: + if ( + self._current_mode and self._current_mode.value is None + ) or not self._current_mode_setpoint_enums: # guard missing value return None - if len(self._current_mode_setpoint_enums) > 1: - return self.target_temperature - return None + if len(self._current_mode_setpoint_enums) < 2: + # current mode has a single temperature + return None + + return self._setpoint_temperature(self._current_mode_setpoint_enums[0]) @property def preset_mode(self) -> str | None: @@ -380,7 +400,7 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity): min_temp = DEFAULT_MIN_TEMP base_unit = TEMP_CELSIUS try: - temp = self._setpoint_value(self._current_mode_setpoint_enums[0]) + temp = self._setpoint_value_or_raise(self._current_mode_setpoint_enums[0]) if temp.metadata.min: min_temp = temp.metadata.min base_unit = self.temperature_unit @@ -396,7 +416,7 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity): max_temp = DEFAULT_MAX_TEMP base_unit = TEMP_CELSIUS try: - temp = self._setpoint_value(self._current_mode_setpoint_enums[0]) + temp = self._setpoint_value_or_raise(self._current_mode_setpoint_enums[0]) if temp.metadata.max: max_temp = temp.metadata.max base_unit = self.temperature_unit @@ -431,17 +451,17 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity): if hvac_mode is not None: await self.async_set_hvac_mode(hvac_mode) if len(self._current_mode_setpoint_enums) == 1: - setpoint: ZwaveValue = self._setpoint_value( + setpoint: ZwaveValue = self._setpoint_value_or_raise( self._current_mode_setpoint_enums[0] ) target_temp: float | None = kwargs.get(ATTR_TEMPERATURE) if target_temp is not None: await self.info.node.async_set_value(setpoint, target_temp) elif len(self._current_mode_setpoint_enums) == 2: - setpoint_low: ZwaveValue = self._setpoint_value( + setpoint_low: ZwaveValue = self._setpoint_value_or_raise( self._current_mode_setpoint_enums[0] ) - setpoint_high: ZwaveValue = self._setpoint_value( + setpoint_high: ZwaveValue = self._setpoint_value_or_raise( self._current_mode_setpoint_enums[1] ) target_temp_low: float | None = kwargs.get(ATTR_TARGET_TEMP_LOW) diff --git a/tests/components/zwave_js/test_climate.py b/tests/components/zwave_js/test_climate.py index 755423e5e43..62dfacc7549 100644 --- a/tests/components/zwave_js/test_climate.py +++ b/tests/components/zwave_js/test_climate.py @@ -65,6 +65,8 @@ async def test_thermostat_v2( assert state.attributes[ATTR_CURRENT_HUMIDITY] == 30 assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 22.2 assert state.attributes[ATTR_TEMPERATURE] == 22.2 + assert state.attributes[ATTR_TARGET_TEMP_HIGH] is None + assert state.attributes[ATTR_TARGET_TEMP_LOW] is None assert state.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE assert state.attributes[ATTR_FAN_MODE] == "Auto low" assert state.attributes[ATTR_FAN_STATE] == "Idle / off" @@ -159,6 +161,8 @@ async def test_thermostat_v2( state = hass.states.get(CLIMATE_RADIO_THERMOSTAT_ENTITY) assert state.state == HVACMode.COOL assert state.attributes[ATTR_TEMPERATURE] == 22.8 + assert state.attributes[ATTR_TARGET_TEMP_HIGH] is None + assert state.attributes[ATTR_TARGET_TEMP_LOW] is None # Test heat_cool mode update from value updated event event = Event( @@ -182,6 +186,7 @@ async def test_thermostat_v2( state = hass.states.get(CLIMATE_RADIO_THERMOSTAT_ENTITY) assert state.state == HVACMode.HEAT_COOL + assert state.attributes[ATTR_TEMPERATURE] is None assert state.attributes[ATTR_TARGET_TEMP_HIGH] == 22.8 assert state.attributes[ATTR_TARGET_TEMP_LOW] == 22.2