Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for the NextDNS service."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from typing import Generic
8 
9 from nextdns import (
10  AnalyticsDnssec,
11  AnalyticsEncryption,
12  AnalyticsIpVersions,
13  AnalyticsProtocols,
14  AnalyticsStatus,
15 )
16 
18  SensorEntity,
19  SensorEntityDescription,
20  SensorStateClass,
21 )
22 from homeassistant.const import PERCENTAGE, EntityCategory
23 from homeassistant.core import HomeAssistant, callback
24 from homeassistant.helpers.entity_platform import AddEntitiesCallback
25 from homeassistant.helpers.typing import StateType
26 from homeassistant.helpers.update_coordinator import CoordinatorEntity
27 
28 from . import NextDnsConfigEntry
29 from .const import (
30  ATTR_DNSSEC,
31  ATTR_ENCRYPTION,
32  ATTR_IP_VERSIONS,
33  ATTR_PROTOCOLS,
34  ATTR_STATUS,
35 )
36 from .coordinator import CoordinatorDataT, NextDnsUpdateCoordinator
37 
38 PARALLEL_UPDATES = 1
39 
40 
41 @dataclass(frozen=True, kw_only=True)
43  SensorEntityDescription, Generic[CoordinatorDataT]
44 ):
45  """NextDNS sensor entity description."""
46 
47  coordinator_type: str
48  value: Callable[[CoordinatorDataT], StateType]
49 
50 
51 SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
52  NextDnsSensorEntityDescription[AnalyticsStatus](
53  key="all_queries",
54  coordinator_type=ATTR_STATUS,
55  entity_category=EntityCategory.DIAGNOSTIC,
56  translation_key="all_queries",
57  state_class=SensorStateClass.TOTAL,
58  value=lambda data: data.all_queries,
59  ),
60  NextDnsSensorEntityDescription[AnalyticsStatus](
61  key="blocked_queries",
62  coordinator_type=ATTR_STATUS,
63  entity_category=EntityCategory.DIAGNOSTIC,
64  translation_key="blocked_queries",
65  state_class=SensorStateClass.TOTAL,
66  value=lambda data: data.blocked_queries,
67  ),
68  NextDnsSensorEntityDescription[AnalyticsStatus](
69  key="relayed_queries",
70  coordinator_type=ATTR_STATUS,
71  entity_category=EntityCategory.DIAGNOSTIC,
72  translation_key="relayed_queries",
73  state_class=SensorStateClass.TOTAL,
74  value=lambda data: data.relayed_queries,
75  ),
76  NextDnsSensorEntityDescription[AnalyticsStatus](
77  key="blocked_queries_ratio",
78  coordinator_type=ATTR_STATUS,
79  entity_category=EntityCategory.DIAGNOSTIC,
80  translation_key="blocked_queries_ratio",
81  native_unit_of_measurement=PERCENTAGE,
82  state_class=SensorStateClass.MEASUREMENT,
83  value=lambda data: data.blocked_queries_ratio,
84  ),
85  NextDnsSensorEntityDescription[AnalyticsProtocols](
86  key="doh_queries",
87  coordinator_type=ATTR_PROTOCOLS,
88  entity_category=EntityCategory.DIAGNOSTIC,
89  entity_registry_enabled_default=False,
90  translation_key="doh_queries",
91  state_class=SensorStateClass.TOTAL,
92  value=lambda data: data.doh_queries,
93  ),
94  NextDnsSensorEntityDescription[AnalyticsProtocols](
95  key="doh3_queries",
96  coordinator_type=ATTR_PROTOCOLS,
97  entity_category=EntityCategory.DIAGNOSTIC,
98  entity_registry_enabled_default=False,
99  translation_key="doh3_queries",
100  state_class=SensorStateClass.TOTAL,
101  value=lambda data: data.doh3_queries,
102  ),
103  NextDnsSensorEntityDescription[AnalyticsProtocols](
104  key="dot_queries",
105  coordinator_type=ATTR_PROTOCOLS,
106  entity_category=EntityCategory.DIAGNOSTIC,
107  entity_registry_enabled_default=False,
108  translation_key="dot_queries",
109  state_class=SensorStateClass.TOTAL,
110  value=lambda data: data.dot_queries,
111  ),
112  NextDnsSensorEntityDescription[AnalyticsProtocols](
113  key="doq_queries",
114  coordinator_type=ATTR_PROTOCOLS,
115  entity_category=EntityCategory.DIAGNOSTIC,
116  entity_registry_enabled_default=False,
117  translation_key="doq_queries",
118  state_class=SensorStateClass.TOTAL,
119  value=lambda data: data.doq_queries,
120  ),
121  NextDnsSensorEntityDescription[AnalyticsProtocols](
122  key="tcp_queries",
123  coordinator_type=ATTR_PROTOCOLS,
124  entity_category=EntityCategory.DIAGNOSTIC,
125  entity_registry_enabled_default=False,
126  translation_key="tcp_queries",
127  state_class=SensorStateClass.TOTAL,
128  value=lambda data: data.tcp_queries,
129  ),
130  NextDnsSensorEntityDescription[AnalyticsProtocols](
131  key="udp_queries",
132  coordinator_type=ATTR_PROTOCOLS,
133  entity_category=EntityCategory.DIAGNOSTIC,
134  entity_registry_enabled_default=False,
135  translation_key="udp_queries",
136  state_class=SensorStateClass.TOTAL,
137  value=lambda data: data.udp_queries,
138  ),
139  NextDnsSensorEntityDescription[AnalyticsProtocols](
140  key="doh_queries_ratio",
141  coordinator_type=ATTR_PROTOCOLS,
142  entity_registry_enabled_default=False,
143  entity_category=EntityCategory.DIAGNOSTIC,
144  translation_key="doh_queries_ratio",
145  native_unit_of_measurement=PERCENTAGE,
146  state_class=SensorStateClass.MEASUREMENT,
147  value=lambda data: data.doh_queries_ratio,
148  ),
149  NextDnsSensorEntityDescription[AnalyticsProtocols](
150  key="doh3_queries_ratio",
151  coordinator_type=ATTR_PROTOCOLS,
152  entity_registry_enabled_default=False,
153  entity_category=EntityCategory.DIAGNOSTIC,
154  translation_key="doh3_queries_ratio",
155  native_unit_of_measurement=PERCENTAGE,
156  state_class=SensorStateClass.MEASUREMENT,
157  value=lambda data: data.doh3_queries_ratio,
158  ),
159  NextDnsSensorEntityDescription[AnalyticsProtocols](
160  key="dot_queries_ratio",
161  coordinator_type=ATTR_PROTOCOLS,
162  entity_category=EntityCategory.DIAGNOSTIC,
163  entity_registry_enabled_default=False,
164  translation_key="dot_queries_ratio",
165  native_unit_of_measurement=PERCENTAGE,
166  state_class=SensorStateClass.MEASUREMENT,
167  value=lambda data: data.dot_queries_ratio,
168  ),
169  NextDnsSensorEntityDescription[AnalyticsProtocols](
170  key="doq_queries_ratio",
171  coordinator_type=ATTR_PROTOCOLS,
172  entity_registry_enabled_default=False,
173  entity_category=EntityCategory.DIAGNOSTIC,
174  translation_key="doq_queries_ratio",
175  native_unit_of_measurement=PERCENTAGE,
176  state_class=SensorStateClass.MEASUREMENT,
177  value=lambda data: data.doq_queries_ratio,
178  ),
179  NextDnsSensorEntityDescription[AnalyticsProtocols](
180  key="tcp_queries_ratio",
181  coordinator_type=ATTR_PROTOCOLS,
182  entity_category=EntityCategory.DIAGNOSTIC,
183  entity_registry_enabled_default=False,
184  translation_key="tcp_queries_ratio",
185  native_unit_of_measurement=PERCENTAGE,
186  state_class=SensorStateClass.MEASUREMENT,
187  value=lambda data: data.tcp_queries_ratio,
188  ),
189  NextDnsSensorEntityDescription[AnalyticsProtocols](
190  key="udp_queries_ratio",
191  coordinator_type=ATTR_PROTOCOLS,
192  entity_category=EntityCategory.DIAGNOSTIC,
193  entity_registry_enabled_default=False,
194  translation_key="udp_queries_ratio",
195  native_unit_of_measurement=PERCENTAGE,
196  state_class=SensorStateClass.MEASUREMENT,
197  value=lambda data: data.udp_queries_ratio,
198  ),
199  NextDnsSensorEntityDescription[AnalyticsEncryption](
200  key="encrypted_queries",
201  coordinator_type=ATTR_ENCRYPTION,
202  entity_category=EntityCategory.DIAGNOSTIC,
203  entity_registry_enabled_default=False,
204  translation_key="encrypted_queries",
205  state_class=SensorStateClass.TOTAL,
206  value=lambda data: data.encrypted_queries,
207  ),
208  NextDnsSensorEntityDescription[AnalyticsEncryption](
209  key="unencrypted_queries",
210  coordinator_type=ATTR_ENCRYPTION,
211  entity_category=EntityCategory.DIAGNOSTIC,
212  entity_registry_enabled_default=False,
213  translation_key="unencrypted_queries",
214  state_class=SensorStateClass.TOTAL,
215  value=lambda data: data.unencrypted_queries,
216  ),
217  NextDnsSensorEntityDescription[AnalyticsEncryption](
218  key="encrypted_queries_ratio",
219  coordinator_type=ATTR_ENCRYPTION,
220  entity_category=EntityCategory.DIAGNOSTIC,
221  entity_registry_enabled_default=False,
222  translation_key="encrypted_queries_ratio",
223  native_unit_of_measurement=PERCENTAGE,
224  state_class=SensorStateClass.MEASUREMENT,
225  value=lambda data: data.encrypted_queries_ratio,
226  ),
227  NextDnsSensorEntityDescription[AnalyticsIpVersions](
228  key="ipv4_queries",
229  coordinator_type=ATTR_IP_VERSIONS,
230  entity_category=EntityCategory.DIAGNOSTIC,
231  entity_registry_enabled_default=False,
232  translation_key="ipv4_queries",
233  state_class=SensorStateClass.TOTAL,
234  value=lambda data: data.ipv4_queries,
235  ),
236  NextDnsSensorEntityDescription[AnalyticsIpVersions](
237  key="ipv6_queries",
238  coordinator_type=ATTR_IP_VERSIONS,
239  entity_category=EntityCategory.DIAGNOSTIC,
240  entity_registry_enabled_default=False,
241  translation_key="ipv6_queries",
242  state_class=SensorStateClass.TOTAL,
243  value=lambda data: data.ipv6_queries,
244  ),
245  NextDnsSensorEntityDescription[AnalyticsIpVersions](
246  key="ipv6_queries_ratio",
247  coordinator_type=ATTR_IP_VERSIONS,
248  entity_category=EntityCategory.DIAGNOSTIC,
249  entity_registry_enabled_default=False,
250  translation_key="ipv6_queries_ratio",
251  native_unit_of_measurement=PERCENTAGE,
252  state_class=SensorStateClass.MEASUREMENT,
253  value=lambda data: data.ipv6_queries_ratio,
254  ),
255  NextDnsSensorEntityDescription[AnalyticsDnssec](
256  key="validated_queries",
257  coordinator_type=ATTR_DNSSEC,
258  entity_category=EntityCategory.DIAGNOSTIC,
259  entity_registry_enabled_default=False,
260  translation_key="validated_queries",
261  state_class=SensorStateClass.TOTAL,
262  value=lambda data: data.validated_queries,
263  ),
264  NextDnsSensorEntityDescription[AnalyticsDnssec](
265  key="not_validated_queries",
266  coordinator_type=ATTR_DNSSEC,
267  entity_category=EntityCategory.DIAGNOSTIC,
268  entity_registry_enabled_default=False,
269  translation_key="not_validated_queries",
270  state_class=SensorStateClass.TOTAL,
271  value=lambda data: data.not_validated_queries,
272  ),
273  NextDnsSensorEntityDescription[AnalyticsDnssec](
274  key="validated_queries_ratio",
275  coordinator_type=ATTR_DNSSEC,
276  entity_category=EntityCategory.DIAGNOSTIC,
277  entity_registry_enabled_default=False,
278  translation_key="validated_queries_ratio",
279  native_unit_of_measurement=PERCENTAGE,
280  state_class=SensorStateClass.MEASUREMENT,
281  value=lambda data: data.validated_queries_ratio,
282  ),
283 )
284 
285 
287  hass: HomeAssistant,
288  entry: NextDnsConfigEntry,
289  async_add_entities: AddEntitiesCallback,
290 ) -> None:
291  """Add a NextDNS entities from a config_entry."""
294  getattr(entry.runtime_data, description.coordinator_type), description
295  )
296  for description in SENSORS
297  )
298 
299 
301  CoordinatorEntity[NextDnsUpdateCoordinator[CoordinatorDataT]], SensorEntity
302 ):
303  """Define an NextDNS sensor."""
304 
305  _attr_has_entity_name = True
306 
307  def __init__(
308  self,
309  coordinator: NextDnsUpdateCoordinator[CoordinatorDataT],
310  description: NextDnsSensorEntityDescription,
311  ) -> None:
312  """Initialize."""
313  super().__init__(coordinator)
314  self._attr_device_info_attr_device_info = coordinator.device_info
315  self._attr_unique_id_attr_unique_id = f"{coordinator.profile_id}_{description.key}"
316  self._attr_native_value_attr_native_value = description.value(coordinator.data)
317  self.entity_description: NextDnsSensorEntityDescription = description
318 
319  @callback
320  def _handle_coordinator_update(self) -> None:
321  """Handle updated data from the coordinator."""
322  self._attr_native_value_attr_native_value = self.entity_description.value(self.coordinator.data)
323  self.async_write_ha_stateasync_write_ha_state()
None __init__(self, NextDnsUpdateCoordinator[CoordinatorDataT] coordinator, NextDnsSensorEntityDescription description)
Definition: sensor.py:311
None async_setup_entry(HomeAssistant hass, NextDnsConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:290