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

Added AU Region for Saic/MG #17544

Merged
merged 9 commits into from
Dec 4, 2024
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
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 {
andig marked this conversation as resolved.
Show resolved Hide resolved
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
Loading