Skip to content

Commit 78c074c

Browse files
authored
Merge pull request mathoudebine#639 from mathoudebine/dev/add-weather-and-ping-to-configure
2 parents 91ce7c6 + 4bc0e84 commit 78c074c

File tree

3 files changed

+173
-4
lines changed

3 files changed

+173
-4
lines changed

config.yaml

+4-3
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ config:
3737
PING: 8.8.8.8
3838

3939
# Weather data with OpenWeatherMap API. Only useful if you want to use a theme that displays it
40-
# Location from which to display the weather. Use for example https://www.latlong.net/ to get latitude/longitude
41-
WEATHER_LATITUDE: 45.75
42-
WEATHER_LONGITUDE: 4.85
40+
4341
# OpenWeatherMap API KEY. Can be obtained by creating a free account on https://home.openweathermap.org/users/sign_up.
4442
# You need to subscribe to the 3.0 OneCallAPI that has 1000 free daily calls
4543
WEATHER_API_KEY: ""
44+
# Location from which to display the weather. Use for example https://www.latlong.net/ to get latitude/longitude
45+
WEATHER_LATITUDE: 45.75
46+
WEATHER_LONGITUDE: 4.85
4647
# Units used to display temperatures (metric - °C, imperial - °F, standard - °K)
4748
WEATHER_UNITS: metric
4849
# Language is used by the API. Find more here https://openweathermap.org/api/one-call-3#multi

configure.py

+168
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,17 @@
9292
hw_lib_map = {"AUTO": "Automatic", "LHM": "LibreHardwareMonitor (admin.)", "PYTHON": "Python libraries",
9393
"STUB": "Fake random data", "STATIC": "Fake static data"}
9494
reverse_map = {False: "classic", True: "reverse"}
95+
weather_unit_map = {"metric": "metric - °C", "imperial": "imperial - °F", "standard": "standard - °K"}
96+
weather_lang_map = {"sq": "Albanian", "af": "Afrikaans", "ar": "Arabic", "az": "Azerbaijani", "eu": "Basque",
97+
"be": "Belarusian", "bg": "Bulgarian", "ca": "Catalan", "zh_cn": "Chinese Simplified",
98+
"zh_tw": "Chinese Traditional", "hr": "Croatian", "cz": "Czech", "da": "Danish", "nl": "Dutch",
99+
"en": "English", "fi": "Finnish", "fr": "French", "gl": "Galician", "de": "German", "el": "Greek",
100+
"he": "Hebrew", "hi": "Hindi", "hu": "Hungarian", "is": "Icelandic", "id": "Indonesian",
101+
"it": "Italian", "ja": "Japanese", "kr": "Korean", "ku": "Kurmanji (Kurdish)", "la": "Latvian",
102+
"lt": "Lithuanian", "mk": "Macedonian", "no": "Norwegian", "fa": "Persian (Farsi)", "pl": "Polish",
103+
"pt": "Portuguese", "pt_br": "Português Brasil", "ro": "Romanian", "ru": "Russian", "sr": "Serbian",
104+
"sk": "Slovak", "sl": "Slovenian", "sp": "Spanish", "sv": "Swedish", "th": "Thai", "tr": "Turkish",
105+
"ua": "Ukrainian", "vi": "Vietnamese", "zu": "Zulu"}
95106

96107
MAIN_DIRECTORY = str(Path(__file__).parent.resolve()) + "/"
97108
THEMES_DIR = MAIN_DIRECTORY + 'res/themes'
@@ -162,6 +173,9 @@ def __init__(self):
162173
self.window.bind("<FocusIn>", self.on_theme_change)
163174
self.window.after(0, self.on_fan_speed_update)
164175

176+
# Subwindow for weather/ping config.
177+
self.more_config_window = MoreConfigWindow(self)
178+
165179
# Make TK look better with Sun Valley ttk theme
166180
sv_ttk.set_theme("light")
167181

@@ -251,6 +265,10 @@ def __init__(self):
251265
"Fans missing from the list? Install lm-sensors package\n"
252266
"and run 'sudo sensors-detect' command, then reboot.")
253267

268+
self.edit_theme_btn = ttk.Button(self.window, text="Weather & ping",
269+
command=lambda: self.on_weatherping_click())
270+
self.edit_theme_btn.place(x=170, y=510, height=50, width=130)
271+
254272
self.edit_theme_btn = ttk.Button(self.window, text="Edit theme", command=lambda: self.on_theme_editor_click())
255273
self.edit_theme_btn.place(x=310, y=510, height=50, width=130)
256274

