Grafana panel — Circuit Power Over Time (stacked)¶
Date: 2026-06-22 File touched: grafana/dashboard.json (source of truth, file-provisioned) Deploy path: push to main → ci.yml deploy-grafana → scp to provisioned path → Grafana file provider auto-reloads ~30s (no restart)
Problem¶
The Grafana Home Intelligence dashboard shows whole-home power (panel 24) and an instantaneous per-circuit snapshot (panel 33, "Circuit Power — Now"), but there is no time-series breakdown of per-circuit power. The user wants to select/zoom a time window and see which circuits were drawing power during that window.
Solution¶
Add one full-width stacked-area timeseries panel to the ⚡ Energy row: one series per branch circuit, stacked so the total height ≈ whole-home draw and each band is one circuit's contribution. Drill-down = Grafana's native zoom + multi-tooltip.
Sensor scope¶
Mirror the existing "Circuit Power — Now" (panel 33) entity set so the stacked total is meaningful and free of double-counting:
em_*_powercircuit sensors, excluding the split-phase main legs*_l1_power/*_l2_power- plus the summed 240 V appliance loads
air_handler_power,stove_power,dryer_power
Queries (InfluxQL)¶
Two targets (not one OR'd query — avoids InfluxQL AND/OR precedence pitfalls; same pattern panel 33 uses). Data model: measurement "W", tags entity_id (no sensor. prefix) and friendly_name.
- A:
SELECT mean("value") FROM "W" WHERE "entity_id" =~ /^em_/ AND "entity_id" =~ /_power$/ AND "entity_id" !~ /_l[12]_power$/ AND $timeFilter GROUP BY time($__interval), "friendly_name" fill(none) - B:
SELECT mean("value") FROM "W" WHERE "entity_id" =~ /^(air_handler|stove|dryer)_power$/ AND $timeFilter GROUP BY time($__interval), "friendly_name" fill(none)
alias: $tag_friendly_name, resultFormat: time_series, rawQuery: true.
Visual¶
drawStyle: line,fillOpacity: 25,lineWidth: 1,showPoints: never,spanNulls: truecustom.stacking.mode: normalunit: watt,color.mode: palette-classic- tooltip
mode: multi,sort: desc - legend: table, bottom, calcs
["lastNotNull", "max"](sortable by biggest consumer) - datasource: copy the InfluxDB uid used by panels 24/33 (
P14502BC03F6B8823) — do not invent
Placement¶
Full width w:24, h:10, inserted directly above panel 33 (the snapshot it complements). Panel 33 and anything below shift down by 10 rows. New unique panel id (max existing + 1).
Testing / verification¶
make pytest— Grafana guards must pass (no${DS_INFLUXDB}, nonow()-24h, real datasource uids, JSON valid)- After deploy, confirm
gh run list --workflow=ci.yml --limit 1succeeded.
Docs¶
grafana/dashboard.json is a technical artifact; no user-facing MkDocs page documents individual Grafana panels (the household manual covers HA dashboards/alerts, not Grafana). No manual update required.
Out of scope (YAGNI)¶
- No per-circuit cost overlay (panel 24 already pairs power with TOU rate).
- No new InfluxDB retention/recording changes — all sensors already log to the
Wmeasurement.