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

@@ -183,6 +183,7 @@ type pageData struct {
BatterySOC float64
GridPowerW float64
PVProductionW float64
PVYieldTodayKWh float64
AmbientTempC float64
CompressorPowerW float64
WWTopTempC float64
@@ -281,6 +282,7 @@ func (s *Store) Handler() http.HandlerFunc {
BatterySOC: s.state.BatterySOC,
GridPowerW: s.state.GridPowerW,
PVProductionW: s.state.PVProductionW,
PVYieldTodayKWh: s.state.PVYieldTodayKWh,
AmbientTempC: s.state.AmbientTempC,
CompressorPowerW: s.state.CompressorPowerW,
WWTopTempC: s.state.WWTopTempC,
@@ -833,6 +835,7 @@ h1 { font-size: 1.4rem; font-weight: 700; color: #14532d; }
<div class="card">
<div class="card-label">PV-Leistung</div>
<div class="card-value" style="color:#d97706">{{formatW .PVProductionW}}</div>
{{if gt .PVYieldTodayKWh 0.0}}<div class="card-sub">Heute: {{printf "%.1f" .PVYieldTodayKWh}} kWh</div>{{end}}
</div>
<!-- Temperature -->
@@ -865,6 +868,7 @@ h1 { font-size: 1.4rem; font-weight: 700; color: #14532d; }
<div class="forecast-row">
<span class="forecast-icon">{{.Forecast.Icon}}</span>
<span class="card-value" style="color:#d97706">{{printf "%.1f" .Forecast.KWh}} kWh</span>
{{if gt .PVYieldTodayKWh 0.0}}<span class="card-sub" style="margin-left:1rem">Ist: {{printf "%.1f" .PVYieldTodayKWh}} kWh</span>{{end}}
</div>
<div class="forecast-quality">{{.Forecast.Quality}}</div>
</div>