diff --git a/library/scheduler.py b/library/scheduler.py index 455742e6..4d03c62a 100644 --- a/library/scheduler.py +++ b/library/scheduler.py @@ -155,6 +155,11 @@ def DateStats(): # logger.debug("Refresh date stats") stats.Date.stats() +@async_job("SystemUptime_Stats") +@schedule(timedelta(seconds=config.THEME_DATA['STATS']['UPTIME'].get("INTERVAL", 0)).total_seconds()) +def SystemUptimeStats(): + # logger.debug("Refresh system uptime stats") + stats.SystemUptime.stats() @async_job("Custom_Stats") @schedule(timedelta(seconds=config.THEME_DATA['STATS']['CUSTOM'].get("INTERVAL", 0)).total_seconds()) diff --git a/library/stats.py b/library/stats.py index 09ed6478..375f1b6c 100644 --- a/library/stats.py +++ b/library/stats.py @@ -30,6 +30,7 @@ import babel.dates from psutil._common import bytes2human +from uptime import uptime import library.config as config from library.display import display @@ -88,6 +89,9 @@ def display_themed_value(theme_data, value, min_size=0, unit=''): if not theme_data.get("SHOW", False): return + if value is None: + return + # overridable MIN_SIZE from theme with backward compatibility min_size = theme_data.get("MIN_SIZE", min_size) @@ -750,6 +754,32 @@ def stats(): ) +class SystemUptime: + @staticmethod + def stats(): + if HW_SENSORS == "STATIC": + # For static sensors, use predefined uptime + uptimesec = 4294036 + else: + uptimesec = int(uptime()) + + uptimeformatted = str(datetime.timedelta(seconds=uptimesec)) + + systemuptime_theme_data = config.THEME_DATA['STATS']['UPTIME'] + + systemuptime_sec_theme_data = systemuptime_theme_data['SECONDS']['TEXT'] + display_themed_value( + theme_data=systemuptime_sec_theme_data, + value=uptimesec + ) + + systemuptime_formatted_theme_data = systemuptime_theme_data['FORMATTED']['TEXT'] + display_themed_value( + theme_data=systemuptime_formatted_theme_data, + value=uptimeformatted + ) + + class Custom: @staticmethod def stats(): diff --git a/main.py b/main.py index 9d710124..5c29b107 100755 --- a/main.py +++ b/main.py @@ -208,6 +208,7 @@ def on_win32_wm_event(hWnd, msg, wParam, lParam): scheduler.DiskStats() scheduler.NetStats() scheduler.DateStats() + scheduler.SystemUptimeStats() scheduler.CustomStats() scheduler.QueueHandler() diff --git a/requirements.txt b/requirements.txt index 381393b4..0de8bef8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,7 @@ babel~=2.15.0 # Date/time formatting ruamel.yaml~=0.18.6 # For configuration editor sv-ttk~=2.6.0 # Tk Sun Valley theme for configuration editor tkinter-tooltip~=3.1.0 # Tooltips for configuration editor +uptime~=3.0.1 # For System Uptime # Efficient image serialization numpy~=1.24.4; python_version < "3.9" # For Python 3.8 max. diff --git a/res/themes/default.yaml b/res/themes/default.yaml index 6528d7db..d2c5cc6d 100644 --- a/res/themes/default.yaml +++ b/res/themes/default.yaml @@ -209,5 +209,13 @@ STATS: HOUR: TEXT: SHOW: False + UPTIME: + INTERVAL: 0 + SECONDS: + TEXT: + SHOW: False + FORMATTED: + TEXT: + SHOW: False CUSTOM: INTERVAL: 0 diff --git a/res/themes/theme_example.yaml b/res/themes/theme_example.yaml index cd98483d..d843c3b6 100644 --- a/res/themes/theme_example.yaml +++ b/res/themes/theme_example.yaml @@ -1427,3 +1427,42 @@ STATS: BACKGROUND_IMAGE: background.png ALIGN: left # left / center / right ANCHOR: lt # Check https://pillow.readthedocs.io/en/stable/handbook/text-anchors.html + UPTIME: + # For seconds display, it is recommended not to change the interval: keep to 1 + INTERVAL: 1 + SECONDS: # Uptime as seconds + TEXT: + SHOW: FALSE + X: 192 + Y: 261 + # Text sensors may vary in size and create "ghosting" effects where old value stay displayed under the new one. + # To avoid this use one of these 2 methods (or both): + # - either use a monospaced font (fonts with "mono" in name, see res/fonts/ for available fonts) + # - or force a static width/height for the text field. Be sure to have enough space for the longest value that can be displayed (e.g. "100%" for a percentage) + # WIDTH: 200 # Uncomment to force a static width + # HEIGHT: 50 # Uncomment to force static height + FONT: jetbrains-mono/JetBrainsMono-Bold.ttf + FONT_SIZE: 23 + FONT_COLOR: 255, 255, 255 + # BACKGROUND_COLOR: 132, 154, 165 + BACKGROUND_IMAGE: background.png + ALIGN: left # left / center / right + ANCHOR: lt # Check https://pillow.readthedocs.io/en/stable/handbook/text-anchors.html + FORMATTED: # Uptime as formatted string with days e.g. "49 days, 16:47:16" + TEXT: + SHOW: FALSE + X: 192 + Y: 261 + # Text sensors may vary in size and create "ghosting" effects where old value stay displayed under the new one. + # To avoid this use one of these 2 methods (or both): + # - either use a monospaced font (fonts with "mono" in name, see res/fonts/ for available fonts) + # - or force a static width/height for the text field. Be sure to have enough space for the longest value that can be displayed (e.g. "100%" for a percentage) + # WIDTH: 200 # Uncomment to force a static width + # HEIGHT: 50 # Uncomment to force static height + FONT: jetbrains-mono/JetBrainsMono-Bold.ttf + FONT_SIZE: 23 + FONT_COLOR: 255, 255, 255 + # BACKGROUND_COLOR: 132, 154, 165 + BACKGROUND_IMAGE: background.png + ALIGN: left # left / center / right + ANCHOR: lt # Check https://pillow.readthedocs.io/en/stable/handbook/text-anchors.html \ No newline at end of file diff --git a/theme-editor.py b/theme-editor.py index 3e6474a7..e0a63266 100755 --- a/theme-editor.py +++ b/theme-editor.py @@ -121,6 +121,8 @@ def refresh_theme(): stats.Net.stats() if config.THEME_DATA['STATS']['DATE'].get("INTERVAL", 0) > 0: stats.Date.stats() + if config.THEME_DATA['STATS']['UPTIME'].get("INTERVAL", 0) > 0: + stats.SystemUptime.stats() if config.THEME_DATA['STATS']['CUSTOM'].get("INTERVAL", 0) > 0: stats.Custom.stats()