Smart EQ: use Mercedes api (#18044)

This commit is contained in:
andig 2025-01-04 16:25:41 +01:00 • committed by GitHub
parent 41da4199be
commit eaff6de83c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 79 deletions

View file

@ -3,8 +3,36 @@ products:
- brand: Smart
description:
generic: EQ
requirements:
description:
de: |
Benötigt `access` und `refresh` Tokens. Diese können über den Befehl `evcc token [name]` generiert werden.
en: |
Requires `access` and `refresh` tokens. These can be generated with command `evcc token [name]`.
params:
- preset: vehicle-base
- preset: vehicle-common
- name: user
required: true
- name: region
required: true
choice: [EMEA, APAC, NORAM]
default: EMEA
- name: accessToken
required: true
mask: true
- name: refreshToken
required: true
mask: true
- name: vin
example: V...
- name: cache
default: 15m
render: |
type: smart
{{ include "vehicle-base" . }}
type: smart-eq
vin: {{ .vin }}
user: {{ .user }}
region: {{ .region }}
tokens:
access: {{ .accessToken }}
refresh: {{ .refreshToken }}
{{ include "vehicle-common" . }}

View file

@ -1,6 +1,7 @@
package vehicle
import (
"errors"
"time"
"github.com/evcc-io/evcc/api"
@ -15,11 +16,16 @@ type Mercedes struct {
}
func init() {
registry.Add("mercedes", NewMercedesFromConfig)
registry.Add("mercedes", func(other map[string]interface{}) (api.Vehicle, error) {
return newMercedesFromConfig("mercedes", other)
})
registry.Add("smart-eq", func(other map[string]interface{}) (api.Vehicle, error) {
return newMercedesFromConfig("smart-eq", other)
})
}
// NewMercedesFromConfig creates a new vehicle
func NewMercedesFromConfig(other map[string]interface{}) (api.Vehicle, error) {
// newMercedesFromConfig creates a new vehicle
func newMercedesFromConfig(brand string, other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
embed `mapstructure:",squash"`
Tokens Tokens
@ -45,21 +51,28 @@ func NewMercedesFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc.User = cc.Account_
}
log := util.NewLogger("mercedes").Redact(cc.Tokens.Access, cc.Tokens.Refresh)
log := util.NewLogger(brand).Redact(cc.Tokens.Access, cc.Tokens.Refresh)
identity, err := mercedes.NewIdentity(log, token, cc.User, cc.Region)
if err != nil {
return nil, err
}
v := &Mercedes{
embed: &cc.embed,
}
api := mercedes.NewAPI(log, identity)
cc.VIN, err = ensureVehicle(cc.VIN, api.Vehicles)
if err == nil {
v.Provider = mercedes.NewProvider(api, cc.VIN, cc.Cache)
if brand == "smart-eq" {
if cc.VIN == "" {
return nil, errors.New("missing VIN")
}
} else {
cc.VIN, err = ensureVehicle(cc.VIN, api.Vehicles)
if err != nil {
return nil, err
}
}
v := &Mercedes{
embed: &cc.embed,
Provider: mercedes.NewProvider(api, cc.VIN, cc.Cache),
}
return v, err

View file

@ -1,65 +0,0 @@
package vehicle
import (
"fmt"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/vehicle/mb"
"github.com/evcc-io/evcc/vehicle/smart"
)
// Smart is an api.Vehicle implementation for Smart cars
type Smart struct {
*embed
*smart.Provider
}
func init() {
registry.Add("smart", NewSmartFromConfig)
}
// NewSmartFromConfig creates a new vehicle
func NewSmartFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
embed `mapstructure:",squash"`
User, Password string
VIN string
Expiry time.Duration
Cache time.Duration
}{
Expiry: expiry,
Cache: interval,
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
if cc.User == "" || cc.Password == "" {
return nil, api.ErrMissingCredentials
}
log := util.NewLogger("smart").Redact(cc.User, cc.Password, cc.VIN)
v := &Smart{
embed: &cc.embed,
}
identity := mb.NewIdentity(log, smart.OAuth2Config)
err := identity.Login(cc.User, cc.Password)
if err != nil {
return v, fmt.Errorf("login failed: %w", err)
}
api := smart.NewAPI(log, identity)
cc.VIN, err = ensureVehicle(cc.VIN, api.Vehicles)
if err == nil {
v.Provider = smart.NewProvider(log, api, cc.VIN, cc.Expiry, cc.Cache)
}
return v, err
}