Skip to content

Commit c0db966

Browse files
authored
Move find_dpcode function out of Tuya entity (#155934)
1 parent 9288995 commit c0db966

File tree

13 files changed

+202
-151
lines changed

13 files changed

+202
-151
lines changed

homeassistant/components/tuya/alarm_control_panel.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from . import TuyaConfigEntry
2222
from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType
2323
from .entity import TuyaEntity
24-
from .models import EnumTypeData
24+
from .models import EnumTypeData, find_dpcode
2525
from .util import get_dpcode
2626

2727

@@ -118,8 +118,8 @@ def __init__(
118118
self._attr_unique_id = f"{super().unique_id}{description.key}"
119119

120120
# Determine supported modes
121-
if supported_modes := self.find_dpcode(
122-
description.key, dptype=DPType.ENUM, prefer_function=True
121+
if supported_modes := find_dpcode(
122+
self.device, description.key, dptype=DPType.ENUM, prefer_function=True
123123
):
124124
if Mode.HOME in supported_modes.range:
125125
self._attr_supported_features |= AlarmControlPanelEntityFeature.ARM_HOME
@@ -131,8 +131,11 @@ def __init__(
131131
self._attr_supported_features |= AlarmControlPanelEntityFeature.TRIGGER
132132

133133
# Determine master state
134-
if enum_type := self.find_dpcode(
135-
description.master_state, dptype=DPType.ENUM, prefer_function=True
134+
if enum_type := find_dpcode(
135+
self.device,
136+
description.master_state,
137+
dptype=DPType.ENUM,
138+
prefer_function=True,
136139
):
137140
self._master_state = enum_type
138141

homeassistant/components/tuya/climate.py

Lines changed: 22 additions & 16 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
29+
from .models import IntegerTypeData, find_dpcode
3030
from .util import get_dpcode
3131

3232
TUYA_HVAC_TO_HA = {
@@ -153,11 +153,13 @@ def __init__(
153153
self._attr_temperature_unit = system_temperature_unit
154154

155155
# Figure out current temperature, use preferred unit or what is available
156-
celsius_type = self.find_dpcode(
157-
(DPCode.TEMP_CURRENT, DPCode.UPPER_TEMP), dptype=DPType.INTEGER
156+
celsius_type = find_dpcode(
157+
self.device, (DPCode.TEMP_CURRENT, DPCode.UPPER_TEMP), dptype=DPType.INTEGER
158158
)
159-
fahrenheit_type = self.find_dpcode(
160-
(DPCode.TEMP_CURRENT_F, DPCode.UPPER_TEMP_F), dptype=DPType.INTEGER
159+
fahrenheit_type = find_dpcode(
160+
self.device,
161+
(DPCode.TEMP_CURRENT_F, DPCode.UPPER_TEMP_F),
162+
dptype=DPType.INTEGER,
161163
)
162164
if fahrenheit_type and (
163165
prefered_temperature_unit == UnitOfTemperature.FAHRENHEIT
@@ -173,11 +175,11 @@ def __init__(
173175
self._current_temperature = celsius_type
174176

175177
# Figure out setting temperature, use preferred unit or what is available
176-
celsius_type = self.find_dpcode(
177-
DPCode.TEMP_SET, dptype=DPType.INTEGER, prefer_function=True
178+
celsius_type = find_dpcode(
179+
self.device, DPCode.TEMP_SET, dptype=DPType.INTEGER, prefer_function=True
178180
)
179-
fahrenheit_type = self.find_dpcode(
180-
DPCode.TEMP_SET_F, dptype=DPType.INTEGER, prefer_function=True
181+
fahrenheit_type = find_dpcode(
182+
self.device, DPCode.TEMP_SET_F, dptype=DPType.INTEGER, prefer_function=True
181183
)
182184
if fahrenheit_type and (
183185
prefered_temperature_unit == UnitOfTemperature.FAHRENHEIT
@@ -201,8 +203,8 @@ def __init__(
201203
# Determine HVAC modes
202204
self._attr_hvac_modes: list[HVACMode] = []
203205
self._hvac_to_tuya = {}
204-
if enum_type := self.find_dpcode(
205-
DPCode.MODE, dptype=DPType.ENUM, prefer_function=True
206+
if enum_type := find_dpcode(
207+
self.device, DPCode.MODE, dptype=DPType.ENUM, prefer_function=True
206208
):
207209
self._attr_hvac_modes = [HVACMode.OFF]
208210
unknown_hvac_modes: list[str] = []
@@ -225,22 +227,26 @@ def __init__(
225227
]
226228

227229
# Determine dpcode to use for setting the humidity
228-
if int_type := self.find_dpcode(
229-
DPCode.HUMIDITY_SET, dptype=DPType.INTEGER, prefer_function=True
230+
if int_type := find_dpcode(
231+
self.device,
232+
DPCode.HUMIDITY_SET,
233+
dptype=DPType.INTEGER,
234+
prefer_function=True,
230235
):
231236
self._attr_supported_features |= ClimateEntityFeature.TARGET_HUMIDITY
232237
self._set_humidity = int_type
233238
self._attr_min_humidity = int(int_type.min_scaled)
234239
self._attr_max_humidity = int(int_type.max_scaled)
235240

236241
# Determine dpcode to use for getting the current humidity
237-
self._current_humidity = self.find_dpcode(
238-
DPCode.HUMIDITY_CURRENT, dptype=DPType.INTEGER
242+
self._current_humidity = find_dpcode(
243+
self.device, DPCode.HUMIDITY_CURRENT, dptype=DPType.INTEGER
239244
)
240245

241246
# Determine fan modes
242247
self._fan_mode_dp_code: str | None = None
243-
if enum_type := self.find_dpcode(
248+
if enum_type := find_dpcode(
249+
self.device,
244250
(DPCode.FAN_SPEED_ENUM, DPCode.LEVEL, DPCode.WINDSPEED),
245251
dptype=DPType.ENUM,
246252
prefer_function=True,

homeassistant/components/tuya/cover.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from . import TuyaConfigEntry
2323
from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType
2424
from .entity import TuyaEntity
25-
from .models import EnumTypeData, IntegerTypeData
25+
from .models import EnumTypeData, IntegerTypeData, find_dpcode
2626
from .util import get_dpcode
2727

2828

@@ -204,8 +204,8 @@ def __init__(
204204
self._attr_supported_features |= (
205205
CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
206206
)
207-
elif enum_type := self.find_dpcode(
208-
description.key, dptype=DPType.ENUM, prefer_function=True
207+
elif enum_type := find_dpcode(
208+
self.device, description.key, dptype=DPType.ENUM, prefer_function=True
209209
):
210210
if description.open_instruction_value in enum_type.range:
211211
self._attr_supported_features |= CoverEntityFeature.OPEN
@@ -217,22 +217,29 @@ def __init__(
217217
self._current_state = get_dpcode(self.device, description.current_state)
218218

219219
# Determine type to use for setting the position
220-
if int_type := self.find_dpcode(
221-
description.set_position, dptype=DPType.INTEGER, prefer_function=True
220+
if int_type := find_dpcode(
221+
self.device,
222+
description.set_position,
223+
dptype=DPType.INTEGER,
224+
prefer_function=True,
222225
):
223226
self._attr_supported_features |= CoverEntityFeature.SET_POSITION
224227
self._set_position = int_type
225228
# Set as default, unless overwritten below
226229
self._current_position = int_type
227230

228231
# Determine type for getting the position
229-
if int_type := self.find_dpcode(
230-
description.current_position, dptype=DPType.INTEGER, prefer_function=True
232+
if int_type := find_dpcode(
233+
self.device,
234+
description.current_position,
235+
dptype=DPType.INTEGER,
236+
prefer_function=True,
231237
):
232238
self._current_position = int_type
233239

234240
# Determine type to use for setting the tilt
235-
if int_type := self.find_dpcode(
241+
if int_type := find_dpcode(
242+
self.device,
236243
(DPCode.ANGLE_HORIZONTAL, DPCode.ANGLE_VERTICAL),
237244
dptype=DPType.INTEGER,
238245
prefer_function=True,
@@ -242,7 +249,8 @@ def __init__(
242249

243250
# Determine type to use for checking motor reverse mode
244251
if (motor_mode := description.motor_reverse_mode) and (
245-
enum_type := self.find_dpcode(
252+
enum_type := find_dpcode(
253+
self.device,
246254
motor_mode,
247255
dptype=DPType.ENUM,
248256
prefer_function=True,
@@ -311,8 +319,11 @@ def is_closed(self) -> bool | None:
311319
def open_cover(self, **kwargs: Any) -> None:
312320
"""Open the cover."""
313321
value: bool | str = True
314-
if self.find_dpcode(
315-
self.entity_description.key, dptype=DPType.ENUM, prefer_function=True
322+
if find_dpcode(
323+
self.device,
324+
self.entity_description.key,
325+
dptype=DPType.ENUM,
326+
prefer_function=True,
316327
):
317328
value = self.entity_description.open_instruction_value
318329

@@ -337,8 +348,11 @@ def open_cover(self, **kwargs: Any) -> None:
337348
def close_cover(self, **kwargs: Any) -> None:
338349
"""Close cover."""
339350
value: bool | str = False
340-
if self.find_dpcode(
341-
self.entity_description.key, dptype=DPType.ENUM, prefer_function=True
351+
if find_dpcode(
352+
self.device,
353+
self.entity_description.key,
354+
dptype=DPType.ENUM,
355+
prefer_function=True,
342356
):
343357
value = self.entity_description.close_instruction_value
344358

homeassistant/components/tuya/entity.py

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22

33
from __future__ import annotations
44

5-
from typing import Any, Literal, overload
5+
from typing import Any
66

77
from tuya_sharing import CustomerDevice, Manager
88

99
from homeassistant.helpers.device_registry import DeviceInfo
1010
from homeassistant.helpers.dispatcher import async_dispatcher_connect
1111
from homeassistant.helpers.entity import Entity
1212

13-
from .const import DOMAIN, LOGGER, TUYA_HA_SIGNAL_UPDATE_ENTITY, DPCode, DPType
14-
from .models import EnumTypeData, IntegerTypeData
13+
from .const import DOMAIN, LOGGER, TUYA_HA_SIGNAL_UPDATE_ENTITY
1514

1615

1716
class TuyaEntity(Entity):
@@ -44,77 +43,6 @@ def available(self) -> bool:
4443
"""Return if the device is available."""
4544
return self.device.online
4645

47-
@overload
48-
def find_dpcode(
49-
self,
50-
dpcodes: str | DPCode | tuple[DPCode, ...] | None,
51-
*,
52-
prefer_function: bool = False,
53-
dptype: Literal[DPType.ENUM],
54-
) -> EnumTypeData | None: ...
55-
56-
@overload
57-
def find_dpcode(
58-
self,
59-
dpcodes: str | DPCode | tuple[DPCode, ...] | None,
60-
*,
61-
prefer_function: bool = False,
62-
dptype: Literal[DPType.INTEGER],
63-
) -> IntegerTypeData | None: ...
64-
65-
def find_dpcode(
66-
self,
67-
dpcodes: str | DPCode | tuple[DPCode, ...] | None,
68-
*,
69-
prefer_function: bool = False,
70-
dptype: DPType,
71-
) -> EnumTypeData | IntegerTypeData | None:
72-
"""Find type information for a matching DP code available for this device."""
73-
if dptype not in (DPType.ENUM, DPType.INTEGER):
74-
raise NotImplementedError("Only ENUM and INTEGER types are supported")
75-
76-
if dpcodes is None:
77-
return None
78-
79-
if isinstance(dpcodes, str):
80-
dpcodes = (DPCode(dpcodes),)
81-
elif not isinstance(dpcodes, tuple):
82-
dpcodes = (dpcodes,)
83-
84-
order = ["status_range", "function"]
85-
if prefer_function:
86-
order = ["function", "status_range"]
87-
88-
for dpcode in dpcodes:
89-
for key in order:
90-
if dpcode not in getattr(self.device, key):
91-
continue
92-
if (
93-
dptype == DPType.ENUM
94-
and getattr(self.device, key)[dpcode].type == DPType.ENUM
95-
):
96-
if not (
97-
enum_type := EnumTypeData.from_json(
98-
dpcode, getattr(self.device, key)[dpcode].values
99-
)
100-
):
101-
continue
102-
return enum_type
103-
104-
if (
105-
dptype == DPType.INTEGER
106-
and getattr(self.device, key)[dpcode].type == DPType.INTEGER
107-
):
108-
if not (
109-
integer_type := IntegerTypeData.from_json(
110-
dpcode, getattr(self.device, key)[dpcode].values
111-
)
112-
):
113-
continue
114-
return integer_type
115-
116-
return None
117-
11846
async def async_added_to_hass(self) -> None:
11947
"""Call when entity is added to hass."""
12048
self.async_on_remove(

homeassistant/components/tuya/event.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from . import TuyaConfigEntry
1717
from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType
1818
from .entity import TuyaEntity
19+
from .models import find_dpcode
1920

2021
# All descriptions can be found here. Mostly the Enum data types in the
2122
# default status set of each category (that don't have a set instruction)
@@ -125,7 +126,7 @@ def __init__(
125126
self.entity_description = description
126127
self._attr_unique_id = f"{super().unique_id}{description.key}"
127128

128-
if dpcode := self.find_dpcode(description.key, dptype=DPType.ENUM):
129+
if dpcode := find_dpcode(self.device, description.key, dptype=DPType.ENUM):
129130
self._attr_event_types: list[str] = dpcode.range
130131

131132
async def _handle_state_update(

homeassistant/components/tuya/fan.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from . import TuyaConfigEntry
2424
from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType
2525
from .entity import TuyaEntity
26-
from .models import EnumTypeData, IntegerTypeData
26+
from .models import EnumTypeData, IntegerTypeData, find_dpcode
2727
from .util import get_dpcode
2828

2929
_DIRECTION_DPCODES = (DPCode.FAN_DIRECTION,)
@@ -106,21 +106,24 @@ def __init__(
106106
self._switch = get_dpcode(self.device, _SWITCH_DPCODES)
107107

108108
self._attr_preset_modes = []
109-
if enum_type := self.find_dpcode(
110-
(DPCode.FAN_MODE, DPCode.MODE), dptype=DPType.ENUM, prefer_function=True
109+
if enum_type := find_dpcode(
110+
self.device,
111+
(DPCode.FAN_MODE, DPCode.MODE),
112+
dptype=DPType.ENUM,
113+
prefer_function=True,
111114
):
112115
self._presets = enum_type
113116
self._attr_supported_features |= FanEntityFeature.PRESET_MODE
114117
self._attr_preset_modes = enum_type.range
115118

116119
# Find speed controls, can be either percentage or a set of speeds
117-
if int_type := self.find_dpcode(
118-
_SPEED_DPCODES, dptype=DPType.INTEGER, prefer_function=True
120+
if int_type := find_dpcode(
121+
self.device, _SPEED_DPCODES, dptype=DPType.INTEGER, prefer_function=True
119122
):
120123
self._attr_supported_features |= FanEntityFeature.SET_SPEED
121124
self._speed = int_type
122-
elif enum_type := self.find_dpcode(
123-
_SPEED_DPCODES, dptype=DPType.ENUM, prefer_function=True
125+
elif enum_type := find_dpcode(
126+
self.device, _SPEED_DPCODES, dptype=DPType.ENUM, prefer_function=True
124127
):
125128
self._attr_supported_features |= FanEntityFeature.SET_SPEED
126129
self._speeds = enum_type
@@ -129,8 +132,8 @@ def __init__(
129132
self._oscillate = dpcode
130133
self._attr_supported_features |= FanEntityFeature.OSCILLATE
131134

132-
if enum_type := self.find_dpcode(
133-
_DIRECTION_DPCODES, dptype=DPType.ENUM, prefer_function=True
135+
if enum_type := find_dpcode(
136+
self.device, _DIRECTION_DPCODES, dptype=DPType.ENUM, prefer_function=True
134137
):
135138
self._direction = enum_type
136139
self._attr_supported_features |= FanEntityFeature.DIRECTION

0 commit comments

Comments
 (0)