From 479377f0d475ef77bb092699cd6c85313e338026 Mon Sep 17 00:00:00 2001 From: andig Date: Thu, 20 Jan 2022 19:40:49 +0100 Subject: [PATCH] Add soc push event every 10% charge progress (#2337) --- core/loadpoint.go | 16 ++++++++++++++++ core/loadpoint_test.go | 7 ++++--- core/progress.go | 29 +++++++++++++++++++++++++++++ core/progress_test.go | 33 +++++++++++++++++++++++++++++++++ evcc.dist.yaml | 3 +++ go.mod | 1 + 6 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 core/progress.go create mode 100644 core/progress_test.go diff --git a/core/loadpoint.go b/core/loadpoint.go index b542eab5c..055a291a2 100644 --- a/core/loadpoint.go +++ b/core/loadpoint.go @@ -31,6 +31,7 @@ const ( evChargePower = "power" // update chargeRater evVehicleConnect = "connect" // vehicle connected evVehicleDisconnect = "disconnect" // vehicle disconnected + evVehicleSoC = "soc" // vehicle soc progress pvTimer = "pv" pvEnable = "enable" @@ -147,6 +148,7 @@ type LoadPoint struct { chargedEnergy float64 // Charged energy while connected in Wh chargeRemainingDuration time.Duration // Remaining charge duration chargeRemainingEnergy float64 // Remaining charge energy in Wh + progress *Progress // Step-wise progress indicator } // NewLoadPointFromConfig creates a new loadpoint @@ -254,6 +256,7 @@ func NewLoadPoint(log *util.Logger) *LoadPoint { MaxCurrent: 16, // A SoC: SoCConfig{Min: 0, Target: 100}, // % GuardDuration: 5 * time.Minute, + progress: NewProgress(0, 10), // soc progress indicator } return lp @@ -431,6 +434,13 @@ func (lp *LoadPoint) evVehicleDisconnectHandler() { lp.socTimer.Reset() } +// evVehicleSoCProgressHandler sends external start event +func (lp *LoadPoint) evVehicleSoCProgressHandler(soc float64) { + if lp.progress.NextStep(soc) { + lp.pushEvent(evVehicleSoC) + } +} + // evChargeCurrentHandler publishes the charge current func (lp *LoadPoint) evChargeCurrentHandler(current float64) { if !lp.enabled { @@ -495,6 +505,7 @@ func (lp *LoadPoint) Prepare(uiChan chan<- util.Param, pushChan chan<- push.Even _ = lp.bus.Subscribe(evVehicleConnect, lp.evVehicleConnectHandler) _ = lp.bus.Subscribe(evVehicleDisconnect, lp.evVehicleDisconnectHandler) _ = lp.bus.Subscribe(evChargeCurrent, lp.evChargeCurrentHandler) + _ = lp.bus.Subscribe(evVehicleSoC, lp.evVehicleSoCProgressHandler) // publish initial values lp.publish("title", lp.Title) @@ -775,6 +786,8 @@ func (lp *LoadPoint) setActiveVehicle(vehicle api.Vehicle) { lp.applyAction(vehicle.OnIdentified()) lp.setVehiclePhases() + + lp.progress.Reset() } else { lp.socEstimator = nil @@ -1346,6 +1359,9 @@ func (lp *LoadPoint) publishSoCAndRange() { lp.publish("vehicleOdometer", odo) } } + + // trigger message after variables are updated + lp.bus.Publish(evVehicleSoC, f) } else { if errors.Is(err, api.ErrMustRetry) { lp.socUpdated = time.Time{} diff --git a/core/loadpoint_test.go b/core/loadpoint_test.go index 1928081e5..387e07977 100644 --- a/core/loadpoint_test.go +++ b/core/loadpoint_test.go @@ -379,9 +379,10 @@ func TestDisableAndEnableAtTargetSoC(t *testing.T) { bus: evbus.New(), clock: clock, charger: charger, - chargeMeter: &Null{}, // silence nil panics - chargeRater: &Null{}, // silence nil panics - chargeTimer: &Null{}, // silence nil panics + chargeMeter: &Null{}, // silence nil panics + chargeRater: &Null{}, // silence nil panics + chargeTimer: &Null{}, // silence nil panics + progress: NewProgress(0, 10), // silence nil panics MinCurrent: minA, MaxCurrent: maxA, vehicle: vehicle, // needed for targetSoC check diff --git a/core/progress.go b/core/progress.go new file mode 100644 index 000000000..73b0268e6 --- /dev/null +++ b/core/progress.go @@ -0,0 +1,29 @@ +package core + +type Progress struct { + min, step, current float64 +} + +func NewProgress(min, step float64) *Progress { + return &Progress{ + min: min, + step: step, + current: min, + } +} + +func (p *Progress) NextStep(value float64) bool { + if value >= p.current { + for p.current <= value { + p.current += p.step + } + + return true + } + + return false +} + +func (p *Progress) Reset() { + p.current = p.min +} diff --git a/core/progress_test.go b/core/progress_test.go new file mode 100644 index 000000000..1ebbfe7c7 --- /dev/null +++ b/core/progress_test.go @@ -0,0 +1,33 @@ +package core + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestProgress(t *testing.T) { + p := NewProgress(0, 10) + + tc := []struct { + value float64 + res bool + }{ + {-1, false}, + {0, true}, + {1, false}, + {5, false}, + {10, true}, + {15, false}, + {25, true}, + {30, true}, + {60, true}, + {65, false}, + {70, true}, + } + + for _, tc := range tc { + require.Equal(t, tc.res, p.NextStep(tc.value), fmt.Sprintf("%.0f%%", tc.value)) + } +} diff --git a/evcc.dist.yaml b/evcc.dist.yaml index a825b0c09..8c8927f30 100644 --- a/evcc.dist.yaml +++ b/evcc.dist.yaml @@ -166,6 +166,9 @@ messaging: disconnect: # vehicle connected event title: Car disconnected msg: Car disconnected after ${connectedDuration} + soc: # vehicle soc update event + title: SoC updated + msg: Battery charged to ${vehicleSoC:%.0f}% services: # - type: pushover # app: # app id diff --git a/go.mod b/go.mod index ca4ac84d4..c337ab082 100644 --- a/go.mod +++ b/go.mod @@ -83,6 +83,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.10.1 + github.com/stretchr/testify v1.7.0 github.com/thoas/go-funk v0.9.1 github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c github.com/volkszaehler/mbmd v0.0.0-20220108103619-de9b2cf95ebe