Repository: evcc-io/evcc
Pull request #1598 (2021-09-19 19:24:48)

Easee: check phase mode on startup
/cc @premultiply 


Patch:
diff --git a/charger/easee.go b/charger/easee.go
index 88121c69..b4033ae2 100644
--- a/charger/easee.go
+++ b/charger/easee.go
@@ -95,14 +95,6 @@ func NewEasee(user, password, charger string, circuit int, cache time.Duration)
 		Base:   c.Client.Transport,
 	}
 
-	// find site
-	site, err := c.chargerDetails()
-	if err != nil {
-		return c, err
-	}
-
-	c.site = site.ID
-
 	// find charger
 	if charger == "" {
 		chargers, err := c.chargers()
@@ -117,6 +109,14 @@ func NewEasee(user, password, charger string, circuit int, cache time.Duration)
 		c.charger = chargers[0].ID
 	}
 
+	// find site
+	site, err := c.chargerDetails(c.charger)
+	if err != nil {
+		return c, err
+	}
+
+	c.site = site.ID
+
 	// find circuit
 	if circuit == 0 {
 		if len(site.Circuits) != 1 {
@@ -126,6 +126,12 @@ func NewEasee(user, password, charger string, circuit int, cache time.Duration)
 		c.circuit = site.Circuits[0].ID
 	}
 
+	// verify charger config
+	config, err := c.chargerConfig(c.charger)
+	if err == nil && config.PhaseMode != 2 {
+		c.log.WARN.Println("expected PhaseMode auto- switching phases will NOT work")
+	}
+
 	return c, err
 }
 
@@ -140,8 +146,19 @@ func (c *Easee) chargers() (res []easee.Charger, err error) {
 	return res, err
 }
 