@@ -375,6 +393,9 @@ def load_config_values(self):
375393
self.on_brightness_change()
376394
self.on_hwlib_change()
377395

396+
# Load configuration to sub-window as well
397+
self.more_config_window.load_config_values(self.config)
398+
378399
def save_config_values(self):
379400
self.config['config']['THEME'] = self.theme_cb.get()
380401
self.config['config']['HW_SENSORS'] = [k for k, v in hw_lib_map.items() if v == self.hwlib_cb.get()][0]
@@ -401,9 +422,23 @@ def save_config_values(self):
401422
with open("config.yaml", "w", encoding='utf-8') as file:
402423
ruamel.yaml.YAML().dump(self.config, file)
403424

425+
def save_additional_config(self, ping: str, api_key: str, lat: str, long: str, unit: str, lang: str):
426+
self.config['config']['PING'] = ping
427+
self.config['config']['WEATHER_API_KEY'] = api_key
428+
self.config['config']['WEATHER_LATITUDE'] = lat
429+
self.config['config']['WEATHER_LONGITUDE'] = long
430+
self.config['config']['WEATHER_UNITS'] = unit
431+
self.config['config']['WEATHER_LANGUAGE'] = lang
432+
433+
with open("config.yaml", "w", encoding='utf-8') as file:
434+
ruamel.yaml.YAML().dump(self.config, file)
435+
404436
def on_theme_change(self, e=None):
405437
self.load_theme_preview()
406438

439+
def on_weatherping_click(self):
440+
self.more_config_window.show()
441+
407442
def on_theme_editor_click(self):
408443
subprocess.Popen(MAIN_DIRECTORY + "theme-editor.py" + " \"" + self.theme_cb.get() + "\"", shell=True)
409444

@@ -486,6 +521,139 @@ def on_fan_speed_update(self):
486521
self.window.after(500, self.on_fan_speed_update)
487522

488523

