Skip to content

Instantly share code, notes, and snippets.

@filbot
Created March 30, 2025 20:11
Show Gist options
  • Select an option

  • Save filbot/0e98902e0be5b642649541b9df85aaa3 to your computer and use it in GitHub Desktop.

Select an option

Save filbot/0e98902e0be5b642649541b9df85aaa3 to your computer and use it in GitHub Desktop.
Python script to display PiAware data on an LCD
#!/usr/bin/env python3
import time
import json
import os
from RPLCD.i2c import CharLCD
def get_cpu_temperature():
"""Reads CPU temperature in °C from the system file."""
try:
with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
temp = float(f.read().strip()) / 1000.0
return temp
except Exception as e:
print("Error reading CPU temperature:", e)
return None
def get_uptime():
"""Reads uptime from /proc/uptime and returns a string in HH:MM:SS format."""
try:
with open("/proc/uptime", "r") as f:
uptime_seconds = float(f.read().split()[0])
hours = int(uptime_seconds // 3600)
minutes = int((uptime_seconds % 3600) // 60)
seconds = int(uptime_seconds % 60)
return f"{hours:02}:{minutes:02}:{seconds:02}"
except Exception as e:
print("Error reading uptime:", e)
return "N/A"
def get_aircraft_messages():
"""
Reads the aircraft.json file to get the cumulative number of ADS‑B messages.
Returns an integer count or None on failure.
"""
path = "/run/dump1090-fa/aircraft.json"
try:
with open(path, "r") as f:
data = json.load(f)
return int(data.get("messages", 0))
except Exception as e:
print("Error reading aircraft messages:", e)
return None
def update_row(lcd, row, new_str, prev_str):
"""
Updates only the characters that have changed in a given row.
Always iterates over 20 columns.
"""
for col in range(20):
new_char = new_str[col] if col < len(new_str) else " "
prev_char = prev_str[col] if col < len(prev_str) else " "
if new_char != prev_char:
lcd.cursor_pos = (row, col)
lcd.write_string(new_char)
def format_line(label, value):
"""
Returns a 20-character string with the label left-aligned
and the value right-aligned.
"""
remaining = 20 - len(label)
line = f"{label}{value:>{remaining}}"
return line[:20]
def main():
# Initialize the LCD: adjust I2C address if needed (commonly 0x27).
lcd = CharLCD('PCF8574', 0x27, port=1, cols=20, rows=4)
lcd.clear()
# We'll store the last displayed lines to avoid rewriting unchanged characters.
prev_lines = [" " * 20 for _ in range(4)]
# Get initial ADS‑B message count.
prev_messages = get_aircraft_messages()
if prev_messages is None:
prev_messages = 0
# Variable to store peak ADS‑B rate observed.
peak_adsb_rate = 0
while True:
cpu_temp = get_cpu_temperature()
uptime_str = get_uptime()
current_messages = get_aircraft_messages()
if current_messages is None:
current_messages = prev_messages
# Calculate the current ADS‑B message rate (messages per second).
current_adsb_rate = current_messages - prev_messages
prev_messages = current_messages
# Update the peak if needed.
if current_adsb_rate > peak_adsb_rate:
peak_adsb_rate = current_adsb_rate
# Build each line with a label on the left and value on the right.
# New order remains as: Row0 = Current ADS-B, Row1 = Peak ADS-B,
# Row2 = CPU TEMP, Row3 = UPTIME.
adsb_line = format_line("ADS-B:", f"{current_adsb_rate:>3} msg/s")
peak_line = format_line("PEAK:", f"{peak_adsb_rate:>3} msg/s")
cpu_line = format_line("CPU TEMP:", f"{cpu_temp:.1f}C" if cpu_temp is not None else "N/A")
uptime_line = format_line("UPTIME:", uptime_str)
new_lines = [
adsb_line.ljust(20)[:20],
peak_line.ljust(20)[:20],
cpu_line.ljust(20)[:20],
uptime_line.ljust(20)[:20]
]
# Update only changed characters per row.
for row in range(4):
if new_lines[row] != prev_lines[row]:
update_row(lcd, row, new_lines[row], prev_lines[row])
prev_lines[row] = new_lines[row]
time.sleep(1)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment