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
|
"""
Handle external requests and pre-process weather data
Providers:
* OpenWeather
Free Access on OpenWeather allows for some API calls, see
https://openweathermap.org/price
"""
import requests
import pandas as pd
import config
def get_current_weather(city: str) -> dict:
"""https://openweathermap.org/current"""
pos = _get_position(city)
if not pos:
return None
url = f"http://api.openweathermap.org/data/2.5/weather?lat={pos['lat']}&lon={pos['lon']}&appid={config.OPENWEATHER_API_KEY}&units=metric"
data = requests.get(url).json()
data['summary'] = _format_current_weather(data)
# On icon URL codes: https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2
data['icon_url'] = f"https://openweathermap.org/img/wn/{data['weather'][0]['icon']}@2x.png"
return data
def _format_current_weather(data: dict) -> str:
"""final formatting should occur in HTML/JS, not here"""
ts = [data['dt'], data['sys']['sunrise'], data['sys']['sunset']]
ts = [pd.to_datetime(x + data['timezone'], unit='s') for x in ts]
s = f"""{data['name']}, {data['sys']['country']} ({ts[0]})
{data['weather'][0]['description']}
{data['main']['temp']}°C (feels like {data['main']['feels_like']}°C), humidity: {data['main']['humidity']}%, pressure: {data['main']['grnd_level']} hPa
visibility: {data['visibility']/1000:.1f}km
wind: {data['wind']['speed']}m/s from {data['wind']['deg']}°N (with gusts of {data['wind'].get('gust', 0)} m/s)
clouds: {data['clouds']['all']}%
sunrise & sunset: {ts[1].strftime('%H:%M')}, {ts[2].strftime('%H:%M')}"""
return s
def get_forecast(city: str) -> dict:
"""https://openweathermap.org/forecast5"""
# 5 days, 3 hours forecast data
lat, lon = _get_position(city)
url = f"http://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={config.OPENWEATHER_API_KEY}&units=metric"
data = requests.get(url).json()
return data
def _get_position(name) -> dict:
"""direct geocoding
name: City name, state code (only for the US) and country code divided by comma. Please use ISO 3166 country codes.
https://openweathermap.org/api/geocoding-api#direct
"""
limit = 5
url = f"http://api.openweathermap.org/geo/1.0/direct?q={name}&limit={limit}&appid={config.OPENWEATHER_API_KEY}"
data = requests.get(url).json()
if not data:
return None
return data[0]
def get_weathermap() -> dict:
"""https://openweathermap.org/api/weathermaps"""
|