-func (c *Easee) chargerDetails() (res easee.Site, err error) {
-	uri := fmt.Sprintf("%s/chargers/%s/site", easee.API, c.charger)
+func (c *Easee) chargerConfig(charger string) (res easee.ChargerConfig, err error) {
+	uri := fmt.Sprintf("%s/chargers/%s/config", easee.API, charger)
+
+	req, err := request.New(http.MethodGet, uri, nil, request.JSONEncoding)
+	if err == nil {
+		err = c.DoJSON(req, &res)
+	}
+
+	return res, err
+}
+
+func (c *Easee) chargerDetails(charger string) (res easee.Site, err error) {
+	uri := fmt.Sprintf("%s/chargers/%s/site", easee.API, charger)
 
 	req, err := request.New(http.MethodGet, uri, nil, request.JSONEncoding)
 	if err == nil {
diff --git a/charger/easee/message.go b/charger/easee/message.go
index bdc805dd..9f5a91ad 100644
--- a/charger/easee/message.go
+++ b/charger/easee/message.go
@@ -16,102 +16,108 @@ const (
 
 // Charger is the charger type
 type Charger struct {
-	ID   string `json:"id"`
-	Name string `json:"name"`
+	ID   string
+	Name string
+}
+
+type ChargerConfig struct {
+	IsEnabled                    bool
+	LockCablePermanently         bool
+	AuthorizationRequired        bool
+	RemoteStartRequired          bool
+	SmartButtonEnabled           bool
+	WiFiSSID                     string
+	DetectedPowerGridType        int
+	OfflineChargingMode          int
+	CircuitMaxCurrentP1          int
+	CircuitMaxCurrentP2          int
+	CircuitMaxCurrentP3          int
+	EnableIdleCurrent            bool
+	LimitToSinglePhaseCharging   bool
+	PhaseMode                    int
+	LocalNodeType                int
+	LocalAuthorizationRequired   bool
+	LocalRadioChannel            int
+	LocalShortAddress            int
+	LocalParentAddrOrNumOfNodes  int
+	LocalPreAuthorizeEnabled     bool
+	LocalAuthorizeOfflineEnabled bool
+	AllowOfflineTxForUnknownId   bool
+	MaxChargerCurrent            int
+	LedStripBrightness           int
 }
 
 // Site is the site type
 type Site struct {
-	ID       int       `json:"id"`
-	SiteKey  string    `json:"siteKey"`
-	Name     string    `json:"name"`
-	Circuits []Circuit `json:"circuits"`
+	ID       int
+	SiteKey  string
+	Name     string
+	Circuits []Circuit
 }
 
 // Circuit is the circuit type
 type Circuit struct {
-	ID               int     `json:"id"`
-	SiteID           int     `json:"siteId"`
-	CircuitPanelID   int     `json:"circuitPanelId"`
-	PanelName        string  `json:"panelName"`
-	RatedCurrent     float64 `json:"ratedCurrent"`
-	UseDynamicMaster bool    `json:"useDynamicMaster"`
-	ParentCircuitID  int     `json:"parentCircuitId"`
-	// "chargers": [{
-	// 	"id": "string",
-	// 	"name": "string",
-	// 	"color": 1,
-	// 	"createdOn": "2021-01-19T12:39:10.359Z",
-	// 	"updatedOn": "2021-01-19T12:39:10.359Z",
-	// 	"backPlate": {
-	// 		"id": "string",
-	// 		"masterBackPlateId": "string",
-	// 		"name": "string"
-	// 	},
-	// 	"levelOfAccess": 1,
-	// 	"productCode": 1,
-	// 	"userRole": 1,
-	// 	"isTemporary": true
-	// }],
-	// "masterBackplate": {
-	// 	"id": "string",
-	// 	"masterBackPlateId": "string",
-	// 	"name": "string"
-	// },
+	ID               int
+	SiteID           int
+	CircuitPanelID   int
+	PanelName        string
+	RatedCurrent     float64
+	UseDynamicMaster bool
+	ParentCircuitID  int
 }
 
 // ChargerStatus is the charger status type
 type ChargerStatus struct {
-	SmartCharging                                bool    `json:"smartCharging"`
-	CableLocked                                  bool    `json:"cableLocked"`
-	ChargerOpMode                                int     `json:"chargerOpMode"`
-	TotalPower                                   float64 `json:"totalPower"`
-	SessionEnergy                                float64 `json:"sessionEnergy"`
-	EnergyPerHour                                float64 `json:"energyPerHour"`
-	WiFiRSSI                                     int     `json:"wiFiRSSI"`
-	CellRSSI                                     int     `json:"cellRSSI"`
-	LocalRSSI                                    int     `json:"localRSSI"`
-	OutputPhase                                  int     `json:"outputPhase"`
-	DynamicCircuitCurrentP1                      float64 `json:"dynamicCircuitCurrentP1"`
-	DynamicCircuitCurrentP2                      float64 `json:"dynamicCircuitCurrentP2"`
-	DynamicCircuitCurrentP3                      float64 `json:"dynamicCircuitCurrentP3"`
-	LatestPulse                                  string  `json:"latestPulse"`
-	ChargerFirmware                              int     `json:"chargerFirmware"`
-	LatestFirmware                               int     `json:"latestFirmware"`
-	Voltage                                      float64 `json:"voltage"`
-	ChargerRAT                                   int     `json:"chargerRAT"`
-	LockCablePermanently                         bool    `json:"lockCablePermanently"`
-	InCurrentT2                                  float64 `json:"inCurrentT2"`
-	InCurrentT3                                  float64 `json:"inCurrentT3"`
-	InCurrentT4                                  float64 `json:"inCurrentT4"`
-	InCurrentT5                                  float64 `json:"inCurrentT5"`
-	OutputCurrent                                float64 `json:"outputCurrent"`
-	IsOnline                                     bool    `json:"isOnline"`
-	InVoltageT1T2                                float64 `json:"inVoltageT1T2"`
-	InVoltageT1T3                                float64 `json:"inVoltageT1T3"`
-	InVoltageT1T4                                float64 `json:"inVoltageT1T4"`
-	InVoltageT1T5                                float64 `json:"inVoltageT1T5"`
-	InVoltageT2T3                                float64 `json:"inVoltageT2T3"`
-	InVoltageT2T4                                float64 `json:"inVoltageT2T4"`
-	InVoltageT2T5                                float64 `json:"inVoltageT2T5"`
-	InVoltageT3T4                                float64 `json:"inVoltageT3T4"`
-	InVoltageT3T5                                float64 `json:"inVoltageT3T5"`
-	InVoltageT4T5                                float64 `json:"inVoltageT4T5"`
-	LedMode                                      int     `json:"ledMode"`
-	CableRating                                  float64 `json:"cableRating"`
-	DynamicChargerCurrent                        float64 `json:"dynamicChargerCurrent"`
-	CircuitTotalAllocatedPhaseConductorCurrentL1 float64 `json:"circuitTotalAllocatedPhaseConductorCurrentL1"`
-	CircuitTotalAllocatedPhaseConductorCurrentL2 float64 `json:"circuitTotalAllocatedPhaseConductorCurrentL2"`
-	CircuitTotalAllocatedPhaseConductorCurrentL3 float64 `json:"circuitTotalAllocatedPhaseConductorCurrentL3"`
-	CircuitTotalPhaseConductorCurrentL1          float64 `json:"circuitTotalPhaseConductorCurrentL1"`
-	CircuitTotalPhaseConductorCurrentL2          float64 `json:"circuitTotalPhaseConductorCurrentL2"`
-	CircuitTotalPhaseConductorCurrentL3          float64 `json:"circuitTotalPhaseConductorCurrentL3"`
-	ReasonForNoCurrent                           int     `json:"reasonForNoCurrent"`
-	WiFiAPEnabled                                bool    `json:"wiFiAPEnabled"`
-	LifetimeEnergy                               float64 `json:"lifetimeEnergy"`
-	OfflineMaxCircuitCurrentP1                   int     `json:"offlineMaxCircuitCurrentP1"`
-	OfflineMaxCircuitCurrentP2                   int     `json:"offlineMaxCircuitCurrentP2"`
-	OfflineMaxCircuitCurrentP3                   int     `json:"offlineMaxCircuitCurrentP3"`
+	SmartCharging                                bool
+	CableLocked                                  bool
+	ChargerOpMode                                int
+	TotalPower                                   float64
+	SessionEnergy                                float64
+	EnergyPerHour                                float64
+	WiFiRSSI                                     int
+	CellRSSI                                     int
+	LocalRSSI                                    int
+	OutputPhase                                  int
+	DynamicCircuitCurrentP1                      float64
+	DynamicCircuitCurrentP2                      float64
+	DynamicCircuitCurrentP3                      float64
+	LatestPulse                                  string
+	ChargerFirmware                              int
+	LatestFirmware                               int
+	Voltage                                      float64
+	ChargerRAT                                   int
+	LockCablePermanently                         bool
+	InCurrentT2                                  float64
+	InCurrentT3                                  float64
+	InCurrentT4                                  float64
+	InCurrentT5                                  float64
+	OutputCurrent                                float64
+	IsOnline                                     bool
+	InVoltageT1T2                                float64
+	InVoltageT1T3                                float64
+	InVoltageT1T4                                float64
+	InVoltageT1T5                                float64
+	InVoltageT2T3                                float64
+	InVoltageT2T4                                float64
+	InVoltageT2T5                                float64
+	InVoltageT3T4                                float64
+	InVoltageT3T5                                float64
+	InVoltageT4T5                                float64
+	LedMode                                      int
+	CableRating                                  float64
+	DynamicChargerCurrent                        float64
+	CircuitTotalAllocatedPhaseConductorCurrentL1 float64
+	CircuitTotalAllocatedPhaseConductorCurrentL2 float64
+	CircuitTotalAllocatedPhaseConductorCurrentL3 float64
+	CircuitTotalPhaseConductorCurrentL1          float64
+	CircuitTotalPhaseConductorCurrentL2          float64
+	CircuitTotalPhaseConductorCurrentL3          float64
+	ReasonForNoCurrent                           int
+	WiFiAPEnabled                                bool
+	LifetimeEnergy                               float64
+	OfflineMaxCircuitCurrentP1                   int
+	OfflineMaxCircuitCurrentP2                   int
+	OfflineMaxCircuitCurrentP3                   int
 }
 
 // ChargerSettings is the charger settings type
diff --git a/charger/shelly.go b/charger/shelly.go
index 606b31ae..2e9ec2ab 100644
--- a/charger/shelly.go
+++ b/charger/shelly.go
@@ -3,7 +3,7 @@ package charger
 import (
 	"errors"
 	"fmt"
-	"strings"
+	"net/url"
 
 	"github.com/evcc-io/evcc/api"
 	"github.com/evcc-io/evcc/util"
@@ -41,6 +41,8 @@ func init() {
 func NewShellyFromConfig(other map[string]interface{}) (api.Charger, error) {
 	cc := struct {
 		URI          string
+		User         string
+		Password     string
 		Channel      int
 		StandbyPower float64
 	}{}
@@ -53,14 +55,19 @@ func NewShellyFromConfig(other map[string]interface{}) (api.Charger, error) {
 		return nil, errors.New("missing uri")
 	}
 
-	return NewShelly(cc.URI, cc.Channel, cc.StandbyPower)
+	return NewShelly(cc.URI, cc.User, cc.Password, cc.Channel, cc.StandbyPower)
 }
 
 // NewShelly creates Shelly charger
-func NewShelly(uri string, channel int, standbypower float64) (*Shelly, error) {
+func NewShelly(uri, user, password string, channel int, standbypower float64) (*Shelly, error) {
+	u, _ := url.Parse(uri)
+	if u.Host != "" {
+		uri = u.Host
+	}
+
 	c := &Shelly{
 		Helper:       request.NewHelper(util.NewLogger("shelly")),
-		uri:          strings.TrimRight(uri, "/"),
+		uri:          fmt.Sprintf("http://%s:%s@%s", user, password, uri),
 		channel:      channel,
 		standbypower: standbypower,
 	}
diff --git a/core/loadpoint.go b/core/loadpoint.go
index d69261c1..51d24c08 100644
--- a/core/loadpoint.go
+++ b/core/loadpoint.go
@@ -953,7 +953,7 @@ func (lp *LoadPoint) pvScalePhases(availablePower, minCurrent, maxCurrent float6
 }
 
 // pvMaxCurrent calculates the maximum target current for PV mode
-func (lp *LoadPoint) pvMaxCurrent(mode api.ChargeMode, sitePower float64) float64 {
+func (lp *LoadPoint) pvMaxCurrent(mode api.ChargeMode, sitePower float64, batteryBuffered bool) float64 {
 	// read only once to simplify testing
 	minCurrent := lp.GetMinCurrent()
 	maxCurrent := lp.GetMaxCurrent()
@@ -976,7 +976,7 @@ func (lp *LoadPoint) pvMaxCurrent(mode api.ChargeMode, sitePower float64) float6
 	}
 
 	// in MinPV mode return at least minCurrent
-	if mode == api.ModeMinPV && targetCurrent < minCurrent {
+	if (mode == api.ModeMinPV || batteryBuffered) && targetCurrent < minCurrent {
 		return minCurrent
 	}
 
@@ -1206,7 +1206,7 @@ func (lp *LoadPoint) publishSoCAndRange() {
 }
 
 // Update is the main control function. It reevaluates meters and charger state
-func (lp *LoadPoint) Update(sitePower float64, cheap bool) {
+func (lp *LoadPoint) Update(sitePower float64, cheap bool, batteryBuffered bool) {
 	mode := lp.GetMode()
 	lp.publish("mode", mode)
 
@@ -1302,7 +1302,7 @@ func (lp *LoadPoint) Update(sitePower float64, cheap bool) {
 		err = lp.setLimit(targetCurrent, true)
 
 	case mode == api.ModeMinPV || mode == api.ModePV:
-		targetCurrent := lp.pvMaxCurrent(mode, sitePower)
+		targetCurrent := lp.pvMaxCurrent(mode, sitePower, batteryBuffered)
 		lp.log.DEBUG.Printf("pv max charge current: %.3gA", targetCurrent)
 
 		var required bool // false
diff --git a/core/site.go b/core/site.go
index 55176ad4..05ade408 100644
--- a/core/site.go
+++ b/core/site.go
@@ -14,11 +14,9 @@ import (
 	"github.com/evcc-io/evcc/util"
 )
 
-//go:generate mockgen -package mock -destination ../mock/mock_loadpoint.go github.com/evcc-io/evcc/core Updater
-
 // Updater abstracts the LoadPoint implementation for testing
 type Updater interface {
-	Update(float64, bool)
+	Update(availablePower float64, cheapRate bool, batteryBuffered bool)
 }
 
 // Site is the main configuration container. A site can host multiple loadpoints.
@@ -37,6 +35,7 @@ type Site struct {
 	ResidualPower float64      `mapstructure:"residualPower"` // PV meter only: household usage. Grid meter: household safety margin
 	Meters        MetersConfig // Meter references
 	PrioritySoC   float64      `mapstructure:"prioritySoC"` // prefer battery up to this SoC
+	BufferSoC     float64      `mapstructure:"bufferSoC"`   // ignore battery above this SoC
 
 	// meters
 	gridMeter    api.Meter   // Grid usage meter
@@ -47,9 +46,10 @@ type Site struct {
 	loadpoints []*LoadPoint // Loadpoints
 
 	// cached state
-	gridPower    float64 // Grid power
-	pvPower      float64 // PV power
-	batteryPower float64 // Battery charge power
+	gridPower       float64 // Grid power
+	pvPower         float64 // PV power
+	batteryPower    float64 // Battery charge power
+	batteryBuffered bool    // Battery buffer active
 }
 
 // MetersConfig contains the loadpoint's meter configuration
@@ -323,11 +323,14 @@ func (site *Site) sitePower() (float64, error) {
 			site.Lock()
 			defer site.Unlock()
 
-			// if battery is charging give it priority
+			// if battery is charging below prioritySoC give it priority
 			if soc < site.PrioritySoC && batteryPower < 0 {
-				site.log.DEBUG.Printf("giving priority to battery at soc: %.0f", soc)
+				site.log.DEBUG.Printf("giving priority to battery charging at soc: %.0f", soc)
 				batteryPower = 0
 			}
+
+			// if battery is discharging above bufferSoC ignore it
+			site.batteryBuffered = batteryPower > 0 && site.BufferSoC > 0 && soc > site.BufferSoC
 		}
 	}
 
@@ -346,7 +349,7 @@ func (site *Site) update(lp Updater) {
 	}
 
 	if sitePower, err := site.sitePower(); err == nil {
-		lp.Update(sitePower, cheap)
+		lp.Update(sitePower, cheap, site.batteryBuffered)
 		site.Health.Update()
 	}
 }
diff --git a/evcc.dist.yaml b/evcc.dist.yaml
index 50154305..4a09d556 100644
--- a/evcc.dist.yaml
+++ b/evcc.dist.yaml
@@ -61,7 +61,8 @@ site:
     pvs:
     - pv # list of pv inverters/ meters
     battery: battery # battery meter
-  prioritySoC: 60 # give home battery priority up to this soc (0 to disable)
+  prioritySoC: # give home battery priority up to this soc (empty to disable)
+  bufferSoC: # ignore home battery discharge above soc (empty to disable)
 
 # loadpoint describes the charger, charge meter and connected vehicle
 loadpoints:
diff --git a/mock/mock_loadpoint.go b/mock/mock_loadpoint.go
index c0807ccb..7f488e1a 100644
--- a/mock/mock_loadpoint.go
+++ b/mock/mock_loadpoint.go
@@ -34,13 +34,13 @@ func (m *MockUpdater) EXPECT() *MockUpdaterMockRecorder {
 }
 
 // Update mocks base method.
-func (m *MockUpdater) Update(arg0 float64, arg1 bool) {
+func (m *MockUpdater) Update(arg0 float64, arg1, arg2 bool) {
 	m.ctrl.T.Helper()
-	m.ctrl.Call(m, "Update", arg0, arg1)
+	m.ctrl.Call(m, "Update", arg0, arg1, arg2)
 }
 
 // Update indicates an expected call of Update.
-func (mr *MockUpdaterMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockUpdaterMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUpdater)(nil).Update), arg0, arg1)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUpdater)(nil).Update), arg0, arg1, arg2)
 }


Test patch:
diff --git a/core/loadpoint_test.go b/core/loadpoint_test.go
index a5dfcaf9..aace072f 100644
--- a/core/loadpoint_test.go
+++ b/core/loadpoint_test.go
@@ -168,7 +168,7 @@ func TestUpdatePowerZero(t *testing.T) {
 		}
 
 		lp.Mode = tc.mode
-		lp.Update(0, false) // sitePower 0
+		lp.Update(0, false, false) // sitePower 0
 
 		ctrl.Finish()
 	}
@@ -324,7 +324,7 @@ func TestPVHysteresis(t *testing.T) {
 				// charger.EXPECT().Enabled().Return(tc.enabled, nil)
 
 				lp.enabled = tc.enabled
-				current := lp.pvMaxCurrent(api.ModePV, se.site)
+				current := lp.pvMaxCurrent(api.ModePV, se.site, false)
 
 				if current != se.current {
 					t.Errorf("step %d: wanted %.1f, got %.1f", step, se.current, current)
@@ -355,7 +355,7 @@ func TestPVHysteresisForStatusOtherThanC(t *testing.T) {
 
 	// maxCurrent will read enabled state in PV mode
 	sitePower := -float64(lp.Phases)*minA*Voltage + 1 // 1W below min power
-	current := lp.pvMaxCurrent(api.ModePV, sitePower)
+	current := lp.pvMaxCurrent(api.ModePV, sitePower, false)
 
 	if current != 0 {
 		t.Errorf("PV mode could not disable charger as expected. Expected 0, got %.f", current)
@@ -406,7 +406,7 @@ func TestDisableAndEnableAtTargetSoC(t *testing.T) {
 	charger.EXPECT().Status().Return(api.StatusC, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().MaxCurrent(int64(maxA)).Return(nil)
-	lp.Update(500, false)
+	lp.Update(500, false, false)
 
 	t.Log("charging above target - soc deactivates charger")
 	clock.Add(5 * time.Minute)
@@ -414,20 +414,20 @@ func TestDisableAndEnableAtTargetSoC(t *testing.T) {
 	charger.EXPECT().Status().Return(api.StatusC, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Enable(false).Return(nil)
-	lp.Update(500, false)
+	lp.Update(500, false, false)
 
 	t.Log("deactivated charger changes status to B")
 	clock.Add(5 * time.Minute)
 	vehicle.EXPECT().SoC().Return(95.0, nil)
 	charger.EXPECT().Status().Return(api.StatusB, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
-	lp.Update(-5000, false)
+	lp.Update(-5000, false, false)
 
 	t.Log("soc has fallen below target - soc update prevented by timer")
 	clock.Add(5 * time.Minute)
 	charger.EXPECT().Status().Return(api.StatusB, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
-	lp.Update(-5000, false)
+	lp.Update(-5000, false, false)
 
 	t.Log("soc has fallen below target - soc update timer expired")
 	clock.Add(pollInterval)
@@ -435,7 +435,7 @@ func TestDisableAndEnableAtTargetSoC(t *testing.T) {
 	charger.EXPECT().Status().Return(api.StatusB, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Enable(true).Return(nil)
-	lp.Update(-5000, false)
+	lp.Update(-5000, false, false)
 
 	ctrl.Finish()
 }
@@ -475,14 +475,14 @@ func TestSetModeAndSocAtDisconnect(t *testing.T) {
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Status().Return(api.StatusC, nil)
 	charger.EXPECT().MaxCurrent(int64(maxA)).Return(nil)
-	lp.Update(500, false)
+	lp.Update(500, false, false)
 
 	t.Log("switch off when disconnected")
 	clock.Add(5 * time.Minute)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Status().Return(api.StatusA, nil)
 	charger.EXPECT().Enable(false).Return(nil)
-	lp.Update(-3000, false)
+	lp.Update(-3000, false, false)
 
 	if lp.Mode != api.ModeOff {
 		t.Error("unexpected mode", lp.Mode)
@@ -543,14 +543,14 @@ func TestChargedEnergyAtDisconnect(t *testing.T) {
 	rater.EXPECT().ChargedEnergy().Return(0.0, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Status().Return(api.StatusC, nil)
-	lp.Update(-1, false)
+	lp.Update(-1, false, false)
 
 	t.Log("at 1:00h charging at 5 kWh")
 	clock.Add(time.Hour)
 	rater.EXPECT().ChargedEnergy().Return(5.0, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Status().Return(api.StatusC, nil)
-	lp.Update(-1, false)
+	lp.Update(-1, false, false)
 	expectCache("chargedEnergy", 5000.0)
 
 	t.Log("at 1:00h stop charging at 5 kWh")
@@ -558,7 +558,7 @@ func TestChargedEnergyAtDisconnect(t *testing.T) {
 	rater.EXPECT().ChargedEnergy().Return(5.0, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Status().Return(api.StatusB, nil)
-	lp.Update(-1, false)
+	lp.Update(-1, false, false)
 	expectCache("chargedEnergy", 5000.0)
 
 	t.Log("at 1:00h restart charging at 5 kWh")
@@ -566,7 +566,7 @@ func TestChargedEnergyAtDisconnect(t *testing.T) {
 	rater.EXPECT().ChargedEnergy().Return(5.0, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Status().Return(api.StatusC, nil)
-	lp.Update(-1, false)
+	lp.Update(-1, false, false)
 	expectCache("chargedEnergy", 5000.0)
 
 	t.Log("at 1:30h continue charging at 7.5 kWh")
@@ -574,7 +574,7 @@ func TestChargedEnergyAtDisconnect(t *testing.T) {
 	rater.EXPECT().ChargedEnergy().Return(7.5, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Status().Return(api.StatusC, nil)
-	lp.Update(-1, false)
+	lp.Update(-1, false, false)
 	expectCache("chargedEnergy", 7500.0)
 
 	t.Log("at 2:00h stop charging at 10 kWh")
@@ -582,7 +582,7 @@ func TestChargedEnergyAtDisconnect(t *testing.T) {
 	rater.EXPECT().ChargedEnergy().Return(10.0, nil)
 	charger.EXPECT().Enabled().Return(lp.enabled, nil)
 	charger.EXPECT().Status().Return(api.StatusB, nil)
-	lp.Update(-1, false)
+	lp.Update(-1, false, false)
 	expectCache("chargedEnergy", 10000.0)
 
 	ctrl.Finish()