Tesla: validate vehicle current (#13099)

This commit is contained in:
andig 2024-03-24 13:04:43 +01:00 • committed by GitHub
parent be18545837
commit 48772bf142
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 52 additions and 17 deletions

View file

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

View file

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

View file

@ -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_ == "" {

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).ChargeEnable(true), api.ErrAsleep)
require.ErrorIs(t, NewController(v, v).ChargeEnable(true), api.ErrAsleep)
}

View file

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