44import requests_cache
55from retry_requests import retry
66
7+ # All supported hourly fields exposed by this service
8+ ALL_HOURLY_FIELDS = [
9+ "temperature_2m" ,
10+ "relative_humidity_2m" ,
11+ "rain" ,
12+ "apparent_temperature" ,
13+ "precipitation_probability" ,
14+ "precipitation" ,
15+ "wind_direction_10m" ,
16+ "wind_speed_10m" ,
17+ "soil_temperature_0cm" ,
18+ "uv_index" ,
19+ ]
20+
21+
722class ExternalAPIsCoordinator :
823 def __init__ (self ):
924 pass
10-
11- def get_weather (self , latitude : float , longitude : float ):
25+
26+ def get_weather (self , latitude : float , longitude : float , hourly_fields : list [ str ] | None = None ):
1227 """
1328 Get weather data for a given latitude and longitude.
1429
1530 Args:
1631 latitude (float): The latitude of the location.
1732 longitude (float): The longitude of the location.
33+ hourly_fields (list[str] | None): Subset of hourly variables to request.
34+ Defaults to ALL_HOURLY_FIELDS when None or empty.
1835
1936 Returns:
2037 dict: A dictionary containing the weather data.
2138 """
22-
39+ requested = [f for f in (hourly_fields or []) if f in ALL_HOURLY_FIELDS ]
40+ if not requested :
41+ requested = list (ALL_HOURLY_FIELDS )
42+
2343 # Setup the Open-Meteo API client with cache and retry on error
24- cache_session = requests_cache .CachedSession ('.cache' , expire_after = 3600 )
25- retry_session = retry (cache_session , retries = 5 , backoff_factor = 0.2 )
26- openmeteo = openmeteo_requests .Client (session = retry_session )
44+ cache_session = requests_cache .CachedSession ('.cache' , expire_after = 3600 )
45+ retry_session = retry (cache_session , retries = 5 , backoff_factor = 0.2 )
46+ openmeteo = openmeteo_requests .Client (session = retry_session )
2747
28- # Make sure all required weather variables are listed here
29- # The order of variables in hourly or daily is important to assign them correctly below
3048 url = "https://api.open-meteo.com/v1/forecast"
3149 params = {
3250 "latitude" : latitude ,
3351 "longitude" : longitude ,
34- "hourly" : "temperature_2m" ,
52+ "hourly" : requested ,
3553 }
36- responses = openmeteo .weather_api (url , params = params )
54+ responses = openmeteo .weather_api (url , params = params )
3755
38- # Process first location. Add a for-loop for multiple locations or weather models
3956 response = responses [0 ]
4057 print (f"Coordinates: { response .Latitude ()} °N { response .Longitude ()} °E" )
4158 print (f"Elevation: { response .Elevation ()} m asl" )
4259 print (f"Timezone difference to GMT+0: { response .UtcOffsetSeconds ()} s" )
4360
44- # Process hourly data. The order of variables needs to be the same as requested.
4561 hourly = response .Hourly ()
46- hourly_temperature_2m = hourly .Variables (0 ).ValuesAsNumpy ()
4762
48- hourly_data = {
63+ hourly_data : dict = {
4964 "date" : pd .date_range (
50- start = pd .to_datetime (hourly .Time (), unit = "s" , utc = True ),
51- end = pd .to_datetime (hourly .TimeEnd (), unit = "s" , utc = True ),
52- freq = pd .Timedelta (seconds = hourly .Interval ()),
53- inclusive = "left"
65+ start = pd .to_datetime (hourly .Time (), unit = "s" , utc = True ),
66+ end = pd .to_datetime (hourly .TimeEnd (), unit = "s" , utc = True ),
67+ freq = pd .Timedelta (seconds = hourly .Interval ()),
68+ inclusive = "left" ,
5469 )
5570 }
5671
57- hourly_data ["temperature_2m" ] = hourly_temperature_2m .tolist ()
58-
72+ for i , field in enumerate (requested ):
73+ hourly_data [field ] = hourly .Variables (i ).ValuesAsNumpy ().tolist ()
74+
5975 # Convert pandas Timestamp objects to ISO strings for JSON serialization
6076 hourly_data ["date" ] = [d .isoformat () for d in hourly_data ["date" ]]
6177
@@ -66,5 +82,5 @@ def get_weather(self, latitude: float, longitude: float):
6682 "timezone" : response .Timezone (),
6783 "timezone_abbreviation" : response .TimezoneAbbreviation (),
6884 "utc_offset_seconds" : response .UtcOffsetSeconds (),
69- "hourly" : hourly_data
85+ "hourly" : hourly_data ,
7086 }
0 commit comments