-
Notifications
You must be signed in to change notification settings - Fork 0
/
weather.py
207 lines (173 loc) · 5.66 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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env python3
#
# Python script to pull weather from an airport and publish it to a MUCK.
# This gives realistic weather conditions to a MUCK based on real world
# stuff.
from configparser import ConfigParser
from pyfuzzball.mcp import MCP
import math
import os
import requests
import sys
import xml.etree.ElementTree as ET
# Load configuration
if not os.path.exists('config.ini'):
print("You need a config.ini for this to work.")
sys.exit(1)
config = ConfigParser()
config.read('config.ini')
if 'weather' not in config:
print("Config must have a weather section")
# What are the required config paramters?
for param in ('muck_host', 'muck_port', 'mcp_key', 'airport'):
if param not in config['weather']:
print("Could not find config parameter %s." % param)
sys.exit(1)
# What is our METAR URL?
url = "https://www.aviationweather.gov/adds/dataserver_current/httpparam?" \
"dataSource=metars&requestType=retrieve&format=xml&" \
"stationString=%s&mostRecent=true&hoursBeforeNow=3" \
% config['weather']['airport']
response = requests.get(url)
# Load the XML document
root = ET.fromstring(response.content.decode('utf-8'))
# What we want to parse out:
#
# - temp_c
# - dewpoint_c
# - wind_dir_degrees
# - wind_speed_kt
# - wind_gust_kt
# - visibility_statute_mi
# - altim_in_hg
# - sky_condition
# - precip_in
# - snow_in
#
# Fields are described here:
#
# https://www.aviationweather.gov/dataserver/fields?datatype=metar
# Get our elements
metar = {}
for ele in root.find('data').find('METAR').iter():
# Copy these over to our structure with no additional processing.
if ele.tag in ('temp_c', 'dewpoint_c', 'wind_dir_degrees',
'wind_speed_kt', 'wind_gust_kt', 'visibility_statute_mi',
'altim_in_hg', 'precip_in', 'snow_in'):
metar[ele.tag] = ele.text
elif ele.tag == 'sky_condition':
metar["sky_condition_cover"] = ele.attrib.get('sky_cover')
metar["sky_condition_base"] = ele.attrib.get('cloud_base_ft_agl')
# Compile our weather message based on the conditions.
message = []
temp = float(metar['temp_c'])
if temp < 0:
message.append("It is below-0 freezing.")
elif temp < 10:
message.append("It is freezing out.")
elif temp < 20:
message.append("It is chilly out.")
elif temp < 30:
message.append("The tempurature is nice.")
elif temp < 40:
message.append("It is really hot out.")
else:
message.append("It is sweltering out.")
dew_point = float(metar['dewpoint_c'])
if dew_point > temp:
message.append("Right now, it is very foggy.")
elif dew_point > 15:
if dew_point < 21:
message.append("Right now, it is somewhat humid.")
elif dew_point < 26:
message.append("Right now, it is really humid.")
else:
message.append("Right now, the humidity is pretty brutal.")
wind_direction = int(metar['wind_dir_degrees'])
wind_speed = int(metar['wind_speed_kt'])
wind_gust_kt = 0
if 'wind_gust_kt' in metar:
wind_gust_kt = int(metar['wind_gust_kt'])
# Double 0 is calm winds
if not (wind_direction == 0 and wind_speed == 0):
wind = "Winds are "
if wind_direction == 0:
wind += "variable"
elif wind_direction < 20:
wind += "from the north"
elif wind_direction < 70:
wind += "from the north east"
elif wind_direction < 110:
wind += "from the east"
elif wind_direction < 160:
wind += "from the south east"
elif wind_direction < 200:
wind += "from the south"
elif wind_direction < 250:
wind += "from the south west"
elif wind_direction < 290:
wind += "from the west"
elif wind_direction < 340:
wind += "from the north west"
else:
wind += "from the north"
wind += " and "
if wind_speed < 2:
wind += "calm"
elif wind_speed < 5:
wind += "breezy"
elif wind_speed < 10:
wind += "kind of windy"
elif wind_speed < 15:
wind += "strong"
else:
wind += "very strong"
if wind_gust_kt > 20:
wind += " and gusty"
wind += "."
message.append(wind)
if metar["sky_condition_cover"] == "CLR" or \
metar["sky_condition_cover"] == "SKC":
message.append("There isn't a cloud in the sky.")
elif metar["sky_condition_cover"] == "FEW":
message.append("There are a few clouds but it is mostly clear.")
elif metar["sky_condition_cover"] == "SCT":
message.append("It is a little cloudy.")
elif metar["sky_condition_cover"] == "BKN":
message.append("There is a lot of cloud cover.")
elif metar["sky_condition_cover"] == "OVC":
message.append("It is overcast.")
# Easter Island doesn't seem to report precipitation
"""
precip = 0
if 'precip_in' in metar:
float(metar['precip_in'])
if precip > 0:
message.append("And it is raining.")
"""
is_raining = False
is_foggy = False
# Do rain based on dew point
if temp - dew_point < 2:
message.append("And it is raining.")
is_raining = True
elif temp - dew_point < 5 and \
float(metar['visibility_statute_mi']) < 2:
message.append("And it is pretty foggy right now.")
is_foggy = True
m = MCP(config['weather']['muck_host'], config['weather']['muck_port'],
config['weather'].get('use_ssl', False), True)
m.negotiate(['net-hopeisland-weather'])
m.call('net-hopeisland-weather', 'set', {
"auth": config['weather']['mcp_key'],
"weather": " ".join(message),
"temp": str(math.floor(temp)),
"dewpoint": str(math.floor(dew_point)),
"wind_direction": metar['wind_dir_degrees'],
"wind_speed": metar['wind_speed_kt'],
"wind_gust": str(wind_gust_kt),
"clouds": metar["sky_condition_cover"],
"raining": str(int(is_raining)),
"foggy": str(int(is_foggy))
})
m.quit()