Nissan: add Ariya template using v2 api (#13401)
This commit is contained in:
parent
c85ec40ee1
commit
2bae9d8f7e
6 changed files with 91 additions and 55 deletions
13
templates/definition/vehicle/nissan-ariya.yaml
Normal file
13
templates/definition/vehicle/nissan-ariya.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
template: nissan-ariya
|
||||
products:
|
||||
- brand: Nissan
|
||||
description:
|
||||
generic: Ariya
|
||||
params:
|
||||
- preset: vehicle-base
|
||||
- preset: vehicle-identify
|
||||
render: |
|
||||
type: nissan
|
||||
version: v2
|
||||
{{ include "vehicle-base" . }}
|
||||
{{ include "vehicle-identify" . }}
|
||||
|
|
@ -32,11 +32,13 @@ func NewNissanFromConfig(other map[string]interface{}) (api.Vehicle, error) {
|
|||
cc := struct {
|
||||
embed `mapstructure:",squash"`
|
||||
User, Password, VIN string
|
||||
Version string
|
||||
Expiry time.Duration
|
||||
Cache time.Duration
|
||||
}{
|
||||
Expiry: expiry,
|
||||
Cache: interval,
|
||||
Version: "v1", // battery api version: v2 for Ariya
|
||||
Expiry: expiry,
|
||||
Cache: interval,
|
||||
}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
|
|
@ -64,7 +66,7 @@ func NewNissanFromConfig(other map[string]interface{}) (api.Vehicle, error) {
|
|||
cc.VIN, err = ensureVehicle(cc.VIN, api.Vehicles)
|
||||
|
||||
if err == nil {
|
||||
v.Provider = nissan.NewProvider(api, cc.VIN, cc.Expiry, cc.Cache)
|
||||
v.Provider = nissan.NewProvider(api, cc.VIN, cc.Version, cc.Expiry, cc.Cache)
|
||||
}
|
||||
|
||||
return v, err
|
||||
|
|
|
|||
|
|
@ -59,9 +59,9 @@ func (v *API) Vehicles() ([]string, error) {
|
|||
return vehicles, err
|
||||
}
|
||||
|
||||
// Battery provides battery api response
|
||||
func (v *API) BatteryStatus(vin string) (StatusResponse, error) {
|
||||
uri := fmt.Sprintf("%s/v1/cars/%s/battery-status", CarAdapterBaseURL, vin)
|
||||
// BatteryStatus provides battery api response
|
||||
func (v *API) BatteryStatus(vin, version string) (StatusResponse, error) {
|
||||
uri := fmt.Sprintf("%s/%s/cars/%s/battery-status", CarAdapterBaseURL, version, vin)
|
||||
|
||||
var res StatusResponse
|
||||
err := v.GetJSON(uri, &res)
|
||||
|
|
|
|||
|
|
@ -64,29 +64,27 @@ func (v *Identity) Login(user, password string) error {
|
|||
}
|
||||
|
||||
// https://github.com/Tobiaswk/dartnissanconnect/commit/7d28dd5461aaed3e46b5be0c9fd58887e1e0cd0b
|
||||
if err == nil {
|
||||
err = api.ErrNotAvailable // not nil
|
||||
for attempt := 1; attempt <= 10 && err != nil; attempt++ {
|
||||
req, err = request.New(http.MethodPost, uri, request.MarshalJSON(res), map[string]string{
|
||||
"Accept-Api-Version": APIVersion,
|
||||
"X-Username": "anonymous",
|
||||
"X-Password": "anonymous",
|
||||
"Content-type": "application/json",
|
||||
"Accept": "application/json",
|
||||
})
|
||||
if err == nil {
|
||||
if err = v.DoJSON(req, &nToken); err != nil && !nToken.SessionExpired() {
|
||||
break
|
||||
}
|
||||
err = api.ErrNotAvailable // not nil
|
||||
for attempt := 1; attempt <= 10 && err != nil; attempt++ {
|
||||
req, err = request.New(http.MethodPost, uri, request.MarshalJSON(res), map[string]string{
|
||||
"Accept-Api-Version": APIVersion,
|
||||
"X-Username": "anonymous",
|
||||
"X-Password": "anonymous",
|
||||
"Content-type": "application/json",
|
||||
"Accept": "application/json",
|
||||
})
|
||||
if err == nil {
|
||||
if err = v.DoJSON(req, &nToken); err != nil && !nToken.SessionExpired() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if errT := nToken.Error(); err != nil && errT != nil {
|
||||
err = errT
|
||||
}
|
||||
|
||||
realm = strings.Trim(nToken.Realm, "/")
|
||||
}
|
||||
|
||||
if errT := nToken.Error(); err != nil && errT != nil {
|
||||
err = errT
|
||||
}
|
||||
|
||||
realm = strings.Trim(nToken.Realm, "/")
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type Provider struct {
|
|||
}
|
||||
|
||||
// NewProvider returns a kamereon provider
|
||||
func NewProvider(api *API, vin string, expiry, cache time.Duration) *Provider {
|
||||
func NewProvider(api *API, vin, version string, expiry, cache time.Duration) *Provider {
|
||||
impl := &Provider{
|
||||
action: func(value Action) error {
|
||||
_, err := api.ChargingAction(vin, value)
|
||||
|
|
@ -30,7 +30,7 @@ func NewProvider(api *API, vin string, expiry, cache time.Duration) *Provider {
|
|||
|
||||
impl.statusG = provider.Cached(func() (StatusResponse, error) {
|
||||
return impl.status(
|
||||
func() (StatusResponse, error) { return api.BatteryStatus(vin) },
|
||||
func() (StatusResponse, error) { return api.BatteryStatus(vin, version) },
|
||||
func() (ActionResponse, error) { return api.RefreshRequest(vin, "RefreshBatteryStatus") },
|
||||
)
|
||||
}, cache)
|
||||
|
|
@ -43,7 +43,8 @@ func (v *Provider) status(battery func() (StatusResponse, error), refresh func()
|
|||
|
||||
if err == nil {
|
||||
// result valid?
|
||||
if time.Since(res.Attributes.LastUpdateTime.Time) < v.expiry || res.Attributes.LastUpdateTime.IsZero() {
|
||||
updated := res.Attributes.Updated()
|
||||
if time.Since(updated) < v.expiry || updated.IsZero() {
|
||||
v.refreshTime = time.Time{}
|
||||
return res, err
|
||||
}
|
||||
|
|
@ -116,16 +117,20 @@ var _ api.VehicleRange = (*Provider)(nil)
|
|||
// Range implements the api.VehicleRange interface
|
||||
func (v *Provider) Range() (int64, error) {
|
||||
res, err := v.statusG()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
if res.Attributes.RangeHvacOff == nil {
|
||||
return 0, api.ErrNotAvailable
|
||||
}
|
||||
|
||||
if res.Attributes.RangeHvacOff != nil {
|
||||
return int64(*res.Attributes.RangeHvacOff), nil
|
||||
}
|
||||
|
||||
return 0, err
|
||||
// v2
|
||||
if res.Attributes.BatteryAutonomy != nil {
|
||||
return int64(*res.Attributes.BatteryAutonomy), nil
|
||||
}
|
||||
|
||||
return 0, api.ErrNotAvailable
|
||||
}
|
||||
|
||||
var _ api.VehicleFinishTimer = (*Provider)(nil)
|
||||
|
|
@ -133,16 +138,20 @@ var _ api.VehicleFinishTimer = (*Provider)(nil)
|
|||
// FinishTime implements the api.VehicleFinishTimer interface
|
||||
func (v *Provider) FinishTime() (time.Time, error) {
|
||||
res, err := v.statusG()
|
||||
|
||||
if err == nil {
|
||||
if res.Attributes.RemainingTime == nil {
|
||||
return time.Time{}, api.ErrNotAvailable
|
||||
}
|
||||
|
||||
return res.Attributes.LastUpdateTime.Time.Add(time.Duration(*res.Attributes.RemainingTime) * time.Minute), err
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
return time.Time{}, err
|
||||
if res.Attributes.RemainingTime != nil {
|
||||
minutes := time.Duration(*res.Attributes.RemainingTime) * time.Minute
|
||||
|
||||
updated := res.Attributes.Updated()
|
||||
if !updated.IsZero() {
|
||||
return updated.Add(minutes), nil
|
||||
}
|
||||
}
|
||||
|
||||
return time.Time{}, api.ErrNotAvailable
|
||||
}
|
||||
|
||||
var _ api.ChargeController = (*Provider)(nil)
|
||||
|
|
|
|||
|
|
@ -77,18 +77,32 @@ type StatusResponse struct {
|
|||
}
|
||||
|
||||
type Attributes struct {
|
||||
ChargeStatus float32 `json:"chargeStatus"`
|
||||
RangeHvacOff *int `json:"rangeHvacOff"`
|
||||
BatteryLevel int `json:"batteryLevel"`
|
||||
BatteryCapacity int `json:"batteryCapacity"`
|
||||
BatteryTemperature int `json:"batteryTemperature"`
|
||||
PlugStatus int `json:"plugStatus"`
|
||||
LastUpdateTime Timestamp `json:"lastUpdateTime"`
|
||||
ChargePower int `json:"chargePower"`
|
||||
RemainingTime *int `json:"chargingRemainingTime"`
|
||||
RemainingToFullFast int `json:"timeRequiredToFullFast"`
|
||||
RemainingToFullNormal int `json:"timeRequiredToFullNormal"`
|
||||
RemainingToFullSlow int `json:"timeRequiredToFullSlow"`
|
||||
ChargeStatus float32 `json:"chargeStatus"`
|
||||
RangeHvacOff *int `json:"rangeHvacOff"`
|
||||
BatteryLevel int `json:"batteryLevel"`
|
||||
BatteryCapacity int `json:"batteryCapacity"`
|
||||
BatteryTemperature int `json:"batteryTemperature"`
|
||||
PlugStatus int `json:"plugStatus"`
|
||||
LastUpdateTime *Timestamp `json:"lastUpdateTime"`
|
||||
ChargePower int `json:"chargePower"`
|
||||
RemainingTime *int `json:"chargingRemainingTime"`
|
||||
RemainingToFullFast int `json:"timeRequiredToFullFast"`
|
||||
RemainingToFullNormal int `json:"timeRequiredToFullNormal"`
|
||||
RemainingToFullSlow int `json:"timeRequiredToFullSlow"`
|
||||
// v2
|
||||
Timestamp *time.Time `json:"timestamp"`
|
||||
BatteryAutonomy *int `json:"batteryAutonomy"`
|
||||
}
|
||||
|
||||
func (a *Attributes) Updated() time.Time {
|
||||
if a.LastUpdateTime != nil {
|
||||
// v1
|
||||
return a.LastUpdateTime.Time
|
||||
} else if a.Timestamp != nil {
|
||||
// v2
|
||||
return *a.Timestamp
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
type ActionResponse struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue