easee: clamp DCC to 7A before ChargeStart and remove overshoot protection (#30774)

This commit is contained in:
Michael Heß 2026-06-25 10:11:47 +02:00 • committed by GitHub
parent 8f9863538a
commit 3f9e0872bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 15 deletions

View file

@ -527,13 +527,19 @@ func (c *Easee) Enable(enable bool) (err error) {
// resume/stop charger
action := easee.ChargePause
var targetCurrent float64
if enable {
action = easee.ChargeResume
if opMode == easee.ModeAwaitingAuthentication && c.authorize {
action = easee.ChargeStart
}
targetCurrent = 32
}
// Easee firmware delays ~5 min when starting at 6A.
// Vendor docs recommend 7A minimum, clamp DCC before start.
if action == easee.ChargeStart && c.current < 7 {
if err := c.MaxCurrent(7); err != nil {
return err
}
}
uri := fmt.Sprintf("%s/chargers/%s/commands/%s", easee.API, c.charger, action)
@ -545,19 +551,6 @@ func (c *Easee) Enable(enable bool) (err error) {
return err
}
if action == easee.ChargeStart { // ChargeStart does not mingle with DCC, no need for below operations
return nil
}
if err := c.waitForDynamicChargerCurrent(targetCurrent); err != nil {
return err
}
if enable {
// reset currents after enable, as easee automatically resets to maxA
return c.MaxCurrent(int64(c.current))
}
return nil
}

View file

@ -748,3 +748,65 @@ func TestDetermineCircuit(t *testing.T) {
})
}
}
func TestEasee_Enable_clampsCurrentOnChargeStart(t *testing.T) {
const chargerID = "TESTTEST"
tests := []struct {
name string
current float64
expectClamp bool
}{
{"6A clamped to 7A", 6, true},
{"7A unchanged", 7, false},
{"10A unchanged", 10, false},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
e := newEasee()
e.charger = chargerID
e.current = tc.current
e.dynamicChargerCurrent = tc.current
e.opMode = easee.ModeAwaitingAuthentication
e.authorize = true
e.chargerEnabled = true // skip the "enable charger once" path
httpmock.ActivateNonDefault(e.Client)
defer httpmock.DeactivateAndReset()
var callOrder []string
// Mock POST charger settings (DCC clamp)
settingsURI := fmt.Sprintf("%s/chargers/%s/settings", easee.API, chargerID)
httpmock.RegisterResponder(http.MethodPost, settingsURI, func(req *http.Request) (*http.Response, error) {
callOrder = append(callOrder, "settings")
return httpmock.NewStringResponse(202, "[]"), nil
})
// Mock POST start_charging command
startURI := fmt.Sprintf("%s/chargers/%s/commands/%s", easee.API, chargerID, easee.ChargeStart)
httpmock.RegisterResponder(http.MethodPost, startURI, func(req *http.Request) (*http.Response, error) {
callOrder = append(callOrder, "start")
// Transition to expected state for waitForChargerEnabledState(true)
e.mux.Lock()
e.opMode = easee.ModeAwaitingStart
e.mux.Unlock()
return httpmock.NewStringResponse(200, ""), nil
})
err := e.Enable(true)
assert.NoError(t, err)
if tc.expectClamp {
assert.Equal(t, []string{"settings", "start"}, callOrder,
"DCC clamp should be sent before ChargeStart")
assert.Equal(t, 7.0, e.current, "current should be clamped to 7")
} else {
assert.Equal(t, []string{"start"}, callOrder,
"no DCC clamp should be sent")
assert.Equal(t, tc.current, e.current, "current should be unchanged")
}
})
}
}