#!/usr/bin/env python3 """ Matrix64 LED Display Layout: [Weather 24x24] [HDD temps] [HDD temps] 12:37:25 Out 21.5° 65% In 22.3° 58% """ from samplebase import SampleBase from rgbmatrix import graphics import time import datetime from config import LED_ROWS, LED_COLS from weather_icons import draw_weather_icon from home_assistant import ( get_weather, get_weather_description, get_interior_weather, get_brightness ) from netdata import get_hdd_temps def format_temp(value): """Format temperature to one decimal place.""" try: return f"{float(value):.1f}°" except (ValueError, TypeError): return "?°" def format_humidity(value): """Format humidity as integer percentage.""" try: return f"{int(float(value))}%" except (ValueError, TypeError): return "?%" def get_temperature_color(temp): """Determine color based on temperature value.""" try: temp_value = float(temp) if isinstance(temp, (int, float)) else float(str(temp).replace('°', '').strip()) if temp_value < 0: return graphics.Color(0, 100, 255) elif temp_value < 10: return graphics.Color(100, 180, 255) elif temp_value < 20: return graphics.Color(0, 255, 100) elif temp_value < 30: return graphics.Color(255, 200, 0) else: return graphics.Color(255, 50, 50) except ValueError: return graphics.Color(255, 255, 255) class Matrix64Display(SampleBase): def __init__(self, *args, **kwargs): super(Matrix64Display, self).__init__(*args, **kwargs) self.parser.add_argument("-t", "--text", help="Text", default="") self.temperature = None self.humidity = None self.interior_temperature = None self.interior_humidity = None self.last_update = time.time() self.weather_desc = "unknown" self.hdd_temps = None def update_data(self): try: weather = get_weather() if weather.get("temperature") is not None: self.temperature = float(weather.get("temperature")) self.humidity = weather.get("humidity") self.weather_desc = get_weather_description() interior = get_interior_weather() if interior.get("temperature") is not None: self.interior_temperature = float(interior.get("temperature")) self.interior_humidity = interior.get("humidity") except Exception as e: print(f"Error updating data: {e}") def update_brightness(self): try: brightness = get_brightness() if brightness: self.matrix.brightness = int(float(brightness)) / 10 except Exception as e: self.matrix.brightness = 5 def update_hdd_temps(self): self.hdd_temps = get_hdd_temps() def run(self): canvas = self.matrix.CreateFrameCanvas() # Fonts font_dir = "/home/pi/rpi-rgb-led-matrix/fonts" time_font = graphics.Font() time_font.LoadFont(f"{font_dir}/7x13.bdf") data_font = graphics.Font() data_font.LoadFont(f"{font_dir}/5x8.bdf") small_font = graphics.Font() small_font.LoadFont(f"{font_dir}/4x6.bdf") # Colors time_color = graphics.Color(30, 90, 220) humidity_color = graphics.Color(80, 160, 255) hdd_color = graphics.Color(140, 120, 100) # Warm tan, easier to read label_color = graphics.Color(120, 120, 120) # Initial fetch self.update_brightness() self.update_data() self.update_hdd_temps() while True: now = datetime.datetime.now() time_str = f"{now.hour:02d}:{now.minute:02d}:{now.second:02d}" current_time = time.time() if current_time - self.last_update >= 60: self.update_data() self.update_brightness() self.update_hdd_temps() self.last_update = current_time canvas.Clear() # Line color for separators line_color = graphics.Color(40, 40, 40) # === Weather Icon (top-left, 24x24) === draw_weather_icon(canvas, 0, 0, self.weather_desc) # === Vertical separator between weather and HDD === graphics.DrawLine(canvas, 28, 0, 28, 25, line_color) # === HDD Temps (top-right, 5x8 font, 3 rows of 2) === if self.hdd_temps and len(self.hdd_temps) > 1: temps = [str(int(t[0])) for t in self.hdd_temps[1:] if t] if len(temps) >= 2: row1 = " ".join(temps[:2]) graphics.DrawText(canvas, data_font, 34, 8, hdd_color, row1) if len(temps) >= 4: row2 = " ".join(temps[2:4]) graphics.DrawText(canvas, data_font, 34, 16, hdd_color, row2) if len(temps) > 4: row3 = " ".join(temps[4:6]) graphics.DrawText(canvas, data_font, 34, 24, hdd_color, row3) # === Horizontal line above clock === graphics.DrawLine(canvas, 0, 26, 63, 26, line_color) # === Clock (centered) === time_x = (64 - len(time_str) * 7) // 2 graphics.DrawText(canvas, time_font, time_x, 39, time_color, time_str) # === Horizontal line below clock === graphics.DrawLine(canvas, 0, 42, 63, 42, line_color) # === Outdoor: Out + temp + humidity (y=52) === graphics.DrawText(canvas, data_font, 0, 52, 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, 52, temp_color, temp_str) if self.humidity is not None: graphics.DrawText(canvas, data_font, 48, 52, humidity_color, format_humidity(self.humidity)) # === Indoor: In + temp + humidity (y=62) === graphics.DrawText(canvas, data_font, 0, 62, 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, 62, temp_color, temp_str) if self.interior_humidity is not None: graphics.DrawText(canvas, data_font, 48, 62, humidity_color, format_humidity(self.interior_humidity)) time.sleep(0.5) canvas = self.matrix.SwapOnVSync(canvas) if __name__ == "__main__": display = Matrix64Display() if not display.process(): display.print_help()