Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repeating plans: improve overrun behavior #17834

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions core/loadpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,13 @@ type Loadpoint struct {
socEstimator *soc.Estimator

// charge planning
planner *planner.Planner
planTime time.Time // time goal
planEnergy float64 // Plan charge energy in kWh (dumb vehicles)
planSlotEnd time.Time // current plan slot end time
planActive bool // charge plan exists and has a currently active slot
planner *planner.Planner
planTime time.Time // time goal
planEnergy float64 // Plan charge energy in kWh (dumb vehicles)
planSlotEnd time.Time // current plan slot end time
planActive bool // charge plan exists and has a currently active slot
planActiveTime time.Time // needed to calculate the EffectivePlanTime if loading exceeds the target time
planActiveSoc float64 // needed to calculate the EffectivePlanSoc if loading exceeds the target time
Maschga marked this conversation as resolved.
Show resolved Hide resolved

// cached state
status api.ChargeStatus // Charger status
Expand Down
17 changes: 14 additions & 3 deletions core/loadpoint_effective.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ func (lp *Loadpoint) nextVehiclePlan() (time.Time, int, int) {

// EffectivePlanSoc returns the soc target for the current plan
func (lp *Loadpoint) EffectivePlanSoc() int {
if lp.planActive {
return int(lp.planActiveSoc)
}

_, soc, _ := lp.nextVehiclePlan()

return soc
}

Expand All @@ -95,12 +100,18 @@ func (lp *Loadpoint) EffectivePlanId() int {

// EffectivePlanTime returns the effective plan time
func (lp *Loadpoint) EffectivePlanTime() time.Time {
if lp.planActive {
return lp.planActiveTime
}

var ts time.Time

if lp.socBasedPlanning() {
ts, _, _ := lp.nextVehiclePlan()
return ts
ts, _, _ = lp.nextVehiclePlan()
} else {
ts, _ = lp.GetPlanEnergy()
}

ts, _ := lp.GetPlanEnergy()
return ts
}

Expand Down
35 changes: 21 additions & 14 deletions core/loadpoint_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const (
func (lp *Loadpoint) setPlanActive(active bool) {
if !active {
lp.planSlotEnd = time.Time{}
lp.planActiveTime = time.Time{}
lp.planActiveSoc = 0.0
}
if lp.planActive != active {
lp.planActive = active
Expand All @@ -37,6 +39,7 @@ func (lp *Loadpoint) finishPlan() {
} else if v := lp.GetVehicle(); v != nil {
vehicle.Settings(lp.log, v).SetPlanSoc(time.Time{}, 0)
}
lp.log.DEBUG.Println("plan: deleting expired plan")
}

// remainingPlanEnergy returns missing energy amount in kWh
Expand Down Expand Up @@ -85,32 +88,36 @@ func (lp *Loadpoint) GetPlan(targetTime time.Time, requiredDuration time.Duratio

// plannerActive checks if the charging plan has a currently active slot
func (lp *Loadpoint) plannerActive() (active bool) {
defer func() {
lp.setPlanActive(active)
}()

var planStart, planEnd time.Time
var planOverrun time.Duration

defer func() {
lp.publish(keys.PlanProjectedStart, planStart)
lp.publish(keys.PlanProjectedEnd, planEnd)
lp.publish(keys.PlanOverrun, planOverrun)
}()

planTime := lp.EffectivePlanTime()
if planTime.IsZero() {
return false
}

// keep overrunning plans as long as a vehicle is connected
if lp.clock.Until(planTime) < 0 && (!lp.planActive || !lp.connected()) {
lp.log.DEBUG.Println("plan: deleting expired plan")
lp.finishPlan()
return false
}

goal, isSocBased := lp.GetPlanGoal()

defer func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wieso hast du diesen Block nach unten geschoben? Das ändert ja das Laufzeitverhalten, da er nun nicht mehr ausgeführt wird, wenn die plannerActive() Funktion vorher returned.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Das habe ich verschoben, um die Werte von planTime und goal nutzen zu können.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zum besseren Verständnis: Der defer func() Inhalt wird ausgeführt, nachdem der plannerActive Aufruf beendet wurde. Das heißt lp.publish(keys.PlanOverrun, planOverrun) wurde bislang immer(!) ausgeführt. planOverrun hat dabei den Wert nach Ende des Funktionsdurchlaufs. Nun wird es nicht mehr immer ausgeführt.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Danke, da habe ich die defer-Funktionen noch nicht richtig verstanden. Passt jetzt die Logik?

if active {
lp.planActiveTime = planTime
if isSocBased {
lp.planActiveSoc = goal
}
}

lp.setPlanActive(active)

lp.publish(keys.PlanProjectedStart, planStart)
lp.publish(keys.PlanProjectedEnd, planEnd)
lp.publish(keys.PlanOverrun, planOverrun)
}()

maxPower := lp.EffectiveMaxPower()
requiredDuration := lp.GetPlanRequiredDuration(goal, maxPower)
if requiredDuration <= 0 {
Expand Down Expand Up @@ -157,8 +164,8 @@ func (lp *Loadpoint) plannerActive() (active bool) {
}

// remember last active plan's end time
lp.setPlanActive(true)
lp.planSlotEnd = activeSlot.End
return true
} else if lp.planActive {
// planner was active (any slot, not necessarily previous slot) and charge goal has not yet been met
switch {
Expand All @@ -180,5 +187,5 @@ func (lp *Loadpoint) plannerActive() (active bool) {
}
}

return active
return false
}
Loading