-
-
Notifications
You must be signed in to change notification settings - Fork 28.5k
/
demo.py
131 lines (107 loc) · 4.56 KB
/
demo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
"""
Demo platform for the geo location component.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
import logging
import random
from datetime import timedelta
from math import pi, cos, sin, radians
from typing import Optional
from homeassistant.components.geo_location import GeoLocationEvent
from homeassistant.helpers.event import track_time_interval
_LOGGER = logging.getLogger(__name__)
AVG_KM_PER_DEGREE = 111.0
DEFAULT_UNIT_OF_MEASUREMENT = "km"
DEFAULT_UPDATE_INTERVAL = timedelta(minutes=1)
MAX_RADIUS_IN_KM = 50
NUMBER_OF_DEMO_DEVICES = 5
EVENT_NAMES = ["Bushfire", "Hazard Reduction", "Grass Fire", "Burn off",
"Structure Fire", "Fire Alarm", "Thunderstorm", "Tornado",
"Cyclone", "Waterspout", "Dust Storm", "Blizzard", "Ice Storm",
"Earthquake", "Tsunami"]
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Demo geo locations."""
DemoManager(hass, add_entities)
class DemoManager:
"""Device manager for demo geo location events."""
def __init__(self, hass, add_entities):
"""Initialise the demo geo location event manager."""
self._hass = hass
self._add_entities = add_entities
self._managed_devices = []
self._update(count=NUMBER_OF_DEMO_DEVICES)
self._init_regular_updates()
def _generate_random_event(self):
"""Generate a random event in vicinity of this HA instance."""
home_latitude = self._hass.config.latitude
home_longitude = self._hass.config.longitude
# Approx. 111km per degree (north-south).
radius_in_degrees = random.random() * MAX_RADIUS_IN_KM / \
AVG_KM_PER_DEGREE
radius_in_km = radius_in_degrees * AVG_KM_PER_DEGREE
angle = random.random() * 2 * pi
# Compute coordinates based on radius and angle. Adjust longitude value
# based on HA's latitude.
latitude = home_latitude + radius_in_degrees * sin(angle)
longitude = home_longitude + radius_in_degrees * cos(angle) / \
cos(radians(home_latitude))
event_name = random.choice(EVENT_NAMES)
return DemoGeoLocationEvent(event_name, radius_in_km, latitude,
longitude, DEFAULT_UNIT_OF_MEASUREMENT)
def _init_regular_updates(self):
"""Schedule regular updates based on configured time interval."""
track_time_interval(self._hass, lambda now: self._update(),
DEFAULT_UPDATE_INTERVAL)
def _update(self, count=1):
"""Remove events and add new random events."""
# Remove devices.
for _ in range(1, count + 1):
if self._managed_devices:
device = random.choice(self._managed_devices)
if device:
_LOGGER.debug("Removing %s", device)
self._managed_devices.remove(device)
self._hass.add_job(device.async_remove())
# Generate new devices from events.
new_devices = []
for _ in range(1, count + 1):
new_device = self._generate_random_event()
_LOGGER.debug("Adding %s", new_device)
new_devices.append(new_device)
self._managed_devices.append(new_device)
self._add_entities(new_devices)
class DemoGeoLocationEvent(GeoLocationEvent):
"""This represents a demo geo location event."""
def __init__(self, name, distance, latitude, longitude,
unit_of_measurement):
"""Initialize entity with data provided."""
self._name = name
self._distance = distance
self._latitude = latitude
self._longitude = longitude
self._unit_of_measurement = unit_of_measurement
@property
def name(self) -> Optional[str]:
"""Return the name of the event."""
return self._name
@property
def should_poll(self):
"""No polling needed for a demo geo location event."""
return False
@property
def distance(self) -> Optional[float]:
"""Return distance value of this external event."""
return self._distance
@property
def latitude(self) -> Optional[float]:
"""Return latitude value of this external event."""
return self._latitude
@property
def longitude(self) -> Optional[float]:
"""Return longitude value of this external event."""
return self._longitude
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return self._unit_of_measurement