TWC/Tesla: use charger api.PhaseCurrents over vehicle api.CurrentGetter (#14659)
Some checks failed
Release / call-build-workflow (push) Has been cancelled
Release / Publish Docker :release (push) Has been cancelled
Release / Github & APT (push) Has been cancelled
Release / Demo (push) Has been cancelled
Release / Hassio Addon (push) Has been cancelled

This commit is contained in:
andig 2024-07-03 16:28:34 +02:00 • committed by GitHub
parent cb086f8698
commit d5aabc2759
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 20 additions and 36 deletions

View file

@ -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) {

View file

@ -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)

View file

@ -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)
}

View file

@ -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