epaper/modules/weather_api.py

216 lines
7.4 KiB
Python
Raw Normal View History

2022-08-11 12:46:36 +00:00
from datetime import datetime, timedelta, timezone
2023-04-18 12:31:25 +00:00
import itertools
2022-08-11 12:46:36 +00:00
import json
import os
2022-08-19 14:58:30 +00:00
import urllib.error
2022-08-11 12:46:36 +00:00
import urllib.parse
import urllib.request
2023-04-09 13:33:43 +00:00
from zoneinfo import ZoneInfo
2022-08-11 12:46:36 +00:00
2023-04-18 12:31:25 +00:00
class WeatherAPI:
2022-08-11 12:46:36 +00:00
2023-04-18 12:31:25 +00:00
def __init__(self, apikey=None, gps=None, opts={"lang": "fr", "units": "metric"}):
self.apikey = apikey or os.environ["WEATHERAPIKEY"]
self.baseurl = "http://api.weatherapi.com/v1"
2022-08-11 14:35:30 +00:00
self.default_gps = gps or ("GPS" in os.environ and os.environ["GPS"]) or "48.8127,2.3437"
2022-08-11 12:46:36 +00:00
self.opts = opts
2023-04-09 13:33:43 +00:00
self._cached_file = ".weather-%s-%s.cache"
2022-08-11 12:46:36 +00:00
2023-04-18 12:31:25 +00:00
def get_weather(self, apitype="forecast", gps=None, **params):
2022-08-11 12:46:36 +00:00
if gps is None:
gps = self.default_gps
2023-04-18 12:31:25 +00:00
cached_filename = self._cached_file % (apitype + ("" if "dt" not in params else "-{}".format(params["dt"])), gps)
2022-08-11 12:46:36 +00:00
# Read the mod time
statinfo = None
try:
2023-04-18 12:31:25 +00:00
statinfo = os.stat(cached_filename)
2022-08-11 12:46:36 +00:00
except:
pass
2023-04-18 12:31:25 +00:00
params["q"] = gps
params["key"] = str(self.apikey)
params["alerts"] = "yes"
params["aqi"] = "yes"
for k in self.opts:
params[k] = self.opts[k]
2022-08-11 12:49:17 +00:00
if statinfo is None or datetime.fromtimestamp(statinfo.st_mtime, tz=timezone.utc) + timedelta(hours=1) < datetime.now(tz=timezone.utc):
2022-08-11 12:46:36 +00:00
# Do the request and save it
2022-08-19 14:58:30 +00:00
try:
2023-04-18 12:31:25 +00:00
with urllib.request.urlopen(self.baseurl + "/" + apitype + ".json?" + urllib.parse.urlencode(params)) as f:
with open(cached_filename, 'wb') as fd:
2022-08-19 14:58:30 +00:00
fd.write(f.read())
except ConnectionResetError:
pass
except urllib.error.URLError:
pass
2022-08-11 12:46:36 +00:00
# Retrieve cached data
res = {}
2023-04-18 12:31:25 +00:00
with open(cached_filename) as f:
2022-08-11 12:46:36 +00:00
res = json.load(f)
return res
2023-04-09 13:33:43 +00:00
def get_icon(icon, night=False, current=False):
if icon == 1000:
if not night:
return "wi-day-sunny.png"
else:
2023-04-09 13:33:43 +00:00
return "wi-night-clear.png"
2023-04-18 12:31:25 +00:00
elif icon == 1003:
2023-04-09 13:33:43 +00:00
if not night:
2023-04-18 12:31:25 +00:00
return "wi-day-cloudy.png"
else:
2023-04-18 12:31:25 +00:00
return "wi-night-alt-cloudy.png"
elif icon == 1006:
2023-04-09 13:33:43 +00:00
return "wi-cloudy.png"
2023-04-18 12:31:25 +00:00
elif icon == 1009:
2023-04-09 13:33:43 +00:00
if not night:
2023-04-18 12:31:25 +00:00
return "wi-day-sunny-overcast.png"
else:
2023-04-18 12:31:25 +00:00
return "wi-night-alt-partly-cloudy.png"
elif icon == 1030 or icon == 1072:
2023-04-09 13:33:43 +00:00
if not night:
2023-04-18 12:31:25 +00:00
return "wi-day-haze.png"
else:
2023-04-09 13:33:43 +00:00
return "wi-night-fog.png"
2023-04-18 12:31:25 +00:00
elif icon == 1063:
2023-04-09 13:33:43 +00:00
if not night:
return "wi-day-rain.png"
else:
return "wi-night-alt-rain.png"
2023-04-18 12:31:25 +00:00
elif icon == 1066:
if not night:
return "wi-day-snow.png"
else:
return "wi-night-alt-snow.png"
elif icon == 1069 or icon == 1204:
2023-04-09 13:33:43 +00:00
if not night:
return "wi-day-sleet.png"
else:
2023-04-18 12:31:25 +00:00
return "wi-night-alt-sleet.png"
elif icon == 1087:
2023-04-09 13:33:43 +00:00
if not night:
2023-04-18 12:31:25 +00:00
return "wi-day-lightning.png"
2023-04-09 13:33:43 +00:00
else:
2023-04-18 12:31:25 +00:00
return "wi-night-alt-lightning.png"
elif icon == 1114 or icon == 1219 or icon == 1222 or icon == 1258:
return "wi-snow.png"
elif icon == 1117 or icon == 1225:
return "wi-snow-wind.png"
elif icon == 1135 or icon == 1147:
return "wi-fog.png"
elif icon == 1150 or icon == 1153:
2023-04-09 13:33:43 +00:00
return "wi-sprinkle.png"
2023-04-18 12:31:25 +00:00
elif icon == 1168 or icon == 1171 or icon == 1198 or icon == 1201:
return "wi-snowflake-cold.png"
elif icon == 1180 or icon == 1183 or icon == 1186:
2023-04-09 13:33:43 +00:00
if not night:
2023-04-18 12:31:25 +00:00
return "wi-day-rain.png"
2023-04-09 13:33:43 +00:00
else:
2023-04-18 12:31:25 +00:00
return "wi-night-alt-rain.png"
elif icon == 1189 or icon == 1192 or icon == 1195:
return "wi-rain.png"
elif icon == 1240 or icon == 1243:
return "wi-showers.png"
elif icon == 1246:
return "wi-tsunami.png"
elif icon == 1207 or icon == 1249 or icon == 1252:
return "wi-sleet.png"
elif icon == 1210 or icon == 1213 or icon == 1216 or icon == 1255:
if not night:
return "wi-day-snow.png"
else:
return "wi-night-snow.png"
elif icon == 1237:
2023-04-09 13:33:43 +00:00
return "wi-hail.png"
2023-04-18 12:31:25 +00:00
elif icon == 1261 or icon == 1264:
2023-04-09 13:33:43 +00:00
if not night:
return "wi-day-hail.png"
else:
2023-04-09 13:33:43 +00:00
return "wi-night-hail.png"
2023-04-18 12:31:25 +00:00
elif icon == 1273 or icon == 1276:
2023-04-09 13:33:43 +00:00
if not night:
return "wi-day-thunderstorm.png"
else:
2023-04-09 13:33:43 +00:00
return "wi-night-thunderstorm.png"
2023-04-18 12:31:25 +00:00
elif icon == 1279 or icon == 1282:
2023-04-09 13:33:43 +00:00
if not night:
2023-04-18 12:31:25 +00:00
return "wi-day-snow-thunderstorm.png"
2023-04-09 13:33:43 +00:00
else:
2023-04-18 12:31:25 +00:00
return "wi-night-snow-thunderstorm.png"
2023-04-09 13:33:43 +00:00
else:
2023-04-18 12:31:25 +00:00
return "wi-alien.png"
2023-04-09 13:33:43 +00:00
2022-08-11 12:46:36 +00:00
def get_moon_icon(self, day=0):
2023-04-18 12:31:25 +00:00
moon_phase = list(itertools.islice(self.get_daily(), 1))[day]["moon_phase"]
2022-08-11 12:46:36 +00:00
2023-04-18 12:31:25 +00:00
if moon_phase == "New Moon":
2022-08-11 12:46:36 +00:00
return "wi-moon-alt-new.png"
2023-04-18 12:31:25 +00:00
elif moon_phase == "Waxing Crescent":
2022-08-11 12:46:36 +00:00
return "wi-moon-alt-waxing-crescent-4.png"
2023-04-18 12:31:25 +00:00
elif moon_phase == "First Quarter":
2022-08-11 12:46:36 +00:00
return "wi-moon-alt-first-quarter.png"
2023-04-18 12:31:25 +00:00
elif moon_phase == "Waxing Gibbous":
2022-08-11 12:46:36 +00:00
return "wi-moon-alt-waxing-gibbous-4.png"
2023-04-18 12:31:25 +00:00
elif moon_phase == "Full Moon":
2022-08-11 12:46:36 +00:00
return "wi-moon-alt-full.png"
2023-04-18 12:31:25 +00:00
elif moon_phase == "Waning Gibbous":
2022-08-11 12:46:36 +00:00
return "wi-moon-alt-waning-gibbous-4.png"
2023-04-18 12:31:25 +00:00
elif moon_phase == "Last Quarter":
2022-08-11 12:46:36 +00:00
return "wi-moon-alt-third-quarter.png"
else:
2023-04-18 12:31:25 +00:00
return "wi-moon-alt-waning-crescent-3.png"
2022-08-11 12:46:36 +00:00
def get_currently(self, *args, **kwargs):
2023-04-18 12:31:25 +00:00
return self.get_weather("current", *args, **kwargs)["current"]
2022-08-11 12:46:36 +00:00
2023-04-18 12:31:25 +00:00
def get_forecast(self, *args, **kwargs):
for i in [0, 1, 2, 3]:
enddt = datetime.now() + timedelta(days=i)
v = self.get_weather(*args, **kwargs, dt=enddt.strftime("%Y-%m-%d"))["forecast"]["forecastday"][0]
v["day"]["date"] = enddt
yield v
2022-08-11 12:46:36 +00:00
2023-04-18 12:31:25 +00:00
def get_hourly(self, *args, **kwargs):
now = datetime.now().astimezone(ZoneInfo("Europe/Paris"))
for d in self.get_forecast(*args, **kwargs):
for h in d["hour"]:
if d["day"]["date"].day == now.day and now > self.read_timestamp(h["time_epoch"]) + timedelta(hours=1):
continue
yield h
2022-08-11 12:46:36 +00:00
def get_daily(self, *args, **kwargs):
2023-04-18 12:31:25 +00:00
for d in self.get_forecast(*args, **kwargs):
yield {
**d["day"],
**d["astro"]
}
2022-08-11 14:09:01 +00:00
def get_alerts(self, *args, **kwargs):
2023-04-18 12:31:25 +00:00
for i in [0, 1, 2, 3]:
enddt = datetime.now() + timedelta(days=i)
for a in self.get_weather(*args, **kwargs, dt=enddt.strftime("%Y-%m-%d"))["alerts"]["alert"]:
yield a
2022-08-11 14:09:01 +00:00
2022-08-12 10:48:39 +00:00
def read_timestamp(self, timestamp, *args, **kwargs):
2023-04-09 13:33:43 +00:00
PARIS = ZoneInfo("Europe/Paris")
2023-08-16 22:02:48 +00:00
return datetime.fromtimestamp(int(timestamp), tz=timezone.utc).astimezone(PARIS)
2022-08-12 10:48:39 +00:00
2022-08-11 12:46:36 +00:00
2023-04-18 12:31:25 +00:00
#WeatherAPI = TomorrowAPI
2022-08-11 12:46:36 +00:00
if __name__ == '__main__':
2023-04-18 12:31:25 +00:00
dsa = WeatherAPI()
print(json.dumps(dsa.get_currently()))
#print(json.dumps([d for d in dsa.get_daily()][0]))