Home Assistant Unofficial Reference 2024.12.1
device_tracker.py
Go to the documentation of this file.
1 """Platform for device tracker integration."""
2 
3 from __future__ import annotations
4 
5 from devolo_plc_api.device import Device
6 from devolo_plc_api.device_api import ConnectedStationInfo
7 
9  DOMAIN as DEVICE_TRACKER_DOMAIN,
10  ScannerEntity,
11 )
12 from homeassistant.const import STATE_UNKNOWN, UnitOfFrequency
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.helpers import entity_registry as er
15 from homeassistant.helpers.entity_platform import AddEntitiesCallback
16 from homeassistant.helpers.update_coordinator import CoordinatorEntity
17 
18 from . import DevoloHomeNetworkConfigEntry
19 from .const import CONNECTED_WIFI_CLIENTS, DOMAIN, WIFI_APTYPE, WIFI_BANDS
20 from .coordinator import DevoloDataUpdateCoordinator
21 
22 PARALLEL_UPDATES = 0
23 
24 
26  hass: HomeAssistant,
27  entry: DevoloHomeNetworkConfigEntry,
28  async_add_entities: AddEntitiesCallback,
29 ) -> None:
30  """Get all devices and sensors and setup them via config entry."""
31  device = entry.runtime_data.device
32  coordinators: dict[str, DevoloDataUpdateCoordinator[list[ConnectedStationInfo]]] = (
33  entry.runtime_data.coordinators
34  )
35  registry = er.async_get(hass)
36  tracked = set()
37 
38  @callback
39  def new_device_callback() -> None:
40  """Add new devices if needed."""
41  new_entities = []
42  for station in coordinators[CONNECTED_WIFI_CLIENTS].data:
43  if station.mac_address in tracked:
44  continue
45 
46  new_entities.append(
48  coordinators[CONNECTED_WIFI_CLIENTS], device, station.mac_address
49  )
50  )
51  tracked.add(station.mac_address)
52  async_add_entities(new_entities)
53 
54  @callback
55  def restore_entities() -> None:
56  """Restore clients that are not a part of active clients list."""
57  missing = []
58  for entity in er.async_entries_for_config_entry(registry, entry.entry_id):
59  if (
60  entity.platform == DOMAIN
61  and entity.domain == DEVICE_TRACKER_DOMAIN
62  and (
63  mac_address := entity.unique_id.replace(
64  f"{device.serial_number}_", ""
65  )
66  )
67  not in tracked
68  ):
69  missing.append(
71  coordinators[CONNECTED_WIFI_CLIENTS], device, mac_address
72  )
73  )
74  tracked.add(mac_address)
75 
76  async_add_entities(missing)
77 
79  entry.async_on_unload(
80  coordinators[CONNECTED_WIFI_CLIENTS].async_add_listener(new_device_callback)
81  )
82 
83 
84 # The pylint disable is needed because of https://github.com/pylint-dev/pylint/issues/9138
85 class DevoloScannerEntity( # pylint: disable=hass-enforce-class-module
86  CoordinatorEntity[DevoloDataUpdateCoordinator[list[ConnectedStationInfo]]],
87  ScannerEntity,
88 ):
89  """Representation of a devolo device tracker."""
90 
91  def __init__(
92  self,
93  coordinator: DevoloDataUpdateCoordinator[list[ConnectedStationInfo]],
94  device: Device,
95  mac: str,
96  ) -> None:
97  """Initialize entity."""
98  super().__init__(coordinator)
99  self._device = device
100  self._attr_mac_address = mac
101 
102  @property
103  def extra_state_attributes(self) -> dict[str, str]:
104  """Return the attributes."""
105  attrs: dict[str, str] = {}
106  if not self.coordinator.data:
107  return {}
108 
109  station = next(
110  (
111  station
112  for station in self.coordinator.data
113  if station.mac_address == self.mac_address
114  ),
115  None,
116  )
117  if station:
118  attrs["wifi"] = WIFI_APTYPE.get(station.vap_type, STATE_UNKNOWN)
119  attrs["band"] = (
120  f"{WIFI_BANDS.get(station.band)} {UnitOfFrequency.GIGAHERTZ}"
121  if WIFI_BANDS.get(station.band)
122  else STATE_UNKNOWN
123  )
124  return attrs
125 
126  @property
127  def icon(self) -> str:
128  """Return device icon."""
129  if self.is_connected:
130  return "mdi:lan-connect"
131  return "mdi:lan-disconnect"
132 
133  @property
134  def is_connected(self) -> bool:
135  """Return true if the device is connected to the network."""
136  return any(
137  station
138  for station in self.coordinator.data
139  if station.mac_address == self.mac_address
140  )
141 
142  @property
143  def unique_id(self) -> str:
144  """Return unique ID of the entity."""
145  return f"{self._device.serial_number}_{self.mac_address}"
None __init__(self, DevoloDataUpdateCoordinator[list[ConnectedStationInfo]] coordinator, Device device, str mac)
None async_setup_entry(HomeAssistant hass, DevoloHomeNetworkConfigEntry entry, AddEntitiesCallback async_add_entities)
None async_add_listener(HomeAssistant hass, Callable[[], None] listener)
Definition: __init__.py:82
None restore_entities(er.EntityRegistry registry, RuckusDataUpdateCoordinator coordinator, ConfigEntry entry, AddEntitiesCallback async_add_entities, set[str] tracked)