Optimizer: limit precondition demand to required charging duration (#33139)

This commit is contained in:
Michael Geers 2026-08-24 13:51:38 +02:00 • committed by GitHub
parent e395dcf371
commit 661693952a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 0 deletions

View file

@ -1237,6 +1237,15 @@ func applyPrecondition(lp loadpoint.API, demand []float32, minLen int) []float32
return demand
}
// limit to the required charging duration, i.e. "all" must not demand beyond the plan goal
goal, _ := lp.GetPlanGoal()
if required := lp.GetPlanRequiredDuration(goal, lp.EffectiveMaxPower()); required < precondition {
precondition = required
}
if precondition <= 0 {
return demand
}
// TODO precise slot placement
end := time.Until(ts)
start := end - precondition

View file

@ -47,6 +47,8 @@ func TestApplyPrecondition(t *testing.T) {
// plan in 1h, 40min precondition: slots 1 (10min) and 2, 3 (full)
lp.EXPECT().EffectivePlanTime().Return(time.Now().Add(time.Hour)).Times(1)
lp.EXPECT().EffectivePlanStrategy().Return(api.PlanStrategy{Precondition: 40 * time.Minute}).Times(1)
lp.EXPECT().GetPlanGoal().Return(80.0, true).Times(1)
lp.EXPECT().GetPlanRequiredDuration(80.0, 8000.0).Return(2 * time.Hour).Times(1)
res := applyPrecondition(lp, nil, 8)
require.Len(t, res, 8)
assert.InDeltaSlice(t, []float32{0, 2000. / 1.5, 2000, 2000, 0, 0, 0, 0}, res, 1)
@ -54,12 +56,32 @@ func TestApplyPrecondition(t *testing.T) {
// existing demand is kept where higher
lp.EXPECT().EffectivePlanTime().Return(time.Now().Add(time.Hour)).Times(1)
lp.EXPECT().EffectivePlanStrategy().Return(api.PlanStrategy{Precondition: 30 * time.Minute}).Times(1)
lp.EXPECT().GetPlanGoal().Return(80.0, true).Times(1)
lp.EXPECT().GetPlanRequiredDuration(80.0, 8000.0).Return(2 * time.Hour).Times(1)
res = applyPrecondition(lp, []float32{3000, 3000, 3000, 3000, 0, 0, 0, 0}, 8)
assert.InDeltaSlice(t, []float32{3000, 3000, 3000, 3000, 0, 0, 0, 0}, res, 1)
// plan beyond horizon
lp.EXPECT().EffectivePlanTime().Return(time.Now().Add(24 * time.Hour)).Times(1)
lp.EXPECT().EffectivePlanStrategy().Return(api.PlanStrategy{Precondition: time.Hour}).Times(1)
lp.EXPECT().GetPlanGoal().Return(80.0, true).Times(1)
lp.EXPECT().GetPlanRequiredDuration(80.0, 8000.0).Return(2 * time.Hour).Times(1)
assert.Nil(t, applyPrecondition(lp, nil, 8))
// "all" precondition is limited to the required charging duration (#33135)
lp.EXPECT().EffectivePlanTime().Return(time.Now().Add(time.Hour)).Times(1)
lp.EXPECT().EffectivePlanStrategy().Return(api.PlanStrategy{Precondition: 7 * 24 * time.Hour}).Times(1)
lp.EXPECT().GetPlanGoal().Return(80.0, true).Times(1)
lp.EXPECT().GetPlanRequiredDuration(80.0, 8000.0).Return(40 * time.Minute).Times(1)
res = applyPrecondition(lp, nil, 8)
require.Len(t, res, 8)
assert.InDeltaSlice(t, []float32{0, 2000. / 1.5, 2000, 2000, 0, 0, 0, 0}, res, 1)
// goal already reached: no demand
lp.EXPECT().EffectivePlanTime().Return(time.Now().Add(time.Hour)).Times(1)
lp.EXPECT().EffectivePlanStrategy().Return(api.PlanStrategy{Precondition: 7 * 24 * time.Hour}).Times(1)
lp.EXPECT().GetPlanGoal().Return(80.0, true).Times(1)
lp.EXPECT().GetPlanRequiredDuration(80.0, 8000.0).Return(time.Duration(0)).Times(1)
assert.Nil(t, applyPrecondition(lp, nil, 8))
}