Jaguar/Landrover: add more apis (#2480)
This commit is contained in:
parent
dcb6b65002
commit
fb75ec8f63
4 changed files with 123 additions and 5 deletions
|
|
@ -82,7 +82,7 @@ func NewJLRFromConfig(other map[string]interface{}) (api.Vehicle, error) {
|
|||
})
|
||||
|
||||
if err == nil {
|
||||
v.Provider = jlr.NewProvider(api, cc.VIN, cc.Cache)
|
||||
v.Provider = jlr.NewProvider(api, cc.VIN, user.UserId, cc.Cache)
|
||||
}
|
||||
|
||||
return v, err
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package jlr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
|
@ -33,7 +34,6 @@ func NewAPI(log *util.Logger, device string, ts oauth2.TokenSource) *API {
|
|||
if err == nil {
|
||||
for k, v := range map[string]string{
|
||||
"Authorization": fmt.Sprintf("Bearer %s", token.AccessToken),
|
||||
"Content-Type": request.JSONContent,
|
||||
"X-Device-Id": device,
|
||||
"x-telematicsprogramtype": "jlrpy",
|
||||
} {
|
||||
|
|
@ -96,3 +96,67 @@ func (v *API) Status(vin string) (StatusResponse, error) {
|
|||
|
||||
return status, err
|
||||
}
|
||||
|
||||
// Position returns the vehicle position
|
||||
func (v *API) Position(vin string) (PositionResponse, error) {
|
||||
var status PositionResponse
|
||||
|
||||
uri := fmt.Sprintf("%s/vehicles/%s/position", IF9_BASE_URL, vin)
|
||||
req, err := request.New(http.MethodGet, uri, nil, map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
err = v.DoJSON(req, &status)
|
||||
}
|
||||
|
||||
return status, err
|
||||
}
|
||||
|
||||
func (v *API) AuthenticateVinService(vin, user, service string) (PinResponse, error) {
|
||||
pin := vin[len(vin)-4:]
|
||||
data := map[string]string{
|
||||
"serviceName": service,
|
||||
"pin": pin}
|
||||
|
||||
uri := fmt.Sprintf("%s/vehicles/%s/users/%s/authenticate", IF9_BASE_URL, vin, user)
|
||||
req, err := request.New(http.MethodPost, uri, request.MarshalJSON(data), map[string]string{
|
||||
"Content-Type": "application/vnd.wirelesscar.ngtp.if9.AuthenticateRequest-v2+json",
|
||||
})
|
||||
|
||||
var res PinResponse
|
||||
if err == nil {
|
||||
err = v.DoJSON(req, &res)
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (v *API) ChargeAction(vin, user string, start bool) error {
|
||||
var data map[string]interface{}
|
||||
|
||||
pin, err := v.AuthenticateVinService(vin, user, "CP")
|
||||
if err == nil {
|
||||
onoff := map[bool]string{false: "FORCE_OFF", true: "FORCE_ON"}
|
||||
|
||||
data = map[string]interface{}{
|
||||
"token": pin.Token,
|
||||
"serviceParameters": []KeyValue{{"CHARGE_NOW_SETTING", onoff[start]}},
|
||||
}
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("%s/vehicles/%s/chargeProfile", IF9_BASE_URL, vin)
|
||||
req, err := request.New(http.MethodPost, uri, request.MarshalJSON(data), map[string]string{
|
||||
"Content-Type": "application/vnd.wirelesscar.ngtp.if9.PhevService-v1+json",
|
||||
"Accept": "application/vnd.wirelesscar.ngtp.if9.ServiceStatus-v5+json",
|
||||
})
|
||||
|
||||
var res ActionResponse
|
||||
if err == nil {
|
||||
if err = v.DoJSON(req, &res); err == nil && res.FailureDescription != "" {
|
||||
err = errors.New(res.FailureDescription)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,22 @@ import (
|
|||
)
|
||||
|
||||
type Provider struct {
|
||||
statusG func() (interface{}, error)
|
||||
statusG func() (interface{}, error)
|
||||
positionG func() (interface{}, error)
|
||||
actionS func(bool) error
|
||||
}
|
||||
|
||||
func NewProvider(api *API, vin string, cache time.Duration) *Provider {
|
||||
func NewProvider(api *API, vin, user string, cache time.Duration) *Provider {
|
||||
impl := &Provider{
|
||||
statusG: provider.NewCached(func() (interface{}, error) {
|
||||
return api.Status(vin)
|
||||
}, cache).InterfaceGetter(),
|
||||
positionG: provider.NewCached(func() (interface{}, error) {
|
||||
return api.Position(vin)
|
||||
}, cache).InterfaceGetter(),
|
||||
actionS: func(start bool) error {
|
||||
return api.ChargeAction(vin, user, start)
|
||||
},
|
||||
}
|
||||
|
||||
return impl
|
||||
|
|
@ -95,3 +103,29 @@ func (v *Provider) Odometer() (float64, error) {
|
|||
|
||||
return val / 1e3, err
|
||||
}
|
||||
|
||||
var _ api.VehiclePosition = (*Provider)(nil)
|
||||
|
||||
// Position implements the api.VehiclePosition interface
|
||||
func (v *Provider) Position() (float64, float64, error) {
|
||||
res, err := v.positionG()
|
||||
if res, ok := res.(PositionResponse); err == nil && ok {
|
||||
return res.Position.Latitude, res.Position.Longitude, nil
|
||||
}
|
||||
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
var _ api.VehicleStartCharge = (*Provider)(nil)
|
||||
|
||||
// StartCharge implements the api.VehicleStartCharge interface
|
||||
func (v *Provider) StartCharge() error {
|
||||
return v.actionS(true)
|
||||
}
|
||||
|
||||
var _ api.VehicleStopCharge = (*Provider)(nil)
|
||||
|
||||
// StopCharge implements the api.VehicleStopCharge interface
|
||||
func (v *Provider) StopCharge() error {
|
||||
return v.actionS(false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ type VehiclesResponse struct {
|
|||
}
|
||||
|
||||
type KeyValue struct {
|
||||
Key, Value string
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type KeyValueList []KeyValue
|
||||
|
|
@ -41,6 +42,25 @@ type StatusResponse struct {
|
|||
}
|
||||
}
|
||||
|
||||
type PositionResponse struct {
|
||||
Position struct {
|
||||
Latitude float64
|
||||
Longitude float64
|
||||
Timestamp string
|
||||
Speed float64
|
||||
Heading float64
|
||||
PositionQuality interface{}
|
||||
}
|
||||
}
|
||||
|
||||
type PinResponse struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
type ActionResponse struct {
|
||||
FailureDescription string
|
||||
}
|
||||
|
||||
func (l KeyValueList) StringVal(key string) (string, error) {
|
||||
for _, el := range l {
|
||||
if el.Key == key {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue