Skip to content
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1617441
Update oled_stats.py
lwils-tech Sep 24, 2025
6efd54a
Merge pull request #1 from lwils-tech/lwils-tech-patch-1
lwils-tech Sep 24, 2025
36560ca
Update oled_stats.py
lwils-tech Sep 24, 2025
ed1a7a6
Update oled_stats.py
lwils-tech Sep 24, 2025
2bb2807
Update oled_stats.py
lwils-tech Sep 24, 2025
4a43361
Update oled_stats.py
lwils-tech Sep 24, 2025
2506675
Update oled_stats.py
lwils-tech Sep 24, 2025
a0efc68
Update oled_stats.py
lwils-tech Sep 24, 2025
5ee43bd
Update oled_stats.py
lwils-tech Sep 24, 2025
be0727b
Update oled_stats.py
lwils-tech Sep 24, 2025
916b6be
Update oled_stats.py
lwils-tech Sep 24, 2025
520591e
Update oled_stats.py
lwils-tech Sep 24, 2025
3db39fa
Update oled_stats.py
lwils-tech Sep 24, 2025
e8d53f2
Update oled_stats.py
lwils-tech Sep 24, 2025
01264a8
Update oled_stats.py
lwils-tech Sep 24, 2025
9988bde
Update oled_stats.py
lwils-tech Sep 24, 2025
bbd8a81
Update oled_stats.py
lwils-tech Sep 24, 2025
4399a7f
Update oled_stats.py
lwils-tech Sep 24, 2025
9504e18
Update oled_stats.py
lwils-tech Sep 24, 2025
d0d8a5f
Update oled_stats.py
lwils-tech Sep 24, 2025
77f6320
Update oled_stats.py
lwils-tech Sep 24, 2025
0b65d50
Update oled_stats.py
lwils-tech Sep 24, 2025
f4dd9fd
Update oled_stats.py
lwils-tech Sep 24, 2025
42e3c9e
Update oled_stats.py
lwils-tech Sep 24, 2025
72d2ea1
Update oled_stats.py
lwils-tech Sep 24, 2025
b4c348e
Update oled_stats.py
lwils-tech Sep 24, 2025
7eee309
Update oled_stats.py
lwils-tech Sep 24, 2025
a5b6a61
Update oled_stats.py
lwils-tech Sep 24, 2025
0471383
Update oled_stats.py
lwils-tech Sep 24, 2025
013fb95
Update oled_stats.py
lwils-tech Sep 24, 2025
b8b2ad1
Update oled_stats.py
lwils-tech Sep 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 77 additions & 56 deletions oled_stats.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,102 @@
#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
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, 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", 12) # Larger font for IP
welcome_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 11) # Font for welcome message

def display_welcome_message():
with canvas(device) as draw:
welcome_message = "Welcome to Raspi \nHome Media Center"

# Calculate text size and position to center the text
text_width, text_height = draw.textbbox((0, 0), welcome_message, font=welcome_font)[2:]
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
time.sleep(10)
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=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)
return mem.percent, mem.used / (1024**3), mem.total / (1024**3)

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()
celsius = float(raw.split('=')[1].split("'")[0])
fahrenheit = celsius * 9 / 5 + 32
return f"{fahrenheit:.1f}°F"
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)

# Display the welcome message at startup
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"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")

# 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")

# 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")

time.sleep(1)
return disk.percent, disk.used / (1024**3), disk.total / (1024**3)

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).
"""
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_str = f.read().strip()
rpm = int(rpm_str)

percent = min(int(rpm / max_rpm * 100), 100)
return f"{rpm} RPM ({percent}%)"
except Exception:
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_percent()

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)