Home Assistant Unofficial Reference 2024.12.1
select.py
Go to the documentation of this file.
1 """Support for Tuya select."""
2 
3 from __future__ import annotations
4 
5 from tuya_sharing import CustomerDevice, Manager
6 
7 from homeassistant.components.select import SelectEntity, SelectEntityDescription
8 from homeassistant.const import EntityCategory
9 from homeassistant.core import HomeAssistant, callback
10 from homeassistant.helpers.dispatcher import async_dispatcher_connect
11 from homeassistant.helpers.entity_platform import AddEntitiesCallback
12 
13 from . import TuyaConfigEntry
14 from .const import TUYA_DISCOVERY_NEW, DPCode, DPType
15 from .entity import TuyaEntity
16 
17 # All descriptions can be found here. Mostly the Enum data types in the
18 # default instructions set of each category end up being a select.
19 # https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
20 SELECTS: dict[str, tuple[SelectEntityDescription, ...]] = {
21  # Multi-functional Sensor
22  # https://developer.tuya.com/en/docs/iot/categorydgnbj?id=Kaiuz3yorvzg3
23  "dgnbj": (
25  key=DPCode.ALARM_VOLUME,
26  translation_key="volume",
27  entity_category=EntityCategory.CONFIG,
28  ),
29  ),
30  # Coffee maker
31  # https://developer.tuya.com/en/docs/iot/categorykfj?id=Kaiuz2p12pc7f
32  "kfj": (
34  key=DPCode.CUP_NUMBER,
35  translation_key="cups",
36  ),
38  key=DPCode.CONCENTRATION_SET,
39  translation_key="concentration",
40  entity_category=EntityCategory.CONFIG,
41  ),
43  key=DPCode.MATERIAL,
44  translation_key="material",
45  entity_category=EntityCategory.CONFIG,
46  ),
48  key=DPCode.MODE,
49  translation_key="mode",
50  ),
51  ),
52  # Switch
53  # https://developer.tuya.com/en/docs/iot/s?id=K9gf7o5prgf7s
54  "kg": (
56  key=DPCode.RELAY_STATUS,
57  entity_category=EntityCategory.CONFIG,
58  translation_key="relay_status",
59  ),
61  key=DPCode.LIGHT_MODE,
62  entity_category=EntityCategory.CONFIG,
63  translation_key="light_mode",
64  ),
65  ),
66  # Heater
67  # https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
68  "qn": (
70  key=DPCode.LEVEL,
71  translation_key="temperature_level",
72  ),
73  ),
74  # Smart Water Timer
75  "sfkzq": (
76  # Irrigation will not be run within this set delay period
78  key=DPCode.WEATHER_DELAY,
79  translation_key="weather_delay",
80  entity_category=EntityCategory.CONFIG,
81  ),
82  ),
83  # Siren Alarm
84  # https://developer.tuya.com/en/docs/iot/categorysgbj?id=Kaiuz37tlpbnu
85  "sgbj": (
87  key=DPCode.ALARM_VOLUME,
88  translation_key="volume",
89  entity_category=EntityCategory.CONFIG,
90  ),
92  key=DPCode.BRIGHT_STATE,
93  translation_key="brightness",
94  entity_category=EntityCategory.CONFIG,
95  ),
96  ),
97  # Smart Camera
98  # https://developer.tuya.com/en/docs/iot/categorysp?id=Kaiuz35leyo12
99  "sp": (
101  key=DPCode.IPC_WORK_MODE,
102  entity_category=EntityCategory.CONFIG,
103  translation_key="ipc_work_mode",
104  ),
106  key=DPCode.DECIBEL_SENSITIVITY,
107  entity_category=EntityCategory.CONFIG,
108  translation_key="decibel_sensitivity",
109  ),
111  key=DPCode.RECORD_MODE,
112  entity_category=EntityCategory.CONFIG,
113  translation_key="record_mode",
114  ),
116  key=DPCode.BASIC_NIGHTVISION,
117  entity_category=EntityCategory.CONFIG,
118  translation_key="basic_nightvision",
119  ),
121  key=DPCode.BASIC_ANTI_FLICKER,
122  entity_category=EntityCategory.CONFIG,
123  translation_key="basic_anti_flicker",
124  ),
126  key=DPCode.MOTION_SENSITIVITY,
127  entity_category=EntityCategory.CONFIG,
128  translation_key="motion_sensitivity",
129  ),
130  ),
131  # IoT Switch?
132  # Note: Undocumented
133  "tdq": (
135  key=DPCode.RELAY_STATUS,
136  entity_category=EntityCategory.CONFIG,
137  translation_key="relay_status",
138  ),
140  key=DPCode.LIGHT_MODE,
141  entity_category=EntityCategory.CONFIG,
142  translation_key="light_mode",
143  ),
144  ),
145  # Dimmer Switch
146  # https://developer.tuya.com/en/docs/iot/categorytgkg?id=Kaiuz0ktx7m0o
147  "tgkg": (
149  key=DPCode.RELAY_STATUS,
150  entity_category=EntityCategory.CONFIG,
151  translation_key="relay_status",
152  ),
154  key=DPCode.LIGHT_MODE,
155  entity_category=EntityCategory.CONFIG,
156  translation_key="light_mode",
157  ),
159  key=DPCode.LED_TYPE_1,
160  entity_category=EntityCategory.CONFIG,
161  translation_key="led_type",
162  ),
164  key=DPCode.LED_TYPE_2,
165  entity_category=EntityCategory.CONFIG,
166  translation_key="led_type_2",
167  ),
169  key=DPCode.LED_TYPE_3,
170  entity_category=EntityCategory.CONFIG,
171  translation_key="led_type_3",
172  ),
173  ),
174  # Dimmer
175  # https://developer.tuya.com/en/docs/iot/tgq?id=Kaof8ke9il4k4
176  "tgq": (
178  key=DPCode.LED_TYPE_1,
179  entity_category=EntityCategory.CONFIG,
180  translation_key="led_type",
181  ),
183  key=DPCode.LED_TYPE_2,
184  entity_category=EntityCategory.CONFIG,
185  translation_key="led_type_2",
186  ),
187  ),
188  # Fingerbot
189  "szjqr": (
191  key=DPCode.MODE,
192  entity_category=EntityCategory.CONFIG,
193  translation_key="fingerbot_mode",
194  ),
195  ),
196  # Robot Vacuum
197  # https://developer.tuya.com/en/docs/iot/fsd?id=K9gf487ck1tlo
198  "sd": (
200  key=DPCode.CISTERN,
201  entity_category=EntityCategory.CONFIG,
202  translation_key="vacuum_cistern",
203  ),
205  key=DPCode.COLLECTION_MODE,
206  entity_category=EntityCategory.CONFIG,
207  translation_key="vacuum_collection",
208  ),
210  key=DPCode.MODE,
211  entity_category=EntityCategory.CONFIG,
212  translation_key="vacuum_mode",
213  ),
214  ),
215  # Fan
216  # https://developer.tuya.com/en/docs/iot/f?id=K9gf45vs7vkge
217  "fs": (
219  key=DPCode.FAN_VERTICAL,
220  entity_category=EntityCategory.CONFIG,
221  translation_key="vertical_fan_angle",
222  ),
224  key=DPCode.FAN_HORIZONTAL,
225  entity_category=EntityCategory.CONFIG,
226  translation_key="horizontal_fan_angle",
227  ),
229  key=DPCode.COUNTDOWN,
230  entity_category=EntityCategory.CONFIG,
231  translation_key="countdown",
232  ),
234  key=DPCode.COUNTDOWN_SET,
235  entity_category=EntityCategory.CONFIG,
236  translation_key="countdown",
237  ),
238  ),
239  # Curtain
240  # https://developer.tuya.com/en/docs/iot/f?id=K9gf46o5mtfyc
241  "cl": (
243  key=DPCode.CONTROL_BACK_MODE,
244  entity_category=EntityCategory.CONFIG,
245  translation_key="curtain_motor_mode",
246  ),
248  key=DPCode.MODE,
249  entity_category=EntityCategory.CONFIG,
250  translation_key="curtain_mode",
251  ),
252  ),
253  # Humidifier
254  # https://developer.tuya.com/en/docs/iot/categoryjsq?id=Kaiuz1smr440b
255  "jsq": (
257  key=DPCode.SPRAY_MODE,
258  entity_category=EntityCategory.CONFIG,
259  translation_key="humidifier_spray_mode",
260  ),
262  key=DPCode.LEVEL,
263  entity_category=EntityCategory.CONFIG,
264  translation_key="humidifier_level",
265  ),
267  key=DPCode.MOODLIGHTING,
268  entity_category=EntityCategory.CONFIG,
269  translation_key="humidifier_moodlighting",
270  ),
272  key=DPCode.COUNTDOWN,
273  entity_category=EntityCategory.CONFIG,
274  translation_key="countdown",
275  ),
277  key=DPCode.COUNTDOWN_SET,
278  entity_category=EntityCategory.CONFIG,
279  translation_key="countdown",
280  ),
281  ),
282  # Air Purifier
283  # https://developer.tuya.com/en/docs/iot/f?id=K9gf46h2s6dzm
284  "kj": (
286  key=DPCode.COUNTDOWN,
287  entity_category=EntityCategory.CONFIG,
288  translation_key="countdown",
289  ),
291  key=DPCode.COUNTDOWN_SET,
292  entity_category=EntityCategory.CONFIG,
293  translation_key="countdown",
294  ),
295  ),
296  # Dehumidifier
297  # https://developer.tuya.com/en/docs/iot/categorycs?id=Kaiuz1vcz4dha
298  "cs": (
300  key=DPCode.COUNTDOWN_SET,
301  entity_category=EntityCategory.CONFIG,
302  translation_key="countdown",
303  ),
305  key=DPCode.DEHUMIDITY_SET_ENUM,
306  translation_key="target_humidity",
307  entity_category=EntityCategory.CONFIG,
308  ),
309  ),
310  # CO2 Detector
311  # https://developer.tuya.com/en/docs/iot/categoryco2bj?id=Kaiuz3wes7yuy
312  "co2bj": (
314  key=DPCode.ALARM_VOLUME,
315  translation_key="volume",
316  entity_category=EntityCategory.CONFIG,
317  ),
318  ),
319 }
320 
321 # Socket (duplicate of `kg`)
322 # https://developer.tuya.com/en/docs/iot/s?id=K9gf7o5prgf7s
323 SELECTS["cz"] = SELECTS["kg"]
324 
325 # Power Socket (duplicate of `kg`)
326 # https://developer.tuya.com/en/docs/iot/s?id=K9gf7o5prgf7s
327 SELECTS["pc"] = SELECTS["kg"]
328 
329 
331  hass: HomeAssistant, entry: TuyaConfigEntry, async_add_entities: AddEntitiesCallback
332 ) -> None:
333  """Set up Tuya select dynamically through Tuya discovery."""
334  hass_data = entry.runtime_data
335 
336  @callback
337  def async_discover_device(device_ids: list[str]) -> None:
338  """Discover and add a discovered Tuya select."""
339  entities: list[TuyaSelectEntity] = []
340  for device_id in device_ids:
341  device = hass_data.manager.device_map[device_id]
342  if descriptions := SELECTS.get(device.category):
343  entities.extend(
344  TuyaSelectEntity(device, hass_data.manager, description)
345  for description in descriptions
346  if description.key in device.status
347  )
348 
349  async_add_entities(entities)
350 
351  async_discover_device([*hass_data.manager.device_map])
352 
353  entry.async_on_unload(
354  async_dispatcher_connect(hass, TUYA_DISCOVERY_NEW, async_discover_device)
355  )
356 
357 
359  """Tuya Select Entity."""
360 
361  def __init__(
362  self,
363  device: CustomerDevice,
364  device_manager: Manager,
365  description: SelectEntityDescription,
366  ) -> None:
367  """Init Tuya sensor."""
368  super().__init__(device, device_manager)
369  self.entity_descriptionentity_description = description
370  self._attr_unique_id_attr_unique_id_attr_unique_id = f"{super().unique_id}{description.key}"
371 
372  self._attr_options_attr_options: list[str] = []
373  if enum_type := self.find_dpcodefind_dpcodefind_dpcodefind_dpcodefind_dpcode(
374  description.key, dptype=DPType.ENUM, prefer_function=True
375  ):
376  self._attr_options_attr_options = enum_type.range
377 
378  @property
379  def current_option(self) -> str | None:
380  """Return the selected entity option to represent the entity state."""
381  # Raw value
382  value = self.devicedevice.status.get(self.entity_descriptionentity_description.key)
383  if value is None or value not in self._attr_options_attr_options:
384  return None
385 
386  return value
387 
388  def select_option(self, option: str) -> None:
389  """Change the selected option."""
390  self._send_command_send_command(
391  [
392  {
393  "code": self.entity_descriptionentity_description.key,
394  "value": option,
395  }
396  ]
397  )
None _send_command(self, list[dict[str, Any]] commands)
Definition: entity.py:295
DPCode|EnumTypeData|IntegerTypeData|None find_dpcode(self, str|DPCode|tuple[DPCode,...]|None dpcodes, *bool prefer_function=False, DPType|None dptype=None)
Definition: entity.py:206
IntegerTypeData|None find_dpcode(self, str|DPCode|tuple[DPCode,...]|None dpcodes, *bool prefer_function=False, Literal[DPType.INTEGER] dptype)
Definition: entity.py:190
DPCode|None find_dpcode(self, str|DPCode|tuple[DPCode,...]|None dpcodes, *bool prefer_function=False)
Definition: entity.py:198
EnumTypeData|None find_dpcode(self, str|DPCode|tuple[DPCode,...]|None dpcodes, *bool prefer_function=False, Literal[DPType.ENUM] dptype)
Definition: entity.py:181
None __init__(self, CustomerDevice device, Manager device_manager, SelectEntityDescription description)
Definition: select.py:366
ElkSystem|None async_discover_device(HomeAssistant hass, str host)
Definition: discovery.py:78
None async_setup_entry(HomeAssistant hass, TuyaConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: select.py:332
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103