Add SG-Ready startup grace period and daily PV yield tracking

SG-Ready startup grace period (sg_ready_startup_min: 10):
Heat pump compressor takes ~9 minutes to start after receiving the
SG-Ready signal. Previously, idle detection fired after only 3×2min=6min,
turning off SG-Ready before the compressor had time to respond. The grace
period suppresses idle detection for the configured duration after activation.
0 = disabled (tests and unconfigured deployments are unaffected).

Daily PV yield (photovoltaic_production_cumulated_currentDay):
Reads actual kWh produced today from Prometheus (Wh → kWh, ÷1000).
Logged as pv_today_kwh each cycle. Shown on status page in two places:
- PV card sub-line: "Heute: 31.9 kWh"
- Forecast card alongside forecast: "Ist: 31.9 kWh"
Immediately makes forecast vs reality visible (today: forecast 15.9,
actual 31.9 kWh — explains why SOC bypass triggered).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 21:00:57 +02:00
parent 2728755738
commit db46fcf0c6
5 changed files with 27 additions and 5 deletions

View File

@@ -27,6 +27,7 @@ type SystemState struct {
PhaseL2PowerW float64 // per-phase grid power L2
PhaseL3PowerW float64 // per-phase grid power L3
WWTopTempC float64 // DHW cylinder top temperature (°C)
PVYieldTodayKWh float64 // cumulative PV production today (kWh)
}
// IsExporting returns true if the system is exporting to grid.
@@ -93,6 +94,7 @@ func (c *Collector) Collect(ctx context.Context) (SystemState, error) {
{"phase_l2_power", &state.PhaseL2PowerW, 1},
{"phase_l3_power", &state.PhaseL3PowerW, 1},
{"ww_top_temp", &state.WWTopTempC, 1},
{"pv_yield_today", &state.PVYieldTodayKWh, 0.001}, // Wh → kWh
}
for _, t := range targets {
@@ -118,6 +120,7 @@ func (c *Collector) Collect(ctx context.Context) (SystemState, error) {
"grid_w", state.GridPowerW,
"soc", state.BatterySOC,
"pv_w", state.PVProductionW,
"pv_today_kwh", fmt.Sprintf("%.1f", state.PVYieldTodayKWh),
"compressor_w", state.CompressorPowerW,
"ambient_c", state.AmbientTempC,
"l1_w", state.PhaseL1PowerW,