fix(heatpump-heating-loading): Duplikat-Serien kollabieren, ehrliches No-Data #277

Merged
k.renner merged 1 commits from claude-bot/dash-heatpump-heating-loading into master 2026-07-17 11:20:14 +00:00
Member

Review: Wärmepumpe — Heiz-Ladeleistung vs. Außentemperatur (heatpump-heating-loading)

Gesamturteil: Das Dashboard ist konzeptionell korrekt und die "leeren" Panels sind beabsichtigt — der Logging-Sensor sensor.vitocal_heating_loading_power (packages/vitocal_heating_loading_analysis.yaml) ist außerhalb aktiver Heiz-Ladung absichtlich unavailable, damit Prometheus ausschließlich echte Heiz-Ladepunkte aufzeichnet. Im Juli ist das Dashboard daher zu Recht leer. Ein echter Bug wurde gefunden und behoben (Duplikat-Serien), plus eine kleine UX-Verbesserung.

Before

before

After

after

Review-Report

  1. MAJOR — Panel "Außentemperatur & Puffer": 30 Duplikat-Serien. ✅ FIXED — Die Queries selektierten rohe Serien nur über das entity-Label. Über das 90-Tage-Fenster erzeugen 2 Scrape-Jobs (home-assistant + home-assistant-bgp, der am 2026-07-16 gefixte Duplikat-Scrape-Bug) × 15 Pod-Lebenszyklen (das pod-Label wechselt bei jedem HA-Restart) = 30 unterschiedliche Serien pro Entity (verifiziert: count(count_over_time(...[90d])) = 30; count by (job) = 15 + 15). Die Legende war ein unlesbarer Block aus 15× "Außentemp" + 15× "Puffer". Alle 6 Queries des Dashboards sind jetzt in max by (entity) (...) gewrappt (gleiche Form wie im Schwester-PR #276 für heatpump-dhw-loading) → genau eine Serie pro Entity. Verlustfrei: die live überlappenden Job-Serien differieren um exakt 0 (verifiziert per max(...) - min(...) = 0 für beide Temperatur-Entities).

  2. MAJOR (latent) — xychart-Join wäre in der Heizperiode gebrochen. ✅ FIXED (durch dieselbe Änderung) — Das Scatter-Panel joint per joinByField auf Time und braucht dafür eindeutige Feldnamen ("Ladeleistung", "Aussentemp"). Mit mehreren gleichnamigen Serien pro Query (der nächste Pod-Restart genügt) hätte der Join ab der ersten Heizperiode mehrdeutige Spalten produziert und das Kern-Panel des Dashboards zerlegt. Mit max by (entity) ist der Join stabil. (Auf dem DHW-Schwester-Dashboard, das bereits Daten hat, war genau dadurch der Scatter komplett leer und der Ø-Stat zeigte 8 widersprüchliche Werte — dieses Dashboard wäre in der Heizperiode identisch gebrochen.)

  3. MINOR — Stat-Panel zeigte riesiges grünes "No data". ✅ FIXED — jetzt noValue: "keine Heizdaten im Zeitraum", damit klar ist, dass das Sommerverhalten beabsichtigt ist und kein Fehler.

  4. OK — Leere Panels im Sommer sind korrekt, kein Bug. Verdichter aus, 4/3-Wege-Ventil auf "Internal Buffer" → Availability-Template = false → Sensor unavailable → Prometheus exportiert nichts. Genau so im Package dokumentiert ("füllt sich mit dem ersten Heizzyklus im Herbst"). Nichts geändert.

  5. OK — Default-Zeitraum now-90d ist sinnvoll. In der Heizperiode zeigt er die letzten ~3 Monate Heizdaten; ein größerer Default würde im Frühjahr die abgelaufene Saison länger sichtbar halten, macht die Achsen aber gröber. Bewusst so gelassen.

  6. OK — Achsen/Einheiten/Semantik geprüft. xychart: x = Außentemp (°C), y = Ladeleistung (W) — passt zum Titel. Stat "Ø (Zeitraum)" mittelt nur über Samples, die während aktiver Ladung existieren → semantisch korrekt "mittlere Ladeleistung während des Ladens", genau die Zahl für die Boost-Schwelle.

  7. ⚠️ NOT FIXED (bewusst) — Temperatur-Historie beginnt erst am ~03.07. (open3e-Migration; die alten e3_vitocal_*-Entities halten die Daten davor). Ich habe die alten Entity-Namen absichtlich NICHT per Regex dazugenommen: die Alt-Daten altern vor Beginn der Heizperiode aus dem Fenster heraus, und der Zweck des Dashboards (Korrelation mit dem am 07.07. angelegten Logging-Sensor) braucht sie nicht. Sag Bescheid, falls du die Kontinuität trotzdem willst.

Verifikation (live gegen Prometheus + HA API)

  • homeassistant_sensor_power_w{entity="sensor.vitocal_heating_loading_power"}: 0 Samples in 90d — konsistent mit Sensor-Design (unavailable seit Anlage am 07.07.). Metrikname korrekt: andere W-Sensoren (vitocal_250_a_vitocal_power_consumption, ..._thermal_power) erscheinen unter genau diesem Metriknamen, der Template-Sensor hat device_class: power + unit: W → wird beim ersten Heizzyklus unter diesem Namen exportiert.
  • sensor.vitocal_heating_loading_power in HA: existiert, state: unavailable ✓; Gate-Sensoren live geprüft: valve_position = "Internal Buffer", four_way_valve_state = "Normal (Heizen/WW)", power_consumption = 0.0 → Availability-Logik verhält sich exakt wie im Package beschrieben.
  • count(count_over_time(homeassistant_sensor_temperature_celsius{entity="sensor.vitocal_250_a_vitocal_outside_temperature"}[90d])) = 30 (14 Pods × 2 Ports) — Beleg für Finding 1.
  • max by (entity) (homeassistant_sensor_temperature_celsius{entity="..."}) für outside + buffer: je genau 1 Serie ✓ (vorher 30).
  • Verlustfreiheit: max(...) - min(...) über die aktuell überlappenden Job-Serien = 0 für outside und buffer ✓.
  • After-Screenshot via temporärem Preview-Dashboard gerendert (uid heatpump-heating-loading-preview, danach gelöscht).
## Review: Wärmepumpe — Heiz-Ladeleistung vs. Außentemperatur (`heatpump-heating-loading`) **Gesamturteil: Das Dashboard ist konzeptionell korrekt und die "leeren" Panels sind beabsichtigt** — der Logging-Sensor `sensor.vitocal_heating_loading_power` (packages/vitocal_heating_loading_analysis.yaml) ist außerhalb aktiver Heiz-Ladung absichtlich `unavailable`, damit Prometheus ausschließlich echte Heiz-Ladepunkte aufzeichnet. Im Juli ist das Dashboard daher zu Recht leer. Ein echter Bug wurde gefunden und behoben (Duplikat-Serien), plus eine kleine UX-Verbesserung. ### Before ![before](https://gitea.renner.uno/attachments/0077b145-6527-4963-b91c-232bc0aed4aa) ### After ![after](https://gitea.renner.uno/attachments/c79270e4-4f58-4ac8-a214-32fc4a79e79b) ### Review-Report 1. **MAJOR — Panel "Außentemperatur & Puffer": 30 Duplikat-Serien.** ✅ FIXED — Die Queries selektierten rohe Serien nur über das `entity`-Label. Über das 90-Tage-Fenster erzeugen **2 Scrape-Jobs (`home-assistant` + `home-assistant-bgp`, der am 2026-07-16 gefixte Duplikat-Scrape-Bug) × 15 Pod-Lebenszyklen** (das `pod`-Label wechselt bei jedem HA-Restart) = **30 unterschiedliche Serien pro Entity** (verifiziert: `count(count_over_time(...[90d]))` = 30; `count by (job)` = 15 + 15). Die Legende war ein unlesbarer Block aus 15× "Außentemp" + 15× "Puffer". Alle 6 Queries des Dashboards sind jetzt in `max by (entity) (...)` gewrappt (gleiche Form wie im Schwester-PR #276 für `heatpump-dhw-loading`) → genau eine Serie pro Entity. Verlustfrei: die live überlappenden Job-Serien differieren um exakt 0 (verifiziert per `max(...) - min(...)` = 0 für beide Temperatur-Entities). 2. **MAJOR (latent) — xychart-Join wäre in der Heizperiode gebrochen.** ✅ FIXED (durch dieselbe Änderung) — Das Scatter-Panel joint per `joinByField` auf `Time` und braucht dafür eindeutige Feldnamen ("Ladeleistung", "Aussentemp"). Mit mehreren gleichnamigen Serien pro Query (der nächste Pod-Restart genügt) hätte der Join ab der ersten Heizperiode mehrdeutige Spalten produziert und das Kern-Panel des Dashboards zerlegt. Mit `max by (entity)` ist der Join stabil. (Auf dem DHW-Schwester-Dashboard, das bereits Daten hat, war genau dadurch der Scatter komplett leer und der Ø-Stat zeigte 8 widersprüchliche Werte — dieses Dashboard wäre in der Heizperiode identisch gebrochen.) 3. **MINOR — Stat-Panel zeigte riesiges grünes "No data".** ✅ FIXED — jetzt `noValue: "keine Heizdaten im Zeitraum"`, damit klar ist, dass das Sommerverhalten beabsichtigt ist und kein Fehler. 4. **OK — Leere Panels im Sommer sind korrekt, kein Bug.** Verdichter aus, 4/3-Wege-Ventil auf "Internal Buffer" → Availability-Template = false → Sensor `unavailable` → Prometheus exportiert nichts. Genau so im Package dokumentiert ("füllt sich mit dem ersten Heizzyklus im Herbst"). Nichts geändert. 5. **OK — Default-Zeitraum `now-90d` ist sinnvoll.** In der Heizperiode zeigt er die letzten ~3 Monate Heizdaten; ein größerer Default würde im Frühjahr die abgelaufene Saison länger sichtbar halten, macht die Achsen aber gröber. Bewusst so gelassen. 6. **OK — Achsen/Einheiten/Semantik geprüft.** xychart: x = Außentemp (°C), y = Ladeleistung (W) — passt zum Titel. Stat "Ø (Zeitraum)" mittelt nur über Samples, die während aktiver Ladung existieren → semantisch korrekt "mittlere Ladeleistung während des Ladens", genau die Zahl für die Boost-Schwelle. 7. ⚠️ NOT FIXED (bewusst) — **Temperatur-Historie beginnt erst am ~03.07.** (open3e-Migration; die alten `e3_vitocal_*`-Entities halten die Daten davor). Ich habe die alten Entity-Namen absichtlich NICHT per Regex dazugenommen: die Alt-Daten altern vor Beginn der Heizperiode aus dem Fenster heraus, und der Zweck des Dashboards (Korrelation mit dem am 07.07. angelegten Logging-Sensor) braucht sie nicht. Sag Bescheid, falls du die Kontinuität trotzdem willst. ### Verifikation (live gegen Prometheus + HA API) - `homeassistant_sensor_power_w{entity="sensor.vitocal_heating_loading_power"}`: 0 Samples in 90d — konsistent mit Sensor-Design (unavailable seit Anlage am 07.07.). Metrikname korrekt: andere W-Sensoren (`vitocal_250_a_vitocal_power_consumption`, `..._thermal_power`) erscheinen unter genau diesem Metriknamen, der Template-Sensor hat `device_class: power` + `unit: W` → wird beim ersten Heizzyklus unter diesem Namen exportiert. - `sensor.vitocal_heating_loading_power` in HA: existiert, `state: unavailable` ✓; Gate-Sensoren live geprüft: `valve_position` = "Internal Buffer", `four_way_valve_state` = "Normal (Heizen/WW)", `power_consumption` = 0.0 → Availability-Logik verhält sich exakt wie im Package beschrieben. - `count(count_over_time(homeassistant_sensor_temperature_celsius{entity="sensor.vitocal_250_a_vitocal_outside_temperature"}[90d]))` = **30** (14 Pods × 2 Ports) — Beleg für Finding 1. - `max by (entity) (homeassistant_sensor_temperature_celsius{entity="..."})` für outside + buffer: je genau **1** Serie ✓ (vorher 30). - Verlustfreiheit: `max(...) - min(...)` über die aktuell überlappenden Job-Serien = **0** für outside und buffer ✓. - After-Screenshot via temporärem Preview-Dashboard gerendert (uid `heatpump-heating-loading-preview`, danach gelöscht).
claude-bot force-pushed claude-bot/dash-heatpump-heating-loading from bece3d878d to 1165afce02 2026-07-16 22:32:22 +00:00 Compare
k.renner merged commit a1a68e0230 into master 2026-07-17 11:20:14 +00:00
Sign in to join this conversation.