This repository has been archived by the owner on Jan 22, 2021. It is now read-only.
forked from sfelde/Snips-Wetter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
weather.py
executable file
·152 lines (141 loc) · 6.97 KB
/
weather.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
# -*- encoding: utf-8 -*-
import requests
import datetime
import random
class Weather:
def __init__(self, config):
self.fromtimestamp = datetime.datetime.fromtimestamp
self.weather_api_base_url = "http://api.openweathermap.org/data/2.5"
try:
self.weather_api_key = config['secret']['openweathermap_api_key']
except KeyError:
self.weather_api_key = "XXXXXXXXXXXXXXXXXXXXX"
try:
self.default_city_name = config['secret']['default_city']
except KeyError:
self.default_city_name = "Berlin"
def parse_open_weather_map_forecast_response(self, response, location):
# Parse the output of Open Weather Map's forecast endpoint
try:
today = self.fromtimestamp(response["list"][0]["dt"]).day
today_forecasts = list(
filter(lambda forecast: self.fromtimestamp(forecast["dt"]).day == today, response["list"]))
all_min = [x["main"]["temp_min"] for x in today_forecasts]
all_max = [x["main"]["temp_max"] for x in today_forecasts]
all_conditions = [x["weather"][0]["description"] for x in today_forecasts]
rain = list(filter(lambda forecast: forecast["weather"][0]["main"] == "Rain", today_forecasts))
snow = list(filter(lambda forecast: forecast["weather"][0]["main"] == "Snow", today_forecasts))
return {
"rc": 0,
"location": location,
"inLocation": " in {0}".format(location) if location else "",
"temperature": int(today_forecasts[0]["main"]["temp"]),
"temperatureMin": int(min(all_min)),
"temperatureMax": int(max(all_max)),
"rain": len(rain) > 0,
"snow": len(snow) > 0,
"mainCondition": max(set(all_conditions), key=all_conditions.count).lower()
}
except KeyError: # error 404 (locality not found or api key is wrong)
return {'rc': 2}
def error_response(self, data):
error_num = data['rc']
if error_num == 1:
response = random.choice(["Es ist leider kein Internet verfügbar.",
"Ich bin nicht mit dem Internet verbunden.",
"Es ist kein Internet vorhanden."])
if 'location' in data.keys() and data['location'] == self.default_city_name:
response = "Schau doch aus dem Fenster. " + response
elif error_num == 2:
response = random.choice(["Wetter konnte nicht abgerufen werden. Entweder gibt es den Ort nicht, oder der "
"API-Schlüssel ist ungültig.",
"Fehler beim Abrufen. Entweder gibt es den Ort nicht, oder der API-Schlüssel "
"ist ungültig."])
else:
response = random.choice(["Es ist ein Fehler aufgetreten.", "Hier ist ein Fehler aufgetreten."])
return response
def get_weather_forecast(self, intent_message):
# Parse the query slots, and fetch the weather forecast from Open Weather Map's API
locations = []
for (slot_value, slot) in intent_message.slots.items():
if slot_value not in ['forecast_condition_name', 'forecast_start_date_time',
'forecast_item', 'forecast_temperature_name']:
locations.append(slot[0].slot_value.value)
location_objects = [loc_obj for loc_obj in locations if loc_obj is not None]
if location_objects:
location = location_objects[0].value
else:
location = self.default_city_name
forecast_url = "{0}/forecast?q={1}&APPID={2}&units={3}&lang=de".format(
self.weather_api_base_url, location, self.weather_api_key, "metric")
try:
r_forecast = requests.get(forecast_url)
return self.parse_open_weather_map_forecast_response(r_forecast.json(), location)
except (requests.exceptions.ConnectionError, ValueError):
return {'rc': 1} # Error: No internet connection
@staticmethod
def add_warning_if_needed(response, weather_forecast):
if weather_forecast["rain"] and "rain" not in weather_forecast["mainCondition"]\
and "regen" not in weather_forecast["mainCondition"]:
response += ' Es könnte regnen.'
if weather_forecast["snow"] and "snow" not in weather_forecast["mainCondition"]:
response += ' Es könnte schneien.'
return response
def forecast(self, intent_message):
"""
Complete answer:
- condition
- current temperature
- max and min temperature
- warning about rain or snow if needed
"""
weather_forecast = self.get_weather_forecast(intent_message)
if weather_forecast['rc'] != 0:
response = self.error_response(weather_forecast)
else:
response = ("Wetter heute{1}: {0}. "
"Aktuelle Temperatur ist {2} Grad. "
"Höchsttemperatur: {3} Grad. "
"Tiefsttemperatur: {4} Grad.").format(
weather_forecast["mainCondition"],
weather_forecast["inLocation"],
weather_forecast["temperature"],
weather_forecast["temperatureMax"],
weather_forecast["temperatureMin"]
)
response = self.add_warning_if_needed(response, weather_forecast)
return response
def forecast_condition(self, intent_message):
"""
Condition-focused answer:
- condition
- warning about rain or snow if needed
"""
weather_forecast = self.get_weather_forecast(intent_message)
if weather_forecast['rc'] != 0:
response = self.error_response(weather_forecast)
else:
response = "Wetter heute{1}: {0}.".format(
weather_forecast["mainCondition"],
weather_forecast["inLocation"]
)
response = self.add_warning_if_needed(response, weather_forecast)
return response
def forecast_temperature(self, intent_message):
"""
Temperature-focused answer:
- current temperature
- max and min temperature
"""
weather_forecast = self.get_weather_forecast(intent_message)
if weather_forecast['rc'] != 0:
response = self.error_response(weather_forecast)
else:
response = ("{0} hat es aktuell {1} Grad. "
"Heute wird die Höchsttemperatur {2} Grad sein "
"und die Tiefsttemperatur {3} Grad.").format(
weather_forecast["inLocation"],
weather_forecast["temperature"],
weather_forecast["temperatureMax"],
weather_forecast["temperatureMin"])
return response