From 5ecf7795b8722d4f5d8c245b3cae9ded19d24253 Mon Sep 17 00:00:00 2001 From: andig Date: Fri, 20 Feb 2026 12:06:35 +0100 Subject: [PATCH] Toyota: add missing x-channel header (#27542) Co-authored-by: Martin Schuppert --- vehicle/toyota/api.go | 72 +++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/vehicle/toyota/api.go b/vehicle/toyota/api.go index 32f18a0f6..7715b326f 100644 --- a/vehicle/toyota/api.go +++ b/vehicle/toyota/api.go @@ -10,6 +10,7 @@ import ( "github.com/evcc-io/evcc/util" "github.com/evcc-io/evcc/util/request" + "github.com/evcc-io/evcc/util/transport" "golang.org/x/oauth2" ) @@ -21,15 +22,15 @@ const ( AuthorizationPath = "oauth2/realms/root/realms/tme/authorize?client_id=oneapp&scope=openid+profile+write&response_type=code&redirect_uri=com.toyota.oneapp:/oauth2Callback&code_challenge=plain&code_challenge_method=plain" VehicleGuidPath = "v2/vehicle/guid" RemoteElectricStatusPath = "v1/global/remote/electric/status" - ApiKey = "tTZipv6liF74PwMfk9Ed68AQ0bISswwf3iHQdqcF" - ClientRefKey = "3e0b15f6c9c87fbd" + apiKey = "tTZipv6liF74PwMfk9Ed68AQ0bISswwf3iHQdqcF" + clientRefKey = "3e0b15f6c9c87fbd" + channel = "ONEAPP" // Required x-channel header value for Toyota OneApp API ) type API struct { *request.Helper - log *util.Logger - identity *Identity - clientRef string + log *util.Logger + identity *Identity } func NewAPI(log *util.Logger, identity *Identity) *API { @@ -41,16 +42,26 @@ func NewAPI(log *util.Logger, identity *Identity) *API { v.Timeout = 120 * time.Second - // replace client transport with authenticated transport - v.Transport = &oauth2.Transport{ - Source: identity, - Base: v.Transport, - } - // create HMAC digest for x-client-ref header - h := hmac.New(sha256.New, []byte(ClientRefKey)) + h := hmac.New(sha256.New, []byte(clientRefKey)) h.Write([]byte(v.identity.uuid)) - v.clientRef = hex.EncodeToString(h.Sum(nil)) + clientRef := hex.EncodeToString(h.Sum(nil)) + + // replace client transport with authenticated transport + v.Transport = &transport.Decorator{ + Decorator: transport.DecorateHeaders(map[string]string{ + "Accept": request.JSONContent, + "x-guid": v.identity.uuid, + "x-api-key": apiKey, + "x-client-ref": clientRef, + "x-appversion": clientRefKey, + "x-channel": channel, + }), + Base: &oauth2.Transport{ + Source: identity, + Base: v.Transport, + }, + } return v } @@ -58,19 +69,11 @@ func NewAPI(log *util.Logger, identity *Identity) *API { func (v *API) Vehicles() ([]string, error) { uri := fmt.Sprintf("%s/%s", ApiBaseUrl, VehicleGuidPath) - req, err := request.New(http.MethodGet, uri, nil, map[string]string{ - "Accept": request.JSONContent, - "x-guid": v.identity.uuid, - "x-api-key": ApiKey, - "x-client-ref": v.clientRef, - "x-appversion": ClientRefKey, - }) - var resp Vehicles - if err == nil { - err = v.DoJSON(req, &resp) - } + var res Vehicles + err := v.GetJSON(uri, &res) + var vehicles []string - for _, v := range resp.Payload { + for _, v := range res.Payload { vehicles = append(vehicles, v.VIN) } return vehicles, err @@ -79,17 +82,12 @@ func (v *API) Vehicles() ([]string, error) { func (v *API) Status(vin string) (Status, error) { uri := fmt.Sprintf("%s/%s", ApiBaseUrl, RemoteElectricStatusPath) - req, err := request.New(http.MethodGet, uri, nil, map[string]string{ - "Accept": request.JSONContent, - "x-guid": v.identity.uuid, - "x-api-key": ApiKey, - "x-client-ref": v.clientRef, - "x-appversion": ClientRefKey, - "vin": vin, + req, _ := 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 + + var res Status + err := v.DoJSON(req, &res) + + return res, err }