Home Assistant Unofficial Reference 2024.12.1
button.py
Go to the documentation of this file.
1 """Switches for AVM Fritz!Box buttons."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 import logging
8 from typing import Any, Final
9 
11  ButtonDeviceClass,
12  ButtonEntity,
13  ButtonEntityDescription,
14 )
15 from homeassistant.config_entries import ConfigEntry
16 from homeassistant.const import EntityCategory
17 from homeassistant.core import HomeAssistant, callback
18 from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
19 from homeassistant.helpers.dispatcher import async_dispatcher_connect
20 from homeassistant.helpers.entity_platform import AddEntitiesCallback
21 
22 from .const import BUTTON_TYPE_WOL, CONNECTION_TYPE_LAN, DATA_FRITZ, DOMAIN, MeshRoles
23 from .coordinator import AvmWrapper, FritzData, FritzDevice, _is_tracked
24 from .entity import FritzDeviceBase
25 
26 _LOGGER = logging.getLogger(__name__)
27 
28 
29 @dataclass(frozen=True, kw_only=True)
31  """Class to describe a Button entity."""
32 
33  press_action: Callable[[AvmWrapper], Any]
34 
35 
36 BUTTONS: Final = [
38  key="firmware_update",
39  translation_key="firmware_update",
40  device_class=ButtonDeviceClass.UPDATE,
41  entity_category=EntityCategory.CONFIG,
42  press_action=lambda avm_wrapper: avm_wrapper.async_trigger_firmware_update(),
43  ),
45  key="reboot",
46  device_class=ButtonDeviceClass.RESTART,
47  entity_category=EntityCategory.CONFIG,
48  press_action=lambda avm_wrapper: avm_wrapper.async_trigger_reboot(),
49  ),
51  key="reconnect",
52  translation_key="reconnect",
53  device_class=ButtonDeviceClass.RESTART,
54  entity_category=EntityCategory.CONFIG,
55  press_action=lambda avm_wrapper: avm_wrapper.async_trigger_reconnect(),
56  ),
58  key="cleanup",
59  translation_key="cleanup",
60  entity_category=EntityCategory.CONFIG,
61  press_action=lambda avm_wrapper: avm_wrapper.async_trigger_cleanup(),
62  ),
63 ]
64 
65 
67  hass: HomeAssistant,
68  entry: ConfigEntry,
69  async_add_entities: AddEntitiesCallback,
70 ) -> None:
71  """Set buttons for device."""
72  _LOGGER.debug("Setting up buttons")
73  avm_wrapper: AvmWrapper = hass.data[DOMAIN][entry.entry_id]
74 
75  entities_list: list[ButtonEntity] = [
76  FritzButton(avm_wrapper, entry.title, button) for button in BUTTONS
77  ]
78 
79  if avm_wrapper.mesh_role == MeshRoles.SLAVE:
80  async_add_entities(entities_list)
81  return
82 
83  data_fritz: FritzData = hass.data[DATA_FRITZ]
84  entities_list += _async_wol_buttons_list(avm_wrapper, data_fritz)
85 
86  async_add_entities(entities_list)
87 
88  @callback
89  def async_update_avm_device() -> None:
90  """Update the values of the AVM device."""
91  async_add_entities(_async_wol_buttons_list(avm_wrapper, data_fritz))
92 
93  entry.async_on_unload(
95  hass, avm_wrapper.signal_device_new, async_update_avm_device
96  )
97  )
98 
99 
101  """Defines a Fritz!Box base button."""
102 
103  entity_description: FritzButtonDescription
104  _attr_has_entity_name = True
105 
106  def __init__(
107  self,
108  avm_wrapper: AvmWrapper,
109  device_friendly_name: str,
110  description: FritzButtonDescription,
111  ) -> None:
112  """Initialize Fritz!Box button."""
113  self.entity_descriptionentity_description = description
114  self.avm_wrapperavm_wrapper = avm_wrapper
115 
116  self._attr_unique_id_attr_unique_id = f"{self.avm_wrapper.unique_id}-{description.key}"
117 
118  self._attr_device_info_attr_device_info = DeviceInfo(
119  connections={(CONNECTION_NETWORK_MAC, avm_wrapper.mac)},
120  name=device_friendly_name,
121  )
122 
123  async def async_press(self) -> None:
124  """Triggers Fritz!Box service."""
125  await self.entity_descriptionentity_description.press_action(self.avm_wrapperavm_wrapper)
126 
127 
128 @callback
130  avm_wrapper: AvmWrapper,
131  data_fritz: FritzData,
132 ) -> list[FritzBoxWOLButton]:
133  """Add new WOL button entities from the AVM device."""
134  _LOGGER.debug("Setting up %s buttons", BUTTON_TYPE_WOL)
135 
136  new_wols: list[FritzBoxWOLButton] = []
137 
138  if avm_wrapper.unique_id not in data_fritz.wol_buttons:
139  data_fritz.wol_buttons[avm_wrapper.unique_id] = set()
140 
141  for mac, device in avm_wrapper.devices.items():
142  if _is_tracked(mac, data_fritz.wol_buttons.values()):
143  _LOGGER.debug("Skipping wol button creation for device %s", device.hostname)
144  continue
145 
146  if device.connection_type != CONNECTION_TYPE_LAN:
147  _LOGGER.debug(
148  "Skipping wol button creation for device %s, not connected via LAN",
149  device.hostname,
150  )
151  continue
152 
153  new_wols.append(FritzBoxWOLButton(avm_wrapper, device))
154  data_fritz.wol_buttons[avm_wrapper.unique_id].add(mac)
155 
156  _LOGGER.debug("Creating %s wol buttons", len(new_wols))
157  return new_wols
158 
159 
161  """Defines a FRITZ!Box Tools Wake On LAN button."""
162 
163  _attr_icon = "mdi:lan-pending"
164  _attr_entity_registry_enabled_default = False
165 
166  def __init__(self, avm_wrapper: AvmWrapper, device: FritzDevice) -> None:
167  """Initialize Fritz!Box WOL button."""
168  super().__init__(avm_wrapper, device)
169  self._name_name = f"{self.hostname} Wake on LAN"
170  self._attr_unique_id_attr_unique_id = f"{self._mac}_wake_on_lan"
171  self._is_available_is_available = True
172  self._attr_device_info_attr_device_info = DeviceInfo(
173  connections={(CONNECTION_NETWORK_MAC, self._mac)},
174  default_manufacturer="AVM",
175  default_model="FRITZ!Box Tracked device",
176  default_name=device.hostname,
177  via_device=(
178  DOMAIN,
179  avm_wrapper.unique_id,
180  ),
181  )
182 
183  async def async_press(self) -> None:
184  """Press the button."""
185  if self.mac_addressmac_address:
186  await self._avm_wrapper_avm_wrapper.async_wake_on_lan(self.mac_addressmac_address)
None __init__(self, AvmWrapper avm_wrapper, FritzDevice device)
Definition: button.py:166
None __init__(self, AvmWrapper avm_wrapper, str device_friendly_name, FritzButtonDescription description)
Definition: button.py:111
dict[str, Any] async_wake_on_lan(self, str mac_address)
Definition: coordinator.py:875
bool add(self, _T matcher)
Definition: match.py:185
list[FritzBoxWOLButton] _async_wol_buttons_list(AvmWrapper avm_wrapper, FritzData data_fritz)
Definition: button.py:132
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: button.py:70
bool _is_tracked(str mac, ValuesView current_devices)
Definition: coordinator.py:56
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103