Skip to content

Commit

Permalink
Move MySkoda implementation into own package (#14349)
Browse files Browse the repository at this point in the history
  • Loading branch information
GrimmiMeloni committed Jun 13, 2024
1 parent 85b14d3 commit 9ff704e
Show file tree
Hide file tree
Showing 12 changed files with 449 additions and 104 deletions.
16 changes: 8 additions & 8 deletions vehicle/skoda-enyaq.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ 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/skoda"
"github.com/evcc-io/evcc/vehicle/skoda/service"
"github.com/evcc-io/evcc/vehicle/skoda/myskoda"
"github.com/evcc-io/evcc/vehicle/skoda/myskoda/service"
)

// https://gitlab.com/prior99/skoda

// Enyaq is an api.Vehicle implementation for Skoda Enyaq cars
type Enyaq struct {
*embed
*skoda.Provider // provides the api implementations
*myskoda.Provider // provides the api implementations
}

func init() {
Expand Down Expand Up @@ -50,17 +50,17 @@ func NewEnyaqFromConfig(other map[string]interface{}) (api.Vehicle, error) {
log := util.NewLogger("enyaq").Redact(cc.User, cc.Password, cc.VIN)

// use Skoda api to resolve list of vehicles
ts, err := service.TokenRefreshServiceTokenSource(log, skoda.TRSParams, skoda.AuthParams, cc.User, cc.Password)
ts, err := service.TokenRefreshServiceTokenSource(log, myskoda.TRSParams, myskoda.AuthParams, cc.User, cc.Password)
if err != nil {
return nil, err
}

api := skoda.NewAPI(log, ts)
api := myskoda.NewAPI(log, ts)
api.Client.Timeout = cc.Timeout

vehicle, err := ensureVehicleEx(
cc.VIN, api.Vehicles,
func(v skoda.Vehicle) (string, error) {
func(v myskoda.Vehicle) (string, error) {
return v.VIN, nil
},
)
Expand All @@ -75,10 +75,10 @@ func NewEnyaqFromConfig(other map[string]interface{}) (api.Vehicle, error) {

// reuse tokenService to build provider
if err == nil {
api := skoda.NewAPI(log, ts)
api := myskoda.NewAPI(log, ts)
api.Client.Timeout = cc.Timeout

v.Provider = skoda.NewProvider(api, vehicle.VIN, cc.Cache)
v.Provider = myskoda.NewProvider(api, vehicle.VIN, cc.Cache)
}

return v, err
Expand Down
60 changes: 19 additions & 41 deletions vehicle/skoda/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"golang.org/x/oauth2"
)

const BaseURI = "https://mysmob.api.connect.skoda-auto.cz/api"
const BaseURI = "https://api.connect.skoda-auto.cz/api"

// API is the Skoda api client
type API struct {
Expand All @@ -30,84 +30,62 @@ func NewAPI(log *util.Logger, ts oauth2.TokenSource) *API {
return v
}

// Vehicles implements the /v2/garage response
// Vehicles implements the /v3/garage response
func (v *API) Vehicles() ([]Vehicle, error) {
var res VehiclesResponse

uri := fmt.Sprintf("%s/v2/garage", BaseURI)
uri := fmt.Sprintf("%s/v3/garage", BaseURI)
err := v.GetJSON(uri, &res)

return res.Vehicles, err
}

func (v *API) VehicleDetails(vin string) (Vehicle, error) {
var res Vehicle
uri := fmt.Sprintf("%s/v2/garage/vehicles/%s", BaseURI, vin)
err := v.GetJSON(uri, &res)
return res, err
}

// Status implements the /v2/vehicle-status/<vin> response
func (v *API) Status(vin string) (StatusResponse, error) {
var res StatusResponse
uri := fmt.Sprintf("%s/v1/vehicle-health-report/warning-lights/%s", BaseURI, vin)
uri := fmt.Sprintf("%s/v2/vehicle-status/%s", BaseURI, vin)
err := v.GetJSON(uri, &res)
return res, err
}

// Charger implements the /v1/charging/<vin> response
// Charger implements the /v1/charging/<vin>/status response
func (v *API) Charger(vin string) (ChargerResponse, error) {
var res ChargerResponse
uri := fmt.Sprintf("%s/v1/charging/%s", BaseURI, vin)
uri := fmt.Sprintf("%s/v1/charging/%s/status", BaseURI, vin)
err := v.GetJSON(uri, &res)
return res, err
}

// Settings implements the /v1/charging/<vin>/settings response
func (v *API) Settings(vin string) (SettingsResponse, error) {
var res SettingsResponse

chrgRes, err := v.Charger(vin)
if err == nil {
res = chrgRes.Settings
}
return res, err
}

// Climater implements the /v2/air-conditioning/<vin> response
func (v *API) Climater(vin string) (ClimaterResponse, error) {
var res ClimaterResponse
uri := fmt.Sprintf("%s/v2/air-conditioning/%s", BaseURI, vin)
uri := fmt.Sprintf("%s/v1/charging/%s/settings", BaseURI, vin)
err := v.GetJSON(uri, &res)
return res, err
}

const (
ActionCharge = "charging"
ActionChargeStart = "start"
ActionChargeStop = "stop"
ActionChargeStart = "Start"
ActionChargeStop = "Stop"
)

// Action executes a vehicle action
func (v *API) Action(vin, action, value string) error {
// @POST("api/v1/charging/{vin}/start")
// @POST("api/v1/charging/{vin}/stop")
uri := fmt.Sprintf("%s/v1/%s/%s/%s", BaseURI, action, vin, value)
var res map[string]interface{}
uri := fmt.Sprintf("%s/v1/%s/operation-requests?vin=%s", BaseURI, action, vin)

req, err := request.New(http.MethodPost, uri, nil, request.JSONEncoding)
if err == nil {
err = v.DoJSON(req, nil)
data := struct {
Typ string `json:"type"`
}{
Typ: value,
}
return err
}

func (v *API) WakeUp(vin string) error {
// @POST("api/v1/vehicle-wakeup/{vin}")
uri := fmt.Sprintf("%s/v1/vehicle-wakeup/%s", BaseURI, vin)

req, err := request.New(http.MethodPost, uri, nil, request.JSONEncoding)
req, err := request.New(http.MethodPost, uri, request.MarshalJSON(data), request.JSONEncoding)
if err == nil {
err = v.DoJSON(req, nil)
// {"id":"61991908906fa40af9a5cba4","status":"InProgress","deeplink":""}
err = v.DoJSON(req, &res)
}

return err
}
13 changes: 13 additions & 0 deletions vehicle/skoda/connect/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package connect

import (
"net/url"
)

// Skoda connect api
var AuthParams = url.Values{
"response_type": {"code id_token"},
"redirect_uri": {"skodaconnect://oidc.login/"},
"client_id": {"7f045eee-7003-4379-9968-9355ed2adb06@apps_vw-dilab_com"},
"scope": {"openid profile mbb mileage"}, // phone address cars email birthdate badge dealers driversLicense
}
113 changes: 113 additions & 0 deletions vehicle/skoda/myskoda/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package myskoda

import (
"fmt"
"net/http"

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

const BaseURI = "https://mysmob.api.connect.skoda-auto.cz/api"

// API is the Skoda api client
type API struct {
*request.Helper
}

// NewAPI creates a new api client
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 /v2/garage response
func (v *API) Vehicles() ([]Vehicle, error) {
var res VehiclesResponse

uri := fmt.Sprintf("%s/v2/garage", BaseURI)
err := v.GetJSON(uri, &res)

return res.Vehicles, err
}

func (v *API) VehicleDetails(vin string) (Vehicle, error) {
var res Vehicle
uri := fmt.Sprintf("%s/v2/garage/vehicles/%s", BaseURI, vin)
err := v.GetJSON(uri, &res)
return res, err
}

// Status implements the /v2/vehicle-status/<vin> response
func (v *API) Status(vin string) (StatusResponse, error) {
var res StatusResponse
uri := fmt.Sprintf("%s/v1/vehicle-health-report/warning-lights/%s", BaseURI, vin)
err := v.GetJSON(uri, &res)
return res, err
}

// Charger implements the /v1/charging/<vin> response
func (v *API) Charger(vin string) (ChargerResponse, error) {
var res ChargerResponse
uri := fmt.Sprintf("%s/v1/charging/%s", BaseURI, vin)
err := v.GetJSON(uri, &res)
return res, err
}

// Settings implements the /v1/charging/<vin>/settings response
func (v *API) Settings(vin string) (SettingsResponse, error) {
var res SettingsResponse

chrgRes, err := v.Charger(vin)
if err == nil {
res = chrgRes.Settings
}
return res, err
}

// Climater implements the /v2/air-conditioning/<vin> response
func (v *API) Climater(vin string) (ClimaterResponse, error) {
var res ClimaterResponse
uri := fmt.Sprintf("%s/v2/air-conditioning/%s", BaseURI, vin)
err := v.GetJSON(uri, &res)
return res, err
}

const (
ActionCharge = "charging"
ActionChargeStart = "start"
ActionChargeStop = "stop"
)

// Action executes a vehicle action
func (v *API) Action(vin, action, value string) error {
// @POST("api/v1/charging/{vin}/start")
// @POST("api/v1/charging/{vin}/stop")
uri := fmt.Sprintf("%s/v1/%s/%s/%s", BaseURI, action, vin, value)

req, err := request.New(http.MethodPost, uri, nil, request.JSONEncoding)
if err == nil {
err = v.DoJSON(req, nil)
}
return err
}

func (v *API) WakeUp(vin string) error {
// @POST("api/v1/vehicle-wakeup/{vin}")
uri := fmt.Sprintf("%s/v1/vehicle-wakeup/%s", BaseURI, vin)

req, err := request.New(http.MethodPost, uri, nil, request.JSONEncoding)
if err == nil {
err = v.DoJSON(req, nil)
}
return err
}
24 changes: 24 additions & 0 deletions vehicle/skoda/myskoda/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package myskoda

import "net/url"

const (
Brand = "VW"
Country = "CZ"

// Authorization ClientID
AuthClientID = "afb0473b-6d82-42b8-bfea-cead338c46ef"
)

// Skoda native api
var AuthParams = url.Values{
"response_type": {"code id_token"},
"client_id": {"7f045eee-7003-4379-9968-9355ed2adb06@apps_vw-dilab_com"},
"redirect_uri": {"myskoda://redirect/login/"},
"scope": {"address badge birthdate cars driversLicense dealers email mileage mbb nationalIdentifier openid phone profession profile vin"},
}

// TokenRefreshService parameters
var TRSParams = url.Values{
"brand": {"skoda"},
}
Loading

0 comments on commit 9ff704e

Please sign in to comment.