1- import tkinter as tk
1+ import os
2+ from geopy .geocoders import Nominatim
3+ import tkinter as tk
24from tkinter import messagebox
35import requests
46import threading
57import time
6- from dotenv import load_dotenv
8+ from dotenv import load_dotenv
79load_dotenv ()
8- from geopy .geocoders import Nominatim
9- import os
1010
11- API_KEY = os .getenv ('OPENWEATHER_API_KEY' )
11+ API_KEY = os .getenv ('OPENWEATHER_API_KEY' )
1212if API_KEY is None :
13- raise ValueError ("API key not found. Please set the OPENWEATHER_API_KEY in the .env file." )
13+ raise ValueError (
14+ "API key not found. Set the OPENWEATHER_API_KEY in the .env file." )
15+
1416
1517def calculate_lat_long (city ):
1618 geolocator = Nominatim (user_agent = "weather_notifier" )
1719 location = geolocator .geocode (city )
1820 if location :
1921 return location .latitude , location .longitude
20- return None ,None
21- def get_weather (lat ,long ):
22+ return None , None
23+
24+
25+ def get_weather (lat , long ):
2226 try :
23- print (lat ,long )
24- url = f"https://api.openweathermap.org/data/2.5/weather?lat={ lat } &lon={ long } &units=metric&appid={ API_KEY } "
25- res = requests .get (url )
27+ print (lat , long )
28+ url = (
29+ f"https://api.openweathermap.org/data/2.5/weather?lat={ lat } "
30+ f"&lon={ long } &units=metric&appid={ API_KEY } "
31+ )
32+ res = requests .get (url )
2633 data = res .json ()
2734 if data ['cod' ] != 404 :
2835 weather_info = {
29- "City" : data .get ("name" , "N/A" ),
36+ "City" : data .get (
37+ "name" ,
38+ "N/A" ),
3039 "Latitude" : data ['coord' ]['lat' ],
3140 "Longitude" : data ['coord' ]['lon' ],
3241 "Temperature" : data ['main' ]['temp' ],
@@ -38,97 +47,129 @@ def get_weather(lat,long):
3847 "Wind Speed" : data ['wind' ]['speed' ],
3948 "Wind Degree" : data ['wind' ]['deg' ],
4049 "Weather" : data ['weather' ][0 ]['description' ].capitalize (),
41- "Clouds" : f"{ data ['clouds' ]['all' ]} %" ,
42- "Visibility" : data .get ('visibility' , "N/A" ),
43- "Sunrise" : time .strftime ('%Y-%m-%d %H:%M:%S' , time .gmtime (data ['sys' ]['sunrise' ] + data ['timezone' ])),
44- "Sunset" : time .strftime ('%Y-%m-%d %H:%M:%S' , time .gmtime (data ['sys' ]['sunset' ] + data ['timezone' ])),
50+ "Clouds" : f"{
51+ data ['clouds' ]['all' ]} %" ,
52+ "Visibility" : data .get (
53+ 'visibility' ,
54+ "N/A" ),
55+ "Sunrise" : time .strftime (
56+ '%Y-%m-%d %H:%M:%S' ,
57+ time .gmtime (
58+ data ['sys' ]['sunrise' ] + data ['timezone' ])),
59+ "Sunset" : time .strftime (
60+ '%Y-%m-%d %H:%M:%S' ,
61+ time .gmtime (
62+ data ['sys' ]['sunset' ] + data ['timezone' ])),
4563 }
4664 return weather_info
4765 else :
4866 return None
49-
67+
5068 except Exception as e :
5169 messagebox .showerror ("Error" , f"Error fetching weather data: { str (e )} " )
5270 return None
5371
54- # updating the weather
72+ # updating the weather
73+
74+
5575def update_weather ():
56- city = city_entry .get ()
76+ city = city_entry .get ()
5777 if city :
5878 lat , lon = calculate_lat_long (city )
5979 if lat and lon :
6080 weather_info = get_weather (lat , lon )
6181 if weather_info :
62- weather_info_in_str_to_display = covert_the_info_to_display (weather_info )
82+ weather_info_in_str_to_display = covert_the_info_to_display (
83+ weather_info )
6384 weather_label .config (text = weather_info_in_str_to_display )
6485 stop_button .pack (pady = 5 )
65- city_label .pack_forget ()
86+ city_label .pack_forget ()
6687 city_entry .pack_forget ()
67- manual_radio .pack_forget ()
68- auto_radio .pack_forget ()
88+ manual_radio .pack_forget ()
89+ auto_radio .pack_forget ()
6990 start_button .pack_forget ()
91+ interval_label .pack_forget ()
92+ interval_entry .pack_forget ()
7093 else :
7194 weather_label .config (text = "Unable to find coordinates!" )
7295 stop_button .pack_forget ()
7396 else :
7497 weather_label .config (text = "Unable to find coordinates!" )
7598 stop_button .pack_forget ()
7699 else :
77- messagebox .showerror ("Error" , "Please enter a valid city name." )
78- stop_button .pack_forget ()
79- # displaying the info in the tkinter created box
100+ messagebox .showerror ("Error" , "Please enter a valid city name." )
101+ stop_button .pack_forget ()
102+ # displaying the info in the tkinter created box
103+
104+
80105def covert_the_info_to_display (weather_info ):
81106 # Clear the previous text
82- weather_info_in_str_to_display = f'''
83- City: { weather_info ['City' ]} \n
84- Coordinates: ({ weather_info ['Latitude' ]} , { weather_info ['Longitude' ]} )\n
85- Temperature: { weather_info ['Temperature' ]} °C (Feels like { weather_info ['Feels Like' ]} °C)\n
86- Min Temp: { weather_info ['Min Temp' ]} °C, Max Temp: { weather_info ['Max Temp' ]} °C\n
87- Pressure: { weather_info ['Pressure' ]} hPa\n
88- Humidity: { weather_info ['Humidity' ]} %\n
89- Wind: { weather_info ['Wind Speed' ]} m/s, { weather_info ['Wind Degree' ]} °\n
90- Clouds: { weather_info ['Clouds' ]} \n
91- Visibility: { weather_info ['Visibility' ]} meters\n
92- Weather: { weather_info ['Weather' ]} \n
93- Sunrise: { weather_info ['Sunrise' ]} \n
94- Sunset: { weather_info ['Sunset' ]} \n
95- '''
107+ weather_info_in_str_to_display = (
108+ f"City: { weather_info ['City' ]} \n \n "
109+ f"Coordinates: ({ weather_info ['Latitude' ]} , "
110+ f"{ weather_info ['Longitude' ]} )\n \n "
111+ f"Temperature: { weather_info ['Temperature' ]} °C "
112+ f"(Feels like { weather_info ['Feels Like' ]} °C)\n \n "
113+ f"Min Temp: { weather_info ['Min Temp' ]} °C, "
114+ f"Max Temp: { weather_info ['Max Temp' ]} °C\n \n "
115+ f"Pressure: { weather_info ['Pressure' ]} hPa\n \n "
116+ f"Humidity: { weather_info ['Humidity' ]} %\n \n "
117+ f"Wind: { weather_info ['Wind Speed' ]} m/s, "
118+ f"{ weather_info ['Wind Degree' ]} °\n \n "
119+ f"Clouds: { weather_info ['Clouds' ]} \n \n "
120+ f"Visibility: { weather_info ['Visibility' ]} meters\n \n "
121+ f"Weather: { weather_info ['Weather' ]} \n \n "
122+ f"Sunrise: { weather_info ['Sunrise' ]} \n \n "
123+ f"Sunset: { weather_info ['Sunset' ]} \n \n "
124+ )
125+
96126 return weather_info_in_str_to_display
97127
98128# run_in_background logic
129+
130+
99131def run_in_background (interval ):
100132 while auto_mode .get ():
101133 update_weather ()
102134 time .sleep (interval )
103135
104136# Function to handle click
137+
138+
105139def start_notifier ():
106140 if auto_mode .get ():
107141 interval_str = interval_entry .get ().strip ()
108142 if not interval_str :
109- messagebox .showerror ("Error" , "Please enter a valid interval (in seconds)." )
110- return
143+ messagebox .showerror (
144+ "Error" , "Please enter a valid interval (in seconds)." )
145+ return
111146 try :
112- interval = int (interval_str )
147+ interval = int (interval_str )
113148 if interval <= 0 :
114- messagebox .showerror ("Error" , "Please enter a valid interval (in seconds)." )
149+ messagebox .showerror (
150+ "Error" , "Please enter a valid interval (in seconds)." )
115151 return
116- except ValueError as e :
152+ except ValueError :
117153 messagebox .showerror ("Error" , "Please enter a valid number." )
118154 return
119155 start_button .config (state = tk .DISABLED )
120156
121- threading .Thread (target = run_in_background , args = (interval ,), daemon = True ).start ()
157+ threading .Thread (
158+ target = run_in_background , args = (
159+ interval ,), daemon = True ).start ()
122160 else :
123161 update_weather ()
124162
125163# Function to stop auto-updating
164+
165+
126166def stop_notifier ():
127167 auto_mode .set (False )
128168 start_button .config (state = tk .NORMAL )
129- stop_button .pack_forget ()
169+ stop_button .pack_forget ()
130170 go_back ()
131171
172+
132173def go_back ():
133174 weather_label .config (text = "" )
134175 city_label .pack (pady = 10 )
@@ -139,29 +180,33 @@ def go_back():
139180 interval_label .pack_forget ()
140181 interval_entry .pack_forget ()
141182 stop_button .pack_forget ()
142-
183+
143184# gui setup
185+
186+
144187def show_interval_entry ():
145- if auto_mode .get ():
146- interval_label .pack (pady = 5 )
147- interval_entry .pack (pady = 5 )
148- else :
149- interval_label .pack_forget ()
150- interval_entry .pack_forget ()
188+ if auto_mode .get ():
189+ interval_label .pack (pady = 5 )
190+ interval_entry .pack (pady = 5 )
191+ else :
192+ interval_label .pack_forget ()
193+ interval_entry .pack_forget ()
194+
151195
152196def toggle_stop_button ():
153197 if auto_mode .get ():
154198 stop_button .pack (pady = 5 )
155199 else :
156200 stop_button .pack_forget ()
157201
158- if __name__ == '__main__' :
159- city = "Surat"
160- lat ,long = calculate_lat_long (city )
161- if lat == None or long == None :
202+
203+ if __name__ == '__main__' :
204+ city = "Surat"
205+ lat , long = calculate_lat_long (city )
206+ if lat is None or long is None :
162207 print ('No city found' )
163208 exit (0 )
164-
209+
165210 root = tk .Tk ()
166211 root .title ("Weather Notifier" )
167212 root .geometry ("550x500" )
@@ -174,28 +219,39 @@ def toggle_stop_button():
174219 city_entry .pack (pady = 5 )
175220
176221 # Weather Info Label
177- weather_label = tk .Label (root , text = "" , font = ("Helvetica" , 10 ),justify = "left" )
222+ weather_label = tk .Label (
223+ root , text = "" , font = (
224+ "Helvetica" , 10 ), justify = "left" )
178225 weather_label .pack (pady = 20 )
179226
180227 # Mode Selection: Manual or Automatic
181228 auto_mode = tk .BooleanVar ()
182229
183- manual_radio = tk .Radiobutton (root , text = "On-click only" , variable = auto_mode , value = False )
230+ manual_radio = tk .Radiobutton (
231+ root ,
232+ text = "On-click only" ,
233+ variable = auto_mode ,
234+ value = False )
184235 manual_radio .pack (anchor = tk .W , padx = 20 )
185236
186- auto_radio = tk .Radiobutton (root , text = "Run after a fixed interval" , variable = auto_mode , value = True )
237+ auto_radio = tk .Radiobutton (
238+ root ,
239+ text = "Run after a fixed interval" ,
240+ variable = auto_mode ,
241+ value = True )
187242 auto_radio .pack (anchor = tk .W , padx = 20 )
188243
189244 # Interval Entry (only visible when interval mode is selected)
190245 interval_label = tk .Label (root , text = "Enter interval (seconds):" )
191246 interval_entry = tk .Entry (root , width = 10 )
192247
193-
194-
195248 auto_mode .trace_add ("write" , lambda * args : show_interval_entry ())
196249
197250 # Start Button
198- start_button = tk .Button (root , text = "Start Notifier" , command = start_notifier )
251+ start_button = tk .Button (
252+ root ,
253+ text = "Start Notifier" ,
254+ command = start_notifier )
199255 start_button .pack (pady = 10 )
200256
201257 # Stop Button (visible only when auto mode is active)
@@ -205,4 +261,4 @@ def toggle_stop_button():
205261 auto_mode .trace_add ("write" , lambda * args : toggle_stop_button ())
206262
207263 # Run the GUI loop
208- root .mainloop ()
264+ root .mainloop ()
0 commit comments