From 4dd1c4649734148d3f635ed6f814e760edcdf6fb Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 6 May 2020 19:17:29 +0200 Subject: [PATCH] =?UTF-8?q?Ensure=20charger=20target=20status=20is=20alway?= =?UTF-8?q?s=20updated=20even=20while=20car=20disconn=E2=80=A6=20(#106)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/chargerhandler.go | 6 ++--- core/loadpoint.go | 51 ++++++++++++++++++++++++++---------------- core/loadpoint_test.go | 5 +++-- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/core/chargerhandler.go b/core/chargerhandler.go index ea6b3c930e..7cce716660 100644 --- a/core/chargerhandler.go +++ b/core/chargerhandler.go @@ -118,11 +118,11 @@ func (lp *ChargerHandler) rampUpDown(target int64) error { // Setting current and disabling are two steps. If already disabled, this is a nop. func (lp *ChargerHandler) rampOff() error { if lp.enabled { - if lp.targetCurrent == lp.MinCurrent { - return lp.chargerEnable(false) + if lp.targetCurrent != lp.MinCurrent { + return lp.setTargetCurrent(lp.MinCurrent) } - return lp.setTargetCurrent(lp.MinCurrent) + return lp.chargerEnable(false) } return nil diff --git a/core/loadpoint.go b/core/loadpoint.go index cca544ac5f..f51538a3bb 100644 --- a/core/loadpoint.go +++ b/core/loadpoint.go @@ -345,8 +345,7 @@ func (lp *LoadPoint) updateChargeStatus() api.ChargeStatus { return status } -// updateModePV sets "minpv" or "pv" load modes -func (lp *LoadPoint) updateModePV(mode api.ChargeMode) error { +func (lp *LoadPoint) maxCurrent(mode api.ChargeMode) int64 { // grid meter will always be available, if as wrapped pv meter targetPower := lp.chargePower - lp.gridPower - lp.batteryPower - lp.ResidualPower if lp.batteryMeter == nil { @@ -366,6 +365,19 @@ func (lp *LoadPoint) updateModePV(mode api.ChargeMode) error { } } + return targetCurrent +} + +// updateModePV handles "minpv" or "pv" modes by setting charger enabled/disabled state +// and maximum current according to available PV power +func (lp *LoadPoint) updateModePV(mode api.ChargeMode) error { + targetCurrent := lp.maxCurrent(mode) + if !lp.connected() { + // ensure minimum current when not connected + // https://github.com/andig/evcc/issues/105 + targetCurrent = min(lp.MinCurrent, targetCurrent) + } + log.DEBUG.Printf("%s target charge current: %dA", lp.Name, targetCurrent) if targetCurrent == 0 { @@ -435,24 +447,25 @@ func (lp *LoadPoint) update() { // check if car connected and ready for charging var err error - if !lp.connected() { - // ensure restart at min current - err = lp.setTargetCurrent(lp.MinCurrent) - } else { - // execute loading strategy - switch mode := lp.GetMode(); mode { - case api.ModeOff: - err = lp.rampOff() - case api.ModeNow: - err = lp.rampOn(lp.MaxCurrent) - case api.ModeMinPV, api.ModePV: - if meterErr == nil { - // pv modes require meter measurements - err = lp.updateModePV(mode) - } else { - log.WARN.Printf("%s aborting due to meter error", lp.Name) - } + + // execute loading strategy + switch mode := lp.GetMode(); mode { + case api.ModeOff: + err = lp.rampOff() + case api.ModeNow: + // ensure that new connections happen at min current + current := lp.MinCurrent + if lp.connected() { + current = lp.MaxCurrent + } + err = lp.rampOn(current) + case api.ModeMinPV, api.ModePV: + // pv modes require meter measurements + if meterErr != nil { + log.WARN.Printf("%s aborting due to meter error", lp.Name) + break } + err = lp.updateModePV(mode) } if err != nil { diff --git a/core/loadpoint_test.go b/core/loadpoint_test.go index a0ad214ec2..69684de80c 100644 --- a/core/loadpoint_test.go +++ b/core/loadpoint_test.go @@ -133,7 +133,8 @@ func TestMeterConfigurations(t *testing.T) { ctrl := gomock.NewController(t) lp, wb := newEnvironment(t, ctrl, pm, gm, cm) - wb.EXPECT().Status().Return(api.StatusA, nil) + wb.EXPECT().Status().Return(api.StatusA, nil) // disconnected + wb.EXPECT().Enable(false) // "off" mode lp.update() } @@ -184,7 +185,7 @@ func TestInitialUpdate(t *testing.T) { } // disable if not connected - if tc.status != api.StatusA && tc.mode == api.ModeOff { + if tc.mode == api.ModeOff { wb.EXPECT().Enable(false) }