Add various condition for stopping target charging (#2098)

This commit is contained in:
andig 2021-12-29 14:50:18 +01:00 • committed by GitHub
parent fe0572544b
commit f4b783a007
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 24 deletions

View file

@ -416,6 +416,9 @@ func (lp *LoadPoint) evVehicleDisconnectHandler() {
// soc update reset
lp.socUpdated = time.Time{}
// reset timer when vehicle is removed
lp.socTimer.Reset()
}
// evChargeCurrentHandler publishes the charge current
@ -1367,6 +1370,9 @@ func (lp *LoadPoint) Update(sitePower float64, cheap bool, batteryBuffered bool)
// track if remote disabled is actually active
remoteDisabled := loadpoint.RemoteEnable
// reset detection if soc timer needs be deactived after evaluating the loading strategy
lp.socTimer.MustValidateDemand()
// execute loading strategy
switch {
case !lp.connected():
@ -1440,6 +1446,11 @@ func (lp *LoadPoint) Update(sitePower float64, cheap bool, batteryBuffered bool)
err = lp.setLimit(targetCurrent, required)
}
// stop an active target charging session if not currently evaluated
if !lp.socTimer.DemandValidated() {
lp.socTimer.Stop()
}
// effective disabled status
if remoteDisabled != loadpoint.RemoteEnable {
lp.publish("remoteDisabled", remoteDisabled)

View file

@ -118,8 +118,7 @@ func (lp *LoadPoint) SetTargetCharge(finishAt time.Time, soc int) {
// apply immediately
if lp.socTimer.Time != finishAt || lp.SoC.Target != soc {
lp.socTimer.Time = finishAt
lp.publish("targetTime", finishAt)
lp.socTimer.Set(finishAt)
// don't remove soc
if !finishAt.IsZero() {

View file

@ -15,12 +15,13 @@ const (
// Timer is the target charging handler
type Timer struct {
Adapter
log *util.Logger
current float64
SoC int
Time time.Time
finishAt time.Time
active bool
log *util.Logger
current float64
SoC int
Time time.Time
finishAt time.Time
active bool
validated bool
}
// NewTimer creates a Timer
@ -33,30 +34,65 @@ func NewTimer(log *util.Logger, api Adapter) *Timer {
return lp
}
// MustValidateDemand resets the flag for detecting if DemandActive has been called
func (lp *Timer) MustValidateDemand() {
if lp == nil {
return
}
lp.validated = false
}
// DemandValidated returns if DemandActive has been called
func (lp *Timer) DemandValidated() bool {
if lp == nil {
return false
}
return lp.validated
}
// Stop stops the target charging request
func (lp *Timer) Stop() {
if lp == nil {
return
}
if lp.active {
lp.active = false
lp.Publish("targetTimeActive", lp.active)
lp.log.DEBUG.Println("target charging: disable")
}
}
// Set sets the target charging time
func (lp *Timer) Set(t time.Time) {
if lp == nil {
return
}
lp.Time = t
lp.Publish("targetTime", lp.Time)
}
// Reset resets the target charging request
func (lp *Timer) Reset() {
if lp == nil {
return
}
lp.current = lp.GetMaxCurrent()
lp.Time = time.Time{}
lp.active = false
lp.Set(time.Time{})
lp.Stop()
}
// DemandActive calculates remaining charge duration and returns true if charge start is required to achieve target soc in time
func (lp *Timer) DemandActive() bool {
if lp == nil {
if lp == nil || lp.Time.IsZero() {
return false
}
if lp.Time.IsZero() {
return false
}
defer func() {
lp.Publish("targetTimeActive", lp.active)
}()
// demand validation has been called
lp.validated = true
// power
power := lp.GetMaxPower()
@ -66,12 +102,12 @@ func (lp *Timer) DemandActive() bool {
se := lp.SocEstimator()
if se == nil {
lp.log.WARN.Printf("target charging: not possible")
lp.log.WARN.Println("target charging: not possible")
return false
}
// time
remainingDuration := se.AssumedChargeDuration(lp.SoC, power)
remainingDuration := time.Duration(float64(se.AssumedChargeDuration(lp.SoC, power)) / chargeEfficiency)
lp.finishAt = time.Now().Add(remainingDuration).Round(time.Minute)
lp.log.DEBUG.Printf("estimated charge duration: %v to %d%% at %.0fW", remainingDuration.Round(time.Minute), lp.SoC, power)
@ -85,15 +121,17 @@ func (lp *Timer) DemandActive() bool {
// timer charging is already active- only deactivate once charging has stopped
if lp.active {
if time.Now().After(lp.Time) && lp.GetStatus() != api.StatusC {
lp.log.INFO.Printf("target charging: deactivating")
lp.active = false
lp.Stop()
}
return lp.active
}
// check if charging need be activated
if lp.active = lp.finishAt.After(lp.Time); lp.active {
if active := lp.finishAt.After(lp.Time); active {
lp.active = active
lp.Publish("targetTimeActive", lp.active)
lp.current = lp.GetMaxCurrent()
lp.log.INFO.Printf("target charging active for %v: projected %v (%v remaining)", lp.Time, lp.finishAt, remainingDuration.Round(time.Minute))
}