From 44f553e761878fc657343614c54eac8017629fcd Mon Sep 17 00:00:00 2001 From: StellarSea Date: Fri, 7 Aug 2026 20:37:14 +0900 Subject: [PATCH] Use SmartThings cooling setpoint range for air conditioners (#178430) Co-authored-by: Claude Opus 5 --- .../components/smartthings/climate.py | 33 +++++++++++++++++++ .../smartthings/snapshots/test_climate.ambr | 20 ++++++----- tests/components/smartthings/test_climate.py | 32 ++++++++++++++++++ 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/smartthings/climate.py b/homeassistant/components/smartthings/climate.py index b54e115cb80f..13130a9858c4 100644 --- a/homeassistant/components/smartthings/climate.py +++ b/homeassistant/components/smartthings/climate.py @@ -582,6 +582,39 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateEntity): Capability.THERMOSTAT_COOLING_SETPOINT, Attribute.COOLING_SETPOINT ) + def _get_setpoint_range_value(self, key: str) -> float | None: + """Return a value from the cooling setpoint range, if the device reports it.""" + if ( + setpoint_range := self.get_attribute_value( + Capability.THERMOSTAT_COOLING_SETPOINT, + Attribute.COOLING_SETPOINT_RANGE, + ) + ) is None: + return None + return setpoint_range.get(key) + + @property + @override + def target_temperature_step(self) -> float | None: + """Return the supported step of target temperature.""" + return self._get_setpoint_range_value("step") + + @property + @override + def min_temp(self) -> float: + """Return the minimum temperature.""" + if (minimum := self._get_setpoint_range_value("minimum")) is None: + return DEFAULT_MIN_TEMP + return minimum + + @property + @override + def max_temp(self) -> float: + """Return the maximum temperature.""" + if (maximum := self._get_setpoint_range_value("maximum")) is None: + return DEFAULT_MAX_TEMP + return maximum + @property @override def temperature_unit(self) -> str: diff --git a/tests/components/smartthings/snapshots/test_climate.ambr b/tests/components/smartthings/snapshots/test_climate.ambr index 8c29788fe901..fc8330524d3f 100644 --- a/tests/components/smartthings/snapshots/test_climate.ambr +++ b/tests/components/smartthings/snapshots/test_climate.ambr @@ -155,8 +155,8 @@ , , ]), - : 35, - : 7, + : 30, + : 18, : list([ 'none', 'wind_free', @@ -171,6 +171,7 @@ 'horizontal', 'both', ]), + : 0.5, }), 'config_entry_id': , 'config_subentry_id': , @@ -226,8 +227,8 @@ , , ]), - : 35, - : 7, + : 30, + : 18, : 'none', : list([ 'none', @@ -245,6 +246,7 @@ 'horizontal', 'both', ]), + : 0.5, : 20, }), 'context': , @@ -581,8 +583,8 @@ , , ]), - : 35, - : 7, + : 30, + : 16, : list([ 'none', 'sleep', @@ -598,6 +600,7 @@ 'horizontal', 'both', ]), + : 1, }), 'config_entry_id': , 'config_subentry_id': , @@ -654,8 +657,8 @@ , , ]), - : 35, - : 7, + : 30, + : 16, : 'none', : list([ 'none', @@ -674,6 +677,7 @@ 'horizontal', 'both', ]), + : 1, : 23, }), 'context': , diff --git a/tests/components/smartthings/test_climate.py b/tests/components/smartthings/test_climate.py index 0b1d91a80612..208345390a43 100644 --- a/tests/components/smartthings/test_climate.py +++ b/tests/components/smartthings/test_climate.py @@ -22,6 +22,9 @@ from homeassistant.components.climate import ( ATTR_SWING_MODE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, + ATTR_TARGET_TEMP_STEP, + DEFAULT_MAX_TEMP, + DEFAULT_MIN_TEMP, DOMAIN as CLIMATE_DOMAIN, PRESET_BOOST, PRESET_NONE, @@ -616,6 +619,35 @@ async def test_ac_state_attributes_update( ) +@pytest.mark.parametrize("device_fixture", ["da_ac_rac_000001"]) +async def test_ac_setpoint_range_update( + hass: HomeAssistant, + devices: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test the setpoint range is used when the device reports one.""" + await setup_integration(hass, mock_config_entry) + + state = hass.states.get("climate.theater_ac_office_granit") + assert state.attributes[ATTR_MIN_TEMP] == DEFAULT_MIN_TEMP + assert state.attributes[ATTR_MAX_TEMP] == DEFAULT_MAX_TEMP + assert ATTR_TARGET_TEMP_STEP not in state.attributes + + await trigger_update( + hass, + devices, + "96a5ef74-5832-a84b-f1f7-ca799957065d", + Capability.THERMOSTAT_COOLING_SETPOINT, + Attribute.COOLING_SETPOINT_RANGE, + {"minimum": 16, "maximum": 30, "step": 1}, + ) + + state = hass.states.get("climate.theater_ac_office_granit") + assert state.attributes[ATTR_MIN_TEMP] == 16 + assert state.attributes[ATTR_MAX_TEMP] == 30 + assert state.attributes[ATTR_TARGET_TEMP_STEP] == 1 + + @pytest.mark.parametrize("device_fixture", ["virtual_thermostat"]) async def test_thermostat_set_fan_mode( hass: HomeAssistant,