From 010a9519666a7bd27441ca7cc2e4b9426d0d063b Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 28 Aug 2026 21:53:14 +0200 Subject: [PATCH] Restore a SwitchBot Cloud AC temperature in the unit it was published in (#180547) Co-authored-by: Paulus Schoutsen Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../components/switchbot_cloud/climate.py | 24 ++++++++--- .../switchbot_cloud/test_climate.py | 42 ++++++++++++++++++- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/switchbot_cloud/climate.py b/homeassistant/components/switchbot_cloud/climate.py index a3b42ba58edd..0e63dd1bbdc1 100644 --- a/homeassistant/components/switchbot_cloud/climate.py +++ b/homeassistant/components/switchbot_cloud/climate.py @@ -35,6 +35,7 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.restore_state import RestoreEntity +from homeassistant.util.unit_conversion import TemperatureConverter from . import SwitchbotCloudConfigEntry, SwitchBotCoordinator from .const import ( @@ -108,7 +109,7 @@ class SwitchBotCloudAirConditioner(SwitchBotCloudEntity, ClimateEntity, RestoreE ] _attr_hvac_mode = HVACMode.FAN_ONLY _attr_temperature_unit = UnitOfTemperature.CELSIUS - _attr_target_temperature = 21 + _attr_target_temperature = 21.0 _attr_target_temperature_step = 1 _attr_precision = 1 _attr_name = None @@ -130,10 +131,23 @@ class SwitchBotCloudAirConditioner(SwitchBotCloudEntity, ClimateEntity, RestoreE self._attr_fan_mode = last_state.attributes.get( ClimateEntityStateAttribute.FAN_MODE, self._attr_fan_mode ) - self._attr_target_temperature = last_state.attributes.get( - ClimateEntityStateAttribute.TARGET_TEMPERATURE, - self._attr_target_temperature, - ) + if ( + temperature := last_state.attributes.get( + ClimateEntityStateAttribute.TARGET_TEMPERATURE + ) + ) is not None: + # The attribute was published in the unit of the system, not the one + # this entity reports in, so it converts back on the way in + temperature = round( + TemperatureConverter.convert( + temperature, + self.hass.config.units.temperature_unit, + self.temperature_unit, + ) + ) + # A state written before that conversion was made can hold anything + if self.min_temp <= temperature <= self.max_temp: + self._attr_target_temperature = temperature def _get_mode(self, hvac_mode: HVACMode | None) -> int: new_hvac_mode = hvac_mode or self._attr_hvac_mode diff --git a/tests/components/switchbot_cloud/test_climate.py b/tests/components/switchbot_cloud/test_climate.py index b4d31f1c90ce..8460a94f88de 100644 --- a/tests/components/switchbot_cloud/test_climate.py +++ b/tests/components/switchbot_cloud/test_climate.py @@ -1,7 +1,8 @@ """Test for the switchbot_cloud climate.""" -from unittest.mock import patch +from unittest.mock import AsyncMock, patch +import pytest from switchbot_api import Device, Remote, SmartRadiatorThermostatCommands, SwitchBotAPI from homeassistant.components.climate import ( @@ -20,6 +21,7 @@ from homeassistant.components.climate import ( from homeassistant.config_entries import ConfigEntryState from homeassistant.const import ATTR_ENTITY_ID from homeassistant.core import HomeAssistant, State +from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM from . import configure_integration @@ -162,6 +164,44 @@ async def test_air_conditioner_restore_state( assert state.attributes[ATTR_TEMPERATURE] == 25 +@pytest.mark.parametrize( + ("restored_temperature", "expected_temperature"), + [ + pytest.param(75, 75, id="restored_as_published"), + pytest.param(19381607032619749376, 70, id="corrupted_falls_back_to_default"), + ], +) +async def test_air_conditioner_restore_state_in_fahrenheit( + hass: HomeAssistant, + mock_list_devices: AsyncMock, + mock_get_status: AsyncMock, + restored_temperature: float, + expected_temperature: float, +) -> None: + """Test the target temperature is restored in the unit it was published in.""" + hass.config.units = US_CUSTOMARY_SYSTEM + mock_list_devices.return_value = [ + Remote( + deviceId="ac-device-id-1", + deviceName="climate-1", + remoteType="Air Conditioner", + hubDeviceId="test-hub-id", + ), + ] + + entity_id = "climate.climate_1" + mock_restore_cache( + hass, + (State(entity_id, HVACMode.COOL, {ATTR_TEMPERATURE: restored_temperature}),), + ) + + entry = await configure_integration(hass) + assert entry.state is ConfigEntryState.LOADED + + state = hass.states.get(entity_id) + assert state.attributes[ATTR_TEMPERATURE] == expected_temperature + + async def test_air_conditioner_no_last_state( hass: HomeAssistant, mock_list_devices, mock_get_status ) -> None: