5353}
5454
5555
56+ class _DirectionEnumWrapper (DPCodeEnumWrapper ):
57+ """Wrapper for fan direction DP code."""
58+
59+ def read_device_status (self , device : CustomerDevice ) -> str | None :
60+ """Read the device status and return the direction string."""
61+ if (value := super ().read_device_status (device )) and value in {
62+ DIRECTION_FORWARD ,
63+ DIRECTION_REVERSE ,
64+ }:
65+ return value
66+ return None
67+
68+
5669def _has_a_valid_dpcode (device : CustomerDevice ) -> bool :
5770 """Check if the device has at least one valid DP code."""
5871 properties_to_check : list [DPCode | tuple [DPCode , ...] | None ] = [
@@ -85,6 +98,9 @@ def async_discover_device(device_ids: list[str]) -> None:
8598 TuyaFanEntity (
8699 device ,
87100 manager ,
101+ direction_wrapper = _DirectionEnumWrapper .find_dpcode (
102+ device , _DIRECTION_DPCODES , prefer_function = True
103+ ),
88104 mode_wrapper = DPCodeEnumWrapper .find_dpcode (
89105 device , _MODE_DPCODES , prefer_function = True
90106 ),
@@ -105,7 +121,6 @@ def async_discover_device(device_ids: list[str]) -> None:
105121class TuyaFanEntity (TuyaEntity , FanEntity ):
106122 """Tuya Fan Device."""
107123
108- _direction : EnumTypeData | None = None
109124 _oscillate : DPCode | None = None
110125 _speed : IntegerTypeData | None = None
111126 _speeds : EnumTypeData | None = None
@@ -116,13 +131,16 @@ def __init__(
116131 device : CustomerDevice ,
117132 device_manager : Manager ,
118133 * ,
134+ direction_wrapper : _DirectionEnumWrapper | None ,
119135 mode_wrapper : DPCodeEnumWrapper | None ,
120136 switch_wrapper : DPCodeBooleanWrapper | None ,
121137 ) -> None :
122138 """Init Tuya Fan Device."""
123139 super ().__init__ (device , device_manager )
140+ self ._direction_wrapper = direction_wrapper
124141 self ._mode_wrapper = mode_wrapper
125142 self ._switch_wrapper = switch_wrapper
143+
126144 if mode_wrapper :
127145 self ._attr_supported_features |= FanEntityFeature .PRESET_MODE
128146 self ._attr_preset_modes = mode_wrapper .type_information .range
@@ -143,10 +161,7 @@ def __init__(
143161 self ._oscillate = dpcode
144162 self ._attr_supported_features |= FanEntityFeature .OSCILLATE
145163
146- if enum_type := find_dpcode (
147- self .device , _DIRECTION_DPCODES , dptype = DPType .ENUM , prefer_function = True
148- ):
149- self ._direction = enum_type
164+ if direction_wrapper :
150165 self ._attr_supported_features |= FanEntityFeature .DIRECTION
151166 if switch_wrapper :
152167 self ._attr_supported_features |= (
@@ -157,11 +172,9 @@ async def async_set_preset_mode(self, preset_mode: str) -> None:
157172 """Set the preset mode of the fan."""
158173 await self ._async_send_dpcode_update (self ._mode_wrapper , preset_mode )
159174
160- def set_direction (self , direction : str ) -> None :
175+ async def async_set_direction (self , direction : str ) -> None :
161176 """Set the direction of the fan."""
162- if self ._direction is None :
163- return
164- self ._send_command ([{"code" : self ._direction .dpcode , "value" : direction }])
177+ await self ._async_send_dpcode_update (self ._direction_wrapper , direction )
165178
166179 def set_percentage (self , percentage : int ) -> None :
167180 """Set the speed of the fan, as a percentage."""
@@ -244,19 +257,7 @@ def is_on(self) -> bool | None:
244257 @property
245258 def current_direction (self ) -> str | None :
246259 """Return the current direction of the fan."""
247- if (
248- self ._direction is None
249- or (value := self .device .status .get (self ._direction .dpcode )) is None
250- ):
251- return None
252-
253- if value .lower () == DIRECTION_FORWARD :
254- return DIRECTION_FORWARD
255-
256- if value .lower () == DIRECTION_REVERSE :
257- return DIRECTION_REVERSE
258-
259- return None
260+ return self ._read_wrapper (self ._direction_wrapper )
260261
261262 @property
262263 def oscillating (self ) -> bool | None :
0 commit comments