Home Assistant Unofficial Reference 2024.12.1
geo_location.py
Go to the documentation of this file.
1 """Demo platform for the geolocation component."""
2 
3 from __future__ import annotations
4 
5 from datetime import timedelta
6 import logging
7 from math import cos, pi, radians, sin
8 import random
9 
10 from homeassistant.components.geo_location import GeolocationEvent
11 from homeassistant.const import UnitOfLength
12 from homeassistant.core import HomeAssistant
13 from homeassistant.helpers.entity_platform import AddEntitiesCallback
14 from homeassistant.helpers.event import track_time_interval
15 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
16 
17 _LOGGER = logging.getLogger(__name__)
18 
19 AVG_KM_PER_DEGREE = 111.0
20 DEFAULT_UPDATE_INTERVAL = timedelta(minutes=1)
21 MAX_RADIUS_IN_KM = 50
22 NUMBER_OF_DEMO_DEVICES = 5
23 
24 EVENT_NAMES = [
25  "Bushfire",
26  "Hazard Reduction",
27  "Grass Fire",
28  "Burn off",
29  "Structure Fire",
30  "Fire Alarm",
31  "Thunderstorm",
32  "Tornado",
33  "Cyclone",
34  "Waterspout",
35  "Dust Storm",
36  "Blizzard",
37  "Ice Storm",
38  "Earthquake",
39  "Tsunami",
40 ]
41 
42 SOURCE = "demo"
43 
44 
46  hass: HomeAssistant,
47  config: ConfigType,
48  add_entities: AddEntitiesCallback,
49  discovery_info: DiscoveryInfoType | None = None,
50 ) -> None:
51  """Set up the Demo geolocations."""
52  DemoManager(hass, add_entities)
53 
54 
56  """Device manager for demo geolocation events."""
57 
58  def __init__(self, hass: HomeAssistant, add_entities: AddEntitiesCallback) -> None:
59  """Initialise the demo geolocation event manager."""
60  self._hass_hass = hass
61  self._add_entities_add_entities = add_entities
62  self._managed_devices: list[DemoGeolocationEvent] = []
63  self._update_update(count=NUMBER_OF_DEMO_DEVICES)
64  self._init_regular_updates_init_regular_updates()
65 
66  def _generate_random_event(self) -> DemoGeolocationEvent:
67  """Generate a random event in vicinity of this HA instance."""
68  home_latitude = self._hass_hass.config.latitude
69  home_longitude = self._hass_hass.config.longitude
70 
71  # Approx. 111km per degree (north-south).
72  radius_in_degrees = random.random() * MAX_RADIUS_IN_KM / AVG_KM_PER_DEGREE
73  radius_in_km = radius_in_degrees * AVG_KM_PER_DEGREE
74  angle = random.random() * 2 * pi
75  # Compute coordinates based on radius and angle. Adjust longitude value
76  # based on HA's latitude.
77  latitude = home_latitude + radius_in_degrees * sin(angle)
78  longitude = home_longitude + radius_in_degrees * cos(angle) / cos(
79  radians(home_latitude)
80  )
81 
82  event_name = random.choice(EVENT_NAMES)
83  return DemoGeolocationEvent(
84  event_name, radius_in_km, latitude, longitude, UnitOfLength.KILOMETERS
85  )
86 
87  def _init_regular_updates(self) -> None:
88  """Schedule regular updates based on configured time interval."""
90  self._hass_hass,
91  lambda now: self._update_update(),
92  DEFAULT_UPDATE_INTERVAL,
93  cancel_on_shutdown=True,
94  )
95 
96  def _update(self, count: int = 1) -> None:
97  """Remove events and add new random events."""
98  # Remove devices.
99  for _ in range(1, count + 1):
100  if self._managed_devices:
101  device = random.choice(self._managed_devices)
102  if device:
103  _LOGGER.debug("Removing %s", device)
104  self._managed_devices.remove(device)
105  self._hass_hass.add_job(device.async_remove())
106  # Generate new devices from events.
107  new_devices = []
108  for _ in range(1, count + 1):
109  new_device = self._generate_random_event_generate_random_event()
110  _LOGGER.debug("Adding %s", new_device)
111  new_devices.append(new_device)
112  self._managed_devices.append(new_device)
113  self._add_entities_add_entities(new_devices)
114 
115 
117  """Represents a demo geolocation event."""
118 
119  _attr_should_poll = False
120 
121  def __init__(
122  self,
123  name: str,
124  distance: float,
125  latitude: float,
126  longitude: float,
127  unit_of_measurement: str,
128  ) -> None:
129  """Initialize entity with data provided."""
130  self._attr_name_attr_name = name
131  self._distance_distance = distance
132  self._latitude_latitude = latitude
133  self._longitude_longitude = longitude
134  self._unit_of_measurement_unit_of_measurement = unit_of_measurement
135 
136  @property
137  def source(self) -> str:
138  """Return source value of this external event."""
139  return SOURCE
140 
141  @property
142  def distance(self) -> float | None:
143  """Return distance value of this external event."""
144  return self._distance_distance
145 
146  @property
147  def latitude(self) -> float | None:
148  """Return latitude value of this external event."""
149  return self._latitude_latitude
150 
151  @property
152  def longitude(self) -> float | None:
153  """Return longitude value of this external event."""
154  return self._longitude_longitude
155 
156  @property
157  def unit_of_measurement(self) -> str:
158  """Return the unit of measurement."""
159  return self._unit_of_measurement_unit_of_measurement
None __init__(self, str name, float distance, float latitude, float longitude, str unit_of_measurement)
None __init__(self, HomeAssistant hass, AddEntitiesCallback add_entities)
Definition: geo_location.py:58
bool remove(self, _T matcher)
Definition: match.py:214
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: geo_location.py:50