Last active
August 21, 2025 08:52
-
-
Save Oneiroi/edf4e301a3fe8971d69c5b39228b170b to your computer and use it in GitHub Desktop.
FIXED 20250820 old.py - Yahboom Jetson Nano Case Compatible with Jetson Orin Nano SUPER Orin NX SUPER Protective Case Xaver NX TX2-NX with RGB Fan, Antennas, OLED Display
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # coding=utf-8 | |
| import time | |
| import os | |
| import sys | |
| import subprocess | |
| from luma.core.interface.serial import i2c | |
| from luma.oled.device import ssd1306 | |
| from PIL import Image, ImageDraw, ImageFont | |
| # Jetson-compatible OLED class for SSD1306 128x32 display | |
| class OLED: | |
| def __init__(self, i2c_bus=7, i2c_address=0x3C, clear=False, debug=False): | |
| self.__debug = debug | |
| self.__i2c_bus = i2c_bus # Use bus 7 for Jetson | |
| self.__i2c_address = i2c_address # OLED at 0x3C | |
| self.__clear = clear | |
| self.__top = -2 | |
| self.__x = 0 | |
| self.__total_last = 0 | |
| self.__idle_last = 0 | |
| self.__str_CPU = "CPU:0%" | |
| self.__WIDTH = 128 | |
| self.__HEIGHT = 32 | |
| self.__image = Image.new('1', (self.__WIDTH, self.__HEIGHT)) | |
| self.__draw = ImageDraw.Draw(self.__image) | |
| self.__font = ImageFont.load_default() | |
| self.__device = None | |
| def __del__(self): | |
| self.clear(True) | |
| if self.__debug: | |
| print("---OLED-DEL---") | |
| # Initialize OLED using luma.oled for Jetson compatibility | |
| def begin(self): | |
| try: | |
| # Create I2C interface for Jetson | |
| serial = i2c(port=self.__i2c_bus, address=self.__i2c_address) | |
| self.__device = ssd1306(serial, width=128, height=32) | |
| # Clear display | |
| self.__device.clear() | |
| if self.__debug: | |
| print("---OLED begin ok!---") | |
| return True | |
| except Exception as e: | |
| if self.__debug: | |
| print(f"---OLED initialization failed: {e}---") | |
| return False | |
| # Clear the display | |
| def clear(self, refresh=False): | |
| self.__draw.rectangle( | |
| (0, 0, self.__WIDTH, self.__HEIGHT), outline=0, fill=0) | |
| if refresh and self.__device: | |
| try: | |
| self.refresh() | |
| return True | |
| except: | |
| return False | |
| # Add text to display buffer | |
| def add_text(self, start_x, start_y, text, refresh=False): | |
| if start_x > self.__WIDTH or start_x < 0 or start_y < 0 or start_y > self.__HEIGHT: | |
| if self.__debug: | |
| print("oled text: x, y input error!") | |
| return | |
| x = int(start_x + self.__x) | |
| y = int(start_y + self.__top) | |
| self.__draw.text((x, y), str(text), font=self.__font, fill=255) | |
| if refresh: | |
| self.refresh() | |
| # Add line of text (4 lines max for 32px height) | |
| def add_line(self, text, line=1, refresh=False): | |
| if line < 1 or line > 4: | |
| if self.__debug: | |
| print("oled line input error!") | |
| return | |
| y = int(8 * (line - 1)) | |
| self.add_text(0, y, text, refresh) | |
| # Display the image buffer on OLED | |
| def refresh(self): | |
| if self.__device: | |
| self.__device.display(self.__image) | |
| # Read CPU usage (same as original) | |
| def getCPULoadRate(self, index): | |
| count = 10 | |
| if index == 0: | |
| f1 = os.popen("cat /proc/stat", 'r') | |
| stat1 = f1.readline() | |
| data_1 = [] | |
| for i in range(count): | |
| data_1.append(int(stat1.split(' ')[i+2])) | |
| self.__total_last = data_1[0]+data_1[1]+data_1[2]+data_1[3] + \ | |
| data_1[4]+data_1[5]+data_1[6]+data_1[7]+data_1[8]+data_1[9] | |
| self.__idle_last = data_1[3] | |
| elif index == 4: | |
| f2 = os.popen("cat /proc/stat", 'r') | |
| stat2 = f2.readline() | |
| data_2 = [] | |
| for i in range(count): | |
| data_2.append(int(stat2.split(' ')[i+2])) | |
| total_now = data_2[0]+data_2[1]+data_2[2]+data_2[3] + \ | |
| data_2[4]+data_2[5]+data_2[6]+data_2[7]+data_2[8]+data_2[9] | |
| idle_now = data_2[3] | |
| total = int(total_now - self.__total_last) | |
| idle = int(idle_now - self.__idle_last) | |
| usage = int(total - idle) | |
| usageRate = int(float(usage / total) * 100) | |
| self.__str_CPU = "CPU:" + str(usageRate) + "%" | |
| self.__total_last = 0 | |
| self.__idle_last = 0 | |
| return self.__str_CPU | |
| # Get system time | |
| def getSystemTime(self): | |
| cmd = "date +%H:%M:%S" | |
| date_time = subprocess.check_output(cmd, shell=True) | |
| str_Time = str(date_time).lstrip('b\'') | |
| str_Time = str_Time.rstrip('\\n\'') | |
| return str_Time | |
| # Get RAM usage | |
| def getUsagedRAM(self): | |
| cmd = "free | awk 'NR==2{printf \"RAM:%2d%% -> %.1fGB \", 100*($2-$7)/$2, ($2/1048576.0)}'" | |
| FreeRam = subprocess.check_output(cmd, shell=True) | |
| str_FreeRam = str(FreeRam).lstrip('b\'') | |
| str_FreeRam = str_FreeRam.rstrip('\'') | |
| return str_FreeRam | |
| # Get disk usage | |
| def getUsagedDisk(self): | |
| cmd = "df -h | awk '$NF==\"/\"{printf \"SD: %s -> %.1fGB\", $5, $2}'" | |
| Disk = subprocess.check_output(cmd, shell=True) | |
| str_Disk = str(Disk).lstrip('b\'') | |
| str_Disk = str_Disk.rstrip('\'') | |
| return str_Disk | |
| # Get local IP - Auto-detect interface for Jetson | |
| def getLocalIP(self): | |
| try: | |
| # Use ip command to find active interface with IP | |
| cmd = "ip route get 8.8.8.8 | grep -oP 'src \\K\\S+'" | |
| ip = os.popen(cmd).read().strip() | |
| if ip and len(ip) <= 15: | |
| return ip | |
| except: | |
| pass | |
| # Fallback: check common Jetson interface names | |
| interfaces = ['enp*', 'eth*', 'wlp*', 'wlan*'] | |
| for iface_pattern in interfaces: | |
| try: | |
| cmd = f"ip addr show | grep -A2 '{iface_pattern[:-1]}' | grep 'inet ' | head -1 | awk '{{print $2}}' | cut -d'/' -f1" | |
| ip = os.popen(cmd).read().strip() | |
| if ip and len(ip) <= 15 and not ip.startswith('127.'): | |
| return ip | |
| except: | |
| continue | |
| return '<UNKNOWN>' # Your known IP as fallback | |
| # Main display loop | |
| def main_program(self): | |
| try: | |
| cpu_index = 0 | |
| state = self.begin() | |
| while state: | |
| self.clear() | |
| if self.__clear: | |
| self.refresh() | |
| return True | |
| str_CPU = self.getCPULoadRate(cpu_index) | |
| str_Time = self.getSystemTime() | |
| if cpu_index == 0: | |
| str_FreeRAM = self.getUsagedRAM() | |
| str_Disk = self.getUsagedDisk() | |
| str_IP = "IP:" + self.getLocalIP() | |
| self.add_text(0, 0, str_CPU) | |
| self.add_text(50, 0, str_Time) | |
| self.add_line(str_FreeRAM, 2) | |
| self.add_line(str_Disk, 3) | |
| self.add_line(str_IP, 4) | |
| self.refresh() | |
| cpu_index = cpu_index + 1 | |
| if cpu_index >= 5: | |
| cpu_index = 0 | |
| time.sleep(.1) | |
| return False | |
| except Exception as e: | |
| if self.__debug: | |
| print(f"!!!---OLED refresh error: {e}---!!!") | |
| return False | |
| # Fan/RGB shutdown removed - thermal management should be independent | |
| # def close_rgb_fan(): | |
| # try: | |
| # import smbus | |
| # bus = smbus.SMBus(7) | |
| # bus.write_byte_data(0x0E, 0x08, 0) # Turn off fan | |
| # time.sleep(.01) | |
| # bus.write_byte_data(0x0E, 0x04, 0) # Turn off RGB | |
| # except: | |
| # pass | |
| if __name__ == "__main__": | |
| try: | |
| oled_clear = False | |
| oled_debug = False | |
| state = False | |
| if len(sys.argv) > 1: | |
| if str(sys.argv[1]) == "clear": | |
| oled_clear = True | |
| elif str(sys.argv[1]) == "debug": | |
| oled_debug = True | |
| # Use I2C bus 7 for Jetson | |
| oled = OLED(i2c_bus=7, clear=oled_clear, debug=oled_debug) | |
| try: | |
| import smbus | |
| bus = smbus.SMBus(7) # Use bus 7 for Jetson | |
| if not oled_clear: | |
| start = 1 # Turn on fan | |
| bus.write_byte_data(0x0E, 0x08, start) | |
| time.sleep(.05) | |
| effect = 3 # RGB effect 1-5 | |
| bus.write_byte_data(0x0E, 0x04, effect) | |
| time.sleep(.05) | |
| except: | |
| pass | |
| while True: | |
| state = oled.main_program() | |
| oled.clear(True) | |
| if state: | |
| del oled | |
| print("---OLED CLEARED!---") | |
| break | |
| time.sleep(1) | |
| except KeyboardInterrupt: | |
| del oled | |
| print("---Program closed!---") |
Author
Oneiroi
commented
Aug 20, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment