configure logging module
[chrisu/seepark.git] / owm.py
1 #!/usr/bin/python3
2
3 # needs ~/seepark.ini with
4 # [openweathermap]
5 # apikey=...
6 # cityid=..
7 # 3319578 for Obsteig, AT
8
9 # needed packaes: python3-mysqldb python3-sqlalchemy
10
11 from pprint import pprint
12 import argparse
13 import configparser
14 import os
15 import csv
16 import datetime
17 import math
18 import json
19 import warnings
20 import sqlalchemy
21 from sqlalchemy import create_engine
22 import MySQLdb.cursors
23 from seeparklib.openweathermap import openweathermap_json
24
25
26 def fromtimestamp(timestamp):
27     return datetime.datetime.fromtimestamp(timestamp)
28
29
30 # https://stackoverflow.com/questions/7490660/converting-wind-direction-in-angles-to-text-words
31 def degToCompass(num):
32     if num is None or num is math.nan:
33         return 'N/A'
34     val=int((num/22.5)+.5)
35     arr=["N","NNO","NO","ONO","O","OSO", "SO", "SSO","S","SSW","SW","WSW","W","WNW","NW","NNW"]
36     return arr[(val % 16)]
37
38
39 def extractweatherdata(w):
40     data = dict(
41         datetime = fromtimestamp(w['dt']),
42         sunrise = fromtimestamp(w['sys']['sunrise']),
43         sunset = fromtimestamp(w['sys']['sunset']),
44         temp = w['main']['temp'],
45         pressure = w['main']['pressure'],
46         humidity = w['main']['humidity'],
47         weather = w['weather'][0]['description'],
48         sky = w['weather'][0]['main'],
49         windspeed = w['wind']['speed'],
50         cloudiness = w['clouds']['all'],
51     )
52
53     data['winddegrees'] = w['wind']['deg'] if 'deg' in w['wind'] else math.nan
54     data['winddirection'] = degToCompass(data['winddegrees'])
55     data['precipitation'] = w['rain']['3h'] if 'rain' in w else math.nan
56     data['visibility'] = w.get('visibility', math.nan)
57
58     return data
59
60
61 def write_csv(csv_file, weather_data):
62     """output like wetter.at.pl"""
63     with open(csv_file, "a", newline="") as file:
64         writer = csv.writer(file, dialect="excel", delimiter=';')
65         writer.writerow([
66             weather_data['datetime'].date(),
67             weather_data['datetime'].time(),
68             weather_data['sunrise'].time(),
69             weather_data['sunset'].time(),
70             "{:.2f}".format(weather_data['temp']),
71             "{:.2f} mm/h".format(weather_data['precipitation']),
72             "{:.1f} km/h {}".format(weather_data['windspeed'], weather_data['winddirection']),
73             weather_data['weather'],
74             "{}".format(weather_data['cloudiness'])
75         ])
76
77
78 def write_db(config, url, weather_json, weather_data):
79     user = config.get('database', 'user')
80     pwd = config.get('database','password')
81     host = config.get('database','hostname')
82     db = config.get('database','database')
83
84     engine = create_engine('mysql+mysqldb://{}:{}@{}/{}'.format(user, pwd, host, db), echo=False)
85     conn = engine.connect()
86     row = dict(cityid=config.get('openweathermap', 'cityid'), url=url, result=json.dumps(weather_json))
87     row.update(weather_data)
88     for key, value in row.items():
89         if isinstance(value, float) and math.isnan(value):
90             row[key] = None
91     sql_columns = list(row.keys())
92     sql_values = list(row.values())
93     sql = 'insert ignore into openweathermap ({}) values ({})'.format(', '.join(sql_columns), ','.join(['%s'] * len(sql_columns)))
94     with warnings.catch_warnings():
95         # ignore _mysql_exceptions.Warning: Duplicate entry '3319578-2018-08-01 20:50:00' for key 'cityid_datetime'
96         warnings.simplefilter("ignore", category=MySQLdb.cursors.Warning)
97         conn.execute(sql, *sql_values)
98     conn.close()
99
100
101 def main(configfile, debug):
102     config = configparser.ConfigParser()
103     config.read(configfile)
104     apikey = config.get('openweathermap', 'apikey')
105     cityid = config.get('openweathermap', 'cityid')
106     csvfile = config.get("openweathermap", 'csvfilename')
107
108     url, weather_json = openweathermap_json(apikey, cityid)
109     if debug:
110         pprint(weather_json)
111     weather_data = extractweatherdata(weather_json)
112     if debug:
113         pprint(weather_data)
114
115     # write to db
116     write_db(config, url, weather_json, weather_data)
117
118     # write to csv
119     write_csv(os.path.expanduser(csvfile), weather_data)
120
121
122 if __name__ == '__main__':
123     default_config_file = os.path.expanduser('~/seewasser.ini')
124     parser = argparse.ArgumentParser(description='Get OpenWeathermap data')
125     parser.add_argument('--config', default=default_config_file, help='configuration file')
126     parser.add_argument('--debug', action='store_true', default=False, help='print debug information')
127     args = parser.parse_args()
128     main(args.config, args.debug)