Optimizer: extend horizon to 48h plus end of day (#32893)
This commit is contained in:
parent
64d48e5800
commit
4cc75b1a45
2 changed files with 47 additions and 2 deletions
|
|
@ -413,8 +413,7 @@ func (site *Site) optimizerRequest(battery []types.Measurement) (optimizer.Optim
|
|||
}
|
||||
|
||||
if optimizerURI() == OPTIMIZER_URI {
|
||||
// limit to 2 days for sake of performance
|
||||
minLen = min(2*96, minLen)
|
||||
minLen = slotsUntil(grid, optimizerHorizon(time.Now()), minLen)
|
||||
}
|
||||
|
||||
if expectedSlots := 8; minLen < expectedSlots {
|
||||
|
|
@ -1127,6 +1126,27 @@ func currentRates(tariff api.Tariff) api.Rates {
|
|||
})
|
||||
}
|
||||
|
||||
// optimizerHorizon is the timeframe the hosted optimizer is limited to for sake
|
||||
// of performance: 48 hours, extended to the end of that day. In the early hours
|
||||
// the extension would add almost a full day, hence it only applies past 6:00.
|
||||
func optimizerHorizon(t time.Time) time.Time {
|
||||
horizon := t.Add(48 * time.Hour)
|
||||
if t.Hour() < 6 {
|
||||
return horizon
|
||||
}
|
||||
return now.With(horizon).EndOfDay()
|
||||
}
|
||||
|
||||
// slotsUntil limits maxLen to the slots starting before the given horizon
|
||||
func slotsUntil(rates api.Rates, horizon time.Time, maxLen int) int {
|
||||
if i := slices.IndexFunc(rates[:min(maxLen, len(rates))], func(slot api.Rate) bool {
|
||||
return slot.Start.After(horizon)
|
||||
}); i >= 0 {
|
||||
return i
|
||||
}
|
||||
return maxLen
|
||||
}
|
||||
|
||||
func timeSteps(minLen int, now time.Time) []int {
|
||||
res := make([]int, 0, minLen)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/core/loadpoint"
|
||||
"github.com/evcc-io/evcc/core/types"
|
||||
"github.com/evcc-io/evcc/tariff"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
"github.com/evcc-io/evcc/util/config"
|
||||
optimizer "github.com/evcc-io/optimizer/client"
|
||||
|
|
@ -29,6 +30,30 @@ func TestLoadpointProfile(t *testing.T) {
|
|||
require.Equal(t, []float64{250, 250, 250, 250, 250, 250, 250, 50}, loadpointProfile(lp, 8))
|
||||
}
|
||||
|
||||
func TestOptimizerHorizon(t *testing.T) {
|
||||
ts := time.Date(2025, 1, 1, 10, 30, 0, 0, time.Local)
|
||||
horizon := optimizerHorizon(ts)
|
||||
|
||||
// 48h plus end of day
|
||||
assert.Equal(t, time.Date(2025, 1, 3, 23, 59, 59, int(time.Second-time.Nanosecond), time.Local), horizon)
|
||||
|
||||
// before 6:00 the day is not extended
|
||||
assert.Equal(t, time.Date(2025, 1, 3, 5, 30, 0, 0, time.Local),
|
||||
optimizerHorizon(time.Date(2025, 1, 1, 5, 30, 0, 0, time.Local)))
|
||||
|
||||
rates := make(api.Rates, 0, 4*96)
|
||||
for slot := ts.Truncate(tariff.SlotDuration); len(rates) < cap(rates); slot = slot.Add(tariff.SlotDuration) {
|
||||
rates = append(rates, api.Rate{Start: slot, End: slot.Add(tariff.SlotDuration)})
|
||||
}
|
||||
|
||||
// 4 days of slots from 10:30, capped at the last slot of Jan 3rd
|
||||
assert.Equal(t, 246, slotsUntil(rates, horizon, len(rates)))
|
||||
assert.Equal(t, time.Date(2025, 1, 3, 23, 45, 0, 0, time.Local), rates[245].Start)
|
||||
|
||||
// shorter forecast is not extended
|
||||
assert.Equal(t, 8, slotsUntil(rates, horizon, 8))
|
||||
}
|
||||
|
||||
func TestApplyPrecondition(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue