Loadpoint: ignore charge interruption during phase switch (#33109)
This commit is contained in:
parent
c1960b378a
commit
3159126248
2 changed files with 58 additions and 2 deletions
|
|
@ -1236,7 +1236,15 @@ func (lp *Loadpoint) getStatusChanges() ([]api.ChargeStatus, error) {
|
|||
|
||||
// detect if charger status changed
|
||||
prevStatus := lp.GetStatus()
|
||||
if status != prevStatus {
|
||||
|
||||
// ignore charge interruption while switching phases. Status is left unchanged,
|
||||
// hence a real interruption is detected once the timespan has elapsed.
|
||||
ignore := status == api.StatusB && prevStatus == api.StatusC && !lp.phaseSwitchCompleted()
|
||||
|
||||
switch {
|
||||
case ignore:
|
||||
lp.log.DEBUG.Println("ignoring charge interruption during phase switch")
|
||||
case status != prevStatus:
|
||||
res = []api.ChargeStatus{status}
|
||||
}
|
||||
|
||||
|
|
@ -1250,7 +1258,7 @@ func (lp *Loadpoint) getStatusChanges() ([]api.ChargeStatus, error) {
|
|||
defer func() { lp.connectedDuration = d }()
|
||||
|
||||
// connection duration dropped without disconnect status, indicates intermediate disconnect
|
||||
if status != api.StatusA && prevStatus != api.StatusA && d < lp.connectedDuration {
|
||||
if !ignore && status != api.StatusA && prevStatus != api.StatusA && d < lp.connectedDuration {
|
||||
lp.log.DEBUG.Printf("connection duration drop detected (%s -> %v)", lp.connectedDuration.Round(time.Second), d.Round(time.Second))
|
||||
res = []api.ChargeStatus{api.StatusA, status}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,13 @@ package core
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
func TestStatusEvents(t *testing.T) {
|
||||
|
|
@ -31,3 +35,47 @@ func TestStatusEvents(t *testing.T) {
|
|||
assert.Equalf(t, tc.events, ev, "from %s to %s got: %v", tc.from, tc.to, ev)
|
||||
}
|
||||
}
|
||||
|
||||
// TestPhaseSwitchInterruption verifies that a charge interruption right after a phase
|
||||
// switch is ignored while a real interruption is still detected
|
||||
func TestPhaseSwitchInterruption(t *testing.T) {
|
||||
tc := []struct {
|
||||
desc string
|
||||
since time.Duration
|
||||
connection time.Duration
|
||||
expected []api.ChargeStatus
|
||||
}{
|
||||
// the connection duration drops on interruption, too, and must not surface as intermediate disconnect
|
||||
{"during phase switch", phaseSwitchDuration - time.Second, time.Minute, nil},
|
||||
{"after phase switch", phaseSwitchDuration + time.Second, 2 * time.Hour, []api.ChargeStatus{api.StatusB}},
|
||||
}
|
||||
|
||||
for _, tc := range tc {
|
||||
ctrl := gomock.NewController(t)
|
||||
|
||||
charger := api.NewMockCharger(ctrl)
|
||||
charger.EXPECT().Status().Return(api.StatusB, nil)
|
||||
|
||||
timer := api.NewMockConnectionTimer(ctrl)
|
||||
timer.EXPECT().ConnectionDuration().Return(tc.connection, nil)
|
||||
|
||||
lp := &Loadpoint{
|
||||
log: util.NewLogger("foo"),
|
||||
charger: struct {
|
||||
*api.MockCharger
|
||||
*api.MockConnectionTimer
|
||||
}{charger, timer},
|
||||
status: api.StatusC,
|
||||
phasesSwitched: time.Now().Add(-tc.since),
|
||||
connectedDuration: time.Hour,
|
||||
}
|
||||
|
||||
res, err := lp.getStatusChanges()
|
||||
require.NoError(t, err, tc.desc)
|
||||
assert.Equal(t, tc.expected, res, tc.desc)
|
||||
assert.Equal(t, api.StatusC, lp.GetStatus(), tc.desc)
|
||||
|
||||
// connection duration is tracked even while the interruption is ignored
|
||||
assert.Equal(t, tc.connection, lp.connectedDuration, tc.desc)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue