From 2bdab6bff106d0e1325e4d5dbf6b6627fc5c3af0 Mon Sep 17 00:00:00 2001 From: "Reda.Drissi.e" Date: Sat, 25 Jan 2025 22:56:33 +0100 Subject: [PATCH 1/4] Added multi-disk support --- library/config.py | 7 +++ library/sensors/sensors.py | 6 +-- library/sensors/sensors_python.py | 12 ++--- library/sensors/sensors_stub_random.py | 6 +-- library/stats.py | 69 ++++++++++++++----------- res/themes/CustomDataExample/theme.yaml | 63 ++++++++++++++++++++++ res/themes/Cyberpunk/theme.yaml | 60 ++++++++++----------- res/themes/default_disk.yaml | 19 +++++++ 8 files changed, 171 insertions(+), 71 deletions(-) create mode 100644 res/themes/default_disk.yaml diff --git a/library/config.py b/library/config.py index 32e47459..680bf863 100644 --- a/library/config.py +++ b/library/config.py @@ -38,9 +38,12 @@ def load_yaml(configfile): FONTS_DIR = str(MAIN_DIRECTORY / "res" / "fonts") + "/" CONFIG_DATA = load_yaml(MAIN_DIRECTORY / "config.yaml") THEME_DEFAULT = load_yaml(MAIN_DIRECTORY / "res/themes/default.yaml") +THEME_DISK_DEFAULT = load_yaml("res/themes/default_disk.yaml") THEME_DATA = None + + def copy_default(default, theme): """recursively supply default values into a dict of dicts of dicts ....""" for k, v in default.items(): @@ -66,6 +69,10 @@ def load_theme(): copy_default(THEME_DEFAULT, THEME_DATA) + if THEME_DATA['STATS']['DISK'].get("MOUNTS", False): + for mount in THEME_DATA['STATS']['DISK']['MOUNTS']: + mountpoint = [k for k, v in mount.items()][0] + copy_default(THEME_DISK_DEFAULT, mount[mountpoint]) def check_theme_compatible(display_size: str): global THEME_DATA diff --git a/library/sensors/sensors.py b/library/sensors/sensors.py index 0a9ada94..b8ff56b7 100644 --- a/library/sensors/sensors.py +++ b/library/sensors/sensors.py @@ -103,17 +103,17 @@ def virtual_free() -> int: # In bytes class Disk(ABC): @staticmethod @abstractmethod - def disk_usage_percent() -> float: + def disk_usage_percent(path) -> float: pass @staticmethod @abstractmethod - def disk_used() -> int: # In bytes + def disk_used(path) -> int: # In bytes pass @staticmethod @abstractmethod - def disk_free() -> int: # In bytes + def disk_free(path) -> int: # In bytes pass diff --git a/library/sensors/sensors_python.py b/library/sensors/sensors_python.py index fe91c535..78cf22be 100644 --- a/library/sensors/sensors_python.py +++ b/library/sensors/sensors_python.py @@ -443,23 +443,23 @@ def virtual_free() -> int: # In bytes class Disk(sensors.Disk): @staticmethod - def disk_usage_percent() -> float: + def disk_usage_percent(path) -> float: try: - return psutil.disk_usage("/").percent + return psutil.disk_usage(path).percent except: return math.nan @staticmethod - def disk_used() -> int: # In bytes + def disk_used(path) -> int: # In bytes try: - return psutil.disk_usage("/").used + return psutil.disk_usage(path).used except: return -1 @staticmethod - def disk_free() -> int: # In bytes + def disk_free(path) -> int: # In bytes try: - return psutil.disk_usage("/").free + return psutil.disk_usage(path).free except: return -1 diff --git a/library/sensors/sensors_stub_random.py b/library/sensors/sensors_stub_random.py index 07e37748..2c7c7721 100644 --- a/library/sensors/sensors_stub_random.py +++ b/library/sensors/sensors_stub_random.py @@ -91,15 +91,15 @@ def virtual_free() -> int: # In bytes class Disk(sensors.Disk): @staticmethod - def disk_usage_percent() -> float: + def disk_usage_percent(path) -> float: return random.uniform(0, 100) @staticmethod - def disk_used() -> int: # In bytes + def disk_used(path) -> int: # In bytes return random.randint(1000000000, 2000000000000) @staticmethod - def disk_free() -> int: # In bytes + def disk_free(path) -> int: # In bytes return random.randint(1000000000, 2000000000000) diff --git a/library/stats.py b/library/stats.py index 0c32f2f6..6a5f8484 100644 --- a/library/stats.py +++ b/library/stats.py @@ -645,37 +645,46 @@ class Disk: @classmethod def stats(cls): - used = sensors.Disk.disk_used() - free = sensors.Disk.disk_free() - - disk_theme_data = config.THEME_DATA['STATS']['DISK'] - - disk_usage_percent = sensors.Disk.disk_usage_percent() - save_last_value(disk_usage_percent, cls.last_values_disk_usage, - disk_theme_data['USED']['LINE_GRAPH'].get("HISTORY_SIZE", DEFAULT_HISTORY_SIZE)) - display_themed_progress_bar(disk_theme_data['USED']['GRAPH'], disk_usage_percent) - display_themed_percent_radial_bar(disk_theme_data['USED']['RADIAL'], disk_usage_percent) - display_themed_percent_value(disk_theme_data['USED']['PERCENT_TEXT'], disk_usage_percent) - display_themed_line_graph(disk_theme_data['USED']['LINE_GRAPH'], cls.last_values_disk_usage) + if 'MOUNTS' not in config.THEME_DATA['STATS']['DISK']: + print("Doing mounts") + mountpoints = [ config.THEME_DATA['STATS']['DISK'] ] + else: + mountpoints = config.THEME_DATA['STATS']['DISK']['MOUNTS'] - display_themed_value( - theme_data=disk_theme_data['USED']['TEXT'], - value=int(used / 1000000000), - min_size=5, - unit=" G" - ) - display_themed_value( - theme_data=disk_theme_data['TOTAL']['TEXT'], - value=int((free + used) / 1000000000), - min_size=5, - unit=" G" - ) - display_themed_value( - theme_data=disk_theme_data['FREE']['TEXT'], - value=int(free / 1000000000), - min_size=5, - unit=" G" - ) + for mount in mountpoints: + mountpoint = [k for k, v in mount.items()][0] + disk_theme_data = mount[mountpoint] + if not os.path.exists(mountpoint): + logger.warning('Invalid mount point in config: "%s"' % mountpoint) + else: + used = sensors.Disk.disk_used(mountpoint) + free = sensors.Disk.disk_free(mountpoint) + + disk_usage_percent = sensors.Disk.disk_usage_percent(mountpoint) + save_last_value(disk_usage_percent, cls.last_values_disk_usage, DEFAULT_HISTORY_SIZE) + #display_themed_progress_bar(disk_theme_data['USED']['GRAPH'], disk_usage_percent) + #display_themed_percent_radial_bar(disk_theme_data['USED']['RADIAL'], disk_usage_percent) + display_themed_percent_value(disk_theme_data['USED']['PERCENT_TEXT'], disk_usage_percent) + #display_themed_line_graph(disk_theme_data['USED']['LINE_GRAPH'], cls.last_values_disk_usage) + + display_themed_value( + theme_data=disk_theme_data['USED']['TEXT'], + value=int(used / 1000000000), + min_size=5, + unit=" G" + ) + display_themed_value( + theme_data=disk_theme_data['TOTAL']['TEXT'], + value=int((free + used) / 1000000000), + min_size=5, + unit=" G" + ) + display_themed_value( + theme_data=disk_theme_data['FREE']['TEXT'], + value=int(free / 1000000000), + min_size=5, + unit=" G" + ) class Net: diff --git a/res/themes/CustomDataExample/theme.yaml b/res/themes/CustomDataExample/theme.yaml index 571fb96c..a29d5013 100644 --- a/res/themes/CustomDataExample/theme.yaml +++ b/res/themes/CustomDataExample/theme.yaml @@ -16,6 +16,69 @@ static_images: HEIGHT: 320 STATS: + DISK: + INTERVAL: 10 + MOUNTS: + - '/': + USED: + TEXT: + SHOW: True + SHOW_UNIT: True + X: 155 + Y: 338 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 26 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png + PERCENT_TEXT: + SHOW: True + SHOW_UNIT: True + X: 170 + Y: 430 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 30 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png + FREE: + TEXT: + SHOW: True + SHOW_UNIT: True + X: 155 + Y: 383 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 26 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png + - '/boot/efi': + USED: + TEXT: + SHOW: True + SHOW_UNIT: True + X: 155 + Y: 338 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 26 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png + PERCENT_TEXT: + SHOW: True + SHOW_UNIT: True + X: 170 + Y: 430 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 30 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png + FREE: + TEXT: + SHOW: True + SHOW_UNIT: True + X: 155 + Y: 383 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 26 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png DATE: INTERVAL: 1 HOUR: diff --git a/res/themes/Cyberpunk/theme.yaml b/res/themes/Cyberpunk/theme.yaml index 673476b2..1d5ddb6e 100644 --- a/res/themes/Cyberpunk/theme.yaml +++ b/res/themes/Cyberpunk/theme.yaml @@ -185,35 +185,37 @@ STATS: BACKGROUND_IMAGE: background.png DISK: INTERVAL: 10 - USED: - TEXT: - SHOW: True - SHOW_UNIT: True - X: 155 - Y: 338 - FONT: generale-mono/GeneraleMonoA.ttf - FONT_SIZE: 26 - FONT_COLOR: 2, 216, 243 - BACKGROUND_IMAGE: background.png - PERCENT_TEXT: - SHOW: True - SHOW_UNIT: True - X: 170 - Y: 430 - FONT: generale-mono/GeneraleMonoA.ttf - FONT_SIZE: 30 - FONT_COLOR: 2, 216, 243 - BACKGROUND_IMAGE: background.png - FREE: - TEXT: - SHOW: True - SHOW_UNIT: True - X: 155 - Y: 383 - FONT: generale-mono/GeneraleMonoA.ttf - FONT_SIZE: 26 - FONT_COLOR: 2, 216, 243 - BACKGROUND_IMAGE: background.png + MOUNTS: + - '/': + USED: + TEXT: + SHOW: True + SHOW_UNIT: True + X: 155 + Y: 338 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 26 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png + PERCENT_TEXT: + SHOW: True + SHOW_UNIT: True + X: 170 + Y: 320 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 30 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png + FREE: + TEXT: + SHOW: True + SHOW_UNIT: True + X: 155 + Y: 383 + FONT: generale-mono/GeneraleMonoA.ttf + FONT_SIZE: 26 + FONT_COLOR: 2, 216, 243 + BACKGROUND_IMAGE: background.png DATE: INTERVAL: 1 DAY: diff --git a/res/themes/default_disk.yaml b/res/themes/default_disk.yaml new file mode 100644 index 00000000..e52673ac --- /dev/null +++ b/res/themes/default_disk.yaml @@ -0,0 +1,19 @@ +# This file is used to add mandatory sections to a theme file in case they are missing +# This is not a theme! Do not use this file to create a new theme, as a lot of content is missing: use theme_example.yaml +USED: + GRAPH: + SHOW: False + TEXT: + SHOW: False + SHOW_UNIT: False + PERCENT_TEXT: + SHOW: False + SHOW_UNIT: False +TOTAL: + TEXT: + SHOW: False + SHOW_UNIT: False +FREE: + TEXT: + SHOW: False + SHOW_UNIT: False \ No newline at end of file From 6726bd0959e178d9d6494217e8bc1a7a90d3b548 Mon Sep 17 00:00:00 2001 From: "Reda.Drissi.e" Date: Sat, 25 Jan 2025 23:17:39 +0100 Subject: [PATCH 2/4] Added multi-disk support --- library/stats.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/stats.py b/library/stats.py index 6a5f8484..6cfbb8fe 100644 --- a/library/stats.py +++ b/library/stats.py @@ -646,8 +646,7 @@ class Disk: @classmethod def stats(cls): if 'MOUNTS' not in config.THEME_DATA['STATS']['DISK']: - print("Doing mounts") - mountpoints = [ config.THEME_DATA['STATS']['DISK'] ] + mountpoints = [ {"/": config.THEME_DATA['STATS']['DISK'] }] else: mountpoints = config.THEME_DATA['STATS']['DISK']['MOUNTS'] From 5f54579234c5a11ee2a44ef1db0eb32f284282e1 Mon Sep 17 00:00:00 2001 From: Reda DRISSI Date: Wed, 12 Feb 2025 09:21:46 +0100 Subject: [PATCH 3/4] Update sensors_librehardwaremonitor.py --- library/sensors/sensors_librehardwaremonitor.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/sensors/sensors_librehardwaremonitor.py b/library/sensors/sensors_librehardwaremonitor.py index f619a5b3..c05b810f 100644 --- a/library/sensors/sensors_librehardwaremonitor.py +++ b/library/sensors/sensors_librehardwaremonitor.py @@ -448,16 +448,16 @@ def virtual_free() -> int: # In bytes # This is because LHM is a hardware-oriented library, whereas used/free/total space is for partitions, not disks class Disk(sensors.Disk): @staticmethod - def disk_usage_percent() -> float: - return psutil.disk_usage("/").percent + def disk_usage_percent(path) -> float: + return psutil.disk_usage(path).percent @staticmethod - def disk_used() -> int: # In bytes - return psutil.disk_usage("/").used + def disk_used(path) -> int: # In bytes + return psutil.disk_usage(path).used @staticmethod - def disk_free() -> int: # In bytes - return psutil.disk_usage("/").free + def disk_free(path) -> int: # In bytes + return psutil.disk_usage(path).free class Net(sensors.Net): From a23e290b2038c1ca069c16c8825f92a79656ae28 Mon Sep 17 00:00:00 2001 From: Reda DRISSI Date: Wed, 12 Feb 2025 09:22:17 +0100 Subject: [PATCH 4/4] Update sensors_stub_static.py --- library/sensors/sensors_stub_static.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/sensors/sensors_stub_static.py b/library/sensors/sensors_stub_static.py index 5aa16168..cf836d1a 100644 --- a/library/sensors/sensors_stub_static.py +++ b/library/sensors/sensors_stub_static.py @@ -107,18 +107,19 @@ def virtual_free() -> int: # In bytes class Disk(sensors.Disk): @staticmethod - def disk_usage_percent() -> float: + def disk_usage_percent(path) -> float: return PERCENTAGE_SENSOR_VALUE @staticmethod - def disk_used() -> int: # In bytes + def disk_used(path) -> int: # In bytes return int(DISK_TOTAL_SIZE_GB / 100 * PERCENTAGE_SENSOR_VALUE) * 1000000000 @staticmethod - def disk_free() -> int: # In bytes + def disk_free(path) -> int: # In bytes return int(DISK_TOTAL_SIZE_GB / 100 * (100 - PERCENTAGE_SENSOR_VALUE)) * 1000000000 + class Net(sensors.Net): @staticmethod def stats(if_name, interval) -> Tuple[