From 27975c75179fb5f09f1a476c6f96108599bbf250 Mon Sep 17 00:00:00 2001 From: Clifford Roche <1007595+cmroche@users.noreply.github.com> Date: Sun, 7 Jul 2024 11:05:14 -0400 Subject: [PATCH] Fix incorrect temperature in Gree if temp units changed on device (#121041) --- homeassistant/components/gree/climate.py | 36 ++++++++--- tests/components/gree/test_climate.py | 79 +++++++++++++++++++++--- 2 files changed, 96 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/gree/climate.py b/homeassistant/components/gree/climate.py index 20d5d405591..6a8f48780c8 100644 --- a/homeassistant/components/gree/climate.py +++ b/homeassistant/components/gree/climate.py @@ -123,21 +123,15 @@ class GreeClimateEntity(GreeEntity, ClimateEntity): _attr_fan_modes = [*FAN_MODES_REVERSE] _attr_swing_modes = SWING_MODES _attr_name = None + _attr_temperature_unit = UnitOfTemperature.CELSIUS + _attr_min_temp = TEMP_MIN + _attr_max_temp = TEMP_MAX _enable_turn_on_off_backwards_compatibility = False def __init__(self, coordinator: DeviceDataUpdateCoordinator) -> None: """Initialize the Gree device.""" super().__init__(coordinator) self._attr_unique_id = coordinator.device.device_info.mac - units = self.coordinator.device.temperature_units - if units == TemperatureUnits.C: - self._attr_temperature_unit = UnitOfTemperature.CELSIUS - self._attr_min_temp = TEMP_MIN - self._attr_max_temp = TEMP_MAX - else: - self._attr_temperature_unit = UnitOfTemperature.FAHRENHEIT - self._attr_min_temp = TEMP_MIN_F - self._attr_max_temp = TEMP_MAX_F @property def current_temperature(self) -> float: @@ -164,7 +158,7 @@ class GreeClimateEntity(GreeEntity, ClimateEntity): self._attr_name, ) - self.coordinator.device.target_temperature = round(temperature) + self.coordinator.device.target_temperature = temperature await self.coordinator.push_state_update() self.async_write_ha_state() @@ -306,3 +300,25 @@ class GreeClimateEntity(GreeEntity, ClimateEntity): await self.coordinator.push_state_update() self.async_write_ha_state() + + def _handle_coordinator_update(self) -> None: + """Update the state of the entity.""" + units = self.coordinator.device.temperature_units + if ( + units == TemperatureUnits.C + and self._attr_temperature_unit != UnitOfTemperature.CELSIUS + ): + _LOGGER.debug("Setting temperature unit to Celsius") + self._attr_temperature_unit = UnitOfTemperature.CELSIUS + self._attr_min_temp = TEMP_MIN + self._attr_max_temp = TEMP_MAX + elif ( + units == TemperatureUnits.F + and self._attr_temperature_unit != UnitOfTemperature.FAHRENHEIT + ): + _LOGGER.debug("Setting temperature unit to Fahrenheit") + self._attr_temperature_unit = UnitOfTemperature.FAHRENHEIT + self._attr_min_temp = TEMP_MIN_F + self._attr_max_temp = TEMP_MAX_F + + super()._handle_coordinator_update() diff --git a/tests/components/gree/test_climate.py b/tests/components/gree/test_climate.py index 0bd767e4f35..e6f24ade1aa 100644 --- a/tests/components/gree/test_climate.py +++ b/tests/components/gree/test_climate.py @@ -4,13 +4,19 @@ from datetime import timedelta from unittest.mock import DEFAULT as DEFAULT_MOCK, AsyncMock, patch from freezegun.api import FrozenDateTimeFactory -from greeclimate.device import HorizontalSwing, VerticalSwing +from greeclimate.device import ( + TEMP_MAX, + TEMP_MAX_F, + TEMP_MIN, + TEMP_MIN_F, + HorizontalSwing, + VerticalSwing, +) from greeclimate.exceptions import DeviceNotBoundError, DeviceTimeoutError import pytest from syrupy.assertion import SnapshotAssertion from homeassistant.components.climate import ( - ATTR_CURRENT_TEMPERATURE, ATTR_FAN_MODE, ATTR_HVAC_MODE, ATTR_PRESET_MODE, @@ -40,11 +46,13 @@ from homeassistant.components.gree.climate import ( FAN_MODES_REVERSE, HVAC_MODES, HVAC_MODES_REVERSE, + GreeClimateEntity, ) from homeassistant.components.gree.const import FAN_MEDIUM_HIGH, FAN_MEDIUM_LOW from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_TEMPERATURE, + ATTR_UNIT_OF_MEASUREMENT, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_UNAVAILABLE, @@ -385,7 +393,7 @@ async def test_send_power_off_device_timeout( @pytest.mark.parametrize( ("units", "temperature"), - [(UnitOfTemperature.CELSIUS, 26), (UnitOfTemperature.FAHRENHEIT, 74)], + [(UnitOfTemperature.CELSIUS, 26), (UnitOfTemperature.FAHRENHEIT, 73)], ) async def test_send_target_temperature( hass: HomeAssistant, discovery, device, units, temperature @@ -405,6 +413,14 @@ async def test_send_target_temperature( # Make sure we're trying to test something that isn't the default assert fake_device.current_temperature != temperature + hass.states.async_set( + ENTITY_ID, + "off", + { + ATTR_UNIT_OF_MEASUREMENT: units, + }, + ) + await hass.services.async_call( DOMAIN, SERVICE_SET_TEMPERATURE, @@ -415,10 +431,6 @@ async def test_send_target_temperature( state = hass.states.get(ENTITY_ID) assert state is not None assert state.attributes.get(ATTR_TEMPERATURE) == temperature - assert ( - state.attributes.get(ATTR_CURRENT_TEMPERATURE) - == fake_device.current_temperature - ) assert state.state == HVAC_MODES.get(fake_device.mode) # Reset config temperature_unit back to CELSIUS, required for @@ -462,7 +474,11 @@ async def test_send_target_temperature_with_hvac_mode( @pytest.mark.parametrize( ("units", "temperature"), - [(UnitOfTemperature.CELSIUS, 25), (UnitOfTemperature.FAHRENHEIT, 74)], + [ + (UnitOfTemperature.CELSIUS, 25), + (UnitOfTemperature.FAHRENHEIT, 73), + (UnitOfTemperature.FAHRENHEIT, 74), + ], ) async def test_send_target_temperature_device_timeout( hass: HomeAssistant, discovery, device, units, temperature @@ -492,7 +508,11 @@ async def test_send_target_temperature_device_timeout( @pytest.mark.parametrize( ("units", "temperature"), - [(UnitOfTemperature.CELSIUS, 25), (UnitOfTemperature.FAHRENHEIT, 74)], + [ + (UnitOfTemperature.CELSIUS, 25), + (UnitOfTemperature.FAHRENHEIT, 73), + (UnitOfTemperature.FAHRENHEIT, 74), + ], ) async def test_update_target_temperature( hass: HomeAssistant, discovery, device, units, temperature @@ -505,6 +525,13 @@ async def test_update_target_temperature( await async_setup_gree(hass) + await hass.services.async_call( + DOMAIN, + SERVICE_SET_TEMPERATURE, + {ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: temperature}, + blocking=True, + ) + state = hass.states.get(ENTITY_ID) assert state is not None assert state.attributes.get(ATTR_TEMPERATURE) == temperature @@ -843,6 +870,40 @@ async def test_update_swing_mode( assert state.attributes.get(ATTR_SWING_MODE) == swing_mode +async def test_coordinator_update_handler( + hass: HomeAssistant, discovery, device +) -> None: + """Test for coordinator update handler.""" + await async_setup_gree(hass) + await hass.async_block_till_done() + + entity: GreeClimateEntity = hass.data[DOMAIN].get_entity(ENTITY_ID) + assert entity is not None + + # Initial state + assert entity.temperature_unit == UnitOfTemperature.CELSIUS + assert entity.min_temp == TEMP_MIN + assert entity.max_temp == TEMP_MAX + + # Set unit to FAHRENHEIT + device().temperature_units = 1 + entity.coordinator.async_set_updated_data(UnitOfTemperature.FAHRENHEIT) + await hass.async_block_till_done() + + assert entity.temperature_unit == UnitOfTemperature.FAHRENHEIT + assert entity.min_temp == TEMP_MIN_F + assert entity.max_temp == TEMP_MAX_F + + # Set unit back to CELSIUS + device().temperature_units = 0 + entity.coordinator.async_set_updated_data(UnitOfTemperature.CELSIUS) + await hass.async_block_till_done() + + assert entity.temperature_unit == UnitOfTemperature.CELSIUS + assert entity.min_temp == TEMP_MIN + assert entity.max_temp == TEMP_MAX + + @patch("homeassistant.components.gree.PLATFORMS", [DOMAIN]) async def test_registry_settings( hass: HomeAssistant, entity_registry: er.EntityRegistry, snapshot: SnapshotAssertion -- GitLab