From d5aabc275922720815f9c1fdc0d768ba73bed0cb Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 3 Jul 2024 16:28:34 +0200 Subject: [PATCH] TWC/Tesla: use charger api.PhaseCurrents over vehicle api.CurrentGetter (#14659) --- core/loadpoint.go | 22 ++++++++++++++++------ vehicle/tesla.go | 2 +- vehicle/tesla/api_test.go | 2 +- vehicle/tesla/controller.go | 30 ++---------------------------- 4 files changed, 20 insertions(+), 36 deletions(-) diff --git a/core/loadpoint.go b/core/loadpoint.go index c68ff093ca..41dbcd6435 100644 --- a/core/loadpoint.go +++ b/core/loadpoint.go @@ -705,8 +705,15 @@ func (lp *Loadpoint) syncCharger() error { switch { case enabled && lp.enabled: // sync max current - if charger, ok := lp.charger.(api.CurrentGetter); ok { - if current, err := charger.GetMaxCurrent(); err == nil { + var ( + current float64 + err error + ) + + // use chargers actual set current if available + cg, ok := lp.charger.(api.CurrentGetter) + if ok { + if current, err = cg.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 shouldBeConsistent { @@ -718,8 +725,11 @@ func (lp *Loadpoint) syncCharger() error { } else if !errors.Is(err, api.ErrNotAvailable) { return fmt.Errorf("charger get max current: %w", err) } - } else { - // use measured phase currents as fallback, validate if current too high by at least 1A + } + + // use measured phase currents as fallback if charger does not provide max current or does not currently relay from vehicle (TWC3) + if !ok || errors.Is(err, api.ErrNotAvailable) { + // validate if current too high by at least 1A if current := lp.GetMaxPhaseCurrent(); current > lp.chargeCurrent+1.0 { if shouldBeConsistent { lp.log.WARN.Printf("charger logic error: current mismatch (got %.3gA measured, expected %.3gA)", current, lp.chargeCurrent) @@ -738,8 +748,8 @@ func (lp *Loadpoint) syncCharger() error { chargerPhases = 3 } - if ps, ok := lp.charger.(api.PhaseGetter); ok { - if cp, err := ps.GetPhases(); err == nil { + if pg, ok := lp.charger.(api.PhaseGetter); ok { + if cp, err := pg.GetPhases(); err == nil { chargerPhases = cp } else { if errors.Is(err, api.ErrNotAvailable) { diff --git a/vehicle/tesla.go b/vehicle/tesla.go index 9bdb4dbff2..fd5525968f 100644 --- a/vehicle/tesla.go +++ b/vehicle/tesla.go @@ -114,7 +114,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, vehicle.WithClient(tcc)), + Controller: tesla.NewController(vehicle.WithClient(tcc)), } v.fromVehicle(vehicle.DisplayName, 0) diff --git a/vehicle/tesla/api_test.go b/vehicle/tesla/api_test.go index 19b02f359f..f677469254 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, v).ChargeEnable(true), api.ErrAsleep) + require.ErrorIs(t, NewController(v).ChargeEnable(true), api.ErrAsleep) } diff --git a/vehicle/tesla/controller.go b/vehicle/tesla/controller.go index 749e229d6c..e9d1dc5690 100644 --- a/vehicle/tesla/controller.go +++ b/vehicle/tesla/controller.go @@ -3,10 +3,8 @@ 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" ) @@ -15,28 +13,14 @@ 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(ro, rw *tesla.Vehicle) *Controller { +func NewController(vehicle *tesla.Vehicle) *Controller { v := &Controller{ - vehicle: rw, + vehicle: vehicle, } - 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() - if err != nil { - return 0, apiError(err) - } - return float64(res.Response.ChargeState.ChargeAmps), nil - }, time.Minute) - return v } @@ -48,19 +32,9 @@ 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