evcc-io/vehicle/subaru/api.go
2026-03-14 11:45:19 +01:00

103 lines
2.7 KiB
Go

package subaru
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"time"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"github.com/evcc-io/evcc/util/transport"
"golang.org/x/oauth2"
)
const (
BaseUrl = "https://b2c-login.toyota-europe.com"
ApiBaseUrl = "https://ctpa-oneapi.tceu-ctp-prd.toyotaconnectedeurope.io"
AccessTokenPath = "oauth2/realms/root/realms/alliance-subaru/access_token"
AuthenticationPath = "json/realms/root/realms/alliance-subaru/authenticate?authIndexType=service&authIndexValue=oneapp"
AuthorizationPath = "oauth2/realms/root/realms/alliance-subaru/authorize?client_id=8c4921b0b08901fef389ce1af49c4e10.subaru.com&scope=openid+profile+write&response_type=code&redirect_uri=com.subaru.oneapp:/oauth2Callback&code_challenge=plain&code_challenge_method=plain"
VehicleGuidPath = "v2/vehicle/guid"
RemoteElectricStatusPath = "v1/vehicle/electric/status"
ApiKey = "tTZipv6liF74PwMfk9Ed68AQ0bISswwf3iHQdqcF"
ClientRefKey = "2.19.0"
channel = "ONEAPP"
)
type API struct {
*request.Helper
log *util.Logger
identity *Identity
clientRef string
}
func NewAPI(log *util.Logger, identity *Identity) *API {
v := &API{
Helper: request.NewHelper(log),
log: log,
identity: identity,
}
v.Timeout = 120 * time.Second
v.Transport = &oauth2.Transport{
Source: identity,
Base: v.Transport,
}
h := hmac.New(sha256.New, []byte(ClientRefKey))
h.Write([]byte(v.identity.uuid))
v.clientRef = hex.EncodeToString(h.Sum(nil))
headers := map[string]string{
"Accept": request.JSONContent,
"x-guid": v.identity.uuid,
"x-api-key": ApiKey,
"x-client-ref": v.clientRef,
"x-appversion": ClientRefKey,
"X-Appbrand": "S",
"x-channel": channel,
}
v.Transport = &transport.Decorator{
Decorator: transport.DecorateHeaders(headers),
Base: v.Transport,
}
return v
}
func (v *API) IDToken() string {
return v.identity.IDToken()
}
func (v *API) Vehicles() ([]string, error) {
uri := fmt.Sprintf("%s/%s", ApiBaseUrl, VehicleGuidPath)
req, err := request.New(http.MethodGet, uri, nil, nil)
var resp Vehicles
if err == nil {
err = v.DoJSON(req, &resp)
}
var vehicles []string
for _, v := range resp.Payload {
vehicles = append(vehicles, v.VIN)
}
return vehicles, err
}
func (v *API) Status(vin string) (Status, error) {
uri := fmt.Sprintf("%s/%s?vin=%s", ApiBaseUrl, RemoteElectricStatusPath, vin)
req, err := request.New(http.MethodGet, uri, nil, map[string]string{
"vin": vin,
})
var status Status
if err == nil {
err = v.DoJSON(req, &status)
}
return status, err
}