Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """Component providing support for Reolink binary sensors."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 
8 from reolink_aio.api import (
9  DUAL_LENS_DUAL_MOTION_MODELS,
10  FACE_DETECTION_TYPE,
11  PACKAGE_DETECTION_TYPE,
12  PERSON_DETECTION_TYPE,
13  PET_DETECTION_TYPE,
14  VEHICLE_DETECTION_TYPE,
15  Host,
16 )
17 
19  BinarySensorDeviceClass,
20  BinarySensorEntity,
21  BinarySensorEntityDescription,
22 )
23 from homeassistant.const import EntityCategory
24 from homeassistant.core import HomeAssistant
25 from homeassistant.helpers.dispatcher import async_dispatcher_connect
26 from homeassistant.helpers.entity_platform import AddEntitiesCallback
27 
28 from .entity import ReolinkChannelCoordinatorEntity, ReolinkChannelEntityDescription
29 from .util import ReolinkConfigEntry, ReolinkData
30 
31 PARALLEL_UPDATES = 0
32 
33 
34 @dataclass(frozen=True, kw_only=True)
36  BinarySensorEntityDescription,
37  ReolinkChannelEntityDescription,
38 ):
39  """A class that describes binary sensor entities."""
40 
41  value: Callable[[Host, int], bool]
42 
43 
44 BINARY_PUSH_SENSORS = (
46  key="motion",
47  cmd_id=33,
48  device_class=BinarySensorDeviceClass.MOTION,
49  value=lambda api, ch: api.motion_detected(ch),
50  ),
52  key=FACE_DETECTION_TYPE,
53  cmd_id=33,
54  translation_key="face",
55  value=lambda api, ch: api.ai_detected(ch, FACE_DETECTION_TYPE),
56  supported=lambda api, ch: api.ai_supported(ch, FACE_DETECTION_TYPE),
57  ),
59  key=PERSON_DETECTION_TYPE,
60  cmd_id=33,
61  translation_key="person",
62  value=lambda api, ch: api.ai_detected(ch, PERSON_DETECTION_TYPE),
63  supported=lambda api, ch: api.ai_supported(ch, PERSON_DETECTION_TYPE),
64  ),
66  key=VEHICLE_DETECTION_TYPE,
67  cmd_id=33,
68  translation_key="vehicle",
69  value=lambda api, ch: api.ai_detected(ch, VEHICLE_DETECTION_TYPE),
70  supported=lambda api, ch: api.ai_supported(ch, VEHICLE_DETECTION_TYPE),
71  ),
73  key=PET_DETECTION_TYPE,
74  cmd_id=33,
75  translation_key="pet",
76  value=lambda api, ch: api.ai_detected(ch, PET_DETECTION_TYPE),
77  supported=lambda api, ch: (
78  api.ai_supported(ch, PET_DETECTION_TYPE)
79  and not api.supported(ch, "ai_animal")
80  ),
81  ),
83  key=PET_DETECTION_TYPE,
84  cmd_id=33,
85  translation_key="animal",
86  value=lambda api, ch: api.ai_detected(ch, PET_DETECTION_TYPE),
87  supported=lambda api, ch: api.supported(ch, "ai_animal"),
88  ),
90  key=PACKAGE_DETECTION_TYPE,
91  cmd_id=33,
92  translation_key="package",
93  value=lambda api, ch: api.ai_detected(ch, PACKAGE_DETECTION_TYPE),
94  supported=lambda api, ch: api.ai_supported(ch, PACKAGE_DETECTION_TYPE),
95  ),
97  key="visitor",
98  cmd_id=33,
99  translation_key="visitor",
100  value=lambda api, ch: api.visitor_detected(ch),
101  supported=lambda api, ch: api.is_doorbell(ch),
102  ),
103 )
104 
105 BINARY_SENSORS = (
107  key="sleep",
108  cmd_id=145,
109  cmd_key="GetChannelstatus",
110  translation_key="sleep",
111  entity_category=EntityCategory.DIAGNOSTIC,
112  value=lambda api, ch: api.sleeping(ch),
113  supported=lambda api, ch: api.supported(ch, "sleep"),
114  ),
115 )
116 
117 
119  hass: HomeAssistant,
120  config_entry: ReolinkConfigEntry,
121  async_add_entities: AddEntitiesCallback,
122 ) -> None:
123  """Set up a Reolink IP Camera."""
124  reolink_data: ReolinkData = config_entry.runtime_data
125 
126  entities: list[ReolinkBinarySensorEntity] = []
127  for channel in reolink_data.host.api.channels:
128  entities.extend(
129  ReolinkPushBinarySensorEntity(reolink_data, channel, entity_description)
130  for entity_description in BINARY_PUSH_SENSORS
131  if entity_description.supported(reolink_data.host.api, channel)
132  )
133  entities.extend(
134  ReolinkBinarySensorEntity(reolink_data, channel, entity_description)
135  for entity_description in BINARY_SENSORS
136  if entity_description.supported(reolink_data.host.api, channel)
137  )
138 
139  async_add_entities(entities)
140 
141 
143  """Base binary-sensor class for Reolink IP camera."""
144 
145  entity_description: ReolinkBinarySensorEntityDescription
146 
147  def __init__(
148  self,
149  reolink_data: ReolinkData,
150  channel: int,
151  entity_description: ReolinkBinarySensorEntityDescription,
152  ) -> None:
153  """Initialize Reolink binary sensor."""
154  self.entity_descriptionentity_description = entity_description
155  super().__init__(reolink_data, channel)
156 
157  if self._host_host.api.model in DUAL_LENS_DUAL_MOTION_MODELS:
158  if entity_description.translation_key is not None:
159  key = entity_description.translation_key
160  else:
161  key = entity_description.key
162  self._attr_translation_key_attr_translation_key = f"{key}_lens_{self._channel}"
163 
164  @property
165  def is_on(self) -> bool:
166  """State of the sensor."""
167  return self.entity_descriptionentity_description.value(self._host_host.api, self._channel_channel)
168 
169 
171  """Binary-sensor class for Reolink IP camera motion sensors."""
172 
173  async def async_added_to_hass(self) -> None:
174  """Entity created."""
175  await super().async_added_to_hass()
176  self.async_on_removeasync_on_remove(
178  self.hasshasshass,
179  f"{self._host.unique_id}_{self._channel}",
180  self._async_handle_event_async_handle_event,
181  )
182  )
183  self.async_on_removeasync_on_remove(
185  self.hasshasshass,
186  f"{self._host.unique_id}_all",
187  self._async_handle_event_async_handle_event,
188  )
189  )
190 
191  async def _async_handle_event(self, event: str) -> None:
192  """Handle incoming event for motion detection."""
193  self.async_write_ha_stateasync_write_ha_state()
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103