524+
class MoreConfigWindow:
525+
def __init__(self, main_window: TuringConfigWindow):
526+
self.window = Toplevel()
527+
self.window.withdraw()
528+
self.window.title('Configure weather & ping')
529+
self.window.geometry("750x400")
530+
531+
self.main_window = main_window
532+
533+
# Make TK look better with Sun Valley ttk theme
534+
sv_ttk.set_theme("light")
535+
536+
self.ping_label = ttk.Label(self.window, text='Hostname / IP to ping')
537+
self.ping_label.place(x=10, y=10)
538+
self.ping_entry = ttk.Entry(self.window)
539+
self.ping_entry.place(x=190, y=5, width=250)
540+
541+
weather_label = ttk.Label(self.window, text='Weather forecast (OpenWeatherMap API)', font='bold')
542+
weather_label.place(x=10, y=70)
543+
544+
weather_info_label = ttk.Label(self.window,
545+
text="To display weather forecast on themes that support it, you need an OpenWeatherMap \"One Call API 3.0\" key.\n"
546+
"You will get 1,000 API calls per day for free. This program is configured to stay under this threshold (~300 calls/day).")
547+
weather_info_label.place(x=10, y=100)
548+
weather_api_link_label = ttk.Label(self.window,
549+
text="Click here to subscribe to OpenWeatherMap One Call API 3.0.")
550+
weather_api_link_label.place(x=10, y=140)
551+
weather_api_link_label.config(foreground="#a3a3ff", cursor="hand2")
552+
weather_api_link_label.bind("<Button-1>",
553+
lambda e: webbrowser.open_new_tab("https://openweathermap.org/api"))
554+
555+
self.api_label = ttk.Label(self.window, text='OpenWeatherMap API key')
556+
self.api_label.place(x=10, y=170)
557+
self.api_entry = ttk.Entry(self.window)
558+
self.api_entry.place(x=190, y=165, width=250)
559+
560+
latlong_label = ttk.Label(self.window,
561+
text="You can use online services to get your latitude/longitude e.g. latlong.net (click here)")
562+
latlong_label.place(x=10, y=210)
563+
latlong_label.config(foreground="#a3a3ff", cursor="hand2")
564+
latlong_label.bind("<Button-1>",
565+
lambda e: webbrowser.open_new_tab("https://www.latlong.net/"))
566+
567+
self.lat_label = ttk.Label(self.window, text='Latitude')
568+
self.lat_label.place(x=10, y=250)
569+
self.lat_entry = ttk.Entry(self.window, validate='key',
570+
validatecommand=(self.window.register(self.validateCoord), '%P'))
571+
self.lat_entry.place(x=80, y=245, width=100)
572+
573+
self.long_label = ttk.Label(self.window, text='Longitude')
574+
self.long_label.place(x=270, y=250)
575+
self.long_entry = ttk.Entry(self.window, validate='key',
576+
validatecommand=(self.window.register(self.validateCoord), '%P'))
577+
self.long_entry.place(x=340, y=245, width=100)
578+
579+
self.unit_label = ttk.Label(self.window, text='Units')
580+
self.unit_label.place(x=10, y=290)
581+
self.unit_cb = ttk.Combobox(self.window, values=list(weather_unit_map.values()), state='readonly')
582+
self.unit_cb.place(x=190, y=285, width=250)
583+
584+
self.lang_label = ttk.Label(self.window, text='Language')
585+
self.lang_label.place(x=10, y=330)
586+
self.lang_cb = ttk.Combobox(self.window, values=list(weather_lang_map.values()), state='readonly')
587+
self.lang_cb.place(x=190, y=325, width=250)
588+
589+
self.save_btn = ttk.Button(self.window, text="Save settings", command=lambda: self.on_save_click())
590+
self.save_btn.place(x=590, y=340, height=50, width=130)
591+
592+
self.window.protocol("WM_DELETE_WINDOW", self.on_closing)
593+
594+
def validateCoord(self, coord: str):
595+
if not coord:
596+
return True
597+
try:
598+
float(coord)
599+
except:
600+
return False
601+
return True
602+
603+
def show(self):
604+
self.window.deiconify()
605+
606+
def on_closing(self):
607+
self.window.withdraw()
608+
609+
def load_config_values(self, config):
610+
self.config = config
611+
612+
try:
613+
self.ping_entry.insert(0, self.config['config']['PING'])
614+
except:
615+
self.ping_entry.insert(0, "8.8.8.8")
616+
617+
try:
618+
self.api_entry.insert(0, self.config['config']['WEATHER_API_KEY'])
619+
except:
620+
pass
621+
622+
try:
623+
self.lat_entry.insert(0, self.config['config']['WEATHER_LATITUDE'])
624+
except:
625+
self.lat_entry.insert(0, "45.75")
626+
627+
try:
628+
self.long_entry.insert(0, self.config['config']['WEATHER_LONGITUDE'])
629+
except:
630+
self.long_entry.insert(0, "45.75")
631+
632+
try:
633+
self.unit_cb.set(weather_unit_map[self.config['config']['WEATHER_UNITS']])
634+
except:
635+
self.unit_cb.set(0)
636+
637+
try:
638+
self.lang_cb.set(weather_lang_map[self.config['config']['WEATHER_LANGUAGE']])
639+
except:
640+
self.lang_cb.set(weather_lang_map["en"])
641+
642+
def on_save_click(self):
643+
self.save_config_values()
644+
self.on_closing()
645+
646+
def save_config_values(self):
647+
ping = self.ping_entry.get()
648+
api_key = self.api_entry.get()
649+
lat = self.lat_entry.get()
650+
long = self.long_entry.get()
651+
unit = [k for k, v in weather_unit_map.items() if v == self.unit_cb.get()][0]
652+
lang = [k for k, v in weather_lang_map.items() if v == self.lang_cb.get()][0]
653+
654+
self.main_window.save_additional_config(ping, api_key, lat, long, unit, lang)
655+
656+
489657
if __name__ == "__main__":
490658
configurator = TuringConfigWindow()
491659
configurator.run()

library/scheduler.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def CustomStats():
171171

172172

173173
@async_job("Weather_Stats")
174-
@schedule(timedelta(seconds=config.THEME_DATA['STATS'].get('WEATHER', {}).get("INTERVAL", 0)).total_seconds())
174+
@schedule(timedelta(seconds=max(300.0, config.THEME_DATA['STATS'].get('WEATHER', {}).get("INTERVAL", 0))).total_seconds())
175175
def WeatherStats():
176176
# logger.debug("Refresh Weather data")
177177
stats.Weather.stats()

0 commit comments

Comments
 (0)