From 12586fa383b8e2dc302c40cea69b07ab279deed0 Mon Sep 17 00:00:00 2001 From: retr0 <42kdesigners@gmail.com> Date: Sun, 26 Apr 2026 12:14:24 +0200 Subject: [PATCH] HAOS Add-on v1.1.1: Sparkline-Graphen (letzte 5 Minuten) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SVG-Sparkline pro Sensor-Karte, farbkodiert nach device_class - Backend: (timestamp, value) deque pro Sensor, API filtert auf 300s - Kein Datenverlust bei Neustart (In-Memory, reicht für Trendanzeige) Co-Authored-By: Claude Sonnet 4.6 --- haos-addon/config.yaml | 2 +- haos-addon/src/main.py | 14 ++++++++++++++ haos-addon/src/web/index.html | 27 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/haos-addon/config.yaml b/haos-addon/config.yaml index 3abe35c..537eb07 100644 --- a/haos-addon/config.yaml +++ b/haos-addon/config.yaml @@ -1,5 +1,5 @@ name: Growatt ShineLAN-X -version: "1.1.0" +version: "1.1.1" slug: growatt_shinelan_x description: Growatt Wechselrichter via ShineLAN-X (NuttX Modbus TCP) - MQTT Discovery + Web UI url: https://gitea.bitfire.work/retr0/Growatt-Wechselrichter-HAOS diff --git a/haos-addon/src/main.py b/haos-addon/src/main.py index f4d9fd3..c8b2760 100644 --- a/haos-addon/src/main.py +++ b/haos-addon/src/main.py @@ -4,6 +4,7 @@ import os import threading import time import uuid +from collections import deque from typing import Any, Dict, List, Optional from flask import Flask, jsonify, request, send_from_directory @@ -112,6 +113,12 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event): d["last_update"] = time.time() d["modbus_ok"] = True d["poll_count"] = d.get("poll_count", 0) + 1 + # History: (timestamp, value) pro Sensor, maximal 5 Minuten + hist = d.setdefault("history", {}) + now = time.time() + for sid, val in values.items(): + q = hist.setdefault(sid, deque(maxlen=300)) + q.append((now, val)) if _publisher: _publisher.publish_data(values, prefix) _publisher.publish_status("online", prefix) @@ -209,10 +216,17 @@ def api_get_data(): model_id = inv_cfg.get("inverter_model", "MIC_1500_TL_X") inverter = INVERTERS.get(model_id, INVERTERS["MIC_1500_TL_X"]) d = State.inv_data.get(inv_id, {}) + cutoff = time.time() - 300 # letzte 5 Minuten + raw_hist = d.get("history", {}) + history = { + sid: [v for (t, v) in q if t >= cutoff] + for sid, q in raw_hist.items() + } result[inv_id] = { "name": inv_cfg.get("name", inverter.name), "inverter_name": inverter.name, "values": d.get("values", {}), + "history": history, "sensors": [ {"id": s.id, "name": s.name, "unit": s.unit, "icon": s.icon, "device_class": s.device_class} diff --git a/haos-addon/src/web/index.html b/haos-addon/src/web/index.html index 99db124..9fa910c 100644 --- a/haos-addon/src/web/index.html +++ b/haos-addon/src/web/index.html @@ -64,6 +64,7 @@ .sensor-value { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; } .sensor-unit { font-size: 11px; color: var(--text-dim); margin-left: 2px; } + .sparkline { margin-top: 8px; opacity: .7; } .dc-power .sensor-value { color: var(--accent); } .dc-voltage .sensor-value { color: var(--blue); } .dc-current .sensor-value { color: var(--orange); } @@ -220,6 +221,30 @@