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
10 changes: 10 additions & 0 deletions templates/definition/vehicle/mg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@ 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" . }}
{{- if ne .region "EU" }}
region: {{ .region }}
{{- end }}
andig marked this conversation as resolved.
Show resolved Hide resolved
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(url string, baseUrl 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(
url,
baseUrl,
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(url string, baseUrl 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(url, baseUrl, 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,
url := v.identity.baseUrl + "vehicle/status?vin=" + requests.Sha256(vin)
req, err = requests.CreateRequest(
url,
v.identity.baseUrl,
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)

url := v.identity.baseUrl + "vehicle/charging/mgmtData?vin=" + requests.Sha256(vin)
// get charging status of vehicle
req, err = requests.CreateRequest(url,
req, err = requests.CreateRequest(
url,
v.identity.baseUrl,
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(
url,
v.identity.baseUrl,
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(url, v.identity.baseUrl, 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",
v.baseUrl,
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/"
)
8 changes: 4 additions & 4 deletions vehicle/saic/requests/encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ 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(url, baseUrl 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)
replace = strings.Replace(url, baseUrl, "/", -1)
}

encryptedBody := ""
Expand All @@ -70,9 +70,9 @@ 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(url string, baseUrl string, time int64, tenant, token, body, contentType string) string {
timeStamp := strconv.FormatInt(time, 10)
resourcePath := strings.Replace(url, BASE_URL_P, "/", -1)
resourcePath := strings.Replace(url, baseUrl, "/", -1)
if len(body) != 0 {
sb3 := Md5(resourcePath+tenant+token+USER_TYPE) + timeStamp + CONTENT_ENCRYPTED + contentType
a2 := Md5(sb3)
Expand Down
4 changes: 3 additions & 1 deletion vehicle/saic/requests/sendRequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func Decorate(req *http.Request) error {

func CreateRequest(
endpoint string,
baseUrl string,
httpMethod string,
request string,
contentType string,
Expand All @@ -32,6 +33,7 @@ func CreateRequest(
if len(request) != 0 {
request = EncryptRequest(
endpoint,
baseUrl,
appSendDate,
TENANT_ID,
token,
Expand All @@ -56,7 +58,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