Skip to content

Commit 779590c

Browse files
authored
Migrate Tuya climate (humidity) to use wrapper class (home-assistant#156575)
1 parent f3a185f commit 779590c

File tree

1 file changed

+33
-46
lines changed

1 file changed

+33
-46
lines changed

homeassistant/components/tuya/climate.py

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from . import TuyaConfigEntry
2727
from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType
2828
from .entity import TuyaEntity
29-
from .models import IntegerTypeData, find_dpcode
29+
from .models import DPCodeIntegerWrapper, IntegerTypeData, find_dpcode
3030
from .util import get_dpcode
3131

3232
TUYA_HVAC_TO_HA = {
@@ -41,6 +41,16 @@
4141
}
4242

4343

44+
class _RoundedIntegerWrapper(DPCodeIntegerWrapper):
45+
"""An integer that always rounds its value."""
46+
47+
def read_device_status(self, device: CustomerDevice) -> int | None:
48+
"""Read and round the device status."""
49+
if (value := super().read_device_status(device)) is None:
50+
return None
51+
return round(value)
52+
53+
4454
@dataclass(frozen=True, kw_only=True)
4555
class TuyaClimateEntityDescription(ClimateEntityDescription):
4656
"""Describe an Tuya climate entity."""
@@ -97,6 +107,12 @@ def async_discover_device(device_ids: list[str]) -> None:
97107
manager,
98108
CLIMATE_DESCRIPTIONS[device.category],
99109
hass.config.units.temperature_unit,
110+
current_humidity_wrapper=_RoundedIntegerWrapper.find_dpcode(
111+
device, DPCode.HUMIDITY_CURRENT
112+
),
113+
target_humidity_wrapper=_RoundedIntegerWrapper.find_dpcode(
114+
device, DPCode.HUMIDITY_SET, prefer_function=True
115+
),
100116
)
101117
)
102118
async_add_entities(entities)
@@ -111,10 +127,8 @@ def async_discover_device(device_ids: list[str]) -> None:
111127
class TuyaClimateEntity(TuyaEntity, ClimateEntity):
112128
"""Tuya Climate Device."""
113129

114-
_current_humidity: IntegerTypeData | None = None
115130
_current_temperature: IntegerTypeData | None = None
116131
_hvac_to_tuya: dict[str, str]
117-
_set_humidity: IntegerTypeData | None = None
118132
_set_temperature: IntegerTypeData | None = None
119133
entity_description: TuyaClimateEntityDescription
120134
_attr_name = None
@@ -125,12 +139,17 @@ def __init__(
125139
device_manager: Manager,
126140
description: TuyaClimateEntityDescription,
127141
system_temperature_unit: UnitOfTemperature,
142+
*,
143+
current_humidity_wrapper: _RoundedIntegerWrapper | None = None,
144+
target_humidity_wrapper: _RoundedIntegerWrapper | None = None,
128145
) -> None:
129146
"""Determine which values to use."""
130147
self._attr_target_temperature_step = 1.0
131148
self.entity_description = description
132149

133150
super().__init__(device, device_manager)
151+
self._current_humidity_wrapper = current_humidity_wrapper
152+
self._target_humidity_wrapper = target_humidity_wrapper
134153

135154
# If both temperature values for celsius and fahrenheit are present,
136155
# use whatever the device is set to, with a fallback to celsius.
@@ -227,21 +246,14 @@ def __init__(
227246
]
228247

229248
# Determine dpcode to use for setting the humidity
230-
if int_type := find_dpcode(
231-
self.device,
232-
DPCode.HUMIDITY_SET,
233-
dptype=DPType.INTEGER,
234-
prefer_function=True,
235-
):
249+
if target_humidity_wrapper:
236250
self._attr_supported_features |= ClimateEntityFeature.TARGET_HUMIDITY
237-
self._set_humidity = int_type
238-
self._attr_min_humidity = int(int_type.min_scaled)
239-
self._attr_max_humidity = int(int_type.max_scaled)
240-
241-
# Determine dpcode to use for getting the current humidity
242-
self._current_humidity = find_dpcode(
243-
self.device, DPCode.HUMIDITY_CURRENT, dptype=DPType.INTEGER
244-
)
251+
self._attr_min_humidity = round(
252+
target_humidity_wrapper.type_information.min_scaled
253+
)
254+
self._attr_max_humidity = round(
255+
target_humidity_wrapper.type_information.max_scaled
256+
)
245257

246258
# Determine fan modes
247259
self._fan_mode_dp_code: str | None = None
@@ -303,20 +315,9 @@ def set_fan_mode(self, fan_mode: str) -> None:
303315

304316
self._send_command([{"code": self._fan_mode_dp_code, "value": fan_mode}])
305317

306-
def set_humidity(self, humidity: int) -> None:
318+
async def async_set_humidity(self, humidity: int) -> None:
307319
"""Set new target humidity."""
308-
if TYPE_CHECKING:
309-
# guarded by ClimateEntityFeature.TARGET_HUMIDITY
310-
assert self._set_humidity is not None
311-
312-
self._send_command(
313-
[
314-
{
315-
"code": self._set_humidity.dpcode,
316-
"value": self._set_humidity.scale_value_back(humidity),
317-
}
318-
]
319-
)
320+
await self._async_send_dpcode_update(self._target_humidity_wrapper, humidity)
320321

321322
def set_swing_mode(self, swing_mode: str) -> None:
322323
"""Set new target swing operation."""
@@ -382,14 +383,7 @@ def current_temperature(self) -> float | None:
382383
@property
383384
def current_humidity(self) -> int | None:
384385
"""Return the current humidity."""
385-
if self._current_humidity is None:
386-
return None
387-
388-
humidity = self.device.status.get(self._current_humidity.dpcode)
389-
if humidity is None:
390-
return None
391-
392-
return round(self._current_humidity.scale_value(humidity))
386+
return self._read_wrapper(self._current_humidity_wrapper)
393387

394388
@property
395389
def target_temperature(self) -> float | None:
@@ -406,14 +400,7 @@ def target_temperature(self) -> float | None:
406400
@property
407401
def target_humidity(self) -> int | None:
408402
"""Return the humidity currently set to be reached."""
409-
if self._set_humidity is None:
410-
return None
411-
412-
humidity = self.device.status.get(self._set_humidity.dpcode)
413-
if humidity is None:
414-
return None
415-
416-
return round(self._set_humidity.scale_value(humidity))
403+
return self._read_wrapper(self._target_humidity_wrapper)
417404

418405
@property
419406
def hvac_mode(self) -> HVACMode:

0 commit comments

Comments
 (0)