Home Assistant Unofficial Reference 2024.12.1
device_tracker.py
Go to the documentation of this file.
1 """Support for Tado Smart device trackers."""
2 
3 from __future__ import annotations
4 
5 import logging
6 
8  DOMAIN as DEVICE_TRACKER_DOMAIN,
9  TrackerEntity,
10 )
11 from homeassistant.const import STATE_HOME, STATE_NOT_HOME
12 from homeassistant.core import HomeAssistant, callback
13 from homeassistant.helpers import entity_registry as er
14 from homeassistant.helpers.dispatcher import async_dispatcher_connect
15 from homeassistant.helpers.entity_platform import AddEntitiesCallback
16 
17 from . import TadoConfigEntry
18 from .const import DOMAIN, SIGNAL_TADO_MOBILE_DEVICE_UPDATE_RECEIVED
19 from .tado_connector import TadoConnector
20 
21 _LOGGER = logging.getLogger(__name__)
22 
23 
25  hass: HomeAssistant,
26  entry: TadoConfigEntry,
27  async_add_entities: AddEntitiesCallback,
28 ) -> None:
29  """Set up the Tado device scannery entity."""
30  _LOGGER.debug("Setting up Tado device scanner entity")
31  tado = entry.runtime_data
32  tracked: set = set()
33 
34  # Fix non-string unique_id for device trackers
35  # Can be removed in 2025.1
36  entity_registry = er.async_get(hass)
37  for device_key in tado.data["mobile_device"]:
38  if entity_id := entity_registry.async_get_entity_id(
39  DEVICE_TRACKER_DOMAIN, DOMAIN, device_key
40  ):
41  entity_registry.async_update_entity(
42  entity_id, new_unique_id=str(device_key)
43  )
44 
45  @callback
46  def update_devices() -> None:
47  """Update the values of the devices."""
48  add_tracked_entities(hass, tado, async_add_entities, tracked)
49 
51 
52  entry.async_on_unload(
54  hass,
55  SIGNAL_TADO_MOBILE_DEVICE_UPDATE_RECEIVED.format(tado.home_id),
56  update_devices,
57  )
58  )
59 
60 
61 @callback
63  hass: HomeAssistant,
64  tado: TadoConnector,
65  async_add_entities: AddEntitiesCallback,
66  tracked: set[str],
67 ) -> None:
68  """Add new tracker entities from Tado."""
69  _LOGGER.debug("Fetching Tado devices from API for (newly) tracked entities")
70  new_tracked = []
71  for device_key, device in tado.data["mobile_device"].items():
72  if device_key in tracked:
73  continue
74 
75  _LOGGER.debug(
76  "Adding Tado device %s with deviceID %s", device["name"], device_key
77  )
78  new_tracked.append(TadoDeviceTrackerEntity(device_key, device["name"], tado))
79  tracked.add(device_key)
80 
81  async_add_entities(new_tracked)
82 
83 
84 class TadoDeviceTrackerEntity(TrackerEntity):
85  """A Tado Device Tracker entity."""
86 
87  _attr_should_poll = False
88  _attr_available = False
89 
90  def __init__(
91  self,
92  device_id: str,
93  device_name: str,
94  tado: TadoConnector,
95  ) -> None:
96  """Initialize a Tado Device Tracker entity."""
97  super().__init__()
98  self._attr_unique_id_attr_unique_id = str(device_id)
99  self._device_id_device_id = device_id
100  self._device_name_device_name = device_name
101  self._tado_tado = tado
102  self._active_active = False
103 
104  @callback
105  def update_state(self) -> None:
106  """Update the Tado device."""
107  _LOGGER.debug(
108  "Updating Tado mobile device: %s (ID: %s)",
109  self._device_name_device_name,
110  self._device_id_device_id,
111  )
112  device = self._tado_tado.data["mobile_device"][self._device_id_device_id]
113 
114  self._attr_available_attr_available_attr_available = False
115  _LOGGER.debug(
116  "Tado device %s has geoTracking state %s",
117  device["name"],
118  device["settings"]["geoTrackingEnabled"],
119  )
120 
121  if device["settings"]["geoTrackingEnabled"] is False:
122  return
123 
124  self._attr_available_attr_available_attr_available = True
125  self._active_active = False
126  if device.get("location") is not None and device["location"]["atHome"]:
127  _LOGGER.debug("Tado device %s is at home", device["name"])
128  self._active_active = True
129  else:
130  _LOGGER.debug("Tado device %s is not at home", device["name"])
131 
132  @callback
133  def on_demand_update(self) -> None:
134  """Update state on demand."""
135  self.update_stateupdate_state()
136  self.async_write_ha_state()
137 
138  async def async_added_to_hass(self) -> None:
139  """Register state update callback."""
140  _LOGGER.debug("Registering Tado device tracker entity")
141  self.async_on_remove(
143  self.hass,
144  SIGNAL_TADO_MOBILE_DEVICE_UPDATE_RECEIVED.format(self._tado_tado.home_id),
145  self.on_demand_updateon_demand_update,
146  )
147  )
148 
149  self.update_stateupdate_state()
150 
151  @property
152  def name(self) -> str:
153  """Return the name of the device."""
154  return self._device_name_device_name
155 
156  @property
157  def location_name(self) -> str:
158  """Return the state of the device."""
159  return STATE_HOME if self._active_active else STATE_NOT_HOME
None __init__(self, str device_id, str device_name, TadoConnector tado)
None update_devices(HomeAssistant hass, ConfigEntry config_entry, dict[int, Roller] api)
Definition: helpers.py:47
None async_setup_entry(HomeAssistant hass, TadoConfigEntry entry, AddEntitiesCallback async_add_entities)
None add_tracked_entities(HomeAssistant hass, TadoConnector tado, AddEntitiesCallback async_add_entities, set[str] tracked)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103