Home Assistant Unofficial Reference 2024.12.1
device_tracker.py
Go to the documentation of this file.
1 """Support for the Geofency device tracker platform."""
2 
3 from homeassistant.components.device_tracker import TrackerEntity
4 from homeassistant.config_entries import ConfigEntry
5 from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE
6 from homeassistant.core import HomeAssistant, callback
7 from homeassistant.helpers import device_registry as dr
8 from homeassistant.helpers.device_registry import DeviceInfo
9 from homeassistant.helpers.dispatcher import async_dispatcher_connect
10 from homeassistant.helpers.entity_platform import AddEntitiesCallback
11 from homeassistant.helpers.restore_state import RestoreEntity
12 
13 from . import DOMAIN as GF_DOMAIN, TRACKER_UPDATE
14 
15 
17  hass: HomeAssistant,
18  config_entry: ConfigEntry,
19  async_add_entities: AddEntitiesCallback,
20 ) -> None:
21  """Set up Geofency config entry."""
22 
23  @callback
24  def _receive_data(device, gps, location_name, attributes):
25  """Fire HA event to set location."""
26  if device in hass.data[GF_DOMAIN]["devices"]:
27  return
28 
29  hass.data[GF_DOMAIN]["devices"].add(device)
30 
31  async_add_entities([GeofencyEntity(device, gps, location_name, attributes)])
32 
33  hass.data[GF_DOMAIN]["unsub_device_tracker"][config_entry.entry_id] = (
34  async_dispatcher_connect(hass, TRACKER_UPDATE, _receive_data)
35  )
36 
37  # Restore previously loaded devices
38  dev_reg = dr.async_get(hass)
39  dev_ids = {
40  identifier[1]
41  for device in dev_reg.devices.get_devices_for_config_entry_id(
42  config_entry.entry_id
43  )
44  for identifier in device.identifiers
45  }
46 
47  if dev_ids:
48  hass.data[GF_DOMAIN]["devices"].update(dev_ids)
49  async_add_entities(GeofencyEntity(dev_id) for dev_id in dev_ids)
50 
51 
52 class GeofencyEntity(TrackerEntity, RestoreEntity):
53  """Represent a tracked device."""
54 
55  _attr_has_entity_name = True
56  _attr_name = None
57 
58  def __init__(self, device, gps=None, location_name=None, attributes=None):
59  """Set up Geofency entity."""
60  self._attr_extra_state_attributes_attr_extra_state_attributes = attributes or {}
61  self._name_name = device
62  self._attr_location_name_attr_location_name = location_name
63  if gps:
64  self._attr_latitude_attr_latitude = gps[0]
65  self._attr_longitude_attr_longitude = gps[1]
66  self._unsub_dispatcher_unsub_dispatcher = None
67  self._attr_unique_id_attr_unique_id = device
68  self._attr_device_info_attr_device_info = DeviceInfo(
69  identifiers={(GF_DOMAIN, device)},
70  name=device,
71  )
72 
73  async def async_added_to_hass(self) -> None:
74  """Register state update callback."""
75  await super().async_added_to_hass()
76  self._unsub_dispatcher_unsub_dispatcher = async_dispatcher_connect(
77  self.hasshass, TRACKER_UPDATE, self._async_receive_data_async_receive_data
78  )
79 
80  if self._attr_extra_state_attributes_attr_extra_state_attributes:
81  return
82 
83  if (state := await self.async_get_last_stateasync_get_last_state()) is None:
84  self._attr_latitude_attr_latitude = None
85  self._attr_longitude_attr_longitude = None
86  return
87 
88  attr = state.attributes
89  self._attr_latitude_attr_latitude = attr.get(ATTR_LATITUDE)
90  self._attr_longitude_attr_longitude = attr.get(ATTR_LONGITUDE)
91 
92  async def async_will_remove_from_hass(self) -> None:
93  """Clean up after entity before removal."""
94  await super().async_will_remove_from_hass()
95  self._unsub_dispatcher_unsub_dispatcher()
96  self.hasshass.data[GF_DOMAIN]["devices"].remove(self.unique_idunique_id)
97 
98  @callback
99  def _async_receive_data(self, device, gps, location_name, attributes):
100  """Mark the device as seen."""
101  if device != self._name_name:
102  return
103 
104  self._attr_extra_state_attributes_attr_extra_state_attributes.update(attributes)
105  self._attr_location_name_attr_location_name = location_name
106  self._attr_latitude_attr_latitude = gps[0]
107  self._attr_longitude_attr_longitude = gps[1]
108  self.async_write_ha_stateasync_write_ha_state()
def __init__(self, device, gps=None, location_name=None, attributes=None)
def _async_receive_data(self, device, gps, location_name, attributes)
bool add(self, _T matcher)
Definition: match.py:185
bool remove(self, _T matcher)
Definition: match.py:214
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
IssData update(pyiss.ISS iss)
Definition: __init__.py:33
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103