-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
168 lines (143 loc) · 6.53 KB
/
main.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import settings
import apprise
import requests
import time
from datetime import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
def get_weather():
"""
Fetches the weather from an API
"""
latitude = settings.latitude
longitude = settings.longitude
weather_endpoint = settings.endpoint
api_key = settings.api_key
request_url = f"{weather_endpoint}/{api_key}/{latitude},{longitude}"
payload = {"units": settings.units}
weather_data = requests.get(request_url, params=payload).json()
return weather_data
def main():
# Create an Apprise instance
app = apprise.Apprise()
for service in settings.apprise_services:
app.add(service)
check_for_weather = True
# The threshold to decide whether rain is forecast
rain_chance_threshold = 0.25
# Prevent notifications if it's still raining
is_still_raining = False
while check_for_weather:
# Sleep for 10 minutes between each check
interval_secs = 600
is_rain_forecast = False
# Retrieve weather for the next 10 minutes
minutely_weather = get_weather()["minutely"]
minutely_weather_data = minutely_weather["data"]
rain_check_window = minutely_weather_data[:12]
# Find out when rain is starting
for index, minute in enumerate(rain_check_window):
print(minute)
# If debugging is True, force rain to start in 5 minutes
if settings.debug:
if index == 5:
minute["precipProbability"] = 0.7
if minute["precipProbability"] > rain_chance_threshold:
is_rain_forecast = True
rain_starting_index = index
break
if not is_rain_forecast:
# Reset the is_still_raining variable so we notify next time
# it starts raining
is_still_raining = False
else:
# Check if it's still raining - if it is, don't resend the
# notification
if is_still_raining:
print("It's still raining - don't send another notification")
else:
# Find out when the rain is stopping
# Default rain_stopping_index - if this remains unchanged, then
# assume it's going to rain for the hour
rain_stopping_index = len(minutely_weather_data) - 1
for index, minute in enumerate(
minutely_weather_data[rain_starting_index:]
):
# If debugging is True, force rain to stop in 15 minutes
if settings.debug:
if index < 20:
minute["precipProbability"] = 0.7
else:
minute["precipProbability"] = rain_chance_threshold - 0.1
if minute["precipProbability"] < rain_chance_threshold:
rain_stopping_index = index
break
rain_starting = minutely_weather_data[rain_starting_index]
rain_starting_datetime = datetime.fromtimestamp(rain_starting["time"])
rain_starting_time_difference = rain_starting_datetime - datetime.now()
rain_starting_time_difference_mins = int(
rain_starting_time_difference.total_seconds() // 60
)
rain_stopping = minutely_weather_data[rain_stopping_index]
rain_stopping_datetime = datetime.fromtimestamp(rain_stopping["time"])
rain_stopping_time_difference = (
rain_stopping_datetime - rain_starting_datetime
)
rain_stopping_time_difference_mins = int(
rain_stopping_time_difference.total_seconds() // 60
)
# Set the probability to a readable percentage
rain_probability = int(rain_starting["precipProbability"] * 100)
# precipType isn't always provided from DarkSky. Default to "rain"
# if it's not in the response.
if "precipType" in rain_starting:
precipitation_type = rain_starting["precipType"].title()
else:
precipitation_type = "Rain"
# Build the message
if rain_starting_time_difference_mins > 1:
duration_text = f"in {rain_starting_time_difference_mins} minutes"
else:
duration_text = "now"
app_title = f"{precipitation_type} starting {duration_text}"
app_message_lines = [
f"Duration: {rain_stopping_time_difference_mins} minutes",
f"Probabiity: {rain_probability}%",
]
app_message = "\n".join(app_message_lines)
print(f"{app_title}\n{app_message}")
# Create the minutely rain graph
minute_list = []
rain_chance_list = []
number_of_minutes = 60
for index, minute in enumerate(minutely_weather_data):
if index == number_of_minutes:
break
minute_list.append(index)
rain_chance_list.append(minute["precipProbability"] * 100)
# Plot the graph
plt.figure()
plt.grid()
plt.ylim(0, 100)
plt.xlim(0, number_of_minutes)
plt.fill_between(minute_list, rain_chance_list)
# Format the Dark Sky summary - remove full-stop-abbreviation
# (e.g. "20 min." becomes "20 min")
formatted_summary = minutely_weather["summary"].replace(".", "")
plt.title(formatted_summary)
plt.xlabel("Minutes")
plt.ylabel("Chance of rain")
plt.plot(minute_list, rain_chance_list, linewidth=3.0)
plt.savefig("rain_graph.png")
# Send the message to the Apprise services
app.notify(body=app_message, title=app_title, attach="rain_graph.png")
# Set so we don't send duplicate notification for every 10
# minutes
is_still_raining = True
# Go to sleep for 10 minutes
interval_secs = 600
interval_mins = interval_secs // 60
print(f"Sleeping for {interval_secs} seconds ({interval_mins} minutes)")
time.sleep(interval_secs)
if __name__ == "__main__":
main()