Repository: evcc-io/evcc
Pull request #12866 (2024-03-11 11:25:04)

Fix vehicle unable to override min current
Fix https://github.com/evcc-io/evcc/issues/11636

This PR should address the following cases (and fix an issue with effective max current):

<img width="568" alt="Screenshot 2024-03-11 at 12 29 19" src="https://github.com/evcc-io/evcc/assets/184815/68bd188f-fccb-4d64-980d-327e0bd85fad">



Patch:
diff --git a/core/loadpoint_effective.go b/core/loadpoint_effective.go
index 57a441f6..1fe8faf8 100644
--- a/core/loadpoint_effective.go
+++ b/core/loadpoint_effective.go
@@ -60,26 +60,29 @@ func (lp *Loadpoint) SocBasedPlanning() bool {
 
 // effectiveMinCurrent returns the effective min current
 func (lp *Loadpoint) effectiveMinCurrent() float64 {
-	minCurrent := lp.GetMinCurrent()
+	lpMin := lp.GetMinCurrent()
+	var vehicleMin, chargerMin float64
 
 	if v := lp.GetVehicle(); v != nil {
 		if res, ok := v.OnIdentified().GetMinCurrent(); ok {
-			minCurrent = max(minCurrent, res)
+			vehicleMin = res
 		}
 	}
 
 	if c, ok := lp.charger.(api.CurrentLimiter); ok {
 		if res, _, err := c.GetMinMaxCurrent(); err == nil {
-			if res > 0 && res < minCurrent {
-				minCurrent = res
-			} else {
-				minCurrent = max(minCurrent, res)
-			}
-			lp.publish(keys.EffectiveMinCurrent, minCurrent)
+			chargerMin = res
 		}
 	}
 
-	return minCurrent
+	switch {
+	case max(vehicleMin, chargerMin) == 0:
+		return lpMin
+	case chargerMin > 0:
+		return max(vehicleMin, chargerMin)
+	default:
+		return max(vehicleMin, lpMin)
+	}
 }
 
 // effectiveMaxCurrent returns the effective max current
@@ -87,13 +90,13 @@ func (lp *Loadpoint) effectiveMaxCurrent() float64 {
 	maxCurrent := lp.GetMaxCurrent()
 
 	if v := lp.GetVehicle(); v != nil {
-		if res, ok := v.OnIdentified().GetMaxCurrent(); ok {
+		if res, ok := v.OnIdentified().GetMaxCurrent(); ok && res > 0 {
 			maxCurrent = min(maxCurrent, res)
 		}
 	}
 
 	if c, ok := lp.charger.(api.CurrentLimiter); ok {
-		if _, res, err := c.GetMinMaxCurrent(); err == nil {
+		if _, res, err := c.GetMinMaxCurrent(); err == nil && res > 0 {
 			maxCurrent = min(maxCurrent, res)
 			lp.publish(keys.EffectiveMaxCurrent, maxCurrent)
 		}


Test patch:
diff --git a/core/loadpoint_effective_test.go b/core/loadpoint_effective_test.go
index 52e2957a..f2165478 100644
--- a/core/loadpoint_effective_test.go
+++ b/core/loadpoint_effective_test.go
@@ -21,12 +21,16 @@ func TestEffectiveMinMaxCurrent(t *testing.T) {
 		effectiveMin, effectiveMax float64
 	}{
 		{0, 0, 0, 0, 6, 16},
-		{1, 10, 0, 0, 1, 10},     // charger lower
-		{10, 20, 0, 0, 10, 16},   // charger higher - max ignored
-		{0, 0, 1, 10, 6, 10},     // vehicle lower - min ignored
-		{0, 0, 10, 20, 10, 16},   // vehicle higher - max ignored
-		{1, 10, 2, 12, 1, 10},    // charger + vehicle lower
-		{10, 20, 12, 22, 10, 16}, // charger + vehicle higher
+		{2, 0, 0, 0, 2, 16},   // charger min lower, max empty - charger wins
+		{7, 0, 0, 0, 7, 16},   // charger min higher, max empty (no practical use)
+		{0, 10, 0, 0, 6, 10},  // charger max lower, min empty - loadpoint wins
+		{0, 20, 0, 0, 6, 16},  // charger max higher, min empty - loadpoint wins
+		{0, 0, 5, 0, 6, 16},   // vehicle min lower, max empty - loadpoint wins
+		{0, 0, 8, 0, 8, 16},   // vehicle min higher, max empty - vehicle wins
+		{0, 0, 0, 10, 6, 10},  // vehicle max lower, min empty - vehicle wins
+		{0, 0, 0, 20, 6, 16},  // vehicle max higher, min empty - loadpoint wins
+		{2, 0, 5, 0, 5, 16},   // charger + vehicle min lower, max empty - vehicle wins
+		{0, 20, 0, 32, 6, 16}, // charger + vehicle max higher, min empty - loadpoint wins
 	}
 
 	for _, tc := range tc {
@@ -60,7 +64,7 @@ func TestEffectiveMinMaxCurrent(t *testing.T) {
 			lp.vehicle = vehicle
 		}
 
-		assert.Equal(t, tc.effectiveMin, lp.effectiveMinCurrent())
-		assert.Equal(t, tc.effectiveMax, lp.effectiveMaxCurrent())
+		assert.Equal(t, tc.effectiveMin, lp.effectiveMinCurrent(), "min")
+		assert.Equal(t, tc.effectiveMax, lp.effectiveMaxCurrent(), "max")
 	}
 }