Loadpoint: show remaining duration when soc estimator is disabled (#27772)

This commit is contained in:
Ingo 2026-03-10 14:25:29 +01:00 • committed by GitHub
parent 1ea07c6dba
commit b636d37f6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 34 additions and 22 deletions

View file

@ -1765,10 +1765,10 @@ func (lp *Loadpoint) publishSocAndRange() {
return socR, limitR
}
soc, limit := socAndLimit("charger", lp.charger)
if soc == nil && (lp.vehicleSocPollAllowed() || lp.chargerHasFeature(api.IntegratedDevice)) {
socR, limitR := socAndLimit("charger", lp.charger)
if socR == nil && (lp.vehicleSocPollAllowed() || lp.chargerHasFeature(api.IntegratedDevice)) {
lp.socUpdated = lp.clock.Now()
soc, limit = socAndLimit("vehicle", lp.GetVehicle())
socR, limitR = socAndLimit("vehicle", lp.GetVehicle())
// range
if vs, ok := lp.GetVehicle().(api.VehicleRange); ok {
@ -1781,35 +1781,42 @@ func (lp *Loadpoint) publishSocAndRange() {
}
}
if soc != nil {
if socR != nil {
if socEstimator == nil {
lp.vehicleSoc = *soc
lp.vehicleSoc = *socR
} else {
lp.vehicleSoc = socEstimator.Soc(soc, lp.GetChargedEnergy())
lp.vehicleSoc = socEstimator.Soc(socR, lp.GetChargedEnergy())
lp.log.DEBUG.Printf("vehicle soc (estimator): %.0f%%", lp.vehicleSoc)
}
}
lp.publish(keys.VehicleSoc, lp.vehicleSoc)
apiLimitSoc := 100
if limit != nil {
apiLimitSoc = int(*limit)
if limitR != nil {
apiLimitSoc = int(*limitR)
// https://github.com/evcc-io/evcc/issues/13349
lp.publish(keys.VehicleLimitSoc, float64(*limit))
lp.publish(keys.VehicleLimitSoc, float64(*limitR))
}
if socEstimator != nil {
// use minimum of vehicle and loadpoint
limitSoc := min(apiLimitSoc, lp.EffectiveLimitSoc())
limitSoc := min(apiLimitSoc, lp.EffectiveLimitSoc())
v := lp.GetVehicle()
var d time.Duration
var d time.Duration
var e float64
switch {
case socEstimator != nil:
if lp.charging() {
d = socEstimator.RemainingChargeDuration(float64(limitSoc), lp.chargePower)
}
lp.SetRemainingDuration(d)
lp.SetRemainingEnergy(socEstimator.RemainingChargeEnergy(limitSoc))
e = socEstimator.RemainingChargeEnergy(limitSoc)
case v != nil && v.Capacity() > 0 && lp.vehicleSoc > 0:
if lp.charging() {
d = soc.RemainingChargeDuration(float64(limitSoc), lp.chargePower, lp.vehicleSoc, v.Capacity())
}
e = soc.RemainingChargeEnergy(limitSoc, lp.vehicleSoc, v.Capacity())
}
lp.SetRemainingDuration(d)
lp.SetRemainingEnergy(e)
// trigger message after variables are updated
lp.bus.Publish(evVehicleSoc, lp.vehicleSoc)

View file

@ -78,14 +78,19 @@ func remainingChargeDuration(targetSoc, chargePower, vehicleSoc, virtualCapacity
// RemainingChargeEnergy returns the remaining charge energy in kWh
func (s *Estimator) RemainingChargeEnergy(targetSoc int) float64 {
percentRemaining := float64(targetSoc) - s.vehicleSoc
if percentRemaining <= 0 || s.virtualCapacity <= 0 {
return remainingChargeEnergy(targetSoc, s.vehicleSoc, s.virtualCapacity)
}
func RemainingChargeEnergy(targetSoc int, vehicleSoc, capacity float64) float64 {
return remainingChargeEnergy(targetSoc, vehicleSoc, capacity*1e3/ChargeEfficiency)
}
func remainingChargeEnergy(targetSoc int, vehicleSoc, virtualCapacity float64) float64 {
percentRemaining := float64(targetSoc) - vehicleSoc
if percentRemaining <= 0 || virtualCapacity <= 0 {
return 0
}
// estimate remaining energy
whRemaining := percentRemaining / 100 * s.virtualCapacity
return whRemaining / 1e3
return percentRemaining / 100 * virtualCapacity / 1e3
}
// Soc replaces the api.Vehicle.Soc interface to take charged energy into account