1818from homeassistant .helpers .entity_platform import AddConfigEntryEntitiesCallback
1919
2020from . import TuyaConfigEntry
21- from .const import TUYA_DISCOVERY_NEW , DeviceCategory , DPCode , DPType
21+ from .const import TUYA_DISCOVERY_NEW , DeviceCategory , DPCode
2222from .entity import TuyaEntity
23- from .models import IntegerTypeData , find_dpcode
23+ from .models import DPCodeBooleanWrapper , DPCodeEnumWrapper , DPCodeIntegerWrapper
2424from .util import ActionDPCodeNotFoundError , get_dpcode
2525
2626
27+ class _RoundedIntegerWrapper (DPCodeIntegerWrapper ):
28+ """An integer that always rounds its value."""
29+
30+ def read_device_status (self , device : CustomerDevice ) -> int | None :
31+ """Read and round the device status."""
32+ if (value := super ().read_device_status (device )) is None :
33+ return None
34+ return round (value )
35+
36+
2737@dataclass (frozen = True )
2838class TuyaHumidifierEntityDescription (HumidifierEntityDescription ):
2939 """Describe an Tuya (de)humidifier entity."""
@@ -84,7 +94,27 @@ def async_discover_device(device_ids: list[str]) -> None:
8494 if (
8595 description := HUMIDIFIERS .get (device .category )
8696 ) and _has_a_valid_dpcode (device , description ):
87- entities .append (TuyaHumidifierEntity (device , manager , description ))
97+ entities .append (
98+ TuyaHumidifierEntity (
99+ device ,
100+ manager ,
101+ description ,
102+ current_humidity_wrapper = _RoundedIntegerWrapper .find_dpcode (
103+ device , description .current_humidity
104+ ),
105+ mode_wrapper = DPCodeEnumWrapper .find_dpcode (
106+ device , DPCode .MODE , prefer_function = True
107+ ),
108+ switch_wrapper = DPCodeBooleanWrapper .find_dpcode (
109+ device ,
110+ description .dpcode or DPCode (description .key ),
111+ prefer_function = True ,
112+ ),
113+ target_humidity_wrapper = _RoundedIntegerWrapper .find_dpcode (
114+ device , description .humidity , prefer_function = True
115+ ),
116+ )
117+ )
88118 async_add_entities (entities )
89119
90120 async_discover_device ([* manager .device_map ])
@@ -97,9 +127,6 @@ def async_discover_device(device_ids: list[str]) -> None:
97127class TuyaHumidifierEntity (TuyaEntity , HumidifierEntity ):
98128 """Tuya (de)humidifier Device."""
99129
100- _current_humidity : IntegerTypeData | None = None
101- _set_humidity : IntegerTypeData | None = None
102- _switch_dpcode : DPCode | None = None
103130 entity_description : TuyaHumidifierEntityDescription
104131 _attr_name = None
105132
@@ -108,115 +135,83 @@ def __init__(
108135 device : CustomerDevice ,
109136 device_manager : Manager ,
110137 description : TuyaHumidifierEntityDescription ,
138+ * ,
139+ current_humidity_wrapper : _RoundedIntegerWrapper | None = None ,
140+ mode_wrapper : DPCodeEnumWrapper | None = None ,
141+ switch_wrapper : DPCodeBooleanWrapper | None = None ,
142+ target_humidity_wrapper : _RoundedIntegerWrapper | None = None ,
111143 ) -> None :
112144 """Init Tuya (de)humidifier."""
113145 super ().__init__ (device , device_manager )
114146 self .entity_description = description
115147 self ._attr_unique_id = f"{ super ().unique_id } { description .key } "
116148
117- # Determine main switch DPCode
118- self ._switch_dpcode = get_dpcode (
119- self .device , description . dpcode or DPCode ( description . key )
120- )
149+ self . _current_humidity_wrapper = current_humidity_wrapper
150+ self ._mode_wrapper = mode_wrapper
151+ self ._switch_wrapper = switch_wrapper
152+ self . _target_humidity_wrapper = target_humidity_wrapper
121153
122154 # Determine humidity parameters
123- if int_type := find_dpcode (
124- self .device ,
125- description .humidity ,
126- dptype = DPType .INTEGER ,
127- prefer_function = True ,
128- ):
129- self ._set_humidity = int_type
130- self ._attr_min_humidity = int (int_type .min_scaled )
131- self ._attr_max_humidity = int (int_type .max_scaled )
132-
133- # Determine current humidity DPCode
134- if int_type := find_dpcode (
135- self .device ,
136- description .current_humidity ,
137- dptype = DPType .INTEGER ,
138- ):
139- self ._current_humidity = int_type
155+ if target_humidity_wrapper :
156+ self ._attr_min_humidity = round (
157+ target_humidity_wrapper .type_information .min_scaled
158+ )
159+ self ._attr_max_humidity = round (
160+ target_humidity_wrapper .type_information .max_scaled
161+ )
140162
141163 # Determine mode support and provided modes
142- if enum_type := find_dpcode (
143- self .device , DPCode .MODE , dptype = DPType .ENUM , prefer_function = True
144- ):
164+ if mode_wrapper :
145165 self ._attr_supported_features |= HumidifierEntityFeature .MODES
146- self ._attr_available_modes = enum_type .range
166+ self ._attr_available_modes = mode_wrapper . type_information .range
147167
148168 @property
149- def is_on (self ) -> bool :
169+ def is_on (self ) -> bool | None :
150170 """Return the device is on or off."""
151- if self ._switch_dpcode is None :
152- return False
153- return self .device .status .get (self ._switch_dpcode , False )
171+ return self ._read_wrapper (self ._switch_wrapper )
154172
155173 @property
156174 def mode (self ) -> str | None :
157175 """Return the current mode."""
158- return self .device . status . get ( DPCode . MODE )
176+ return self ._read_wrapper ( self . _mode_wrapper )
159177
160178 @property
161179 def target_humidity (self ) -> int | None :
162180 """Return the humidity we try to reach."""
163- if self ._set_humidity is None :
164- return None
165-
166- humidity = self .device .status .get (self ._set_humidity .dpcode )
167- if humidity is None :
168- return None
169-
170- return round (self ._set_humidity .scale_value (humidity ))
181+ return self ._read_wrapper (self ._target_humidity_wrapper )
171182
172183 @property
173184 def current_humidity (self ) -> int | None :
174185 """Return the current humidity."""
175- if self ._current_humidity is None :
176- return None
186+ return self ._read_wrapper (self ._current_humidity_wrapper )
177187
178- if (
179- current_humidity := self .device .status .get (self ._current_humidity .dpcode )
180- ) is None :
181- return None
182-
183- return round (self ._current_humidity .scale_value (current_humidity ))
184-
185- def turn_on (self , ** kwargs : Any ) -> None :
188+ async def async_turn_on (self , ** kwargs : Any ) -> None :
186189 """Turn the device on."""
187- if self ._switch_dpcode is None :
190+ if self ._switch_wrapper is None :
188191 raise ActionDPCodeNotFoundError (
189192 self .device ,
190193 self .entity_description .dpcode or self .entity_description .key ,
191194 )
192- self ._send_command ([{ "code" : self ._switch_dpcode , "value" : True }] )
195+ await self ._async_send_dpcode_update ( self ._switch_wrapper , True )
193196
194- def turn_off (self , ** kwargs : Any ) -> None :
197+ async def async_turn_off (self , ** kwargs : Any ) -> None :
195198 """Turn the device off."""
196- if self ._switch_dpcode is None :
199+ if self ._switch_wrapper is None :
197200 raise ActionDPCodeNotFoundError (
198201 self .device ,
199202 self .entity_description .dpcode or self .entity_description .key ,
200203 )
201- self ._send_command ([{ "code" : self ._switch_dpcode , "value" : False }] )
204+ await self ._async_send_dpcode_update ( self ._switch_wrapper , False )
202205
203- def set_humidity (self , humidity : int ) -> None :
206+ async def async_set_humidity (self , humidity : int ) -> None :
204207 """Set new target humidity."""
205- if self ._set_humidity is None :
208+ if self ._target_humidity_wrapper is None :
206209 raise ActionDPCodeNotFoundError (
207210 self .device ,
208211 self .entity_description .humidity ,
209212 )
213+ await self ._async_send_dpcode_update (self ._target_humidity_wrapper , humidity )
210214
211- self ._send_command (
212- [
213- {
214- "code" : self ._set_humidity .dpcode ,
215- "value" : self ._set_humidity .scale_value_back (humidity ),
216- }
217- ]
218- )
219-
220- def set_mode (self , mode : str ) -> None :
215+ async def async_set_mode (self , mode : str ) -> None :
221216 """Set new target preset mode."""
222- self ._send_command ([{ "code" : DPCode . MODE , "value" : mode }] )
217+ await self ._async_send_dpcode_update ( self . _mode_wrapper , mode )
0 commit comments