From 0643648a944e61bf3fdc79aaeb05f26468cd3971 Mon Sep 17 00:00:00 2001 From: andig Date: Fri, 23 Jan 2026 17:26:49 +0100 Subject: [PATCH] Loadpoint: fix soc read from offline vehicles (#26942) --- core/loadpoint.go | 28 ++++++++++++---------------- core/loadpoint_vehicle.go | 4 ++++ core/loadpoint_vehicle_test.go | 9 +++++++-- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/core/loadpoint.go b/core/loadpoint.go index 591d23b51..555670f5a 100644 --- a/core/loadpoint.go +++ b/core/loadpoint.go @@ -1760,14 +1760,20 @@ func (lp *Loadpoint) publishSocAndRange() { return socR, limitR } - pollAllowed := lp.vehicleSocPollAllowed() - if pollAllowed { - lp.socUpdated = lp.clock.Now() - } - soc, limit := socAndLimit("charger", lp.charger) - if soc == nil && (pollAllowed || lp.chargerHasFeature(api.IntegratedDevice)) { + if soc == nil && (lp.vehicleSocPollAllowed() || lp.chargerHasFeature(api.IntegratedDevice)) { + lp.socUpdated = lp.clock.Now() soc, limit = socAndLimit("vehicle", lp.GetVehicle()) + + // range + if vs, ok := lp.GetVehicle().(api.VehicleRange); ok { + if rng, err := vs.Range(); err == nil { + lp.log.DEBUG.Printf("vehicle range: %dkm", rng) + lp.publish(keys.VehicleRange, rng) + } else if !loadpoint.AcceptableError(err) { + lp.log.ERROR.Printf("vehicle range: %v", err) + } + } } if soc != nil { @@ -1800,16 +1806,6 @@ func (lp *Loadpoint) publishSocAndRange() { lp.SetRemainingEnergy(socEstimator.RemainingChargeEnergy(limitSoc)) } - // range - if vs, ok := lp.GetVehicle().(api.VehicleRange); ok && pollAllowed { - if rng, err := vs.Range(); err == nil { - lp.log.DEBUG.Printf("vehicle range: %dkm", rng) - lp.publish(keys.VehicleRange, rng) - } else if !loadpoint.AcceptableError(err) { - lp.log.ERROR.Printf("vehicle range: %v", err) - } - } - // trigger message after variables are updated lp.bus.Publish(evVehicleSoc, lp.vehicleSoc) } diff --git a/core/loadpoint_vehicle.go b/core/loadpoint_vehicle.go index e68d29ea1..8c23aa01d 100644 --- a/core/loadpoint_vehicle.go +++ b/core/loadpoint_vehicle.go @@ -326,6 +326,10 @@ func (lp *Loadpoint) vehicleClimatePollAllowed() bool { // vehicleSocPollAllowed validates charging state against polling mode func (lp *Loadpoint) vehicleSocPollAllowed() bool { + if lp.vehicleHasFeature(api.Offline) { + return false + } + // always update soc when charging if lp.charging() || lp.vehicleHasFeature(api.Streaming) { return true diff --git a/core/loadpoint_vehicle_test.go b/core/loadpoint_vehicle_test.go index c61ddca8a..2cdcfd10f 100644 --- a/core/loadpoint_vehicle_test.go +++ b/core/loadpoint_vehicle_test.go @@ -113,7 +113,8 @@ func TestPublishSocAndRangeVehiclesAndChargers(t *testing.T) { charger api.Charger vehicle api.Vehicle soc float64 - socBased bool + socBased bool // soc based planning + socPoll bool // may poll vehicle }{ { name: "offline vehicle", @@ -121,6 +122,7 @@ func TestPublishSocAndRangeVehiclesAndChargers(t *testing.T) { vehicle: offlineVehicle, soc: 0.0, socBased: false, + socPoll: false, }, { name: "regular vehicle", @@ -128,6 +130,7 @@ func TestPublishSocAndRangeVehiclesAndChargers(t *testing.T) { vehicle: vehicle, soc: socVehicle, socBased: true, + socPoll: true, }, { name: "offline vehicle with iso charger", @@ -135,6 +138,7 @@ func TestPublishSocAndRangeVehiclesAndChargers(t *testing.T) { vehicle: offlineVehicle, soc: socCharger, socBased: true, + socPoll: false, }, { name: "regular vehicle with iso charger", @@ -142,6 +146,7 @@ func TestPublishSocAndRangeVehiclesAndChargers(t *testing.T) { vehicle: vehicle, soc: socCharger, socBased: true, + socPoll: true, }, } @@ -167,7 +172,7 @@ func TestPublishSocAndRangeVehiclesAndChargers(t *testing.T) { attachChannels(lp, x, y, z) test := func(t *testing.T) { - assert.True(t, lp.vehicleSocPollAllowed()) + assert.Equal(t, tc.socPoll, lp.vehicleSocPollAllowed()) lp.publishSocAndRange() assert.Equal(t, tc.soc, lp.vehicleSoc)