Repository: evcc-io/evcc
Pull request #13128 (2024-03-24 11:47:58)

chore: upgrade alpine image


Patch:
diff --git a/Dockerfile b/Dockerfile
index 8f845e87..e029d25c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -69,7 +69,7 @@ RUN RELEASE=${RELEASE} GOOS=${TARGETOS} GOARCH=${TARGETARCH} make build
 
 
 # STEP 3 build a small image including module support
-FROM alpine:3.18
+FROM alpine:3.19
 
 WORKDIR /app
 
diff --git a/charger/twc3.go b/charger/twc3.go
index 1ec03994..416e8848 100644
--- a/charger/twc3.go
+++ b/charger/twc3.go
@@ -146,6 +146,18 @@ func (c *Twc3) MaxCurrent(current int64) error {
 	return v.MaxCurrent(current)
 }
 
+var _ api.CurrentGetter = (*Twc3)(nil)
+
+// GetMaxCurrent implements the api.CurrentGetter interface
+func (c *Twc3) GetMaxCurrent() (float64, error) {
+	v, ok := c.lp.GetVehicle().(api.CurrentGetter)
+	if !ok {
+		return 0, api.ErrNotAvailable
+	}
+
+	return v.GetMaxCurrent()
+}
+
 var _ api.ChargeRater = (*Twc3)(nil)
 
 // ChargedEnergy implements the api.ChargeRater interface
diff --git a/core/loadpoint.go b/core/loadpoint.go
index 80e6d5d9..0f9a85d5 100644
--- a/core/loadpoint.go
+++ b/core/loadpoint.go
@@ -689,18 +689,17 @@ func (lp *Loadpoint) syncCharger() error {
 	if enabled == lp.enabled {
 		// sync max current
 		if charger, ok := lp.charger.(api.CurrentGetter); ok && enabled {
-			current, err := charger.GetMaxCurrent()
-			if err != nil {
-				return fmt.Errorf("charger get max current: %w", err)
-			}
-
-			// smallest adjustment most PWM-Controllers can do is: 100%÷256×0,6A = 0.234A
-			if math.Abs(lp.chargeCurrent-current) > 0.23 {
-				if lp.chargerUpdateCompleted() {
-					lp.log.WARN.Printf("charger logic error: current mismatch (got %.3gA, expected %.3gA)", current, lp.chargeCurrent)
+			if current, err := charger.GetMaxCurrent(); err == nil {
+				// smallest adjustment most PWM-Controllers can do is: 100%÷256×0,6A = 0.234A
+				if math.Abs(lp.chargeCurrent-current) > 0.23 {
+					if lp.chargerUpdateCompleted() {
+						lp.log.WARN.Printf("charger logic error: current mismatch (got %.3gA, expected %.3gA)", current, lp.chargeCurrent)
+					}
+					lp.chargeCurrent = current
+					lp.bus.Publish(evChargeCurrent, lp.chargeCurrent)
 				}
-				lp.chargeCurrent = current
-				lp.bus.Publish(evChargeCurrent, lp.chargeCurrent)
+			} else if !errors.Is(err, api.ErrNotAvailable) {
+				return fmt.Errorf("charger get max current: %w", err)
 			}
 		}
 
diff --git a/vehicle/tesla.go b/vehicle/tesla.go
index 2a9c9429..62b9acf5 100644
--- a/vehicle/tesla.go
+++ b/vehicle/tesla.go
@@ -112,7 +112,7 @@ func NewTeslaFromConfig(other map[string]interface{}) (api.Vehicle, error) {
 	v := &Tesla{
 		embed:      &cc.embed,
 		Provider:   tesla.NewProvider(vehicle, cc.Cache),
-		Controller: tesla.NewController(vehicle.WithClient(tcc)),
+		Controller: tesla.NewController(vehicle, vehicle.WithClient(tcc)),
 	}
 
 	if v.Title_ == "" {
diff --git a/vehicle/tesla/controller.go b/vehicle/tesla/controller.go
index 0152ca8e..61cf046d 100644
--- a/vehicle/tesla/controller.go
+++ b/vehicle/tesla/controller.go
@@ -3,8 +3,10 @@ package tesla
 import (
 	"errors"
 	"slices"
+	"time"
 
 	"github.com/evcc-io/evcc/api"
+	"github.com/evcc-io/evcc/provider"
 	"github.com/evcc-io/evcc/util/sponsor"
 	"github.com/evcc-io/tesla-proxy-client"
 )
@@ -13,14 +15,26 @@ const ProxyBaseUrl = "https://tesla.evcc.io"
 
 type Controller struct {
 	vehicle *tesla.Vehicle
+	current int64
+	dataG   provider.Cacheable[float64]
 }
 
 // NewController creates a vehicle current and charge controller
-func NewController(vehicle *tesla.Vehicle) *Controller {
-	impl := &Controller{
-		vehicle: vehicle,
+func NewController(ro, rw *tesla.Vehicle) *Controller {
+	v := &Controller{
+		vehicle: rw,
 	}
-	return impl
+
+	v.dataG = provider.ResettableCached(func() (float64, error) {
+		if v.current >= 6 {
+			// assume match above 6A to save API requests
+			return float64(v.current), nil
+		}
+		res, err := ro.Data()
+		return float64(res.Response.ChargeState.ChargeAmps), apiError(err)
+	}, time.Minute)
+
+	return v
 }
 
 var _ api.CurrentController = (*Controller)(nil)
@@ -31,9 +45,19 @@ func (v *Controller) MaxCurrent(current int64) error {
 		return api.ErrSponsorRequired
 	}
 
+	v.current = current
+	v.dataG.Reset()
+
 	return apiError(v.vehicle.SetChargingAmps(int(current)))
 }
 
+var _ api.CurrentGetter = (*Controller)(nil)
+
+// StartCharge implements the api.VehicleChargeController interface
+func (v *Controller) GetMaxCurrent() (float64, error) {
+	return v.dataG.Get()
+}
+
 var _ api.ChargeController = (*Controller)(nil)
 
 // ChargeEnable implements the api.ChargeController interface


Test patch:
diff --git a/vehicle/tesla/api_test.go b/vehicle/tesla/api_test.go
index f6774692..19b02f35 100644
--- a/vehicle/tesla/api_test.go
+++ b/vehicle/tesla/api_test.go
@@ -40,5 +40,5 @@ func TestCommandResponse(t *testing.T) {
 	v, err := client.Vehicle("abc")
 	require.NoError(t, err)
 
-	require.ErrorIs(t, NewController(v).ChargeEnable(true), api.ErrAsleep)
+	require.ErrorIs(t, NewController(v, v).ChargeEnable(true), api.ErrAsleep)
 }