diff options
| author | Mitsuo Tokumori <[email protected]> | 2025-03-08 16:03:30 +0900 |
|---|---|---|
| committer | Mitsuo Tokumori <[email protected]> | 2025-03-08 16:03:30 +0900 |
| commit | 51163b167cce01af6101438e5e61145ad798f213 (patch) | |
| tree | 9c8e75266cedfb205db175b0b2bc41b49df75cea /app/utils/block_weather.py | |
| parent | d9af103b9a8aed86d6ac834f1240edfb2173ffa0 (diff) | |
| download | masu-51163b167cce01af6101438e5e61145ad798f213.tar.gz masu-51163b167cce01af6101438e5e61145ad798f213.tar.bz2 masu-51163b167cce01af6101438e5e61145ad798f213.zip | |
Restructure python code to be modular
The python code is now a package named app.
app/models: db models
app/routes: flask blueprints
app/static: css, js
app/templates: jinja html templates
Diffstat (limited to 'app/utils/block_weather.py')
| -rw-r--r-- | app/utils/block_weather.py | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/app/utils/block_weather.py b/app/utils/block_weather.py new file mode 100644 index 0000000..eec4e4a --- /dev/null +++ b/app/utils/block_weather.py @@ -0,0 +1,66 @@ +""" +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 flask +import requests +import pandas as pd + +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={flask.current_app.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']}.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.get('visibility', 0)/1000:.1f}km +wind: {data['wind']['speed']}m/s from {data['wind']['deg']}°N +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={flask.current_app.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={flask.current_app.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""" |
