Renault: add wakeup api (#2841)

Co-authored-by: chrissooo <christof@federowicz.de>
This commit is contained in:
premultiply 2022-04-27 20:17:15 +02:00 • committed by GitHub
parent 7adb242b3e
commit 9a775d12ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3,6 +3,7 @@ package vehicle
import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strings"
@ -16,11 +17,11 @@ import (
)
// Credits to
// https://github.com/hacf-fr/renault-api
// https://github.com/edent/Renault-Zoe-API/issues/18
// https://github.com/epenet/Renault-Zoe-API/blob/newapimockup/Test/MyRenault.py
// https://github.com/jamesremuscat/pyze
// https://github.com/hacf-fr/renault-api
// https://muscatoxblog.blogspot.com/2019/07/delving-into-renaults-new-api.html
// https://muscatoxblog.blogspot.com/2019/07/delving-into-renaults-new-api.html
const (
keyStore = "https://renault-wrd-prod-1-euw1-myrapp-one.s3-eu-west-1.amazonaws.com/configuration/android/config_%s.json"
@ -199,10 +200,15 @@ func (v *Renault) authFlow() error {
return err
}
func (v *Renault) request(uri string, data url.Values, headers ...map[string]string) (*http.Request, error) {
req, err := request.New(http.MethodGet, uri, nil, headers...)
func (v *Renault) request(uri string, params url.Values, body io.Reader, headers ...map[string]string) (*http.Request, error) {
method := http.MethodGet
if body != nil {
method = http.MethodPost
}
req, err := request.New(method, uri, body, headers...)
if err == nil {
req.URL.RawQuery = data.Encode()
req.URL.RawQuery = params.Encode()
}
return req, err
@ -217,7 +223,7 @@ func (v *Renault) sessionCookie(user, password string) (string, error) {
"apiKey": []string{v.gigya.APIKey},
}
req, err := v.request(uri, data)
req, err := v.request(uri, data, nil)
var res gigyaResponse
if err == nil {
@ -238,7 +244,7 @@ func (v *Renault) personID(sessionCookie string) (string, error) {
"login_token": []string{sessionCookie},
}
req, err := v.request(uri, data)
req, err := v.request(uri, data, nil)
var res gigyaResponse
if err == nil {
@ -258,7 +264,7 @@ func (v *Renault) jwtToken(sessionCookie string) (string, error) {
"expiration": []string{"900"},
}
req, err := v.request(uri, data)
req, err := v.request(uri, data, nil)
var res gigyaResponse
if err == nil {
@ -268,15 +274,15 @@ func (v *Renault) jwtToken(sessionCookie string) (string, error) {
return res.IDToken, err
}
func (v *Renault) kamereonRequest(uri string) (kamereonResponse, error) {
data := url.Values{"country": []string{"DE"}}
func (v *Renault) kamereonRequest(uri string, body io.Reader) (kamereonResponse, error) {
params := url.Values{"country": []string{"DE"}}
headers := map[string]string{
"x-gigya-id_token": v.gigyaJwtToken,
"apikey": "VAX7XYKGfa92yMvXculCkEFyfZbuM7Ss", // v.kamereon.APIKey
}
var res kamereonResponse
req, err := v.request(uri, data, headers)
req, err := v.request(uri, params, body, headers)
if err == nil {
err = v.DoJSON(req, &res)
}
@ -286,7 +292,7 @@ func (v *Renault) kamereonRequest(uri string) (kamereonResponse, error) {
func (v *Renault) kamereonPerson(personID string) (string, error) {
uri := fmt.Sprintf("%s/commerce/v1/persons/%s", v.kamereon.Target, personID)
res, err := v.kamereonRequest(uri)
res, err := v.kamereonRequest(uri, nil)
if len(res.Accounts) == 0 {
return "", err
@ -297,7 +303,7 @@ func (v *Renault) kamereonPerson(personID string) (string, error) {
func (v *Renault) kamereonVehicles(accountID string) ([]string, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/vehicles", v.kamereon.Target, accountID)
res, err := v.kamereonRequest(uri)
res, err := v.kamereonRequest(uri, nil)
var vehicles []string
if err == nil {
@ -314,12 +320,12 @@ func (v *Renault) kamereonVehicles(accountID string) ([]string, error) {
// batteryAPI provides battery-status api response
func (v *Renault) batteryAPI() (kamereonResponse, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v2/cars/%s/battery-status", v.kamereon.Target, v.accountID, v.vin)
res, err := v.kamereonRequest(uri)
res, err := v.kamereonRequest(uri, nil)
// repeat auth if error
if err != nil {
if err = v.authFlow(); err == nil {
res, err = v.kamereonRequest(uri)
res, err = v.kamereonRequest(uri, nil)
}
}
@ -329,12 +335,12 @@ func (v *Renault) batteryAPI() (kamereonResponse, error) {
// hvacAPI provides hvac-status api response
func (v *Renault) hvacAPI() (kamereonResponse, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v1/cars/%s/hvac-status", v.kamereon.Target, v.accountID, v.vin)
res, err := v.kamereonRequest(uri)
res, err := v.kamereonRequest(uri, nil)
// repeat auth if error
if err != nil {
if err = v.authFlow(); err == nil {
res, err = v.kamereonRequest(uri)
res, err = v.kamereonRequest(uri, nil)
}
}
@ -344,12 +350,12 @@ func (v *Renault) hvacAPI() (kamereonResponse, error) {
// cockpitAPI provides cockpit api response
func (v *Renault) cockpitAPI() (kamereonResponse, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v2/cars/%s/cockpit", v.kamereon.Target, v.accountID, v.vin)
res, err := v.kamereonRequest(uri)
res, err := v.kamereonRequest(uri, nil)
// repeat auth if error
if err != nil {
if err = v.authFlow(); err == nil {
res, err = v.kamereonRequest(uri)
res, err = v.kamereonRequest(uri, nil)
}
}
@ -456,3 +462,30 @@ func (v *Renault) Climater() (active bool, outsideTemp float64, targetTemp float
return false, 0, 0, err
}
var _ api.AlarmClock = (*Renault)(nil)
// WakeUp implements the api.AlarmClock interface
func (v *Renault) WakeUp() error {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kcm/v1/vehicles/%s/charge/pause-resume", v.kamereon.Target, v.accountID, v.vin)
data := map[string]interface{}{
"data": map[string]interface{}{
"type": "ChargePauseResume",
"attributes": map[string]interface{}{
"action": "resume",
},
},
}
_, err := v.kamereonRequest(uri, request.MarshalJSON(data))
// repeat auth if error
if err != nil {
if err = v.authFlow(); err == nil {
_, err = v.kamereonRequest(uri, request.MarshalJSON(data))
}
}
return err
}