51
51
import sv_ttk
52
52
from PIL import Image
53
53
from serial .tools .list_ports import comports
54
+ from tktooltip import ToolTip
54
55
except :
55
56
print (
56
57
"[ERROR] Python dependencies not installed. Please follow start guide: https://github.com/mathoudebine/turing-smart-screen-python/wiki/System-monitor-:-how-to-start" )
59
60
except :
60
61
os ._exit (0 )
61
62
63
+ from library .sensors .sensors_python import sensors_fans , is_cpu_fan
64
+
62
65
TURING_MODEL = "Turing Smart Screen"
63
66
USBPCMONITOR_MODEL = "UsbPCMonitor"
64
67
XUANFANG_MODEL = "XuanFang rev. B & flagship"
@@ -141,14 +144,28 @@ def get_net_if():
141
144
return if_list
142
145
143
146
147
+ def get_fans ():
148
+ fan_list = list ()
149
+ auto_detected_cpu_fan = "None"
150
+ for name , entries in sensors_fans ().items ():
151
+ for entry in entries :
152
+ fan_list .append ("%s/%s (%d%% - %d RPM)" % (name , entry .label , entry .percent , entry .current ))
153
+ if (is_cpu_fan (entry .label ) or is_cpu_fan (name )) and auto_detected_cpu_fan == "None" :
154
+ auto_detected_cpu_fan = "Auto-detected: %s/%s" % (name , entry .label )
155
+
156
+ fan_list .insert (0 , auto_detected_cpu_fan ) # Add manual entry on top if auto-detection succeeded
157
+ return fan_list
158
+
159
+
144
160
class TuringConfigWindow :
145
161
def __init__ (self ):
146
162
self .window = Tk ()
147
163
self .window .title ('Turing System Monitor configuration' )
148
- self .window .geometry ("770x550 " )
164
+ self .window .geometry ("770x570 " )
149
165
self .window .iconphoto (True , PhotoImage (file = "res/icons/monitor-icon-17865/64.png" ))
150
166
# When window gets focus again, reload theme preview in case it has been updated by theme editor
151
167
self .window .bind ("<FocusIn>" , self .on_theme_change )
168
+ self .window .after (0 , self .on_fan_speed_update )
152
169
153
170
# Make TK look better with Sun Valley ttk theme
154
171
sv_ttk .set_theme ("light" )
@@ -224,18 +241,29 @@ def __init__(self):
224
241
self .wl_cb = ttk .Combobox (self .window , values = get_net_if (), state = 'readonly' )
225
242
self .wl_cb .place (x = 500 , y = 415 , width = 250 )
226
243
244
+ # For Windows platform only
227
245
self .lhm_admin_warning = ttk .Label (self .window ,
228
246
text = "❌ Restart as admin. or select another Hardware monitoring" ,
229
247
foreground = '#f00' )
248
+ # For platform != Windows
249
+ self .cpu_fan_label = ttk .Label (self .window , text = 'CPU fan (?)' )
250
+ self .cpu_fan_label .config (foreground = "#a3a3ff" , cursor = "hand2" )
251
+ self .cpu_fan_cb = ttk .Combobox (self .window , values = get_fans (), state = 'readonly' )
252
+
253
+ self .tooltip = ToolTip (self .cpu_fan_label ,
254
+ msg = "If \" None\" is selected, CPU fan was not auto-detected.\n "
255
+ "Manually select your CPU fan from the list.\n \n "
256
+ "Fans missing from the list? Install lm-sensors package\n "
257
+ "and run 'sudo sensors-detect' command, then reboot." )
230
258
231
259
self .edit_theme_btn = ttk .Button (self .window , text = "Edit theme" , command = lambda : self .on_theme_editor_click ())
232
- self .edit_theme_btn .place (x = 310 , y = 490 , height = 50 , width = 130 )
260
+ self .edit_theme_btn .place (x = 310 , y = 510 , height = 50 , width = 130 )
233
261
234
262
self .save_btn = ttk .Button (self .window , text = "Save settings" , command = lambda : self .on_save_click ())
235
- self .save_btn .place (x = 450 , y = 490 , height = 50 , width = 130 )
263
+ self .save_btn .place (x = 450 , y = 510 , height = 50 , width = 130 )
236
264
237
265
self .save_run_btn = ttk .Button (self .window , text = "Save and run" , command = lambda : self .on_saverun_click ())
238
- self .save_run_btn .place (x = 590 , y = 490 , height = 50 , width = 130 )
266
+ self .save_run_btn .place (x = 590 , y = 510 , height = 50 , width = 130 )
239
267
240
268
self .config = None
241
269
self .load_config_values ()
@@ -261,7 +289,8 @@ def load_theme_preview(self):
261
289
self .theme_author .config (text = "Author: " + author_name )
262
290
if author_name .startswith ("@" ):
263
291
self .theme_author .config (foreground = "#a3a3ff" , cursor = "hand2" )
264
- self .theme_author .bind ("<Button-1>" , lambda e : webbrowser .open_new_tab ("https://github.com/" + author_name [1 :]))
292
+ self .theme_author .bind ("<Button-1>" ,
293
+ lambda e : webbrowser .open_new_tab ("https://github.com/" + author_name [1 :]))
265
294
else :
266
295
self .theme_author .config (foreground = "#a3a3a3" , cursor = "" )
267
296
self .theme_author .unbind ("<Button-1>" )
@@ -336,6 +365,14 @@ def load_config_values(self):
336
365
except :
337
366
self .brightness_slider .set (50 )
338
367
368
+ try :
369
+ if self .config ['config' ]['CPU_FAN' ] == "AUTO" :
370
+ self .cpu_fan_cb .current (0 )
371
+ else :
372
+ self .cpu_fan_cb .set (self .config ['config' ]['CPU_FAN' ])
373
+ except :
374
+ self .cpu_fan_cb .current (0 )
375
+
339
376
# Reload content on screen
340
377
self .on_model_change ()
341
378
self .on_size_change ()
@@ -358,6 +395,10 @@ def save_config_values(self):
358
395
self .config ['config' ]['COM_PORT' ] = "AUTO"
359
396
else :
360
397
self .config ['config' ]['COM_PORT' ] = self .com_cb .get ()
398
+ if self .cpu_fan_cb .current () == 0 :
399
+ self .config ['config' ]['CPU_FAN' ] = "AUTO"
400
+ else :
401
+ self .config ['config' ]['CPU_FAN' ] = self .cpu_fan_cb .get ().split (' ' )[0 ]
361
402
self .config ['display' ]['REVISION' ] = model_and_size_to_revision_map [(self .model_cb .get (), self .size_cb .get ())]
362
403
self .config ['display' ]['DISPLAY_REVERSE' ] = [k for k , v in reverse_map .items () if v == self .orient_cb .get ()][0 ]
363
404
self .config ['display' ]['BRIGHTNESS' ] = int (self .brightness_slider .get ())
@@ -421,11 +462,18 @@ def on_hwlib_change(self, e=None):
421
462
import ctypes
422
463
is_admin = ctypes .windll .shell32 .IsUserAnAdmin () != 0
423
464
if (hwlib == "LHM" or hwlib == "AUTO" ) and not is_admin :
424
- self .lhm_admin_warning .place (x = 320 , y = 455 )
465
+ self .lhm_admin_warning .place (x = 320 , y = 460 )
425
466
self .save_run_btn .state (["disabled" ])
426
467
else :
427
468
self .lhm_admin_warning .place_forget ()
428
469
self .save_run_btn .state (["!disabled" ])
470
+ else :
471
+ if hwlib == "PYTHON" or hwlib == "AUTO" :
472
+ self .cpu_fan_label .place (x = 320 , y = 460 )
473
+ self .cpu_fan_cb .place (x = 500 , y = 455 , width = 250 )
474
+ else :
475
+ self .cpu_fan_label .place_forget ()
476
+ self .cpu_fan_cb .place_forget ()
429
477
430
478
def show_hide_brightness_warning (self , e = None ):
431
479
if int (self .brightness_slider .get ()) > 50 and self .model_cb .get () == TURING_MODEL and self .size_cb .get () == SIZE_3_5_INCH :
@@ -434,6 +482,14 @@ def show_hide_brightness_warning(self, e=None):
434
482
else :
435
483
self .brightness_warning_label .place_forget ()
436
484
485
+ def on_fan_speed_update (self ):
486
+ # Update fan speed periodically
487
+ prev_value = self .cpu_fan_cb .current () # Save currently selected index
488
+ self .cpu_fan_cb .config (values = get_fans ())
489
+ if prev_value != - 1 :
490
+ self .cpu_fan_cb .current (prev_value ) # Force select same index to refresh displayed value
491
+ self .window .after (500 , self .on_fan_speed_update )
492
+
437
493
438
494
if __name__ == "__main__" :
439
495
configurator = TuringConfigWindow ()
0 commit comments