Refresh forecast up to 3× per day within daylight window

forecast.solar updates estimates as the day progresses, so a single
morning fetch can be stale by afternoon. New behaviour:
- Re-fetch every 4h within 07:00–19:00 window (3 fetches/day)
- Outside the window always serve the cached value
- Free tier limit is 12 req/day — 3 fetches is well within budget
- First startup outside window still fetches if cache is empty

Config: forecast.fetch_interval, fetch_window_start, fetch_window_end

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-06 10:19:29 +02:00
parent 79828a46c5
commit 5f22df3e0f
3 changed files with 62 additions and 8 deletions

View File

@@ -128,12 +128,23 @@ type SeasonConfig struct {
// ForecastConfig holds forecast.solar API parameters.
type ForecastConfig struct {
Enabled bool `yaml:"enabled"`
Lat float64 `yaml:"lat"`
Lon float64 `yaml:"lon"`
Declination int `yaml:"declination"` // panel tilt in degrees
Azimuth int `yaml:"azimuth"` // degrees from south (south=0, west=90)
KWp float64 `yaml:"kwp"` // installed peak power
Enabled bool `yaml:"enabled"`
Lat float64 `yaml:"lat"`
Lon float64 `yaml:"lon"`
Declination int `yaml:"declination"` // panel tilt in degrees
Azimuth int `yaml:"azimuth"` // degrees from south (south=0, west=90)
KWp float64 `yaml:"kwp"` // installed peak power
FetchInterval string `yaml:"fetch_interval"` // how often to re-fetch during the day (e.g. "4h")
FetchWindowStart string `yaml:"fetch_window_start"` // e.g. "07:00" — no fetches before this
FetchWindowEnd string `yaml:"fetch_window_end"` // e.g. "19:00" — no fetches after this
}
func (f *ForecastConfig) FetchIntervalParsed() time.Duration {
d, err := time.ParseDuration(f.FetchInterval)
if err != nil || d <= 0 {
return 24 * time.Hour // safe default: once per day
}
return d
}
// EMSConfig holds operational settings for the EMS daemon.