aboutsummaryrefslogtreecommitdiffstats
path: root/block_weather.py
diff options
context:
space:
mode:
authorMitsuo Tokumori <[email protected]>2025-03-06 11:24:57 +0900
committerMitsuo Tokumori <[email protected]>2025-03-06 11:24:57 +0900
commit304d0a2c3e0e1eea58d6db1762c1b96e450b5843 (patch)
tree70976dfdec1b65f92849125a47b7ff7ff18740f7 /block_weather.py
downloadmasu-304d0a2c3e0e1eea58d6db1762c1b96e450b5843.tar.gz
masu-304d0a2c3e0e1eea58d6db1762c1b96e450b5843.tar.bz2
masu-304d0a2c3e0e1eea58d6db1762c1b96e450b5843.zip
Initial commit
Only 2 blocks: time and weather. Currently data is passed in formatted strings made server-side (python) just for testing, later the formatting should be client-side (html). Also the "time" API might be redundant, ideally it should pass the city names, and offsets (time zone), and then just use the system time (otherwise DST jumps would need to be taken into account).
Diffstat (limited to 'block_weather.py')
-rw-r--r--block_weather.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/block_weather.py b/block_weather.py
new file mode 100644
index 0000000..dc041fd
--- /dev/null
+++ b/block_weather.py
@@ -0,0 +1,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"""