Home Assistant Unofficial Reference 2024.12.1
switch.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 Any
8 
9 from aiohttp import ClientError
10 from aiohttp.client_exceptions import ClientConnectorError
11 from nextdns import ApiError, Settings
12 
13 from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
14 from homeassistant.const import EntityCategory
15 from homeassistant.core import HomeAssistant, callback
16 from homeassistant.exceptions import HomeAssistantError
17 from homeassistant.helpers.entity_platform import AddEntitiesCallback
18 from homeassistant.helpers.update_coordinator import CoordinatorEntity
19 
20 from . import NextDnsConfigEntry
21 from .coordinator import NextDnsUpdateCoordinator
22 
23 PARALLEL_UPDATES = 1
24 
25 
26 @dataclass(frozen=True, kw_only=True)
28  """NextDNS switch entity description."""
29 
30  state: Callable[[Settings], bool]
31 
32 
33 SWITCHES = (
35  key="block_page",
36  translation_key="block_page",
37  entity_category=EntityCategory.CONFIG,
38  state=lambda data: data.block_page,
39  ),
41  key="cache_boost",
42  translation_key="cache_boost",
43  entity_category=EntityCategory.CONFIG,
44  state=lambda data: data.cache_boost,
45  ),
47  key="cname_flattening",
48  translation_key="cname_flattening",
49  entity_category=EntityCategory.CONFIG,
50  state=lambda data: data.cname_flattening,
51  ),
53  key="anonymized_ecs",
54  translation_key="anonymized_ecs",
55  entity_category=EntityCategory.CONFIG,
56  state=lambda data: data.anonymized_ecs,
57  ),
59  key="logs",
60  translation_key="logs",
61  entity_category=EntityCategory.CONFIG,
62  state=lambda data: data.logs,
63  ),
65  key="web3",
66  translation_key="web3",
67  entity_category=EntityCategory.CONFIG,
68  state=lambda data: data.web3,
69  ),
71  key="allow_affiliate",
72  translation_key="allow_affiliate",
73  entity_category=EntityCategory.CONFIG,
74  state=lambda data: data.allow_affiliate,
75  ),
77  key="block_disguised_trackers",
78  translation_key="block_disguised_trackers",
79  entity_category=EntityCategory.CONFIG,
80  state=lambda data: data.block_disguised_trackers,
81  ),
83  key="ai_threat_detection",
84  translation_key="ai_threat_detection",
85  entity_category=EntityCategory.CONFIG,
86  state=lambda data: data.ai_threat_detection,
87  ),
89  key="block_csam",
90  translation_key="block_csam",
91  entity_category=EntityCategory.CONFIG,
92  state=lambda data: data.block_csam,
93  ),
95  key="block_ddns",
96  translation_key="block_ddns",
97  entity_category=EntityCategory.CONFIG,
98  state=lambda data: data.block_ddns,
99  ),
101  key="block_nrd",
102  translation_key="block_nrd",
103  entity_category=EntityCategory.CONFIG,
104  state=lambda data: data.block_nrd,
105  ),
107  key="block_parked_domains",
108  translation_key="block_parked_domains",
109  entity_category=EntityCategory.CONFIG,
110  state=lambda data: data.block_parked_domains,
111  ),
113  key="cryptojacking_protection",
114  translation_key="cryptojacking_protection",
115  entity_category=EntityCategory.CONFIG,
116  state=lambda data: data.cryptojacking_protection,
117  ),
119  key="dga_protection",
120  translation_key="dga_protection",
121  entity_category=EntityCategory.CONFIG,
122  state=lambda data: data.dga_protection,
123  ),
125  key="dns_rebinding_protection",
126  translation_key="dns_rebinding_protection",
127  entity_category=EntityCategory.CONFIG,
128  state=lambda data: data.dns_rebinding_protection,
129  ),
131  key="google_safe_browsing",
132  translation_key="google_safe_browsing",
133  entity_category=EntityCategory.CONFIG,
134  state=lambda data: data.google_safe_browsing,
135  ),
137  key="idn_homograph_attacks_protection",
138  translation_key="idn_homograph_attacks_protection",
139  entity_category=EntityCategory.CONFIG,
140  state=lambda data: data.idn_homograph_attacks_protection,
141  ),
143  key="threat_intelligence_feeds",
144  translation_key="threat_intelligence_feeds",
145  entity_category=EntityCategory.CONFIG,
146  state=lambda data: data.threat_intelligence_feeds,
147  ),
149  key="typosquatting_protection",
150  translation_key="typosquatting_protection",
151  entity_category=EntityCategory.CONFIG,
152  state=lambda data: data.typosquatting_protection,
153  ),
155  key="block_bypass_methods",
156  translation_key="block_bypass_methods",
157  entity_category=EntityCategory.CONFIG,
158  state=lambda data: data.block_bypass_methods,
159  ),
161  key="safesearch",
162  translation_key="safesearch",
163  entity_category=EntityCategory.CONFIG,
164  state=lambda data: data.safesearch,
165  ),
167  key="youtube_restricted_mode",
168  translation_key="youtube_restricted_mode",
169  entity_category=EntityCategory.CONFIG,
170  state=lambda data: data.youtube_restricted_mode,
171  ),
173  key="block_9gag",
174  translation_key="block_9gag",
175  entity_category=EntityCategory.CONFIG,
176  entity_registry_enabled_default=False,
177  state=lambda data: data.block_9gag,
178  ),
180  key="block_amazon",
181  translation_key="block_amazon",
182  entity_category=EntityCategory.CONFIG,
183  entity_registry_enabled_default=False,
184  state=lambda data: data.block_amazon,
185  ),
187  key="block_bereal",
188  translation_key="block_bereal",
189  entity_category=EntityCategory.CONFIG,
190  entity_registry_enabled_default=False,
191  state=lambda data: data.block_bereal,
192  ),
194  key="block_blizzard",
195  translation_key="block_blizzard",
196  entity_category=EntityCategory.CONFIG,
197  entity_registry_enabled_default=False,
198  state=lambda data: data.block_blizzard,
199  ),
201  key="block_chatgpt",
202  translation_key="block_chatgpt",
203  entity_category=EntityCategory.CONFIG,
204  entity_registry_enabled_default=False,
205  state=lambda data: data.block_chatgpt,
206  ),
208  key="block_dailymotion",
209  translation_key="block_dailymotion",
210  entity_category=EntityCategory.CONFIG,
211  entity_registry_enabled_default=False,
212  state=lambda data: data.block_dailymotion,
213  ),
215  key="block_discord",
216  translation_key="block_discord",
217  entity_category=EntityCategory.CONFIG,
218  entity_registry_enabled_default=False,
219  state=lambda data: data.block_discord,
220  ),
222  key="block_disneyplus",
223  translation_key="block_disneyplus",
224  entity_category=EntityCategory.CONFIG,
225  entity_registry_enabled_default=False,
226  state=lambda data: data.block_disneyplus,
227  ),
229  key="block_ebay",
230  translation_key="block_ebay",
231  entity_category=EntityCategory.CONFIG,
232  entity_registry_enabled_default=False,
233  state=lambda data: data.block_ebay,
234  ),
236  key="block_facebook",
237  translation_key="block_facebook",
238  entity_category=EntityCategory.CONFIG,
239  entity_registry_enabled_default=False,
240  state=lambda data: data.block_facebook,
241  ),
243  key="block_fortnite",
244  translation_key="block_fortnite",
245  entity_category=EntityCategory.CONFIG,
246  entity_registry_enabled_default=False,
247  state=lambda data: data.block_fortnite,
248  ),
250  key="block_google_chat",
251  translation_key="block_google_chat",
252  entity_category=EntityCategory.CONFIG,
253  entity_registry_enabled_default=False,
254  state=lambda data: data.block_google_chat,
255  ),
257  key="block_hbomax",
258  translation_key="block_hbomax",
259  entity_category=EntityCategory.CONFIG,
260  entity_registry_enabled_default=False,
261  state=lambda data: data.block_hbomax,
262  ),
264  key="block_hulu",
265  name="Block Hulu",
266  entity_category=EntityCategory.CONFIG,
267  entity_registry_enabled_default=False,
268  state=lambda data: data.block_hulu,
269  ),
271  key="block_imgur",
272  translation_key="block_imgur",
273  entity_category=EntityCategory.CONFIG,
274  entity_registry_enabled_default=False,
275  state=lambda data: data.block_imgur,
276  ),
278  key="block_instagram",
279  translation_key="block_instagram",
280  entity_category=EntityCategory.CONFIG,
281  entity_registry_enabled_default=False,
282  state=lambda data: data.block_instagram,
283  ),
285  key="block_leagueoflegends",
286  translation_key="block_leagueoflegends",
287  entity_category=EntityCategory.CONFIG,
288  entity_registry_enabled_default=False,
289  state=lambda data: data.block_leagueoflegends,
290  ),
292  key="block_mastodon",
293  translation_key="block_mastodon",
294  entity_category=EntityCategory.CONFIG,
295  entity_registry_enabled_default=False,
296  state=lambda data: data.block_mastodon,
297  ),
299  key="block_messenger",
300  translation_key="block_messenger",
301  entity_category=EntityCategory.CONFIG,
302  entity_registry_enabled_default=False,
303  state=lambda data: data.block_messenger,
304  ),
306  key="block_minecraft",
307  translation_key="block_minecraft",
308  entity_category=EntityCategory.CONFIG,
309  entity_registry_enabled_default=False,
310  state=lambda data: data.block_minecraft,
311  ),
313  key="block_netflix",
314  translation_key="block_netflix",
315  entity_category=EntityCategory.CONFIG,
316  entity_registry_enabled_default=False,
317  state=lambda data: data.block_netflix,
318  ),
320  key="block_pinterest",
321  translation_key="block_pinterest",
322  entity_category=EntityCategory.CONFIG,
323  entity_registry_enabled_default=False,
324  state=lambda data: data.block_pinterest,
325  ),
327  key="block_playstation_network",
328  translation_key="block_playstation_network",
329  entity_category=EntityCategory.CONFIG,
330  entity_registry_enabled_default=False,
331  state=lambda data: data.block_playstation_network,
332  ),
334  key="block_primevideo",
335  translation_key="block_primevideo",
336  entity_category=EntityCategory.CONFIG,
337  entity_registry_enabled_default=False,
338  state=lambda data: data.block_primevideo,
339  ),
341  key="block_reddit",
342  translation_key="block_reddit",
343  entity_category=EntityCategory.CONFIG,
344  entity_registry_enabled_default=False,
345  state=lambda data: data.block_reddit,
346  ),
348  key="block_roblox",
349  translation_key="block_roblox",
350  entity_category=EntityCategory.CONFIG,
351  entity_registry_enabled_default=False,
352  state=lambda data: data.block_roblox,
353  ),
355  key="block_signal",
356  translation_key="block_signal",
357  entity_category=EntityCategory.CONFIG,
358  entity_registry_enabled_default=False,
359  state=lambda data: data.block_signal,
360  ),
362  key="block_skype",
363  translation_key="block_skype",
364  entity_category=EntityCategory.CONFIG,
365  entity_registry_enabled_default=False,
366  state=lambda data: data.block_skype,
367  ),
369  key="block_snapchat",
370  translation_key="block_snapchat",
371  entity_category=EntityCategory.CONFIG,
372  entity_registry_enabled_default=False,
373  state=lambda data: data.block_snapchat,
374  ),
376  key="block_spotify",
377  translation_key="block_spotify",
378  entity_category=EntityCategory.CONFIG,
379  entity_registry_enabled_default=False,
380  state=lambda data: data.block_spotify,
381  ),
383  key="block_steam",
384  translation_key="block_steam",
385  entity_category=EntityCategory.CONFIG,
386  entity_registry_enabled_default=False,
387  state=lambda data: data.block_steam,
388  ),
390  key="block_telegram",
391  translation_key="block_telegram",
392  entity_category=EntityCategory.CONFIG,
393  entity_registry_enabled_default=False,
394  state=lambda data: data.block_telegram,
395  ),
397  key="block_tiktok",
398  translation_key="block_tiktok",
399  entity_category=EntityCategory.CONFIG,
400  entity_registry_enabled_default=False,
401  state=lambda data: data.block_tiktok,
402  ),
404  key="block_tinder",
405  translation_key="block_tinder",
406  entity_category=EntityCategory.CONFIG,
407  entity_registry_enabled_default=False,
408  state=lambda data: data.block_tinder,
409  ),
411  key="block_tumblr",
412  translation_key="block_tumblr",
413  entity_category=EntityCategory.CONFIG,
414  entity_registry_enabled_default=False,
415  state=lambda data: data.block_tumblr,
416  ),
418  key="block_twitch",
419  translation_key="block_twitch",
420  entity_category=EntityCategory.CONFIG,
421  entity_registry_enabled_default=False,
422  state=lambda data: data.block_twitch,
423  ),
425  key="block_twitter",
426  translation_key="block_twitter",
427  entity_category=EntityCategory.CONFIG,
428  entity_registry_enabled_default=False,
429  state=lambda data: data.block_twitter,
430  ),
432  key="block_vimeo",
433  translation_key="block_vimeo",
434  entity_category=EntityCategory.CONFIG,
435  entity_registry_enabled_default=False,
436  state=lambda data: data.block_vimeo,
437  ),
439  key="block_vk",
440  translation_key="block_vk",
441  entity_category=EntityCategory.CONFIG,
442  entity_registry_enabled_default=False,
443  state=lambda data: data.block_vk,
444  ),
446  key="block_whatsapp",
447  translation_key="block_whatsapp",
448  entity_category=EntityCategory.CONFIG,
449  entity_registry_enabled_default=False,
450  state=lambda data: data.block_whatsapp,
451  ),
453  key="block_xboxlive",
454  translation_key="block_xboxlive",
455  entity_category=EntityCategory.CONFIG,
456  entity_registry_enabled_default=False,
457  state=lambda data: data.block_xboxlive,
458  ),
460  key="block_youtube",
461  translation_key="block_youtube",
462  entity_category=EntityCategory.CONFIG,
463  entity_registry_enabled_default=False,
464  state=lambda data: data.block_youtube,
465  ),
467  key="block_zoom",
468  translation_key="block_zoom",
469  entity_category=EntityCategory.CONFIG,
470  entity_registry_enabled_default=False,
471  state=lambda data: data.block_zoom,
472  ),
474  key="block_dating",
475  translation_key="block_dating",
476  entity_category=EntityCategory.CONFIG,
477  entity_registry_enabled_default=False,
478  state=lambda data: data.block_dating,
479  ),
481  key="block_gambling",
482  translation_key="block_gambling",
483  entity_category=EntityCategory.CONFIG,
484  entity_registry_enabled_default=False,
485  state=lambda data: data.block_gambling,
486  ),
488  key="block_online_gaming",
489  translation_key="block_online_gaming",
490  entity_category=EntityCategory.CONFIG,
491  entity_registry_enabled_default=False,
492  state=lambda data: data.block_online_gaming,
493  ),
495  key="block_piracy",
496  translation_key="block_piracy",
497  entity_category=EntityCategory.CONFIG,
498  entity_registry_enabled_default=False,
499  state=lambda data: data.block_piracy,
500  ),
502  key="block_porn",
503  translation_key="block_porn",
504  entity_category=EntityCategory.CONFIG,
505  entity_registry_enabled_default=False,
506  state=lambda data: data.block_porn,
507  ),
509  key="block_social_networks",
510  translation_key="block_social_networks",
511  entity_category=EntityCategory.CONFIG,
512  entity_registry_enabled_default=False,
513  state=lambda data: data.block_social_networks,
514  ),
516  key="block_video_streaming",
517  translation_key="block_video_streaming",
518  entity_category=EntityCategory.CONFIG,
519  entity_registry_enabled_default=False,
520  state=lambda data: data.block_video_streaming,
521  ),
522 )
523 
524 
526  hass: HomeAssistant,
527  entry: NextDnsConfigEntry,
528  async_add_entities: AddEntitiesCallback,
529 ) -> None:
530  """Add NextDNS entities from a config_entry."""
531  coordinator = entry.runtime_data.settings
532 
534  NextDnsSwitch(coordinator, description) for description in SWITCHES
535  )
536 
537 
539  CoordinatorEntity[NextDnsUpdateCoordinator[Settings]], SwitchEntity
540 ):
541  """Define an NextDNS switch."""
542 
543  _attr_has_entity_name = True
544  entity_description: NextDnsSwitchEntityDescription
545 
546  def __init__(
547  self,
548  coordinator: NextDnsUpdateCoordinator[Settings],
549  description: NextDnsSwitchEntityDescription,
550  ) -> None:
551  """Initialize."""
552  super().__init__(coordinator)
553  self._attr_device_info_attr_device_info = coordinator.device_info
554  self._attr_unique_id_attr_unique_id = f"{coordinator.profile_id}_{description.key}"
555  self._attr_is_on_attr_is_on = description.state(coordinator.data)
556  self.entity_descriptionentity_description = description
557 
558  @callback
559  def _handle_coordinator_update(self) -> None:
560  """Handle updated data from the coordinator."""
561  self._attr_is_on_attr_is_on = self.entity_descriptionentity_description.state(self.coordinator.data)
562  self.async_write_ha_stateasync_write_ha_state()
563 
564  async def async_turn_on(self, **kwargs: Any) -> None:
565  """Turn on switch."""
566  await self.async_set_settingasync_set_setting(True)
567 
568  async def async_turn_off(self, **kwargs: Any) -> None:
569  """Turn off switch."""
570  await self.async_set_settingasync_set_setting(False)
571 
572  async def async_set_setting(self, new_state: bool) -> None:
573  """Set the new state."""
574  try:
575  result = await self.coordinator.nextdns.set_setting(
576  self.coordinator.profile_id, self.entity_descriptionentity_description.key, new_state
577  )
578  except (
579  ApiError,
580  ClientConnectorError,
581  TimeoutError,
582  ClientError,
583  ) as err:
584  raise HomeAssistantError(
585  "NextDNS API returned an error calling set_setting for"
586  f" {self.entity_id}: {err}"
587  ) from err
588 
589  if result:
590  self._attr_is_on_attr_is_on = new_state
591  self.async_write_ha_stateasync_write_ha_state()
None __init__(self, NextDnsUpdateCoordinator[Settings] coordinator, NextDnsSwitchEntityDescription description)
Definition: switch.py:550
None async_set_setting(self, bool new_state)
Definition: switch.py:572
Literal["on", "off"]|None state(self)
Definition: entity.py:1686
None async_setup_entry(HomeAssistant hass, NextDnsConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: switch.py:529