Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seat: fix retrieving list of vehicles #9703

Merged
merged 5 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions vehicle/seat-cupra.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"github.com/evcc-io/evcc/vehicle/seat"
"github.com/evcc-io/evcc/vehicle/seat/cupra"
"github.com/evcc-io/evcc/vehicle/vag/service"
"github.com/evcc-io/evcc/vehicle/vag/vwidentity"
Expand Down Expand Up @@ -51,7 +50,7 @@ func NewCupraFromConfig(other map[string]interface{}) (api.Vehicle, error) {

log := util.NewLogger("cupra").Redact(cc.User, cc.Password, cc.VIN)

ts, err := service.TokenRefreshServiceTokenSource(log, seat.TRSParams, seat.AuthParams, cc.User, cc.Password)
ts, err := service.TokenRefreshServiceTokenSource(log, cupra.TRSParams, cupra.AuthParams, cc.User, cc.Password)
if err != nil {
return nil, err
}
Expand Down
59 changes: 55 additions & 4 deletions vehicle/seat.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package vehicle

import (
"context"
"fmt"
"net/http"
"net/url"
"strings"
"time"

"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"github.com/evcc-io/evcc/vehicle/seat"
"github.com/evcc-io/evcc/vehicle/seat/cupra"
"github.com/evcc-io/evcc/vehicle/vag/service"
"github.com/evcc-io/evcc/vehicle/vag/vwidentity"
"github.com/evcc-io/evcc/vehicle/vw"
"golang.org/x/oauth2"
)

// https://github.com/trocotronic/weconnect
Expand Down Expand Up @@ -50,22 +58,65 @@ func NewSeatFromConfig(other map[string]interface{}) (api.Vehicle, error) {

log := util.NewLogger("seat").Redact(cc.User, cc.Password, cc.VIN)

trs, err := service.TokenRefreshServiceTokenSource(log, seat.TRSParams, seat.AuthParams, cc.User, cc.Password)
trs, err := service.TokenRefreshServiceTokenSource(log, cupra.TRSParams, cupra.AuthParams, cc.User, cc.Password)
if err != nil {
return nil, err
}

// get OIDC user information
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, request.NewClient(log))
ui, err := vwidentity.Config.NewProvider(ctx).UserInfo(ctx, trs)
if err != nil {
return nil, fmt.Errorf("failed getting user information: %w", err)
}

mbbId, err := mbbUserId(log, trs, ui.Subject)
if err != nil {
return nil, fmt.Errorf("failed getting mbbUserId: %w", err)
}

ts := service.MbbTokenSource(log, trs, seat.AuthClientID)
api := vw.NewAPI(log, ts, seat.Brand, seat.Country)
api.Client.Timeout = cc.Timeout
api := seat.NewAPI(log, ts)

cc.VIN, err = ensureVehicle(cc.VIN, api.Vehicles)
cc.VIN, err = ensureVehicle(
cc.VIN, func() ([]string, error) {
return api.Vehicles(mbbId)
},
)

if err == nil {
api := vw.NewAPI(log, ts, seat.Brand, seat.Country)
api.Client.Timeout = cc.Timeout

if err = api.HomeRegion(cc.VIN); err == nil {
v.Provider = vw.NewProvider(api, cc.VIN, cc.Cache)
}
}

return v, err
}

func mbbUserId(log *util.Logger, ts oauth2.TokenSource, uid string) (string, error) {
client := request.NewHelper(log)
client.Transport = &oauth2.Transport{
Source: ts,
Base: client.Transport,
}

data := url.Values{
"scopeId": []string{"commonMandatoryFields"},
}

var mandatoryConsentInfo struct {
MbbUserId string `json:"mbbUserId"`
}

uri := fmt.Sprintf("https://profileintegrityservice.apps.emea.vwapps.io/iaa/pic/v1/users/%s/check-profile", uid)
req, err := request.New(http.MethodPost, uri, strings.NewReader(data.Encode()), request.URLEncoding)

if err == nil {
err = client.DoJSON(req, &mandatoryConsentInfo)
}

return mandatoryConsentInfo.MbbUserId, err
}
53 changes: 53 additions & 0 deletions vehicle/seat/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package seat

import (
"fmt"

"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"golang.org/x/oauth2"
)

// BaseURL is the API base url
const BaseURL = "https://mal-3a.prd.eu.dp.vwg-connect.com/api"

// API provides list of vehicles for Seat cars
type API struct {
*request.Helper
}

// NewAPI creates a new vehicle
func NewAPI(log *util.Logger, ts oauth2.TokenSource) *API {
v := &API{
Helper: request.NewHelper(log),
}

v.Client.Transport = &oauth2.Transport{
Source: ts,
Base: v.Client.Transport,
}

return v
}

// Vehicles implements the /vehicles response
func (v *API) Vehicles(userID string) ([]string, error) {
var res struct {
UserVehicles struct {
UserId string
Vehicle []struct {
Content string
}
}
}

uri := fmt.Sprintf("%s/usermanagement/users/v2/users/%s/vehicles", BaseURL, userID)
err := v.GetJSON(uri, &res)

var vehicles []string
for _, v := range res.UserVehicles.Vehicle {
vehicles = append(vehicles, v.Content)
}

return vehicles, err
}
16 changes: 16 additions & 0 deletions vehicle/seat/cupra/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cupra

import "net/url"

// Authorization parameters
var AuthParams = url.Values{
"response_type": {"code id_token"}, // token
"client_id": {"30e33736-c537-4c72-ab60-74a7b92cfe83@apps_vw-dilab_com"},
"redirect_uri": {"cupraconnect://identity-kit/login"},
"scope": {"openid profile mbb"}, // cars birthdate nickname address phone
}

// TokenRefreshService parameters
var TRSParams = url.Values{
"brand": {"cupra"},
}
13 changes: 4 additions & 9 deletions vehicle/seat/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@ const (
Country = "ES"

// Authorization ClientID
AuthClientID = "9d183b70-d129-424f-9a26-c3778edf95e1"
AuthClientID = "9dcc70f0-8e79-423a-a3fa-4065d99088b4"
)

// Authorization parameters
var AuthParams = url.Values{
"response_type": {"code id_token"}, // token
"client_id": {"30e33736-c537-4c72-ab60-74a7b92cfe83@apps_vw-dilab_com"},
"redirect_uri": {"cupraconnect://identity-kit/login"},
"scope": {"openid profile mbb"}, // cars birthdate nickname address phone
}

// TokenRefreshService parameters
var TRSParams = url.Values{
"brand": {"cupra"},
"client_id": {"3c8e98bc-3ae9-4277-a563-d5ee65ddebba@apps_vw-dilab_com"},
"redirect_uri": {"seatconnect://identity-kit/login"},
"scope": {"openid profile"}, // address phone email birthdate nationalIdentifier cars mbb dealers badge nationality
}