From 16174411d5700c4ea910339efe25d92a3bf9105e Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 09:58:25 -0400 Subject: [PATCH 01/30] Update oled_stats.py --- oled_stats.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oled_stats.py b/oled_stats.py index b67dc61..f2564c0 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -70,7 +70,7 @@ def get_disk_usage(): draw.text((0, 0), f"IP: {ip_address}", font=ip_font, fill="yellow") # Combine CPU and Temperature on one line - draw.text((0, 15), f"CPU: {cpu_usage}% Temp: {temperature}", font=default_font, fill="blue") + draw.text((0, 15), f"CPU:{cpu_usage}% Temp:{temperature}", font=default_font, fill="blue") # Memory Usage in GB with percentage draw.text((0, 30), f"RAM: {memory_used:.2f}/{memory_total:.2f}GB ({memory_usage_percent}%)", font=default_font, fill="blue") @@ -79,3 +79,4 @@ def get_disk_usage(): draw.text((0, 45), f"Disk: {disk_used:.2f}/{disk_total:.2f}GB ({disk_usage_percent}%)", font=default_font, fill="blue") time.sleep(1) + From 36560caac7a6d0f7ca4265bf05dc71c45c2f7d10 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:07:11 -0400 Subject: [PATCH 02/30] Update oled_stats.py --- oled_stats.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oled_stats.py b/oled_stats.py index f2564c0..bcf7db8 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -70,7 +70,7 @@ def get_disk_usage(): draw.text((0, 0), f"IP: {ip_address}", font=ip_font, fill="yellow") # Combine CPU and Temperature on one line - draw.text((0, 15), f"CPU:{cpu_usage}% Temp:{temperature}", font=default_font, fill="blue") + draw.text((0, 15), f"CPU:{cpu_usage}% TEST:{temperature}", font=default_font, fill="blue") # Memory Usage in GB with percentage draw.text((0, 30), f"RAM: {memory_used:.2f}/{memory_total:.2f}GB ({memory_usage_percent}%)", font=default_font, fill="blue") @@ -80,3 +80,4 @@ def get_disk_usage(): time.sleep(1) + From ed1a7a64bb9fd0870b14cb3b21552a32290a07b8 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:11:10 -0400 Subject: [PATCH 03/30] Update oled_stats.py --- oled_stats.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index bcf7db8..1280480 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -22,7 +22,7 @@ def display_welcome_message(): with canvas(device) as draw: - welcome_message = "Welcome to Raspi \nHome Media Center" + welcome_message = "HELLO!!!!" # Calculate text size and position to center the text text_width, text_height = draw.textbbox((0, 0), welcome_message, font=welcome_font)[2:] @@ -70,14 +70,15 @@ def get_disk_usage(): draw.text((0, 0), f"IP: {ip_address}", font=ip_font, fill="yellow") # Combine CPU and Temperature on one line - draw.text((0, 15), f"CPU:{cpu_usage}% TEST:{temperature}", font=default_font, fill="blue") + draw.text((0, 15), f"CPU:{cpu_usage}% Temp:{temperature}", font=default_font, fill="blue") # Memory Usage in GB with percentage - draw.text((0, 30), f"RAM: {memory_used:.2f}/{memory_total:.2f}GB ({memory_usage_percent}%)", font=default_font, fill="blue") + draw.text((0, 30), f"RAM: {memory_used:.2f}/{memory_total:.2f}GB", font=default_font, fill="blue") # Disk Usage in GB with percentage - draw.text((0, 45), f"Disk: {disk_used:.2f}/{disk_total:.2f}GB ({disk_usage_percent}%)", font=default_font, fill="blue") + draw.text((0, 45), f"Disk: {disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="blue") time.sleep(1) + From 2bb2807229b0abf46964a46150918cc05283ab8d Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:18:06 -0400 Subject: [PATCH 04/30] Update oled_stats.py --- oled_stats.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 1280480..2acb0cf 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -73,12 +73,13 @@ def get_disk_usage(): draw.text((0, 15), f"CPU:{cpu_usage}% Temp:{temperature}", font=default_font, fill="blue") # Memory Usage in GB with percentage - draw.text((0, 30), f"RAM: {memory_used:.2f}/{memory_total:.2f}GB", font=default_font, fill="blue") + draw.text((0, 30), f"RAM:{memory_used:.2f}/{memory_total:.2f}GB", font=default_font, fill="blue") # Disk Usage in GB with percentage - draw.text((0, 45), f"Disk: {disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="blue") + draw.text((0, 45), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="blue") time.sleep(1) + From 4a4336169235cf443c5193f8e4cadd39f015896f Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:19:35 -0400 Subject: [PATCH 05/30] Update oled_stats.py --- oled_stats.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 2acb0cf..5614ae7 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -17,12 +17,12 @@ # Load fonts default_font = ImageFont.load_default() # Small default font -ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 12) # Larger font for IP -welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 11) # Font for welcome message +ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) # Larger font for IP +welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 15) # Font for welcome message def display_welcome_message(): with canvas(device) as draw: - welcome_message = "HELLO!!!!" + welcome_message = ":D" # Calculate text size and position to center the text text_width, text_height = draw.textbbox((0, 0), welcome_message, font=welcome_font)[2:] @@ -83,3 +83,4 @@ def get_disk_usage(): + From 2506675350d478954f0d939a72591b69a59057bf Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:20:36 -0400 Subject: [PATCH 06/30] Update oled_stats.py --- oled_stats.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 5614ae7..d524501 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -17,8 +17,8 @@ # Load fonts default_font = ImageFont.load_default() # Small default font -ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) # Larger font for IP -welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 15) # Font for welcome message +ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 5) # Larger font for IP +welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 20) # Font for welcome message def display_welcome_message(): with canvas(device) as draw: @@ -84,3 +84,4 @@ def get_disk_usage(): + From a0efc686654ff303394a3a2c7b40b14d39f7303e Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:21:28 -0400 Subject: [PATCH 07/30] Update oled_stats.py --- oled_stats.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index d524501..fd9d45c 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -17,12 +17,12 @@ # Load fonts default_font = ImageFont.load_default() # Small default font -ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 5) # Larger font for IP -welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 20) # Font for welcome message +ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 8) # Larger font for IP +welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 15) # Font for welcome message def display_welcome_message(): with canvas(device) as draw: - welcome_message = ":D" + welcome_message = "Getting Info, Please Wait" # Calculate text size and position to center the text text_width, text_height = draw.textbbox((0, 0), welcome_message, font=welcome_font)[2:] @@ -85,3 +85,4 @@ def get_disk_usage(): + From 5ee43bdfc3a93522c3a31c2b66bf3d847c0a37bb Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:22:12 -0400 Subject: [PATCH 08/30] Update oled_stats.py --- oled_stats.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index fd9d45c..6ea885b 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -17,12 +17,12 @@ # Load fonts default_font = ImageFont.load_default() # Small default font -ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 8) # Larger font for IP +ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) # Larger font for IP welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 15) # Font for welcome message def display_welcome_message(): with canvas(device) as draw: - welcome_message = "Getting Info, Please Wait" + welcome_message = "Getting Info" # Calculate text size and position to center the text text_width, text_height = draw.textbbox((0, 0), welcome_message, font=welcome_font)[2:] @@ -86,3 +86,4 @@ def get_disk_usage(): + From be0727bb90248841901867cce0b2ae79795dff70 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:23:12 -0400 Subject: [PATCH 09/30] Update oled_stats.py --- oled_stats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 6ea885b..c286503 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -66,8 +66,7 @@ def get_disk_usage(): disk_usage_percent, disk_used, disk_total = get_disk_usage() with canvas(device) as draw: - # Draw IP address with larger font - draw.text((0, 0), f"IP: {ip_address}", font=ip_font, fill="yellow") + # Combine CPU and Temperature on one line draw.text((0, 15), f"CPU:{cpu_usage}% Temp:{temperature}", font=default_font, fill="blue") @@ -87,3 +86,4 @@ def get_disk_usage(): + From 916b6be2081c51fc8e7d2cd45d806c4f4838aafe Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:24:09 -0400 Subject: [PATCH 10/30] Update oled_stats.py --- oled_stats.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index c286503..9c520ad 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -22,7 +22,7 @@ def display_welcome_message(): with canvas(device) as draw: - welcome_message = "Getting Info" + welcome_message = "Getting Info..." # Calculate text size and position to center the text text_width, text_height = draw.textbbox((0, 0), welcome_message, font=welcome_font)[2:] @@ -66,7 +66,8 @@ def get_disk_usage(): disk_usage_percent, disk_used, disk_total = get_disk_usage() with canvas(device) as draw: - + # Draw IP address with larger font + draw.text((0, 0), f"Pi Stats", font=ip_font, fill="yellow") # Combine CPU and Temperature on one line draw.text((0, 15), f"CPU:{cpu_usage}% Temp:{temperature}", font=default_font, fill="blue") @@ -87,3 +88,4 @@ def get_disk_usage(): + From 520591e6384ea498dca1f221f308d01b9e609006 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:26:26 -0400 Subject: [PATCH 11/30] Update oled_stats.py --- oled_stats.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oled_stats.py b/oled_stats.py index 9c520ad..31ceb0e 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -67,7 +67,7 @@ def get_disk_usage(): with canvas(device) as draw: # Draw IP address with larger font - draw.text((0, 0), f"Pi Stats", font=ip_font, fill="yellow") + draw.text((0, 0), f"Raspberry Pi Stats:", font=ip_font, fill="yellow") # Combine CPU and Temperature on one line draw.text((0, 15), f"CPU:{cpu_usage}% Temp:{temperature}", font=default_font, fill="blue") @@ -89,3 +89,4 @@ def get_disk_usage(): + From 3db39fa829368a1f67293527fb25cd5a153087ca Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:28:39 -0400 Subject: [PATCH 12/30] Update oled_stats.py --- oled_stats.py | 95 ++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 55 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 31ceb0e..ab16641 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -1,38 +1,30 @@ -#oled_project -#author : souvik roychoudhury -#version: 4.1 -#feature: with welcome screen || it has only IP, CPU, Temp, RAM and Disk information. - import time import subprocess import psutil from luma.core.interface.serial import i2c from luma.core.render import canvas from luma.oled.device import ssd1306 -from PIL import ImageFont, ImageDraw +from PIL import ImageFont # OLED setup serial = i2c(port=1, address=0x3C) # Adjust the I2C address if needed device = ssd1306(serial, width=128, height=64) # Load fonts -default_font = ImageFont.load_default() # Small default font -ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) # Larger font for IP -welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 15) # Font for welcome message +default_font = ImageFont.load_default() +ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) +welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 15) def display_welcome_message(): with canvas(device) as draw: welcome_message = "Getting Info..." - - # Calculate text size and position to center the text - text_width, text_height = draw.textbbox((0, 0), welcome_message, font=welcome_font)[2:] + # Correct width/height calculation + x0, y0, x1, y1 = draw.textbbox((0, 0), welcome_message, font=welcome_font) + text_width = x1 - x0 + text_height = y1 - y0 text_x = (device.width - text_width) // 2 text_y = (device.height - text_height) // 2 - - # Draw the welcome message centered - draw.multiline_text((text_x, text_y), welcome_message, font=welcome_font, fill="white", align="center") - - # Display the message for 10 seconds + draw.text((text_x, text_y), welcome_message, font=welcome_font, fill="white") time.sleep(10) def get_ip_address(): @@ -40,53 +32,46 @@ def get_ip_address(): return subprocess.check_output(cmd, shell=True).decode('utf-8').strip() def get_cpu_usage(): - return psutil.cpu_percent(interval=1) + return psutil.cpu_percent(interval=0.5) def get_memory_usage(): mem = psutil.virtual_memory() return mem.percent, mem.used / (1024 * 1024 * 1024), mem.total / (1024 * 1024 * 1024) -def get_temperature(): - temp = subprocess.check_output(["vcgencmd", "measure_temp"]).decode() - return temp.replace("temp=", "").strip() +def get_temperature_f(): + """Return CPU temperature in Fahrenheit as a string like '120.3°F'.""" + try: + raw = subprocess.check_output(["vcgencmd", "measure_temp"]).decode() + # raw looks like "temp=47.8'C\n" + celsius = float(raw.split('=')[1].split("'")[0]) + fahrenheit = celsius * 9 / 5 + 32 + return f"{fahrenheit:.1f}°F" + except (FileNotFoundError, subprocess.CalledProcessError, ValueError): + return "N/A" def get_disk_usage(): disk = psutil.disk_usage('/') return disk.percent, disk.used / (1024 * 1024 * 1024), disk.total / (1024 * 1024 * 1024) -# Display the welcome message at startup +# Show welcome screen display_welcome_message() -# Main loop for displaying system stats -while True: - ip_address = get_ip_address() - cpu_usage = get_cpu_usage() - memory_usage_percent, memory_used, memory_total = get_memory_usage() - temperature = get_temperature() - disk_usage_percent, disk_used, disk_total = get_disk_usage() - - with canvas(device) as draw: - # Draw IP address with larger font - draw.text((0, 0), f"Raspberry Pi Stats:", font=ip_font, fill="yellow") - - # Combine CPU and Temperature on one line - draw.text((0, 15), f"CPU:{cpu_usage}% Temp:{temperature}", font=default_font, fill="blue") - - # Memory Usage in GB with percentage - draw.text((0, 30), f"RAM:{memory_used:.2f}/{memory_total:.2f}GB", font=default_font, fill="blue") - - # Disk Usage in GB with percentage - draw.text((0, 45), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="blue") - - time.sleep(1) - - - - - - - - - - - +try: + while True: + ip_address = get_ip_address() + cpu_usage = get_cpu_usage() + mem_percent, mem_used, mem_total = get_memory_usage() + temperature_f = get_temperature_f() + disk_percent, disk_used, disk_total = get_disk_usage() + + with canvas(device) as draw: + draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") + draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 30), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") + + time.sleep(1) + +except KeyboardInterrupt: + device.clear() From e8d53f2a5a8a14973b20f23db44f131aef6a4b44 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:31:38 -0400 Subject: [PATCH 13/30] Update oled_stats.py --- oled_stats.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index ab16641..84ce1e4 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -66,12 +66,13 @@ def get_disk_usage(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") - draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 30), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 10), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 20), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 30), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 40), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() + From 01264a8f5f10f3ce6bfd450f21e2b36921a61278 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:32:43 -0400 Subject: [PATCH 14/30] Update oled_stats.py --- oled_stats.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 84ce1e4..36279a4 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -66,13 +66,14 @@ def get_disk_usage(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") - draw.text((0, 10), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 20), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 30), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 40), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 20), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 30), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 40), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 50), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() + From 9988bdef7dbf998a325dcbd5885fa8eb0a6849c3 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:34:06 -0400 Subject: [PATCH 15/30] Update oled_stats.py --- oled_stats.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 36279a4..e59e72e 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -66,10 +66,10 @@ def get_disk_usage(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") - draw.text((0, 20), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") draw.text((0, 30), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 40), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 50), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 45), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 60), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) @@ -77,3 +77,4 @@ def get_disk_usage(): device.clear() + From bbd8a813bf6b4c7c4060b9f7a8c6539e426deaf9 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:34:54 -0400 Subject: [PATCH 16/30] Update oled_stats.py --- oled_stats.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index e59e72e..3a70b0b 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -67,9 +67,9 @@ def get_disk_usage(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 30), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 60), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) @@ -78,3 +78,4 @@ def get_disk_usage(): + From 4399a7f59377c63048a622fef465204e74a85dc0 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:36:02 -0400 Subject: [PATCH 17/30] Update oled_stats.py --- oled_stats.py | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 3a70b0b..d20b762 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -13,19 +13,6 @@ # Load fonts default_font = ImageFont.load_default() ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) -welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 15) - -def display_welcome_message(): - with canvas(device) as draw: - welcome_message = "Getting Info..." - # Correct width/height calculation - x0, y0, x1, y1 = draw.textbbox((0, 0), welcome_message, font=welcome_font) - text_width = x1 - x0 - text_height = y1 - y0 - text_x = (device.width - text_width) // 2 - text_y = (device.height - text_height) // 2 - draw.text((text_x, text_y), welcome_message, font=welcome_font, fill="white") - time.sleep(10) def get_ip_address(): cmd = "hostname -I | cut -d' ' -f1" @@ -42,7 +29,6 @@ def get_temperature_f(): """Return CPU temperature in Fahrenheit as a string like '120.3°F'.""" try: raw = subprocess.check_output(["vcgencmd", "measure_temp"]).decode() - # raw looks like "temp=47.8'C\n" celsius = float(raw.split('=')[1].split("'")[0]) fahrenheit = celsius * 9 / 5 + 32 return f"{fahrenheit:.1f}°F" @@ -53,9 +39,6 @@ def get_disk_usage(): disk = psutil.disk_usage('/') return disk.percent, disk.used / (1024 * 1024 * 1024), disk.total / (1024 * 1024 * 1024) -# Show welcome screen -display_welcome_message() - try: while True: ip_address = get_ip_address() @@ -65,17 +48,13 @@ def get_disk_usage(): disk_percent, disk_used, disk_total = get_disk_usage() with canvas(device) as draw: - draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") + draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() - - - - From 9504e1856292fed6abf128776c756e2f013ac646 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:37:07 -0400 Subject: [PATCH 18/30] Update oled_stats.py --- oled_stats.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index d20b762..349e300 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -50,11 +50,12 @@ def get_disk_usage(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 28), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 38), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 48), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() + From d0d8a5f968fe6f9401fffb7095092cbc16074084 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:37:44 -0400 Subject: [PATCH 19/30] Update oled_stats.py --- oled_stats.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 349e300..5782380 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -50,12 +50,13 @@ def get_disk_usage(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 28), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 38), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 48), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() + From 77f632007d98f46b8e73086171588587ea592d7e Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:40:03 -0400 Subject: [PATCH 20/30] Update oled_stats.py --- oled_stats.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 5782380..87bd4a2 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -1,6 +1,7 @@ import time import subprocess import psutil +import glob # NEW: for finding the fan speed file from luma.core.interface.serial import i2c from luma.core.render import canvas from luma.oled.device import ssd1306 @@ -39,6 +40,21 @@ def get_disk_usage(): disk = psutil.disk_usage('/') return disk.percent, disk.used / (1024 * 1024 * 1024), disk.total / (1024 * 1024 * 1024) +def get_fan_speed(): + """ + Return built-in Raspberry Pi 5 fan speed in RPM. + Looks for /sys/devices/platform/cooling_fan/hwmon*/fan1_input. + """ + try: + paths = glob.glob("/sys/devices/platform/cooling_fan/hwmon*/fan1_input") + if not paths: + return "N/A" + with open(paths[0], "r") as f: + rpm = int(f.read().strip()) + return f"{rpm} RPM" + except (FileNotFoundError, ValueError, PermissionError): + return "N/A" + try: while True: ip_address = get_ip_address() @@ -46,17 +62,17 @@ def get_disk_usage(): mem_percent, mem_used, mem_total = get_memory_usage() temperature_f = get_temperature_f() disk_percent, disk_used, disk_total = get_disk_usage() + fan_speed = get_fan_speed() # NEW with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") + draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() - - From 0b65d506292eb9fac5488c4bb3f62b778cd236ac Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:47:22 -0400 Subject: [PATCH 21/30] Update oled_stats.py --- oled_stats.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 87bd4a2..127f733 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -67,12 +67,13 @@ def get_fan_speed(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") - draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 26), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 37), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 48), f"Fan: {fan_speed}", font=default_font, fill="white") + draw.text((0, 59), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() + From f4dd9fdc45eaa71ea55735c15f75b073e9dd50ba Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:49:38 -0400 Subject: [PATCH 22/30] Update oled_stats.py --- oled_stats.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 127f733..ea45edb 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -67,13 +67,14 @@ def get_fan_speed(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 26), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 37), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 48), f"Fan: {fan_speed}", font=default_font, fill="white") - draw.text((0, 59), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") + draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() + From 42e3c9e4d0e6dc34884472e109a2f0cd1cd22ff9 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:50:23 -0400 Subject: [PATCH 23/30] Update oled_stats.py --- oled_stats.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index ea45edb..49afd78 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -66,11 +66,11 @@ def get_fan_speed(): with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") - draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") - draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 10), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 21), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 32), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 43), f"Fan: {fan_speed}", font=default_font, fill="white") + draw.text((0, 54), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) @@ -78,3 +78,4 @@ def get_fan_speed(): device.clear() + From 72d2ea167793c20730c48f25d4b09418db2817c9 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:51:25 -0400 Subject: [PATCH 24/30] Update oled_stats.py --- oled_stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oled_stats.py b/oled_stats.py index 49afd78..927cd55 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -65,7 +65,6 @@ def get_fan_speed(): fan_speed = get_fan_speed() # NEW with canvas(device) as draw: - draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") draw.text((0, 10), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") draw.text((0, 21), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") draw.text((0, 32), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") @@ -79,3 +78,4 @@ def get_fan_speed(): + From b4c348e2e75a36701ce6b12ca9ef9090924b7534 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 10:53:38 -0400 Subject: [PATCH 25/30] Update oled_stats.py --- oled_stats.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 927cd55..87bd4a2 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -65,17 +65,14 @@ def get_fan_speed(): fan_speed = get_fan_speed() # NEW with canvas(device) as draw: - draw.text((0, 10), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 21), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 32), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 43), f"Fan: {fan_speed}", font=default_font, fill="white") - draw.text((0, 54), f"IP: {ip_address}", font=default_font, fill="white") + draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") + draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") + draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") time.sleep(1) except KeyboardInterrupt: device.clear() - - - - From 7eee309b1feae1993f76d907c7af9427dc073663 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 11:57:21 -0400 Subject: [PATCH 26/30] Update oled_stats.py --- oled_stats.py | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/oled_stats.py b/oled_stats.py index 87bd4a2..0dca2aa 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -1,6 +1,99 @@ import time import subprocess import psutil +import glob +import signal +import sys +from luma.core.interface.serial import i2c +from luma.core.render import canvas +from luma.oled.device import ssd1306 +from PIL import ImageFont + +# OLED setup +serial = i2c(port=1, address=0x3C) # Adjust the I2C address if needed +device = ssd1306(serial, width=128, height=64) + +# Load fonts +default_font = ImageFont.load_default() +ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) + +# ---- Shutdown handler ---- +def shutdown_handler(signum, frame): + """Clear and power off OLED on shutdown/exit.""" + try: + device.clear() + device.hide() # sends 'display off' command (0xAE) + except Exception as e: + print(f"Error turning off OLED: {e}") + sys.exit(0) + +# Catch system signals (shutdown/reboot/ctrl+c) +signal.signal(signal.SIGTERM, shutdown_handler) +signal.signal(signal.SIGINT, shutdown_handler) + +# ---- System info functions ---- +def get_ip_address(): + cmd = "hostname -I | cut -d' ' -f1" + return subprocess.check_output(cmd, shell=True).decode('utf-8').strip() + +def get_cpu_usage(): + return psutil.cpu_percent(interval=0.5) + +def get_memory_usage(): + mem = psutil.virtual_memory() + return mem.percent, mem.used / (1024 * 1024 * 1024), mem.total / (1024 * 1024 * 1024) + +def get_temperature_f(): + """Return CPU temperature in Fahrenheit as a string like '120.3°F'.""" + try: + raw = subprocess.check_output(["vcgencmd", "measure_temp"]).decode() + celsius = float(raw.split('=')[1].split("'")[0]) + fahrenheit = celsius * 9 / 5 + 32 + return f"{fahrenheit:.1f}°F" + except (FileNotFoundError, subprocess.CalledProcessError, ValueError): + return "N/A" + +def get_disk_usage(): + disk = psutil.disk_usage('/') + return disk.percent, disk.used / (1024 * 1024 * 1024), disk.total / (1024 * 1024 * 1024) + +def get_fan_speed(): + """Return built-in Raspberry Pi 5 fan speed in RPM.""" + try: + paths = glob.glob("/sys/devices/platform/cooling_fan/hwmon*/fan1_input") + if not paths: + return "N/A" + with open(paths[0], "r") as f: + rpm = int(f.read().strip()) + return f"{rpm} RPM" + except (FileNotFoundError, ValueError, PermissionError): + return "N/A" + +# ---- Main loop ---- +try: + while True: + ip_address = get_ip_address() + cpu_usage = get_cpu_usage() + mem_percent, mem_used, mem_total = get_memory_usage() + temperature_f = get_temperature_f() + disk_percent, disk_used, disk_total = get_disk_usage() + fan_speed = get_fan_speed() + + with canvas(device) as draw: + draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") + draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") + draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") + + time.sleep(1) + +except KeyboardInterrupt: + shutdown_handler(None, None) +import time +import subprocess +import psutil import glob # NEW: for finding the fan speed file from luma.core.interface.serial import i2c from luma.core.render import canvas @@ -76,3 +169,4 @@ def get_fan_speed(): except KeyboardInterrupt: device.clear() + From a5b6a615a5710c0c7dc7b54c78065b84e4522c34 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 11:58:40 -0400 Subject: [PATCH 27/30] Update oled_stats.py --- oled_stats.py | 162 ++++++++++++++------------------------------------ 1 file changed, 45 insertions(+), 117 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 0dca2aa..745a6af 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -10,28 +10,23 @@ from PIL import ImageFont # OLED setup -serial = i2c(port=1, address=0x3C) # Adjust the I2C address if needed +serial = i2c(port=1, address=0x3C) device = ssd1306(serial, width=128, height=64) -# Load fonts default_font = ImageFont.load_default() ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) -# ---- Shutdown handler ---- def shutdown_handler(signum, frame): - """Clear and power off OLED on shutdown/exit.""" try: device.clear() - device.hide() # sends 'display off' command (0xAE) + device.hide() except Exception as e: print(f"Error turning off OLED: {e}") sys.exit(0) -# Catch system signals (shutdown/reboot/ctrl+c) signal.signal(signal.SIGTERM, shutdown_handler) signal.signal(signal.SIGINT, shutdown_handler) -# ---- System info functions ---- def get_ip_address(): cmd = "hostname -I | cut -d' ' -f1" return subprocess.check_output(cmd, shell=True).decode('utf-8').strip() @@ -41,132 +36,65 @@ def get_cpu_usage(): def get_memory_usage(): mem = psutil.virtual_memory() - return mem.percent, mem.used / (1024 * 1024 * 1024), mem.total / (1024 * 1024 * 1024) + return mem.percent, mem.used / (1024**3), mem.total / (1024**3) def get_temperature_f(): - """Return CPU temperature in Fahrenheit as a string like '120.3°F'.""" try: raw = subprocess.check_output(["vcgencmd", "measure_temp"]).decode() celsius = float(raw.split('=')[1].split("'")[0]) fahrenheit = celsius * 9 / 5 + 32 return f"{fahrenheit:.1f}°F" - except (FileNotFoundError, subprocess.CalledProcessError, ValueError): + except Exception: return "N/A" def get_disk_usage(): disk = psutil.disk_usage('/') - return disk.percent, disk.used / (1024 * 1024 * 1024), disk.total / (1024 * 1024 * 1024) - -def get_fan_speed(): - """Return built-in Raspberry Pi 5 fan speed in RPM.""" - try: - paths = glob.glob("/sys/devices/platform/cooling_fan/hwmon*/fan1_input") - if not paths: - return "N/A" - with open(paths[0], "r") as f: - rpm = int(f.read().strip()) - return f"{rpm} RPM" - except (FileNotFoundError, ValueError, PermissionError): - return "N/A" - -# ---- Main loop ---- -try: - while True: - ip_address = get_ip_address() - cpu_usage = get_cpu_usage() - mem_percent, mem_used, mem_total = get_memory_usage() - temperature_f = get_temperature_f() - disk_percent, disk_used, disk_total = get_disk_usage() - fan_speed = get_fan_speed() - - with canvas(device) as draw: - draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") - draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") - draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") - - time.sleep(1) - -except KeyboardInterrupt: - shutdown_handler(None, None) -import time -import subprocess -import psutil -import glob # NEW: for finding the fan speed file -from luma.core.interface.serial import i2c -from luma.core.render import canvas -from luma.oled.device import ssd1306 -from PIL import ImageFont - -# OLED setup -serial = i2c(port=1, address=0x3C) # Adjust the I2C address if needed -device = ssd1306(serial, width=128, height=64) - -# Load fonts -default_font = ImageFont.load_default() -ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) - -def get_ip_address(): - cmd = "hostname -I | cut -d' ' -f1" - return subprocess.check_output(cmd, shell=True).decode('utf-8').strip() - -def get_cpu_usage(): - return psutil.cpu_percent(interval=0.5) - -def get_memory_usage(): - mem = psutil.virtual_memory() - return mem.percent, mem.used / (1024 * 1024 * 1024), mem.total / (1024 * 1024 * 1024) - -def get_temperature_f(): - """Return CPU temperature in Fahrenheit as a string like '120.3°F'.""" - try: - raw = subprocess.check_output(["vcgencmd", "measure_temp"]).decode() - celsius = float(raw.split('=')[1].split("'")[0]) - fahrenheit = celsius * 9 / 5 + 32 - return f"{fahrenheit:.1f}°F" - except (FileNotFoundError, subprocess.CalledProcessError, ValueError): - return "N/A" - -def get_disk_usage(): - disk = psutil.disk_usage('/') - return disk.percent, disk.used / (1024 * 1024 * 1024), disk.total / (1024 * 1024 * 1024) + return disk.percent, disk.used / (1024**3), disk.total / (1024**3) def get_fan_speed(): """ - Return built-in Raspberry Pi 5 fan speed in RPM. - Looks for /sys/devices/platform/cooling_fan/hwmon*/fan1_input. + Try to read the fan1_input from cooling_fan hwmon. + Return string like "1234 RPM" or "N/A" if not readable. """ try: - paths = glob.glob("/sys/devices/platform/cooling_fan/hwmon*/fan1_input") - if not paths: + paths = glob.glob("/sys/devices/platform/cooling_fan/hwmon/*/fan1_input") + # Filter out paths that don’t exist or aren’t files + valid = [p for p in paths if os.path.isfile(p)] + if not valid: + return "N/A" + # Use the first matching file + with open(valid[0], "r") as f: + rpm = f.read().strip() + # If string is empty or not numeric, fail + if not rpm or not rpm.isdigit(): return "N/A" - with open(paths[0], "r") as f: - rpm = int(f.read().strip()) - return f"{rpm} RPM" - except (FileNotFoundError, ValueError, PermissionError): + return f"{int(rpm)} RPM" + except Exception as e: + # Optionally print debug info + # print(f"get_fan_speed error: {e}") return "N/A" -try: - while True: - ip_address = get_ip_address() - cpu_usage = get_cpu_usage() - mem_percent, mem_used, mem_total = get_memory_usage() - temperature_f = get_temperature_f() - disk_percent, disk_used, disk_total = get_disk_usage() - fan_speed = get_fan_speed() # NEW - - with canvas(device) as draw: - draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") - draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") - draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") - - time.sleep(1) - -except KeyboardInterrupt: - device.clear() - +def main_loop(): + try: + while True: + ip_address = get_ip_address() + cpu_usage = get_cpu_usage() + mem_percent, mem_used, mem_total = get_memory_usage() + temperature_f = get_temperature_f() + disk_percent, disk_used, disk_total = get_disk_usage() + fan_speed = get_fan_speed() + + with canvas(device) as draw: + draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") + draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") + draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") + + time.sleep(1) + except KeyboardInterrupt: + shutdown_handler(None, None) + +if __name__ == "__main__": + main_loop() From 0471383b12cb3a554db954ac978f1fb32dad086e Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 12:19:57 -0400 Subject: [PATCH 28/30] Update oled_stats.py --- oled_stats.py | 78 +++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index 745a6af..e204bfd 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -4,29 +4,35 @@ import glob import signal import sys +import os from luma.core.interface.serial import i2c from luma.core.render import canvas from luma.oled.device import ssd1306 from PIL import ImageFont # OLED setup -serial = i2c(port=1, address=0x3C) +serial = i2c(port=1, address=0x3C) # Adjust the I2C address if needed device = ssd1306(serial, width=128, height=64) +# Load fonts default_font = ImageFont.load_default() ip_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10) +# ---- Shutdown handler ---- def shutdown_handler(signum, frame): + """Clear and power off OLED on shutdown/exit.""" try: device.clear() - device.hide() + device.hide() # sends 'display off' command (0xAE) except Exception as e: print(f"Error turning off OLED: {e}") sys.exit(0) +# Catch system signals (shutdown/reboot/ctrl+c) signal.signal(signal.SIGTERM, shutdown_handler) signal.signal(signal.SIGINT, shutdown_handler) +# ---- System info functions ---- def get_ip_address(): cmd = "hostname -I | cut -d' ' -f1" return subprocess.check_output(cmd, shell=True).decode('utf-8').strip() @@ -39,6 +45,7 @@ def get_memory_usage(): return mem.percent, mem.used / (1024**3), mem.total / (1024**3) def get_temperature_f(): + """Return CPU temperature in Fahrenheit as a string like '120.3°F'.""" try: raw = subprocess.check_output(["vcgencmd", "measure_temp"]).decode() celsius = float(raw.split('=')[1].split("'")[0]) @@ -58,43 +65,36 @@ def get_fan_speed(): """ try: paths = glob.glob("/sys/devices/platform/cooling_fan/hwmon/*/fan1_input") - # Filter out paths that don’t exist or aren’t files - valid = [p for p in paths if os.path.isfile(p)] - if not valid: + if not paths: return "N/A" - # Use the first matching file - with open(valid[0], "r") as f: - rpm = f.read().strip() - # If string is empty or not numeric, fail - if not rpm or not rpm.isdigit(): - return "N/A" - return f"{int(rpm)} RPM" - except Exception as e: - # Optionally print debug info - # print(f"get_fan_speed error: {e}") + + with open(paths[0], "r") as f: + rpm_str = f.read().strip() + + rpm = int(rpm_str) # convert string to int + return f"{rpm} RPM" + except Exception: return "N/A" -def main_loop(): - try: - while True: - ip_address = get_ip_address() - cpu_usage = get_cpu_usage() - mem_percent, mem_used, mem_total = get_memory_usage() - temperature_f = get_temperature_f() - disk_percent, disk_used, disk_total = get_disk_usage() - fan_speed = get_fan_speed() - - with canvas(device) as draw: - draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") - draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") - draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") - draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") - draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") - - time.sleep(1) - except KeyboardInterrupt: - shutdown_handler(None, None) - -if __name__ == "__main__": - main_loop() +# ---- Main loop ---- +try: + while True: + ip_address = get_ip_address() + cpu_usage = get_cpu_usage() + mem_percent, mem_used, mem_total = get_memory_usage() + temperature_f = get_temperature_f() + disk_percent, disk_used, disk_total = get_disk_usage() + fan_speed = get_fan_speed() + + with canvas(device) as draw: + draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") + draw.text((0, 15), f"CPU:{cpu_usage:.1f}% Temp:{temperature_f}", font=default_font, fill="white") + draw.text((0, 25), f"RAM:{mem_used:.2f}/{mem_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 35), f"Disk:{disk_used:.2f}/{disk_total:.2f}GB", font=default_font, fill="white") + draw.text((0, 45), f"Fan: {fan_speed}", font=default_font, fill="white") + draw.text((0, 55), f"IP: {ip_address}", font=default_font, fill="white") + + time.sleep(1) + +except KeyboardInterrupt: + shutdown_handler(None, None) From 013fb952b816882ccf99bbb5c49d9d246fd74193 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 12:28:34 -0400 Subject: [PATCH 29/30] Update oled_stats.py --- oled_stats.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/oled_stats.py b/oled_stats.py index e204bfd..4d0b216 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -58,10 +58,10 @@ def get_disk_usage(): disk = psutil.disk_usage('/') return disk.percent, disk.used / (1024**3), disk.total / (1024**3) -def get_fan_speed(): +def get_fan_speed_with_percent(max_rpm=4200): """ - Try to read the fan1_input from cooling_fan hwmon. - Return string like "1234 RPM" or "N/A" if not readable. + Returns a string like '2450 RPM (58%)'. + `max_rpm` should be set to your fan's max RPM (consult spec, e.g., 4200 RPM). """ try: paths = glob.glob("/sys/devices/platform/cooling_fan/hwmon/*/fan1_input") @@ -70,9 +70,10 @@ def get_fan_speed(): with open(paths[0], "r") as f: rpm_str = f.read().strip() + rpm = int(rpm_str) - rpm = int(rpm_str) # convert string to int - return f"{rpm} RPM" + percent = min(int(rpm / max_rpm * 100), 100) + return f"{rpm} RPM ({percent}%)" except Exception: return "N/A" @@ -84,7 +85,7 @@ def get_fan_speed(): mem_percent, mem_used, mem_total = get_memory_usage() temperature_f = get_temperature_f() disk_percent, disk_used, disk_total = get_disk_usage() - fan_speed = get_fan_speed() + fan_speed = get_fan_speed_with_percent() with canvas(device) as draw: draw.text((0, 0), "Raspberry Pi Stats:", font=ip_font, fill="white") From b8b2ad1f670dc6815c8b0befbb0f2b21d55da639 Mon Sep 17 00:00:00 2001 From: lwils-tech Date: Wed, 24 Sep 2025 12:33:35 -0400 Subject: [PATCH 30/30] Update oled_stats.py --- oled_stats.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oled_stats.py b/oled_stats.py index 4d0b216..d49a46c 100644 --- a/oled_stats.py +++ b/oled_stats.py @@ -58,7 +58,7 @@ def get_disk_usage(): disk = psutil.disk_usage('/') return disk.percent, disk.used / (1024**3), disk.total / (1024**3) -def get_fan_speed_with_percent(max_rpm=4200): +def get_fan_speed_with_percent(max_rpm=6500): """ Returns a string like '2450 RPM (58%)'. `max_rpm` should be set to your fan's max RPM (consult spec, e.g., 4200 RPM). @@ -99,3 +99,4 @@ def get_fan_speed_with_percent(max_rpm=4200): except KeyboardInterrupt: shutdown_handler(None, None) +