Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """Support for Hue binary sensors."""
2 
3 from __future__ import annotations
4 
5 from functools import partial
6 
7 from aiohue.v2 import HueBridgeV2
8 from aiohue.v2.controllers.config import (
9  EntertainmentConfiguration,
10  EntertainmentConfigurationController,
11 )
12 from aiohue.v2.controllers.events import EventType
13 from aiohue.v2.controllers.sensors import (
14  CameraMotionController,
15  ContactController,
16  MotionController,
17  TamperController,
18 )
19 from aiohue.v2.models.camera_motion import CameraMotion
20 from aiohue.v2.models.contact import Contact, ContactState
21 from aiohue.v2.models.entertainment_configuration import EntertainmentStatus
22 from aiohue.v2.models.motion import Motion
23 from aiohue.v2.models.tamper import Tamper, TamperState
24 
26  BinarySensorDeviceClass,
27  BinarySensorEntity,
28  BinarySensorEntityDescription,
29 )
30 from homeassistant.config_entries import ConfigEntry
31 from homeassistant.const import EntityCategory
32 from homeassistant.core import HomeAssistant, callback
33 from homeassistant.helpers.entity_platform import AddEntitiesCallback
34 
35 from ..bridge import HueBridge
36 from ..const import DOMAIN
37 from .entity import HueBaseEntity
38 
39 type SensorType = CameraMotion | Contact | Motion | EntertainmentConfiguration | Tamper
40 type ControllerType = (
41  CameraMotionController
42  | ContactController
43  | MotionController
44  | EntertainmentConfigurationController
45  | TamperController
46 )
47 
48 
50  hass: HomeAssistant,
51  config_entry: ConfigEntry,
52  async_add_entities: AddEntitiesCallback,
53 ) -> None:
54  """Set up Hue Sensors from Config Entry."""
55  bridge: HueBridge = hass.data[DOMAIN][config_entry.entry_id]
56  api: HueBridgeV2 = bridge.api
57 
58  @callback
59  def register_items(controller: ControllerType, sensor_class: SensorType):
60  make_binary_sensor_entity = partial(sensor_class, bridge, controller)
61 
62  @callback
63  def async_add_sensor(event_type: EventType, resource: SensorType) -> None:
64  """Add Hue Binary Sensor."""
65  async_add_entities([make_binary_sensor_entity(resource)])
66 
67  # add all current items in controller
68  async_add_entities(make_binary_sensor_entity(sensor) for sensor in controller)
69 
70  # register listener for new sensors
71  config_entry.async_on_unload(
72  controller.subscribe(
73  async_add_sensor, event_filter=EventType.RESOURCE_ADDED
74  )
75  )
76 
77  # setup for each binary-sensor-type hue resource
78  register_items(api.sensors.camera_motion, HueMotionSensor)
79  register_items(api.sensors.motion, HueMotionSensor)
80  register_items(api.config.entertainment_configuration, HueEntertainmentActiveSensor)
81  register_items(api.sensors.contact, HueContactSensor)
82  register_items(api.sensors.tamper, HueTamperSensor)
83 
84 
85 # pylint: disable-next=hass-enforce-class-module
87  """Representation of a Hue Motion sensor."""
88 
89  controller: CameraMotionController | MotionController
90  resource: CameraMotion | Motion
91 
92  entity_description = BinarySensorEntityDescription(
93  key="motion_sensor",
94  device_class=BinarySensorDeviceClass.MOTION,
95  has_entity_name=True,
96  )
97 
98  @property
99  def is_on(self) -> bool | None:
100  """Return true if the binary sensor is on."""
101  if not self.resourceresource.enabled:
102  # Force None (unknown) if the sensor is set to disabled in Hue
103  return None
104  return self.resourceresource.motion.value
105 
106 
107 # pylint: disable-next=hass-enforce-class-module
109  """Representation of a Hue Entertainment Configuration as binary sensor."""
110 
111  controller: EntertainmentConfigurationController
112  resource: EntertainmentConfiguration
113 
114  entity_description = BinarySensorEntityDescription(
115  key="entertainment_active_sensor",
116  device_class=BinarySensorDeviceClass.RUNNING,
117  has_entity_name=False,
118  )
119 
120  @property
121  def is_on(self) -> bool | None:
122  """Return true if the binary sensor is on."""
123  return self.resourceresource.status == EntertainmentStatus.ACTIVE
124 
125  @property
126  def name(self) -> str:
127  """Return sensor name."""
128  return self.resourceresource.metadata.name
129 
130 
131 # pylint: disable-next=hass-enforce-class-module
133  """Representation of a Hue Contact sensor."""
134 
135  controller: ContactController
136  resource: Contact
137 
138  entity_description = BinarySensorEntityDescription(
139  key="contact_sensor",
140  device_class=BinarySensorDeviceClass.OPENING,
141  has_entity_name=True,
142  )
143 
144  @property
145  def is_on(self) -> bool | None:
146  """Return true if the binary sensor is on."""
147  if not self.resourceresource.enabled:
148  # Force None (unknown) if the sensor is set to disabled in Hue
149  return None
150  return self.resourceresource.contact_report.state != ContactState.CONTACT
151 
152 
153 # pylint: disable-next=hass-enforce-class-module
155  """Representation of a Hue Tamper sensor."""
156 
157  controller: TamperController
158  resource: Tamper
159 
160  entity_description = BinarySensorEntityDescription(
161  key="tamper_sensor",
162  device_class=BinarySensorDeviceClass.TAMPER,
163  entity_category=EntityCategory.DIAGNOSTIC,
164  has_entity_name=True,
165  )
166 
167  @property
168  def is_on(self) -> bool | None:
169  """Return true if the binary sensor is on."""
170  if not self.resourceresource.tamper_reports:
171  return False
172  return self.resourceresource.tamper_reports[0].state == TamperState.TAMPERED
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)