@@ -19,104 +19,50 @@ def get_weather_data(self, station="", start_time="", end_time=""):
1919 - If end_time is provided but no start_time → raises ValueError.
2020
2121 """
22-
22+
2323 url = "https://weather.umd.edu/wordpress/wp-content/plugins/meso-fsct/functions/get-data.php"
24-
25- station = station .lower ()
26- db = ""
27-
28- current_data_flag = False
29-
30- def validate_date_format (date_str ):
31- try :
32- if date_str : # Only validate if the string is not empty
33- datetime .strptime (date_str , '%m/%d/%y' )
34- except ValueError :
35- raise ValueError (f"Invalid date format: { date_str } . Expected format: MM/DD/YY" )
36-
37- # Ensure start_time is provided if end_time is set
38- if start_time == '' and end_time != '' :
24+
25+ stations_db = {
26+ "" : "mesoterp7DB" , "atlantic" : "mesoterp7DB" , "golf" : "mesoterp6DB" ,
27+ "vmh" : "mesoterp1DB" , "williams" : "mesoterp8DB" , "chem" : "mesoterp3DB"
28+ }
29+
30+ if station .lower () not in stations_db :
31+ raise ValueError ("Valid Station not Provided" )
32+
33+ def to_timestamp (date_str ):
34+ return int (datetime .strptime (date_str , '%m/%d/%y' ).replace (hour = 0 , minute = 0 , second = 0 ).timestamp ())
35+
36+ if end_time and not start_time :
3937 raise ValueError ("Start Time Must be Provided" )
40-
41- # Validate date formats if they are provided
42- if start_time != '' :
43- validate_date_format (start_time )
44- if end_time != '' :
45- validate_date_format (end_time )
46-
47- # Convert provided times to Unix timestamps
48- if start_time != '' and end_time != '' :
49- start_time = int (datetime .strptime (start_time , '%m/%d/%y' ).replace (hour = 0 , minute = 0 , second = 0 ).timestamp ())
50- end_time = int (datetime .strptime (end_time , '%m/%d/%y' ).replace (hour = 0 , minute = 0 , second = 0 ).timestamp ())
51- elif start_time != '' and end_time == '' :
52- start_time = int (datetime .strptime (start_time , '%m/%d/%y' ).replace (hour = 0 , minute = 0 , second = 0 ).timestamp ())
53- end_time = int (time ())
54- elif start_time == '' and end_time == '' :
55- current_data_flag = True
56-
57- start_time = int (time ()) - 120 # 2 minutes ago
58- end_time = int (time ()) # Now
59-
38+
39+ start_time = to_timestamp (start_time ) if start_time else int (time ()) - 120
40+ end_time = to_timestamp (end_time ) if end_time else int (time ())
41+
6042 if end_time <= start_time :
6143 raise ValueError ("End time must be greater than Start time" )
62-
63- match station :
64- case '' :
65- db = 'mesoterp7DB'
66- case 'atlantic' :
67- db = "mesoterp7DB"
68- case 'golf' :
69- db = "mesoterp6DB"
70- case 'vmh' :
71- db = "mesoterp1DB"
72- case 'williams' :
73- db = "mesoterp8DB"
74- case 'chem' :
75- db = "mesoterp3DB"
76- case _:
77- raise ValueError ("Valid Station not Provided" )
78-
79-
80- PAYLOAD = {
81- "startms" : start_time ,
44+
45+ payload = {
46+ "startms" : start_time ,
8247 "endms" : end_time ,
83- "db" : db ,
48+ "db" : stations_db [ station . lower ()] ,
8449 "table" : "archive" ,
8550 "cols" : ["dateTime" , "outTemp" , "dewpoint" , "barometer" , "rainRate" , "windSpeed" , "windGust" , "windDir" ]
8651 }
87-
52+
8853 try :
89- result = requests .post (url , json = PAYLOAD )
90- result .raise_for_status () # Raise error for bad HTTP responses
91- data = result .json ().get (' data' )
92-
54+ response = requests .post (url , json = payload )
55+ response .raise_for_status ()
56+ data = response .json ().get (" data" )
57+
9358 if not data :
9459 raise ValueError ("No data returned from the API" )
95-
96- result_dict = {}
97-
98- if current_data_flag :
99- result_dict = data [0 ]
100-
101- for key in result_dict :
102- try :
103- result_dict [key ] = float (result_dict [key ])
104- except (ValueError , TypeError ):
105- pass
106- else :
107- result_dict = data
108-
109- for i in range (len (result_dict )):
110- for key in result_dict [i ]:
111- try :
112- result_dict [i ][key ] = float (result_dict [i ][key ])
113- except (ValueError , TypeError ):
114- pass
115-
116- return result_dict
117-
60+
61+ return [{k : float (v ) if isinstance (v , (int , float , str )) and str (v ).replace ('.' , '' , 1 ).isdigit () else v for k , v in row .items ()} for row in data ]
62+
11863 except requests .exceptions .RequestException as e :
11964 raise RuntimeError (f"API request failed: { e } " )
65+
12066
12167 def save_radar_gif (self , dir = "" ):
12268 """
@@ -157,7 +103,7 @@ def save_radar_gif(self, dir=""):
157103 except OSError as e :
158104 print (f"Error saving file: { e } " )
159105
160- def get_weather_description ():
106+ def get_weather_description (self ):
161107 url = 'https://weather.umd.edu/'
162108
163109 response = requests .get (url )
@@ -175,3 +121,61 @@ def get_weather_description():
175121 else :
176122 raise requests .exceptions .HTTPError (f"Failed to fetch the webpage. Status code: { response .status_code } " )
177123
124+ def get_co2_levels (self , start_time , end_time = None ):
125+
126+ """
127+
128+ Fetch CO2 levels from the API.
129+
130+ - `start_time` (str) must be provided in 'MM/DD/YY' format.
131+ - `end_time` (str, optional) defaults to the current time if not provided.
132+ - Start and end times must be at least one day apart.
133+
134+ """
135+
136+ url = "https://weather.umd.edu/wordpress/wp-content/plugins/meso-fsct/functions/get-data.php"
137+
138+ def validate_date (date_str ):
139+ try :
140+ return datetime .strptime (date_str , '%m/%d/%y' )
141+ except ValueError :
142+ raise ValueError (f"Invalid date format: { date_str } . Expected format: MM/DD/YY" )
143+
144+ start_dt = validate_date (start_time )
145+ end_dt = validate_date (end_time ) if end_time else datetime .utcnow ()
146+
147+ start_ts , end_ts = int (start_dt .timestamp ()), int (end_dt .timestamp ())
148+
149+ if end_ts <= start_ts :
150+ raise ValueError ("End time must be greater than Start time" )
151+
152+ if (end_ts - start_ts ) < 86400 :
153+ raise ValueError ("Start to End range must be at least one day" )
154+
155+ payload = {
156+ "start_timestamp" : start_dt .strftime ('%Y-%m-%d %H:%M:%S' ),
157+ "end_timestamp" : end_dt .strftime ('%Y-%m-%d %H:%M:%S' ),
158+ "db" : "atl_co2" ,
159+ "table" : "co2_readings" ,
160+ "cols" : ["timestamp" , "measurement_value" ]
161+ }
162+
163+ try :
164+ response = requests .post (url , json = payload )
165+ response .raise_for_status ()
166+ data = response .json ().get ('data' , [])
167+
168+ if not data :
169+ raise ValueError ("No data returned from the API" )
170+
171+ for record in data :
172+ for key in record :
173+ try :
174+ record [key ] = float (record [key ])
175+ except (ValueError , TypeError ):
176+ pass
177+
178+ return data
179+
180+ except requests .exceptions .RequestException as e :
181+ raise RuntimeError (f"API request failed: { e } " )
0 commit comments