Skip to content

Commit

Permalink
Saic/MG: add AU region (#17544)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjhgmailcom authored Dec 4, 2024
1 parent 15d0a78 commit 28b0919
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 42 deletions.
8 changes: 8 additions & 0 deletions templates/definition/vehicle/mg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,15 @@ params:
de: Erforderlich
en: Required
required: true
- name: region
description:
de: Region
en: Region
validvalues: ["EU", "AU"]
default: EU
advanced: true
render: |
type: mg
{{ include "vehicle-base" . }}
{{ include "vehicle-identify" . }}
region: {{ .region }}
15 changes: 13 additions & 2 deletions vehicle/mg.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package vehicle

import (
"strings"
"time"

"github.com/evcc-io/evcc/api"
Expand All @@ -23,9 +24,11 @@ func NewMGFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
embed `mapstructure:",squash"`
User, Password, VIN string
Region string
Cache time.Duration
}{
Cache: interval,
Region: "EU",
Cache: interval,
}

if err := util.DecodeOther(other, &cc); err != nil {
Expand All @@ -36,8 +39,16 @@ func NewMGFromConfig(other map[string]interface{}) (api.Vehicle, error) {
return nil, api.ErrMissingCredentials
}

var baseUrl string
switch strings.ToUpper(cc.Region) {
case "AU":
baseUrl = saic.RegionAU
default:
baseUrl = saic.RegionEU
}

log := util.NewLogger("mg").Redact(cc.User, cc.Password, cc.VIN)
identity := saic.NewIdentity(log, cc.User, cc.Password)
identity := saic.NewIdentity(log, cc.User, cc.Password, baseUrl)

if err := identity.Login(); err != nil {
return nil, err
Expand Down
52 changes: 26 additions & 26 deletions vehicle/saic/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ const (
StatInvalid
)

const (
RegionEU = "https://gateway-mg-eu.soimt.com/api.app/v1/"
RegionAU = "https://gateway-mg-au.soimt.com/api.app/v1/"
)

type ConcurrentRequest struct {
Status int
Result requests.ChargeStatus
Expand Down Expand Up @@ -50,17 +55,7 @@ func NewAPI(log *util.Logger, identity *Identity) *API {
return v
}

/*
func (v *API) printAnswer() {
v.Logger.DEBUG.Printf("SOC:%d ", v.request.Result.ChrgMgmtData.BmsPackSOCDsp)
v.Logger.DEBUG.Printf("GUN:%d ", v.request.Result.RvsChargeStatus.ChargingGunState)
v.Logger.DEBUG.Printf("Chrg State:%d ", v.request.Result.ChrgMgmtData.BmsChrgSts)
v.Logger.DEBUG.Printf("Mileage:%d ", v.request.Result.RvsChargeStatus.Mileage)
v.Logger.DEBUG.Printf("Range:%d ", v.request.Result.RvsChargeStatus.FuelRangeElec)
}
*/

func (v *API) doRepeatedRequest(url string, event_id string) error {
func (v *API) doRepeatedRequest(path string, event_id string) error {
var req *http.Request

answer := requests.Answer{
Expand All @@ -73,7 +68,9 @@ func (v *API) doRepeatedRequest(url string, event_id string) error {
return err
}

req, err = requests.CreateRequest(url,
req, err = requests.CreateRequest(
v.identity.baseUrl,
path,
http.MethodGet,
"",
request.JSONContent,
Expand All @@ -94,20 +91,19 @@ func (v *API) doRepeatedRequest(url string, event_id string) error {
}

// This is running concurrently
func (v *API) repeatRequest(url string, event_id string) {
func (v *API) repeatRequest(path string, event_id string) {
var err error
var count = 0
var count int

v.request.Status = StatRunning
for err = api.ErrMustRetry; err == api.ErrMustRetry && count < 20; {
time.Sleep(2 * time.Second)
v.Logger.DEBUG.Printf("Starting repeated query. Count: %d\n", count)
err = v.doRepeatedRequest(url, event_id)
err = v.doRepeatedRequest(path, event_id)
count++
}

v.Logger.DEBUG.Printf("Exitig repeated query. Count: %d\n", count)
//v.printAnswer()
v.Logger.DEBUG.Printf("Exiting repeated query. Count: %d\n", count)
}

func (v *API) DoRequest(req *http.Request, result *requests.Answer) (string, error) {
Expand Down Expand Up @@ -166,8 +162,10 @@ func (v *API) Wakeup(vin string) error {
return err
}

url := requests.BASE_URL_P + "vehicle/status?vin=" + requests.Sha256(vin)
req, err = requests.CreateRequest(url,
path := "vehicle/status?vin=" + requests.Sha256(vin)
req, err = requests.CreateRequest(
v.identity.baseUrl,
path,
http.MethodGet,
"",
request.JSONContent,
Expand Down Expand Up @@ -197,7 +195,7 @@ func (v *API) Status(vin string) (requests.ChargeStatus, error) {
if v.request.Status == StatValid {
v.request.Status = StatInvalid
v.Logger.DEBUG.Printf("StatVaild. Returning stored value\n")
//v.printAnswer()
// v.printAnswer()
return v.request.Result, nil
} else if v.request.Status == StatRunning {
v.Logger.DEBUG.Printf("StatRunning. Exiting\n")
Expand All @@ -210,10 +208,11 @@ func (v *API) Status(vin string) (requests.ChargeStatus, error) {
return res, err
}

url := requests.BASE_URL_P + "vehicle/charging/mgmtData?vin=" + requests.Sha256(vin)

path := "vehicle/charging/mgmtData?vin=" + requests.Sha256(vin)
// get charging status of vehicle
req, err = requests.CreateRequest(url,
req, err = requests.CreateRequest(
v.identity.baseUrl,
path,
http.MethodGet,
"",
request.JSONContent,
Expand All @@ -224,7 +223,6 @@ func (v *API) Status(vin string) (requests.ChargeStatus, error) {
}

event_id, err = v.DoRequest(req, &answer)

if err != nil {
v.Logger.DEBUG.Printf("Getting event id failed")
return res, err
Expand All @@ -235,7 +233,9 @@ func (v *API) Status(vin string) (requests.ChargeStatus, error) {
return res, api.ErrMustRetry
}

req, err = requests.CreateRequest(url,
req, err = requests.CreateRequest(
v.identity.baseUrl,
path,
http.MethodGet,
"",
request.JSONContent,
Expand All @@ -252,7 +252,7 @@ func (v *API) Status(vin string) (requests.ChargeStatus, error) {
if err == api.ErrMustRetry {
v.request.Status = StatRunning
v.Logger.DEBUG.Printf(" No answer yet. Continue status query in background\n")
go v.repeatRequest(url, event_id)
go v.repeatRequest(path, event_id)
} else if err != nil {
v.Logger.ERROR.Printf("doRequest failed with %s", err.Error())
}
Expand Down
7 changes: 5 additions & 2 deletions vehicle/saic/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@ type Identity struct {
User string
Password string
deviceId string
baseUrl string
}

// NewIdentity creates SAIC identity
func NewIdentity(log *util.Logger, user, password string) *Identity {
func NewIdentity(log *util.Logger, user, password, baseUrl string) *Identity {
v := &Identity{
Helper: request.NewHelper(log),
User: user,
Password: requests.Sha1(password),
baseUrl: baseUrl,
}

v.deviceId = lo.RandomString(64, lo.AlphanumericCharset) + "###com.saicmotor.europecar"
Expand Down Expand Up @@ -74,7 +76,8 @@ func (v *Identity) retrieveToken(data url.Values) (*oauth2.Token, error) {

// get charging status of vehicle
req, err := requests.CreateRequest(
requests.BASE_URL_P+"oauth/token",
v.baseUrl,
"oauth/token",
http.MethodPost,
data.Encode(),
request.FormContent,
Expand Down
1 change: 0 additions & 1 deletion vehicle/saic/requests/api_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ const (
PARAM_AUTHENTICATION = "Basic c3dvcmQ6c3dvcmRfc2VjcmV0"
TENANT_ID = "459771"
USER_TYPE = "app"
BASE_URL_P = "https://gateway-mg-eu.soimt.com/api.app/v1/"
)
20 changes: 12 additions & 8 deletions vehicle/saic/requests/encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package requests

import (
"strconv"
"strings"
)

func CalculateRequestVerification(
Expand Down Expand Up @@ -48,18 +47,18 @@ func CalculateResponseVerification(str, str2, str3 string) string {
return HmacSha256(a4, str5)
}

func EncryptRequest(url string, time int64, tenant, token, body, contentType string) string {
func EncryptRequest(path string, time int64, tenant, token, body, contentType string) string {
sendDate := strconv.FormatInt(time, 10)
// tenant
replace := ""
if len(url) != 0 {
replace = strings.Replace(url, BASE_URL_P, "/", -1)
resourcePath := ""
if len(path) != 0 {
resourcePath = "/" + path
}

encryptedBody := ""

if len(body) != 0 {
sb3 := Md5(replace+tenant+token+USER_TYPE) + sendDate + CONTENT_ENCRYPTED + contentType
sb3 := Md5(resourcePath+tenant+token+USER_TYPE) + sendDate + CONTENT_ENCRYPTED + contentType
a2 := Md5(sb3)
a3 := Md5(sendDate)
if len(body) != 0 && len(a2) != 0 && len(a3) != 0 {
Expand All @@ -70,9 +69,14 @@ func EncryptRequest(url string, time int64, tenant, token, body, contentType str
return encryptedBody
}

func DecryptRequest(url string, time int64, tenant, token, body, contentType string) string {
func DecryptRequest(path string, time int64, tenant, token, body, contentType string) string {
timeStamp := strconv.FormatInt(time, 10)
resourcePath := strings.Replace(url, BASE_URL_P, "/", -1)
resourcePath := ""

if len(path) != 0 {
resourcePath = "/" + path
}

if len(body) != 0 {
sb3 := Md5(resourcePath+tenant+token+USER_TYPE) + timeStamp + CONTENT_ENCRYPTED + contentType
a2 := Md5(sb3)
Expand Down
9 changes: 6 additions & 3 deletions vehicle/saic/requests/sendRequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ func Decorate(req *http.Request) error {
}

func CreateRequest(
endpoint string,
baseUrl string,
path string,
httpMethod string,
request string,
contentType string,
Expand All @@ -29,9 +30,11 @@ func CreateRequest(
) (*http.Request, error) {
appSendDate := time.Now().UnixMilli()

endpoint := baseUrl + path

if len(request) != 0 {
request = EncryptRequest(
endpoint,
path,
appSendDate,
TENANT_ID,
token,
Expand All @@ -56,7 +59,7 @@ func CreateRequest(
req.Header.Set("event-id", eventId)
}

replace := strings.Replace(endpoint, BASE_URL_P, "/", -1)
replace := strings.Replace(endpoint, baseUrl, "/", -1)

req.Header.Set("app-verification-string",
CalculateRequestVerification(
Expand Down

0 comments on commit 28b0919

Please sign in to comment.