Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """Support for Tuya binary sensors."""
2 
3 from __future__ import annotations
4 
5 from dataclasses import dataclass
6 
7 from tuya_sharing import CustomerDevice, Manager
8 
10  BinarySensorDeviceClass,
11  BinarySensorEntity,
12  BinarySensorEntityDescription,
13 )
14 from homeassistant.const import EntityCategory
15 from homeassistant.core import HomeAssistant, callback
16 from homeassistant.helpers.dispatcher import async_dispatcher_connect
17 from homeassistant.helpers.entity_platform import AddEntitiesCallback
18 
19 from . import TuyaConfigEntry
20 from .const import TUYA_DISCOVERY_NEW, DPCode
21 from .entity import TuyaEntity
22 
23 
24 @dataclass(frozen=True)
26  """Describes a Tuya binary sensor."""
27 
28  # DPCode, to use. If None, the key will be used as DPCode
29  dpcode: DPCode | None = None
30 
31  # Value or values to consider binary sensor to be "on"
32  on_value: bool | float | int | str | set[bool | float | int | str] = True
33 
34 
35 # Commonly used sensors
36 TAMPER_BINARY_SENSOR = TuyaBinarySensorEntityDescription(
37  key=DPCode.TEMPER_ALARM,
38  name="Tamper",
39  device_class=BinarySensorDeviceClass.TAMPER,
40  entity_category=EntityCategory.DIAGNOSTIC,
41 )
42 
43 
44 # All descriptions can be found here. Mostly the Boolean data types in the
45 # default status set of each category (that don't have a set instruction)
46 # end up being a binary sensor.
47 # https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
48 BINARY_SENSORS: dict[str, tuple[TuyaBinarySensorEntityDescription, ...]] = {
49  # Multi-functional Sensor
50  # https://developer.tuya.com/en/docs/iot/categorydgnbj?id=Kaiuz3yorvzg3
51  "dgnbj": (
53  key=DPCode.GAS_SENSOR_STATE,
54  device_class=BinarySensorDeviceClass.GAS,
55  on_value="alarm",
56  ),
58  key=DPCode.CH4_SENSOR_STATE,
59  translation_key="methane",
60  device_class=BinarySensorDeviceClass.GAS,
61  on_value="alarm",
62  ),
64  key=DPCode.VOC_STATE,
65  translation_key="voc",
66  device_class=BinarySensorDeviceClass.SAFETY,
67  on_value="alarm",
68  ),
70  key=DPCode.PM25_STATE,
71  translation_key="pm25",
72  device_class=BinarySensorDeviceClass.SAFETY,
73  on_value="alarm",
74  ),
76  key=DPCode.CO_STATE,
77  translation_key="carbon_monoxide",
78  device_class=BinarySensorDeviceClass.SAFETY,
79  on_value="alarm",
80  ),
82  key=DPCode.CO2_STATE,
83  translation_key="carbon_dioxide",
84  device_class=BinarySensorDeviceClass.SAFETY,
85  on_value="alarm",
86  ),
88  key=DPCode.CH2O_STATE,
89  translation_key="formaldehyde",
90  device_class=BinarySensorDeviceClass.SAFETY,
91  on_value="alarm",
92  ),
94  key=DPCode.DOORCONTACT_STATE,
95  device_class=BinarySensorDeviceClass.DOOR,
96  ),
98  key=DPCode.WATERSENSOR_STATE,
99  device_class=BinarySensorDeviceClass.MOISTURE,
100  on_value="alarm",
101  ),
103  key=DPCode.PRESSURE_STATE,
104  translation_key="pressure",
105  on_value="alarm",
106  ),
108  key=DPCode.SMOKE_SENSOR_STATE,
109  device_class=BinarySensorDeviceClass.SMOKE,
110  on_value="alarm",
111  ),
112  TAMPER_BINARY_SENSOR,
113  ),
114  # CO2 Detector
115  # https://developer.tuya.com/en/docs/iot/categoryco2bj?id=Kaiuz3wes7yuy
116  "co2bj": (
118  key=DPCode.CO2_STATE,
119  device_class=BinarySensorDeviceClass.SAFETY,
120  on_value="alarm",
121  ),
122  TAMPER_BINARY_SENSOR,
123  ),
124  # CO Detector
125  # https://developer.tuya.com/en/docs/iot/categorycobj?id=Kaiuz3u1j6q1v
126  "cobj": (
128  key=DPCode.CO_STATE,
129  device_class=BinarySensorDeviceClass.SAFETY,
130  on_value="1",
131  ),
133  key=DPCode.CO_STATUS,
134  device_class=BinarySensorDeviceClass.SAFETY,
135  on_value="alarm",
136  ),
137  TAMPER_BINARY_SENSOR,
138  ),
139  # Smart Pet Feeder
140  # https://developer.tuya.com/en/docs/iot/categorycwwsq?id=Kaiuz2b6vydld
141  "cwwsq": (
143  key=DPCode.FEED_STATE,
144  translation_key="feeding",
145  on_value="feeding",
146  ),
147  ),
148  # Human Presence Sensor
149  # https://developer.tuya.com/en/docs/iot/categoryhps?id=Kaiuz42yhn1hs
150  "hps": (
152  key=DPCode.PRESENCE_STATE,
153  device_class=BinarySensorDeviceClass.OCCUPANCY,
154  on_value={"presence", "small_move", "large_move", "peaceful"},
155  ),
156  ),
157  # Formaldehyde Detector
158  # Note: Not documented
159  "jqbj": (
161  key=DPCode.CH2O_STATE,
162  device_class=BinarySensorDeviceClass.SAFETY,
163  on_value="alarm",
164  ),
165  TAMPER_BINARY_SENSOR,
166  ),
167  # Methane Detector
168  # https://developer.tuya.com/en/docs/iot/categoryjwbj?id=Kaiuz40u98lkm
169  "jwbj": (
171  key=DPCode.CH4_SENSOR_STATE,
172  device_class=BinarySensorDeviceClass.GAS,
173  on_value="alarm",
174  ),
175  TAMPER_BINARY_SENSOR,
176  ),
177  # Door and Window Controller
178  # https://developer.tuya.com/en/docs/iot/s?id=K9gf48r5zjsy9
179  "mc": (
181  key=DPCode.STATUS,
182  device_class=BinarySensorDeviceClass.DOOR,
183  on_value={"open", "opened"},
184  ),
185  ),
186  # Door Window Sensor
187  # https://developer.tuya.com/en/docs/iot/s?id=K9gf48hm02l8m
188  "mcs": (
190  key=DPCode.DOORCONTACT_STATE,
191  device_class=BinarySensorDeviceClass.DOOR,
192  ),
194  key=DPCode.SWITCH, # Used by non-standard contact sensor implementations
195  device_class=BinarySensorDeviceClass.DOOR,
196  ),
197  TAMPER_BINARY_SENSOR,
198  ),
199  # Access Control
200  # https://developer.tuya.com/en/docs/iot/s?id=Kb0o2xhlkxbet
201  "mk": (
203  key=DPCode.CLOSED_OPENED_KIT,
204  device_class=BinarySensorDeviceClass.LOCK,
205  on_value={"AQAB"},
206  ),
207  ),
208  # Luminance Sensor
209  # https://developer.tuya.com/en/docs/iot/categoryldcg?id=Kaiuz3n7u69l8
210  "ldcg": (
212  key=DPCode.TEMPER_ALARM,
213  device_class=BinarySensorDeviceClass.TAMPER,
214  entity_category=EntityCategory.DIAGNOSTIC,
215  ),
216  TAMPER_BINARY_SENSOR,
217  ),
218  # PIR Detector
219  # https://developer.tuya.com/en/docs/iot/categorypir?id=Kaiuz3ss11b80
220  "pir": (
222  key=DPCode.PIR,
223  device_class=BinarySensorDeviceClass.MOTION,
224  on_value="pir",
225  ),
226  TAMPER_BINARY_SENSOR,
227  ),
228  # PM2.5 Sensor
229  # https://developer.tuya.com/en/docs/iot/categorypm25?id=Kaiuz3qof3yfu
230  "pm2.5": (
232  key=DPCode.PM25_STATE,
233  device_class=BinarySensorDeviceClass.SAFETY,
234  on_value="alarm",
235  ),
236  TAMPER_BINARY_SENSOR,
237  ),
238  # Gas Detector
239  # https://developer.tuya.com/en/docs/iot/categoryrqbj?id=Kaiuz3d162ubw
240  "rqbj": (
242  key=DPCode.GAS_SENSOR_STATUS,
243  device_class=BinarySensorDeviceClass.GAS,
244  on_value="alarm",
245  ),
247  key=DPCode.GAS_SENSOR_STATE,
248  device_class=BinarySensorDeviceClass.GAS,
249  on_value="1",
250  ),
251  TAMPER_BINARY_SENSOR,
252  ),
253  # Water Detector
254  # https://developer.tuya.com/en/docs/iot/categorysj?id=Kaiuz3iub2sli
255  "sj": (
257  key=DPCode.WATERSENSOR_STATE,
258  device_class=BinarySensorDeviceClass.MOISTURE,
259  on_value="alarm",
260  ),
261  TAMPER_BINARY_SENSOR,
262  ),
263  # Emergency Button
264  # https://developer.tuya.com/en/docs/iot/categorysos?id=Kaiuz3oi6agjy
265  "sos": (
267  key=DPCode.SOS_STATE,
268  device_class=BinarySensorDeviceClass.SAFETY,
269  ),
270  TAMPER_BINARY_SENSOR,
271  ),
272  # Volatile Organic Compound Sensor
273  # Note: Undocumented in cloud API docs, based on test device
274  "voc": (
276  key=DPCode.VOC_STATE,
277  device_class=BinarySensorDeviceClass.SAFETY,
278  on_value="alarm",
279  ),
280  TAMPER_BINARY_SENSOR,
281  ),
282  # Thermostatic Radiator Valve
283  # Not documented
284  "wkf": (
286  key=DPCode.WINDOW_STATE,
287  device_class=BinarySensorDeviceClass.WINDOW,
288  on_value="opened",
289  ),
290  ),
291  # Temperature and Humidity Sensor
292  # https://developer.tuya.com/en/docs/iot/categorywsdcg?id=Kaiuz3hinij34
293  "wsdcg": (TAMPER_BINARY_SENSOR,),
294  # Pressure Sensor
295  # https://developer.tuya.com/en/docs/iot/categoryylcg?id=Kaiuz3kc2e4gm
296  "ylcg": (
298  key=DPCode.PRESSURE_STATE,
299  on_value="alarm",
300  ),
301  TAMPER_BINARY_SENSOR,
302  ),
303  # Smoke Detector
304  # https://developer.tuya.com/en/docs/iot/categoryywbj?id=Kaiuz3f6sf952
305  "ywbj": (
307  key=DPCode.SMOKE_SENSOR_STATUS,
308  device_class=BinarySensorDeviceClass.SMOKE,
309  on_value="alarm",
310  ),
312  key=DPCode.SMOKE_SENSOR_STATE,
313  device_class=BinarySensorDeviceClass.SMOKE,
314  on_value={"1", "alarm"},
315  ),
316  TAMPER_BINARY_SENSOR,
317  ),
318  # Vibration Sensor
319  # https://developer.tuya.com/en/docs/iot/categoryzd?id=Kaiuz3a5vrzno
320  "zd": (
322  key=f"{DPCode.SHOCK_STATE}_vibration",
323  dpcode=DPCode.SHOCK_STATE,
324  device_class=BinarySensorDeviceClass.VIBRATION,
325  on_value="vibration",
326  ),
328  key=f"{DPCode.SHOCK_STATE}_drop",
329  dpcode=DPCode.SHOCK_STATE,
330  translation_key="drop",
331  on_value="drop",
332  ),
334  key=f"{DPCode.SHOCK_STATE}_tilt",
335  dpcode=DPCode.SHOCK_STATE,
336  translation_key="tilt",
337  on_value="tilt",
338  ),
339  ),
340 }
341 
342 
344  hass: HomeAssistant, entry: TuyaConfigEntry, async_add_entities: AddEntitiesCallback
345 ) -> None:
346  """Set up Tuya binary sensor dynamically through Tuya discovery."""
347  hass_data = entry.runtime_data
348 
349  @callback
350  def async_discover_device(device_ids: list[str]) -> None:
351  """Discover and add a discovered Tuya binary sensor."""
352  entities: list[TuyaBinarySensorEntity] = []
353  for device_id in device_ids:
354  device = hass_data.manager.device_map[device_id]
355  if descriptions := BINARY_SENSORS.get(device.category):
356  for description in descriptions:
357  dpcode = description.dpcode or description.key
358  if dpcode in device.status:
359  entities.append(
361  device, hass_data.manager, description
362  )
363  )
364 
365  async_add_entities(entities)
366 
367  async_discover_device([*hass_data.manager.device_map])
368 
369  entry.async_on_unload(
370  async_dispatcher_connect(hass, TUYA_DISCOVERY_NEW, async_discover_device)
371  )
372 
373 
375  """Tuya Binary Sensor Entity."""
376 
377  entity_description: TuyaBinarySensorEntityDescription
378 
379  def __init__(
380  self,
381  device: CustomerDevice,
382  device_manager: Manager,
383  description: TuyaBinarySensorEntityDescription,
384  ) -> None:
385  """Init Tuya binary sensor."""
386  super().__init__(device, device_manager)
387  self.entity_descriptionentity_description = description
388  self._attr_unique_id_attr_unique_id_attr_unique_id = f"{super().unique_id}{description.key}"
389 
390  @property
391  def is_on(self) -> bool:
392  """Return true if sensor is on."""
393  dpcode = self.entity_descriptionentity_description.dpcode or self.entity_descriptionentity_description.key
394  if dpcode not in self.devicedevice.status:
395  return False
396 
397  if isinstance(self.entity_descriptionentity_description.on_value, set):
398  return self.devicedevice.status[dpcode] in self.entity_descriptionentity_description.on_value
399 
400  return self.devicedevice.status[dpcode] == self.entity_descriptionentity_description.on_value
None __init__(self, CustomerDevice device, Manager device_manager, TuyaBinarySensorEntityDescription description)
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)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103