diff --git a/home_assistant.py b/home_assistant.py index 4eec435..c575405 100644 --- a/home_assistant.py +++ b/home_assistant.py @@ -2,6 +2,7 @@ Home Assistant API client for Matrix64 LED display. """ import requests +import datetime from config import ( HA_TOKEN, HASS_URL, BRIGHTNESS_ENTITY_ID, WEATHER_ENTITY_ID, @@ -114,3 +115,47 @@ def get_solar_status(): "today_energy": safe_float(today_energy), "tesla_power": tesla_power_w, } + + +def get_solar_history(): + """Get today's solar production history from HA History API. + Returns list of (hour_float, watts) tuples.""" + headers = { + "Authorization": f"Bearer {HA_TOKEN}", + "Content-Type": "application/json", + } + now = datetime.datetime.now() + start = now.replace(hour=0, minute=0, second=0, microsecond=0) + start_str = start.strftime("%Y-%m-%dT%H:%M:%S") + url = (f"{HASS_URL}/api/history/period/{start_str}" + f"?filter_entity_id={SOLAR_PRODUCTION_ENTITY}" + f"&minimal_response&no_attributes") + try: + response = requests.get(url, headers=headers, timeout=15) + if response.status_code != 200: + return [] + data = response.json() + if not data or not data[0]: + return [] + points = [] + for entry in data[0]: + try: + state = float(entry.get("state", 0)) + ts = entry.get("last_changed", "") + # Parse ISO timestamp + if "+" in ts: + ts = ts.split("+")[0] + elif ts.endswith("Z"): + ts = ts[:-1] + dt = datetime.datetime.fromisoformat(ts) + # Convert UTC to local time + utc_offset = now - datetime.datetime.utcnow() + dt_local = dt + utc_offset + hour_f = dt_local.hour + dt_local.minute / 60.0 + points.append((hour_f, state)) + except (ValueError, TypeError): + continue + return points + except Exception as e: + print(f"Error fetching solar history: {e}") + return [] diff --git a/matrix.py b/matrix.py index b2c2a7c..02b8ebe 100644 --- a/matrix.py +++ b/matrix.py @@ -26,7 +26,7 @@ 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_solar_status + get_solar_status, get_solar_history ) from netdata import get_hdd_temps from mqtt_listener import MQTTListener @@ -133,8 +133,8 @@ class Matrix64Display(SampleBase): self.hdd_temps = None self.tesla = None self.solar = None - self.pv_history = [] # list of (timestamp, production_w) for today's curve - self.pv_history_date = None # track current day to reset history + self.pv_history = [] # list of (hour_float, watts) from HA history + self.last_pv_history_update = 0 # View state self.current_view = 0 @@ -259,14 +259,6 @@ class Matrix64Display(SampleBase): self.tesla = get_tesla_status() self.solar = get_solar_status() - # Record PV history for today's curve - if self.solar and self.solar.get("production") is not None: - now = datetime.datetime.now() - today = now.date() - if self.pv_history_date != today: - self.pv_history = [] - self.pv_history_date = today - self.pv_history.append((now.hour + now.minute / 60.0, self.solar["production"])) except Exception as e: print(f"Error updating data: {e}") @@ -814,6 +806,14 @@ class Matrix64Display(SampleBase): self.update_hdd_temps() self.last_update = current_time + # Update PV history every 5 minutes + if current_time - self.last_pv_history_update >= 300: + try: + self.pv_history = get_solar_history() + except Exception as e: + print(f"Error updating PV history: {e}") + self.last_pv_history_update = current_time + if current_time - self.last_update >= 15: self.update_brightness()