Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Proximity sensors."""
2 
3 from __future__ import annotations
4 
5 from typing import NamedTuple
6 
8  SensorDeviceClass,
9  SensorEntity,
10  SensorEntityDescription,
11 )
12 from homeassistant.const import UnitOfLength
13 from homeassistant.core import HomeAssistant
14 from homeassistant.helpers import entity_registry as er
15 from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
16 from homeassistant.helpers.entity_platform import AddEntitiesCallback
17 from homeassistant.helpers.update_coordinator import CoordinatorEntity
18 
19 from .const import (
20  ATTR_DIR_OF_TRAVEL,
21  ATTR_DIST_TO,
22  ATTR_NEAREST,
23  ATTR_NEAREST_DIR_OF_TRAVEL,
24  ATTR_NEAREST_DIST_TO,
25  DOMAIN,
26 )
27 from .coordinator import ProximityConfigEntry, ProximityDataUpdateCoordinator
28 
29 DIRECTIONS = ["arrived", "away_from", "stationary", "towards"]
30 
31 SENSORS_PER_ENTITY: list[SensorEntityDescription] = [
33  key=ATTR_DIST_TO,
34  translation_key=ATTR_DIST_TO,
35  device_class=SensorDeviceClass.DISTANCE,
36  native_unit_of_measurement=UnitOfLength.METERS,
37  ),
39  key=ATTR_DIR_OF_TRAVEL,
40  translation_key=ATTR_DIR_OF_TRAVEL,
41  device_class=SensorDeviceClass.ENUM,
42  options=DIRECTIONS,
43  ),
44 ]
45 
46 SENSORS_PER_PROXIMITY: list[SensorEntityDescription] = [
48  key=ATTR_NEAREST,
49  translation_key=ATTR_NEAREST,
50  ),
52  key=ATTR_DIST_TO,
53  translation_key=ATTR_NEAREST_DIST_TO,
54  device_class=SensorDeviceClass.DISTANCE,
55  native_unit_of_measurement=UnitOfLength.METERS,
56  ),
58  key=ATTR_DIR_OF_TRAVEL,
59  translation_key=ATTR_NEAREST_DIR_OF_TRAVEL,
60  device_class=SensorDeviceClass.ENUM,
61  options=DIRECTIONS,
62  ),
63 ]
64 
65 
66 class TrackedEntityDescriptor(NamedTuple):
67  """Descriptor of a tracked entity."""
68 
69  entity_id: str
70  identifier: str
71  name: str
72 
73 
74 def _device_info(coordinator: ProximityDataUpdateCoordinator) -> DeviceInfo:
75  return DeviceInfo(
76  identifiers={(DOMAIN, coordinator.config_entry.entry_id)},
77  name=coordinator.config_entry.title,
78  entry_type=DeviceEntryType.SERVICE,
79  )
80 
81 
83  hass: HomeAssistant,
84  entry: ProximityConfigEntry,
85  async_add_entities: AddEntitiesCallback,
86 ) -> None:
87  """Set up the proximity sensors."""
88 
89  coordinator = entry.runtime_data
90 
91  entities: list[ProximitySensor | ProximityTrackedEntitySensor] = [
92  ProximitySensor(description, coordinator)
93  for description in SENSORS_PER_PROXIMITY
94  ]
95 
96  tracked_entity_descriptors: list[TrackedEntityDescriptor] = []
97 
98  entity_reg = er.async_get(hass)
99  for tracked_entity_id in coordinator.tracked_entities:
100  tracked_entity_object_id = tracked_entity_id.split(".")[-1]
101  if (entity_entry := entity_reg.async_get(tracked_entity_id)) is not None:
102  tracked_entity_descriptors.append(
104  tracked_entity_id,
105  entity_entry.id,
106  entity_entry.name
107  or entity_entry.original_name
108  or tracked_entity_object_id,
109  )
110  )
111  else:
112  tracked_entity_descriptors.append(
114  tracked_entity_id,
115  tracked_entity_id,
116  tracked_entity_object_id,
117  )
118  )
119 
120  entities += [
122  description, coordinator, tracked_entity_descriptor
123  )
124  for description in SENSORS_PER_ENTITY
125  for tracked_entity_descriptor in tracked_entity_descriptors
126  ]
127 
128  async_add_entities(entities)
129 
130 
131 class ProximitySensor(CoordinatorEntity[ProximityDataUpdateCoordinator], SensorEntity):
132  """Represents a Proximity sensor."""
133 
134  _attr_has_entity_name = True
135 
136  def __init__(
137  self,
138  description: SensorEntityDescription,
139  coordinator: ProximityDataUpdateCoordinator,
140  ) -> None:
141  """Initialize the proximity."""
142  super().__init__(coordinator)
143 
144  self.entity_descriptionentity_description = description
145 
146  self._attr_unique_id_attr_unique_id = f"{coordinator.config_entry.entry_id}_{description.key}"
147  self._attr_device_info_attr_device_info = _device_info(coordinator)
148 
149  @property
150  def native_value(self) -> str | float | None:
151  """Return native sensor value."""
152  if (
153  value := self.coordinator.data.proximity[self.entity_descriptionentity_description.key]
154  ) == "not set":
155  return None
156  return value
157 
158 
160  CoordinatorEntity[ProximityDataUpdateCoordinator], SensorEntity
161 ):
162  """Represents a Proximity tracked entity sensor."""
163 
164  _attr_has_entity_name = True
165 
166  def __init__(
167  self,
168  description: SensorEntityDescription,
169  coordinator: ProximityDataUpdateCoordinator,
170  tracked_entity_descriptor: TrackedEntityDescriptor,
171  ) -> None:
172  """Initialize the proximity."""
173  super().__init__(coordinator)
174 
175  self.entity_descriptionentity_description = description
176  self.tracked_entity_idtracked_entity_id = tracked_entity_descriptor.entity_id
177 
178  self._attr_unique_id_attr_unique_id = f"{coordinator.config_entry.entry_id}_{tracked_entity_descriptor.identifier}_{description.key}"
179  self._attr_device_info_attr_device_info = _device_info(coordinator)
180  self._attr_translation_placeholders_attr_translation_placeholders = {
181  "tracked_entity": tracked_entity_descriptor.name
182  }
183 
184  async def async_added_to_hass(self) -> None:
185  """Register entity mapping."""
186  await super().async_added_to_hass()
187  self.coordinator.async_add_entity_mapping(
188  self.tracked_entity_idtracked_entity_id, self.entity_identity_id
189  )
190 
191  @property
192  def data(self) -> dict[str, str | int | None]:
193  """Get data from coordinator."""
194  return self.coordinator.data.entities[self.tracked_entity_idtracked_entity_id]
195 
196  @property
197  def available(self) -> bool:
198  """Return if entity is available."""
199  return (
200  super().available
201  and self.tracked_entity_idtracked_entity_id in self.coordinator.data.entities
202  )
203 
204  @property
205  def native_value(self) -> str | float | None:
206  """Return native sensor value."""
207  return self.datadatadatadata.get(self.entity_descriptionentity_description.key)
None async_add_entity_mapping(self, str tracked_entity_id, str entity_id)
Definition: coordinator.py:104
None __init__(self, SensorEntityDescription description, ProximityDataUpdateCoordinator coordinator)
Definition: sensor.py:140
None __init__(self, SensorEntityDescription description, ProximityDataUpdateCoordinator coordinator, TrackedEntityDescriptor tracked_entity_descriptor)
Definition: sensor.py:171
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
DeviceInfo _device_info(ProximityDataUpdateCoordinator coordinator)
Definition: sensor.py:74
None async_setup_entry(HomeAssistant hass, ProximityConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:86