diff --git a/templates/definition/vehicle/lexus.yaml b/templates/definition/vehicle/lexus.yaml new file mode 100644 index 000000000..e47910975 --- /dev/null +++ b/templates/definition/vehicle/lexus.yaml @@ -0,0 +1,26 @@ +template: lexus +products: + - brand: Lexus +requirements: + description: + de: | + Benötigt Lexus Link+ Connected Services Account. + en: | + Requires Lexus Link+ Connected Services Account. +params: + - preset: vehicle-common + - name: user + required: true + - name: password + required: true + - name: vin + example: JT... + - name: cache + default: 15m +render: | + type: lexus + {{ include "vehicle-common" . }} + user: {{ .user }} + password: {{ .password }} + vin: {{ .vin }} + cache: {{ .cache }} diff --git a/vehicle/toyota.go b/vehicle/toyota.go index 97e1912f9..3f0269f9d 100644 --- a/vehicle/toyota.go +++ b/vehicle/toyota.go @@ -9,18 +9,23 @@ import ( "github.com/evcc-io/evcc/vehicle/toyota" ) -// Toyota is an api.Vehicle implementation for Toyota cars +// Toyota is an api.Vehicle implementation for Toyota/Lexus cars type Toyota struct { *embed *toyota.Provider } func init() { - registry.Add("toyota", NewToyotaFromConfig) + registry.Add("toyota", func(other map[string]any) (api.Vehicle, error) { + return newToyotaFromConfig("toyota", "T", other) + }) + registry.Add("lexus", func(other map[string]any) (api.Vehicle, error) { + return newToyotaFromConfig("lexus", "L", other) + }) } -// NewToyotaFromConfig creates a new vehicle -func NewToyotaFromConfig(other map[string]any) (api.Vehicle, error) { +// newToyotaFromConfig creates a new vehicle +func newToyotaFromConfig(brand, brandCode string, other map[string]any) (api.Vehicle, error) { cc := struct { embed `mapstructure:",squash"` User, Password, VIN string @@ -41,15 +46,15 @@ func NewToyotaFromConfig(other map[string]any) (api.Vehicle, error) { embed: &cc.embed, } - log := util.NewLogger("toyota").Redact(cc.User, cc.Password, cc.VIN) - identity := toyota.NewIdentity(log) + log := util.NewLogger(brand).Redact(cc.User, cc.Password, cc.VIN) + identity := toyota.NewIdentity(log, brandCode) err := identity.Login(cc.User, cc.Password) if err != nil { return v, fmt.Errorf("login failed: %w", err) } - api := toyota.NewAPI(log, identity) + api := toyota.NewAPI(log, identity, brandCode) cc.VIN, err = ensureVehicle(cc.VIN, api.Vehicles) if err == nil { diff --git a/vehicle/toyota/api.go b/vehicle/toyota/api.go index 79a27513f..9c303b501 100644 --- a/vehicle/toyota/api.go +++ b/vehicle/toyota/api.go @@ -34,7 +34,7 @@ type API struct { identity *Identity } -func NewAPI(log *util.Logger, identity *Identity) *API { +func NewAPI(log *util.Logger, identity *Identity, brandCode string) *API { v := &API{ Helper: request.NewHelper(log), log: log, @@ -57,6 +57,7 @@ func NewAPI(log *util.Logger, identity *Identity) *API { "x-client-ref": clientRef, "x-appversion": clientRefKey, "x-channel": channel, + "X-Appbrand": brandCode, }), Base: &oauth2.Transport{ Source: identity, diff --git a/vehicle/toyota/api_test.go b/vehicle/toyota/api_test.go index 0ef3e65d4..cf890d02f 100644 --- a/vehicle/toyota/api_test.go +++ b/vehicle/toyota/api_test.go @@ -21,12 +21,12 @@ func TestAPI(t *testing.T) { // Create and login identity log := util.NewLogger("foo") - identity := NewIdentity(log) + identity := NewIdentity(log, "T") err := identity.Login(user, password) require.NoError(t, err) // Create API client - api := NewAPI(log, identity) + api := NewAPI(log, identity, "T") // Test Vehicles method vehicles, err := api.Vehicles() diff --git a/vehicle/toyota/identity.go b/vehicle/toyota/identity.go index 3583f6c2a..57eeac33c 100644 --- a/vehicle/toyota/identity.go +++ b/vehicle/toyota/identity.go @@ -26,13 +26,15 @@ type Identity struct { log *util.Logger *request.Helper oauth2.TokenSource - uuid string + uuid string + brandCode string } -func NewIdentity(log *util.Logger) *Identity { +func NewIdentity(log *util.Logger, brandCode string) *Identity { return &Identity{ - log: log, - Helper: request.NewHelper(log), + log: log, + Helper: request.NewHelper(log), + brandCode: brandCode, } } @@ -162,7 +164,9 @@ func (v *Identity) refreshToken(token *oauth2.Token) (*oauth2.Token, error) { func (v *Identity) Login(user, password string) error { uri := fmt.Sprintf("%s/%s", BaseUrl, AuthenticationPath) req, err := request.New(http.MethodPost, uri, nil, map[string]string{ - "Accept": "application/json", + "Accept": "application/json", + "X-Brand": v.brandCode, + "X-Region": "EU", }) if err != nil { return fmt.Errorf("failed to create authentication request: %w", err) diff --git a/vehicle/toyota/identity_test.go b/vehicle/toyota/identity_test.go index 7522f2289..3b72fae7d 100644 --- a/vehicle/toyota/identity_test.go +++ b/vehicle/toyota/identity_test.go @@ -20,7 +20,7 @@ func TestIdentityLogin(t *testing.T) { util.LogLevel("trace", nil) // Enable trace logging log := util.NewLogger("test") - identity := NewIdentity(log) + identity := NewIdentity(log, "T") err := identity.Login(user, password) require.NoError(t, err)