148 lines
5.8 KiB
Python
148 lines
5.8 KiB
Python
#!/usr/bin python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
This part of the code exposes functions to fetch data from the open-meteo.com API.
|
|
The bellow code is the generated by the https://open-meteo.com/en/docs itself.
|
|
It has been slighly modified to return a dictionary with all the information nedeed.
|
|
"""
|
|
|
|
import openmeteo_requests
|
|
|
|
import requests_cache
|
|
#import pandas as pd
|
|
from retry_requests import retry
|
|
|
|
|
|
class WeatherHelper:
|
|
|
|
def __init__(self, latitude: float, longitude: float, timezone: str):
|
|
self.latitude = latitude
|
|
self.longitude = longitude
|
|
self.timezone = timezone
|
|
|
|
def fetch_open_meteo_data(self) -> dict:
|
|
|
|
# Setup the Open-Meteo API client with cache and retry on error
|
|
cache_session = requests_cache.CachedSession('.cache', expire_after = 3600)
|
|
retry_session = retry(cache_session, retries = 5, backoff_factor = 0.2)
|
|
openmeteo = openmeteo_requests.Client(session = retry_session)
|
|
|
|
# Make sure all required weather variables are listed here
|
|
# The order of variables in hourly or daily is important to assign them correctly below
|
|
url = "https://api.open-meteo.com/v1/forecast"
|
|
params = {
|
|
"latitude": self.latitude,
|
|
"longitude": self.longitude,
|
|
"current": ["temperature_2m", "is_day", "weather_code"],
|
|
"daily": ["weather_code", "temperature_2m_max", "temperature_2m_min"],
|
|
"timezone": self.timezone,
|
|
"forecast_days": 3
|
|
}
|
|
responses = openmeteo.weather_api(url, params=params)
|
|
|
|
# Process first location. Add a for-loop for multiple locations or weather models
|
|
response = responses[0]
|
|
#print(f"Coordinates {response.Latitude()}°N {response.Longitude()}°E")
|
|
#print(f"Elevation {response.Elevation()} m asl")
|
|
#print(f"Timezone {response.Timezone()} {response.TimezoneAbbreviation()}")
|
|
#print(f"Timezone difference to GMT+0 {response.UtcOffsetSeconds()} s")
|
|
|
|
|
|
# Current values. The order of variables needs to be the same as requested.
|
|
current = response.Current()
|
|
|
|
current_temperature_2m = current.Variables(0).Value()
|
|
|
|
current_is_day = current.Variables(1).Value()
|
|
|
|
current_weather_code = current.Variables(2).Value()
|
|
|
|
#print(f"Current time {current.Time()}")
|
|
|
|
#print(f"Current temperature_2m {current_temperature_2m}")
|
|
#print(f"Current is_day {current_is_day}")
|
|
#print(f"Current weather_code {current_weather_code}")
|
|
# Process daily data. The order of variables needs to be the same as requested.
|
|
daily = response.Daily()
|
|
daily_weather_code = daily.Variables(0).ValuesAsNumpy()
|
|
daily_temperature_2m_max = daily.Variables(1).ValuesAsNumpy()
|
|
daily_temperature_2m_min = daily.Variables(2).ValuesAsNumpy()
|
|
|
|
#daily_data = {"date": pd.date_range(
|
|
# start = pd.to_datetime(daily.Time(), unit = "s", utc = True),
|
|
# end = pd.to_datetime(daily.TimeEnd(), unit = "s", utc = True),
|
|
# freq = pd.Timedelta(seconds = daily.Interval()),
|
|
# inclusive = "left"
|
|
#)}
|
|
|
|
#daily_data["weather_code"] = daily_weather_code
|
|
#daily_data["temperature_2m_max"] = daily_temperature_2m_max
|
|
#daily_data["temperature_2m_min"] = daily_temperature_2m_min
|
|
|
|
#daily_dataframe = pd.DataFrame(data = daily_data)
|
|
#print(daily_dataframe)
|
|
|
|
# Here we are creating the dictionary that will be returned
|
|
weather_data = {}
|
|
|
|
weather_data['current_temperature_2m'] = int(current_temperature_2m)
|
|
weather_data['current_is_day'] = int(current_is_day)
|
|
weather_data['current_weather_code'] = int(current_weather_code)
|
|
|
|
weather_data['tomorrow_temperature_2m_max'] = int(daily_temperature_2m_max[1])
|
|
weather_data['tomorrow_temperature_2m_min'] = int(daily_temperature_2m_min[1])
|
|
weather_data['tomorrow_weather_code'] = int(daily_weather_code[1])
|
|
|
|
weather_data['day_after_temperature_2m_max'] = int(daily_temperature_2m_max[2])
|
|
weather_data['day_after_temperature_2m_min'] = int(daily_temperature_2m_min[2])
|
|
weather_data['day_after_weather_code'] = int(daily_weather_code[2])
|
|
|
|
return weather_data
|
|
|
|
|
|
def iconize_weather(self, weather_code: int) -> str:
|
|
|
|
# This are the WMO Weather interpretation codes (WW)
|
|
# More info in: https://open-meteo.com/en/docs at the end of the page.
|
|
# Here we only put the name of the icons, the path will be handle in main()
|
|
|
|
if weather_code >= 100:
|
|
weather_icon = "placeholder32.bmp"
|
|
return weather_icon
|
|
|
|
if weather_code in [0]:
|
|
weather_icon = "sunny-icon32.bmp"
|
|
elif weather_code in [1, 2, 3]:
|
|
weather_icon = "None"
|
|
elif weather_code in [45, 48]:
|
|
weather_icon = "None"
|
|
elif weather_code in [51, 53, 55]:
|
|
weather_icon = "None"
|
|
elif weather_code in [56, 57]:
|
|
weather_icon = "None"
|
|
elif weather_code in [61, 63, 65]:
|
|
weather_icon = "None"
|
|
elif weather_code in [66, 67]:
|
|
weather_icon = "None"
|
|
elif weather_code in [71, 73, 75]:
|
|
weather_icon = "None"
|
|
elif weather_code in [77]:
|
|
weather_icon = "None"
|
|
elif weather_code in [80, 81, 82]:
|
|
weather_icon = "None"
|
|
elif weather_code in [85, 86]:
|
|
weather_icon = "None"
|
|
elif weather_code in [95]:
|
|
weather_icon = "None"
|
|
elif weather_code in [96, 99]:
|
|
weather_icon = "None"
|
|
else:
|
|
weather_icon = "None"
|
|
|
|
# If there is no an icon for that code, search the next highest icon
|
|
if weather_icon == "None":
|
|
weather_icon = self.iconize_weather(weather_code + 1)
|
|
|
|
return weather_icon
|
|
|
|
|