90 lines
2 KiB
Go
90 lines
2 KiB
Go
package jlr
|
|
|
|
import (
|
|
"fmt"
|
|
"maps"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/evcc-io/evcc/util"
|
|
"github.com/evcc-io/evcc/util/oauth"
|
|
"github.com/evcc-io/evcc/util/request"
|
|
"golang.org/x/oauth2"
|
|
)
|
|
|
|
// https://github.com/ardevd/jlrpy
|
|
|
|
const IFAS_BASE_URL = "https://ifas.prod-row.jlrmotor.com/ifas/jlr"
|
|
|
|
type Identity struct {
|
|
*request.Helper
|
|
user, password, device string
|
|
oauth2.TokenSource
|
|
}
|
|
|
|
func Headers(device string, headers map[string]string) map[string]string {
|
|
res := map[string]string{
|
|
"X-Device-Id": device,
|
|
"x-App-Id": "ICR_JAGUAR",
|
|
"x-App-Secret": "018dd168-6271-707f-9fd4-aed2bf76905e",
|
|
}
|
|
|
|
maps.Copy(res, headers)
|
|
|
|
return res
|
|
}
|
|
|
|
// NewIdentity creates Fiat identity
|
|
func NewIdentity(log *util.Logger, user, password, device string) *Identity {
|
|
return &Identity{
|
|
Helper: request.NewHelper(log),
|
|
user: user,
|
|
password: password,
|
|
device: device,
|
|
}
|
|
}
|
|
|
|
// Login authenticates with given payload
|
|
func (v *Identity) login(data any) (Token, error) {
|
|
uri := fmt.Sprintf("%s/tokens", IFAS_BASE_URL)
|
|
req, err := request.New(http.MethodPost, uri, request.MarshalJSON(data), Headers(v.device, map[string]string{
|
|
"Authorization": "Basic YXM6YXNwYXNz",
|
|
"Content-type": request.JSONContent,
|
|
}))
|
|
|
|
var token Token
|
|
if err == nil {
|
|
err = v.DoJSON(req, &token)
|
|
token.Expiry = time.Now().Add(time.Duration(token.ExpiresIn) * time.Second)
|
|
}
|
|
|
|
return token, err
|
|
}
|
|
|
|
// Login authenticates with username/password
|
|
func (v *Identity) Login() (Token, error) {
|
|
data := map[string]string{
|
|
"grant_type": "password",
|
|
"username": v.user,
|
|
"password": v.password,
|
|
}
|
|
|
|
token, err := v.login(data)
|
|
if err == nil {
|
|
v.TokenSource = oauth.RefreshTokenSource(&token.Token, v)
|
|
}
|
|
|
|
return token, err
|
|
}
|
|
|
|
// RefreshToken implements oauth.TokenRefresher
|
|
func (v *Identity) RefreshToken(token *oauth2.Token) (*oauth2.Token, error) {
|
|
data := map[string]string{
|
|
"grant_type": "refresh_token",
|
|
"refresh_token": token.RefreshToken,
|
|
}
|
|
|
|
res, err := v.login(data)
|
|
|
|
return &res.Token, err
|
|
}
|