The Heat Pump ROI dashboard showed No data / red error triangles on every KPI tile and the SPF/cost panels. Two independent causes:
ViCare → open3e/MQTT migration (2026-07) renamed every heat-pump/PV entity. The dashboard still queried the retired ViCare IDs. Only three survived under their old names (the two e3_vitocal_*_energy_consumption_totalutility_meter helpers + input_number.strompreis); everything else — SPF, this-year, 7-day, and all solar/grid entities — now lives under vitocal_250_a_vitocal_* / vitocharge_vx3_vx3_*.
Duplicate Prometheus scrape. The home-assistant-bgp LoadBalancer carries app.kubernetes.io/name: home-assistant + a port named http, so the home-assistant ServiceMonitor scraped HA a second time via the LB (:8123) on top of the intended proxy (:8124). Every metric existed twice → many-to-many matching not allowed on the surviving-entity panels (and silent double-counting of homeassistant_sensor_* cluster-wide).
What this PR does
Rebuilds the dashboard on InfluxDB (bucket suedstr28), which is authoritative and live (verified: the open3e MQTT entities are being written to it right now). Every panel now reads InfluxDB via the current entity IDs; all Prometheus targets are dropped, so cause #2 can no longer affect this dashboard.
History preserved: for renamed entities (solar/grid, SPF), the Flux queries union() the pre-migration e3_* series with the post-migration series, unit-normalized (PV production is now Wh → ÷1000), so the lines stay unbroken across the 2026-07 boundary.
Surviving utility_meter totals are kept for the cumulative/ROI panels (continuous history; the MQTT device's own lifetime counter differs, so mixing would jump the numbers).
SPF gauges → the device scop_{total,heating,dhw} sensors. This-year tiles → ..._electric_energy_year. The retired *_last_seven_days sensors → a Flux spread() / daily-difference() computed from the surviving totals.
New grid_price dashboard variable (default 0.3271) replaces the retired live input_number.strompreis read.
Also fixes the duplicate scrape (bgp-service.yaml): renames the LB port http → ha so the ServiceMonitor (which matches port: http) no longer picks it up. The LB still serves :8123 by number; nothing references the port by name.
Validation
Every non-trivial Flux query was run live against InfluxDB via Grafana Explore before committing:
Please sanity-check the rendered numbers after deploy. The blended-price/SCOP semantics are close but not identical to the old ViCare-derived figures (SCOP is the device's own seasonal figure vs. the previously HA-computed SPF).
## What was broken
The **Heat Pump ROI** dashboard showed `No data` / red error triangles on every KPI tile and the SPF/cost panels. Two independent causes:
1. **ViCare → open3e/MQTT migration (2026-07) renamed every heat-pump/PV entity.** The dashboard still queried the retired ViCare IDs. Only three survived under their old names (the two `e3_vitocal_*_energy_consumption_total` `utility_meter` helpers + `input_number.strompreis`); everything else — SPF, this-year, 7-day, and all solar/grid entities — now lives under `vitocal_250_a_vitocal_*` / `vitocharge_vx3_vx3_*`.
2. **Duplicate Prometheus scrape.** The `home-assistant-bgp` LoadBalancer carries `app.kubernetes.io/name: home-assistant` + a port named `http`, so the `home-assistant` ServiceMonitor scraped HA a *second* time via the LB (`:8123`) on top of the intended proxy (`:8124`). Every metric existed twice → `many-to-many matching not allowed` on the surviving-entity panels (and silent double-counting of `homeassistant_sensor_*` cluster-wide).
## What this PR does
**Rebuilds the dashboard on InfluxDB** (bucket `suedstr28`), which is authoritative and live (verified: the open3e MQTT entities are being written to it right now). Every panel now reads InfluxDB via the current entity IDs; **all Prometheus targets are dropped**, so cause #2 can no longer affect this dashboard.
- **History preserved:** for renamed entities (solar/grid, SPF), the Flux queries `union()` the pre-migration `e3_*` series with the post-migration series, unit-normalized (**PV production is now Wh → ÷1000**), so the lines stay unbroken across the 2026-07 boundary.
- Surviving `utility_meter` totals are kept for the cumulative/ROI panels (continuous history; the MQTT device's own lifetime counter differs, so mixing would jump the numbers).
- SPF gauges → the device `scop_{total,heating,dhw}` sensors. This-year tiles → `..._electric_energy_year`. The retired `*_last_seven_days` sensors → a Flux `spread()` / daily-`difference()` computed from the surviving totals.
- New `grid_price` dashboard variable (default `0.3271`) replaces the retired live `input_number.strompreis` read.
**Also fixes the duplicate scrape** (`bgp-service.yaml`): renames the LB port `http` → `ha` so the ServiceMonitor (which matches `port: http`) no longer picks it up. The LB still serves `:8123` by number; nothing references the port by name.
## Validation
Every non-trivial Flux query was run live against InfluxDB via Grafana Explore before committing:
| Check | Result |
|---|---|
| Blended price (pivot + solar-ratio) | €0.248/kWh |
| Total consumption (`group()`+`sum()`) | 14284 kWh (12577 + 1707) |
| Projected annual savings (`date` fns + projection) | €4698 |
| Oil proration (epoch math) | €11912 (matches historical panel) |
| Grid-import old∪new union | continuous 15737 → 28088 kWh across migration |
JSON validated (24 panels, 3 variables, 0 Prometheus references).
## Note
Please sanity-check the rendered numbers after deploy. The blended-price/SCOP semantics are close but not identical to the old ViCare-derived figures (SCOP is the device's own seasonal figure vs. the previously HA-computed SPF).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The ViCare cloud integration was replaced by open3e/MQTT (2026-07), renaming all heat-pump/PV entities (e3_vitocal_*/e3_vitocharge_03_* -> vitocal_250_a_vitocal_*/vitocharge_vx3_vx3_*). The dashboard still queried the retired IDs, and a duplicate Prometheus scrape broke the surviving-entity panels with many-to-many errors.
Rebuild every panel on InfluxDB (bucket suedstr28, authoritative + live) using current entity IDs. Where an entity was renamed, UNION the pre-migration e3_* series with the post-migration series (unit-normalized: PV Wh->kWh) so history stays unbroken. Drop all Prometheus targets. Add a grid_price variable (0.3271) replacing the retired live strompreis read.
Also rename the home-assistant-bgp Service port http->ha so the home-assistant ServiceMonitor no longer scrapes HA a second time via the LB (:8123), which duplicated homeassistant_sensor_* series cluster-wide.
Queries validated live via Grafana Explore: blended price 0.248 EUR/kWh, total consumption 14284 kWh, projected annual savings 4698 EUR, oil proration 11912 EUR, old-union-new grid-import continuous.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiLCinB7NLp7YdCjGYzvfh
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What was broken
The Heat Pump ROI dashboard showed
No data/ red error triangles on every KPI tile and the SPF/cost panels. Two independent causes:e3_vitocal_*_energy_consumption_totalutility_meterhelpers +input_number.strompreis); everything else — SPF, this-year, 7-day, and all solar/grid entities — now lives undervitocal_250_a_vitocal_*/vitocharge_vx3_vx3_*.home-assistant-bgpLoadBalancer carriesapp.kubernetes.io/name: home-assistant+ a port namedhttp, so thehome-assistantServiceMonitor scraped HA a second time via the LB (:8123) on top of the intended proxy (:8124). Every metric existed twice →many-to-many matching not allowedon the surviving-entity panels (and silent double-counting ofhomeassistant_sensor_*cluster-wide).What this PR does
Rebuilds the dashboard on InfluxDB (bucket
suedstr28), which is authoritative and live (verified: the open3e MQTT entities are being written to it right now). Every panel now reads InfluxDB via the current entity IDs; all Prometheus targets are dropped, so cause #2 can no longer affect this dashboard.union()the pre-migratione3_*series with the post-migration series, unit-normalized (PV production is now Wh → ÷1000), so the lines stay unbroken across the 2026-07 boundary.utility_metertotals are kept for the cumulative/ROI panels (continuous history; the MQTT device's own lifetime counter differs, so mixing would jump the numbers).scop_{total,heating,dhw}sensors. This-year tiles →..._electric_energy_year. The retired*_last_seven_dayssensors → a Fluxspread()/ daily-difference()computed from the surviving totals.grid_pricedashboard variable (default0.3271) replaces the retired liveinput_number.strompreisread.Also fixes the duplicate scrape (
bgp-service.yaml): renames the LB porthttp→haso the ServiceMonitor (which matchesport: http) no longer picks it up. The LB still serves:8123by number; nothing references the port by name.Validation
Every non-trivial Flux query was run live against InfluxDB via Grafana Explore before committing:
group()+sum())datefns + projection)JSON validated (24 panels, 3 variables, 0 Prometheus references).
Note
Please sanity-check the rendered numbers after deploy. The blended-price/SCOP semantics are close but not identical to the old ViCare-derived figures (SCOP is the device's own seasonal figure vs. the previously HA-computed SPF).
🤖 Generated with Claude Code