New layout: HDD top-right, Out/In separate lines with 5x8
This commit is contained in:
90
matrix.py
90
matrix.py
@@ -1,14 +1,13 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Matrix64 LED Display - Main Entry Point
|
Matrix64 LED Display
|
||||||
|
|
||||||
Displays Home Assistant and Netdata data on a 64x64 LED matrix.
|
Layout:
|
||||||
|
[Weather 24x24] [HDD temps]
|
||||||
Layout (Option A - Vertical Stack):
|
[HDD temps]
|
||||||
[Weather 24x24] [Out 21.5° 65%]
|
12:37:25
|
||||||
[In 22.3° 58%]
|
Out 21.5° 65%
|
||||||
[12:31:05 centered]
|
In 22.3° 58%
|
||||||
[HDD temps corner]
|
|
||||||
"""
|
"""
|
||||||
from samplebase import SampleBase
|
from samplebase import SampleBase
|
||||||
from rgbmatrix import graphics
|
from rgbmatrix import graphics
|
||||||
@@ -27,17 +26,17 @@ from netdata import get_hdd_temps
|
|||||||
def format_temp(value):
|
def format_temp(value):
|
||||||
"""Format temperature to one decimal place."""
|
"""Format temperature to one decimal place."""
|
||||||
try:
|
try:
|
||||||
return f"{float(value):.1f}"
|
return f"{float(value):.1f}°"
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
return "?"
|
return "?°"
|
||||||
|
|
||||||
|
|
||||||
def format_humidity(value):
|
def format_humidity(value):
|
||||||
"""Format humidity as integer percentage."""
|
"""Format humidity as integer percentage."""
|
||||||
try:
|
try:
|
||||||
return f"{int(float(value))}"
|
return f"{int(float(value))}%"
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
return "?"
|
return "?%"
|
||||||
|
|
||||||
|
|
||||||
def get_temperature_color(temp):
|
def get_temperature_color(temp):
|
||||||
@@ -59,8 +58,6 @@ def get_temperature_color(temp):
|
|||||||
|
|
||||||
|
|
||||||
class Matrix64Display(SampleBase):
|
class Matrix64Display(SampleBase):
|
||||||
"""Main display class for the LED matrix."""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(Matrix64Display, self).__init__(*args, **kwargs)
|
super(Matrix64Display, self).__init__(*args, **kwargs)
|
||||||
self.parser.add_argument("-t", "--text", help="Text", default="")
|
self.parser.add_argument("-t", "--text", help="Text", default="")
|
||||||
@@ -73,7 +70,6 @@ class Matrix64Display(SampleBase):
|
|||||||
self.hdd_temps = None
|
self.hdd_temps = None
|
||||||
|
|
||||||
def update_data(self):
|
def update_data(self):
|
||||||
"""Fetch all data from APIs."""
|
|
||||||
try:
|
try:
|
||||||
weather = get_weather()
|
weather = get_weather()
|
||||||
if weather.get("temperature") is not None:
|
if weather.get("temperature") is not None:
|
||||||
@@ -89,7 +85,6 @@ class Matrix64Display(SampleBase):
|
|||||||
print(f"Error updating data: {e}")
|
print(f"Error updating data: {e}")
|
||||||
|
|
||||||
def update_brightness(self):
|
def update_brightness(self):
|
||||||
"""Update LED matrix brightness."""
|
|
||||||
try:
|
try:
|
||||||
brightness = get_brightness()
|
brightness = get_brightness()
|
||||||
if brightness:
|
if brightness:
|
||||||
@@ -98,14 +93,12 @@ class Matrix64Display(SampleBase):
|
|||||||
self.matrix.brightness = 5
|
self.matrix.brightness = 5
|
||||||
|
|
||||||
def update_hdd_temps(self):
|
def update_hdd_temps(self):
|
||||||
"""Update HDD temperatures."""
|
|
||||||
self.hdd_temps = get_hdd_temps()
|
self.hdd_temps = get_hdd_temps()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Main display loop."""
|
|
||||||
canvas = self.matrix.CreateFrameCanvas()
|
canvas = self.matrix.CreateFrameCanvas()
|
||||||
|
|
||||||
# Load fonts
|
# Fonts
|
||||||
font_dir = "/home/pi/rpi-rgb-led-matrix/fonts"
|
font_dir = "/home/pi/rpi-rgb-led-matrix/fonts"
|
||||||
time_font = graphics.Font()
|
time_font = graphics.Font()
|
||||||
time_font.LoadFont(f"{font_dir}/7x13.bdf")
|
time_font.LoadFont(f"{font_dir}/7x13.bdf")
|
||||||
@@ -117,10 +110,8 @@ class Matrix64Display(SampleBase):
|
|||||||
# Colors
|
# Colors
|
||||||
time_color = graphics.Color(30, 90, 220)
|
time_color = graphics.Color(30, 90, 220)
|
||||||
humidity_color = graphics.Color(80, 160, 255)
|
humidity_color = graphics.Color(80, 160, 255)
|
||||||
hdd_color = graphics.Color(60, 60, 60)
|
hdd_color = graphics.Color(80, 80, 80)
|
||||||
label_color = graphics.Color(100, 100, 100)
|
label_color = graphics.Color(120, 120, 120)
|
||||||
degree_color = graphics.Color(150, 150, 150)
|
|
||||||
percent_color = graphics.Color(100, 140, 180)
|
|
||||||
|
|
||||||
# Initial fetch
|
# Initial fetch
|
||||||
self.update_brightness()
|
self.update_brightness()
|
||||||
@@ -143,40 +134,37 @@ class Matrix64Display(SampleBase):
|
|||||||
# === Weather Icon (top-left, 24x24) ===
|
# === Weather Icon (top-left, 24x24) ===
|
||||||
draw_weather_icon(canvas, 0, 0, self.weather_desc)
|
draw_weather_icon(canvas, 0, 0, self.weather_desc)
|
||||||
|
|
||||||
# === Row 1: Outdoor - "Out" label + temp + humidity ===
|
# === HDD Temps (top-right, next to weather icon) ===
|
||||||
graphics.DrawText(canvas, small_font, 26, 6, label_color, "Out")
|
|
||||||
if self.temperature is not None:
|
|
||||||
temp_str = format_temp(self.temperature)
|
|
||||||
temp_color = get_temperature_color(self.temperature)
|
|
||||||
graphics.DrawText(canvas, small_font, 40, 6, temp_color, temp_str)
|
|
||||||
if self.humidity is not None:
|
|
||||||
hum_str = format_humidity(self.humidity)
|
|
||||||
graphics.DrawText(canvas, small_font, 55, 6, humidity_color, hum_str)
|
|
||||||
|
|
||||||
# === Row 2: Indoor - "In" label + temp + humidity ===
|
|
||||||
graphics.DrawText(canvas, small_font, 26, 14, label_color, "In")
|
|
||||||
if self.interior_temperature is not None:
|
|
||||||
temp_str = format_temp(self.interior_temperature)
|
|
||||||
temp_color = get_temperature_color(self.interior_temperature)
|
|
||||||
graphics.DrawText(canvas, small_font, 40, 14, temp_color, temp_str)
|
|
||||||
if self.interior_humidity is not None:
|
|
||||||
hum_str = format_humidity(self.interior_humidity)
|
|
||||||
graphics.DrawText(canvas, small_font, 55, 14, humidity_color, hum_str)
|
|
||||||
|
|
||||||
# === Time Display (centered, y=38) ===
|
|
||||||
time_x = (64 - len(time_str) * 7) // 2
|
|
||||||
graphics.DrawText(canvas, time_font, time_x, 38, time_color, time_str)
|
|
||||||
|
|
||||||
# === HDD Temps (bottom-right corner) ===
|
|
||||||
if self.hdd_temps and len(self.hdd_temps) > 1:
|
if self.hdd_temps and len(self.hdd_temps) > 1:
|
||||||
# Compact: show all temps in 2 rows, right-aligned
|
|
||||||
temps = [str(int(t[0])) for t in self.hdd_temps[1:] if t]
|
temps = [str(int(t[0])) for t in self.hdd_temps[1:] if t]
|
||||||
if len(temps) >= 3:
|
if len(temps) >= 3:
|
||||||
row1 = " ".join(temps[:3])
|
row1 = " ".join(temps[:3])
|
||||||
graphics.DrawText(canvas, small_font, 40, 52, hdd_color, row1)
|
graphics.DrawText(canvas, small_font, 28, 8, hdd_color, row1)
|
||||||
if len(temps) > 3:
|
if len(temps) > 3:
|
||||||
row2 = " ".join(temps[3:6])
|
row2 = " ".join(temps[3:6])
|
||||||
graphics.DrawText(canvas, small_font, 40, 60, hdd_color, row2)
|
graphics.DrawText(canvas, small_font, 28, 16, hdd_color, row2)
|
||||||
|
|
||||||
|
# === Clock (centered, y=32) ===
|
||||||
|
time_x = (64 - len(time_str) * 7) // 2
|
||||||
|
graphics.DrawText(canvas, time_font, time_x, 32, time_color, time_str)
|
||||||
|
|
||||||
|
# === Outdoor: Out + temp + humidity (y=50, 5x8 font) ===
|
||||||
|
graphics.DrawText(canvas, data_font, 0, 50, label_color, "Out")
|
||||||
|
if self.temperature is not None:
|
||||||
|
temp_str = format_temp(self.temperature)
|
||||||
|
temp_color = get_temperature_color(self.temperature)
|
||||||
|
graphics.DrawText(canvas, data_font, 20, 50, temp_color, temp_str)
|
||||||
|
if self.humidity is not None:
|
||||||
|
graphics.DrawText(canvas, data_font, 48, 50, humidity_color, format_humidity(self.humidity))
|
||||||
|
|
||||||
|
# === Indoor: In + temp + humidity (y=60, 5x8 font) ===
|
||||||
|
graphics.DrawText(canvas, data_font, 0, 60, label_color, "In")
|
||||||
|
if self.interior_temperature is not None:
|
||||||
|
temp_str = format_temp(self.interior_temperature)
|
||||||
|
temp_color = get_temperature_color(self.interior_temperature)
|
||||||
|
graphics.DrawText(canvas, data_font, 20, 60, temp_color, temp_str)
|
||||||
|
if self.interior_humidity is not None:
|
||||||
|
graphics.DrawText(canvas, data_font, 48, 60, humidity_color, format_humidity(self.interior_humidity))
|
||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
canvas = self.matrix.SwapOnVSync(canvas)
|
canvas = self.matrix.SwapOnVSync(canvas)
|
||||||
|
|||||||
Reference in New Issue
Block a user