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