Add solar panel view with PV production, battery, grid, home load and Tesla charging

This commit is contained in:
Joan
2026-03-20 13:18:29 +01:00
parent 5bbee94765
commit d53ac19887
5 changed files with 146 additions and 4 deletions

View File

@@ -25,7 +25,8 @@ 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, get_tesla_status
get_interior_weather, get_brightness, get_tesla_status,
get_solar_status
)
from netdata import get_hdd_temps
from mqtt_listener import MQTTListener
@@ -40,7 +41,7 @@ except:
pass
# Number of views
NUM_VIEWS = 4
NUM_VIEWS = 5
# View names (Spanish)
VIEW_NAMES = {
@@ -48,6 +49,7 @@ VIEW_NAMES = {
1: "Discos",
2: "Fecha",
3: "Tesla",
4: "Solar",
}
# Spanish translations
@@ -128,6 +130,7 @@ class Matrix64Display(SampleBase):
self.weather_desc = "unknown"
self.hdd_temps = None
self.tesla = None
self.solar = None
# View state
self.current_view = 0
@@ -251,6 +254,7 @@ class Matrix64Display(SampleBase):
self.interior_humidity = interior.get("humidity")
self.tesla = get_tesla_status()
self.solar = get_solar_status()
except Exception as e:
print(f"Error updating data: {e}")
@@ -511,6 +515,88 @@ class Matrix64Display(SampleBase):
if self.auto_cycle:
graphics.DrawText(canvas, small_font, 58, 62, label_color, "A")
def draw_view_4(self, canvas, fonts, colors):
"""Vista Solar"""
time_font, data_font, small_font = fonts
time_color, humidity_color, hdd_color, label_color, line_color = colors
# Title
title = "Solar"
title_len = len(title) * 5
title_x = (64 - title_len) // 2
graphics.DrawText(canvas, data_font, title_x, 8, time_color, title)
graphics.DrawLine(canvas, 0, 10, 63, 10, line_color)
if self.solar:
# Solar production (W)
production = self.solar.get("production")
if production is not None:
prod_color = graphics.Color(255, 200, 0) if production > 0 else graphics.Color(100, 100, 100)
graphics.DrawText(canvas, data_font, 2, 20, label_color, "PV")
prod_str = f"{int(production)}W"
graphics.DrawText(canvas, data_font, 16, 20, prod_color, prod_str)
# Battery % and power
battery_pct = self.solar.get("battery_pct")
battery_power = self.solar.get("battery_power")
if battery_pct is not None:
if battery_pct > 50:
bat_color = graphics.Color(0, 255, 80)
elif battery_pct > 20:
bat_color = graphics.Color(255, 200, 0)
else:
bat_color = graphics.Color(255, 50, 50)
graphics.DrawText(canvas, data_font, 2, 30, label_color, "Bat")
graphics.DrawText(canvas, data_font, 20, 30, bat_color, f"{int(battery_pct)}%")
if battery_power is not None:
if battery_power < 0:
bp_color = graphics.Color(0, 200, 255) # Charging (blue)
bp_str = f"{int(abs(battery_power))}W"
elif battery_power > 0:
bp_color = graphics.Color(255, 150, 0) # Discharging (orange)
bp_str = f"{int(battery_power)}W"
else:
bp_color = graphics.Color(100, 100, 100)
bp_str = "0W"
graphics.DrawText(canvas, data_font, 44, 30, bp_color, bp_str)
# Grid power (negative = exporting)
grid_power = self.solar.get("grid_power")
if grid_power is not None:
if grid_power < 0:
grid_color = graphics.Color(0, 255, 100) # Exporting (green)
grid_label = "Exp"
grid_str = f"{int(abs(grid_power))}W"
else:
grid_color = graphics.Color(255, 100, 100) # Importing (red)
grid_label = "Imp"
grid_str = f"{int(grid_power)}W"
graphics.DrawText(canvas, data_font, 2, 40, label_color, grid_label)
graphics.DrawText(canvas, data_font, 20, 40, grid_color, grid_str)
# Home consumption (minus Tesla charger)
load_power = self.solar.get("load_power")
tesla_power = self.solar.get("tesla_power", 0)
if load_power is not None:
home_power = max(0, int(load_power - tesla_power))
graphics.DrawText(canvas, data_font, 2, 50, label_color, "Casa")
graphics.DrawText(canvas, data_font, 26, 50, humidity_color, f"{home_power}W")
if tesla_power > 0:
tesla_color = graphics.Color(200, 50, 50)
graphics.DrawText(canvas, small_font, 2, 57, label_color, "Tesla")
graphics.DrawText(canvas, small_font, 26, 57, tesla_color, f"{int(tesla_power)}W")
# Today's energy
today = self.solar.get("today_energy")
if today is not None:
graphics.DrawText(canvas, data_font, 2, 60, label_color, "Hoy")
graphics.DrawText(canvas, data_font, 20, 60, graphics.Color(255, 200, 0), f"{today:.1f}kWh")
else:
graphics.DrawText(canvas, data_font, 4, 32, label_color, "Sin datos")
if self.auto_cycle:
graphics.DrawText(canvas, small_font, 58, 62, label_color, "A")
def run(self):
canvas = self.matrix.CreateFrameCanvas()
@@ -571,6 +657,8 @@ class Matrix64Display(SampleBase):
self.draw_view_2(canvas, fonts, colors)
elif self.current_view == 3:
self.draw_view_3(canvas, fonts, colors)
elif self.current_view == 4:
self.draw_view_4(canvas, fonts, colors)
# Camera alert overlay (highest priority)
if self.mqtt.is_alert_active():