evcc-io/vehicle/renault/kamereon/api.go
2023-12-06 18:29:32 +01:00

144 lines
3.8 KiB
Go

package kamereon
import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"github.com/evcc-io/evcc/vehicle/renault/gigya"
"github.com/evcc-io/evcc/vehicle/renault/keys"
)
const (
ActionStart = "start"
ActionStop = "stop"
)
type API struct {
*request.Helper
keys keys.ConfigServer
identity *gigya.Identity
login func() error
}
func New(log *util.Logger, keys keys.ConfigServer, identity *gigya.Identity, login func() error) *API {
return &API{
Helper: request.NewHelper(log),
keys: keys,
identity: identity,
login: login,
}
}
func (v *API) request_(uri string, body io.Reader) (Response, error) {
params := url.Values{"country": []string{"DE"}}
headers := map[string]string{
"x-gigya-id_token": v.identity.Token,
"apikey": v.keys.APIKey,
}
method := http.MethodGet
if body != nil {
method = http.MethodPost
}
var res Response
req, err := request.New(method, uri+"?"+params.Encode(), body, headers)
if err == nil {
err = v.DoJSON(req, &res)
}
return res, err
}
func (v *API) request(uri string, body io.Reader) (Response, error) {
res, err := v.request_(uri, body)
// repeat auth if error
if err != nil {
if err = v.login(); err == nil {
res, err = v.request_(uri, nil)
}
}
return res, err
}
func (v *API) Person(personID, brand string) (string, error) {
uri := fmt.Sprintf("%s/commerce/v1/persons/%s", v.keys.Target, personID)
res, err := v.request(uri, nil)
if err != nil {
return "", err
}
for _, account := range res.Accounts {
if strings.Contains(strings.ToLower(account.AccountType), strings.ToLower(brand)) {
return account.AccountID, nil
}
}
return "", errors.New("account not found")
}
func (v *API) Vehicles(accountID string) ([]Vehicle, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/vehicles", v.keys.Target, accountID)
res, err := v.request(uri, nil)
return res.VehicleLinks, err
}
// Battery provides battery-status api response
func (v *API) Battery(accountID string, vin string) (Response, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v2/cars/%s/battery-status", v.keys.Target, accountID, vin)
return v.request(uri, nil)
}
// Hvac provides hvac-status api response
func (v *API) Hvac(accountID string, vin string) (Response, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v1/cars/%s/hvac-status", v.keys.Target, accountID, vin)
return v.request(uri, nil)
}
// Cockpit provides cockpit api response
func (v *API) Cockpit(accountID string, vin string) (Response, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v2/cars/%s/cockpit", v.keys.Target, accountID, vin)
return v.request(uri, nil)
}
func (v *API) WakeUp(accountID string, vin string) (Response, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kcm/v1/vehicles/%s/charge/pause-resume", v.keys.Target, accountID, vin)
data := map[string]interface{}{
"data": map[string]interface{}{
"type": "ChargePauseResume",
"attributes": map[string]interface{}{
"action": "resume",
},
},
}
return v.request(uri, request.MarshalJSON(data))
}
func (v *API) Position(accountID string, vin string) (Response, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v1/cars/%s/location", v.keys.Target, accountID, vin)
return v.request(uri, nil)
}
func (v *API) Action(accountID, action string, vin string) (Response, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v1/cars/%s/actions/charging-start", v.keys.Target, accountID, vin)
data := map[string]interface{}{
"data": map[string]interface{}{
"type": "ChargingStart",
"attributes": map[string]interface{}{
"action": action,
},
},
}
return v.request(uri, request.MarshalJSON(data))
}