Optimizer: add plan goals and charge modes
This commit is contained in:
parent
733a3843fc
commit
bdd1857278
2 changed files with 46 additions and 1 deletions
|
|
@ -117,7 +117,7 @@ type API interface {
|
|||
GetPlanEnergy() (time.Time, time.Duration, float64)
|
||||
// SetPlanEnergy sets the charge plan energy
|
||||
SetPlanEnergy(time.Time, time.Duration, float64) error
|
||||
// GetPlanGoal returns the plan goal, precondition duration and if the goal is soc based
|
||||
// GetPlanGoal returns the plan goal and if the goal is soc based
|
||||
GetPlanGoal() (float64, bool)
|
||||
// GetPlanRequiredDuration returns required duration of plan to reach the goal from current state
|
||||
GetPlanRequiredDuration(goal, maxPower float64) time.Duration
|
||||
|
|
|
|||
|
|
@ -170,6 +170,35 @@ func (site *Site) optimizerUpdate(battery []measurement) error {
|
|||
}
|
||||
}
|
||||
|
||||
switch lp.GetMode() {
|
||||
case api.ModeOff:
|
||||
// disable charging
|
||||
bat.CMax = 0
|
||||
|
||||
case api.ModeNow, api.ModeMinPV:
|
||||
// forced min/max charging
|
||||
bat.PDemand = continuousDemand(lp, minLen)
|
||||
|
||||
case api.ModePV:
|
||||
// add plan goal
|
||||
goal, socBased := lp.GetPlanGoal()
|
||||
if goal > 0 {
|
||||
if v := lp.GetVehicle(); socBased && v != nil {
|
||||
goal *= v.Capacity()
|
||||
}
|
||||
}
|
||||
|
||||
if ts := lp.EffectivePlanTime(); !ts.IsZero() {
|
||||
// TODO precise slot placement
|
||||
if slot := int(time.Until(ts) / time.Hour); slot < minLen {
|
||||
bat.SGoal = lo.ToPtr(lo.RepeatBy(minLen, func(_ int) float32 { return 0 }))
|
||||
(*bat.SGoal)[slot] = float32(goal)
|
||||
} else {
|
||||
site.log.WARN.Printf("plan beyond forecast range: %.1f at %v", goal, ts.Round(time.Minute))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req.Batteries = append(req.Batteries, bat)
|
||||
|
||||
details.BatteryDetails = append(details.BatteryDetails, detail)
|
||||
|
|
@ -259,6 +288,22 @@ func (site *Site) optimizerUpdate(battery []measurement) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// continuousDemand creates a slice of power demands depending on loadpoint mode
|
||||
func continuousDemand(lp loadpoint.API, minLen int) *[]float32 {
|
||||
if lp.GetStatus() != api.StatusC {
|
||||
return nil
|
||||
}
|
||||
|
||||
pwr := lp.EffectiveMaxPower()
|
||||
if lp.GetMode() == api.ModeMinPV {
|
||||
pwr = lp.EffectiveMinPower()
|
||||
}
|
||||
|
||||
return lo.ToPtr(lo.RepeatBy(minLen, func(_ int) float32 {
|
||||
return float32(pwr)
|
||||
}))
|
||||
}
|
||||
|
||||
// loadpointProfile returns the loadpoint's charging profile in Wh
|
||||
// TODO consider charging efficiency
|
||||
func loadpointProfile(lp loadpoint.API, firstSlotDuration time.Duration, minLen int) []float64 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue