Skip to content

Commit

Permalink
Nissan: fix api access for added Accept: application/json header (#1996)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig committed Dec 7, 2021
1 parent fd57cc2 commit 245721c
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 51 deletions.
24 changes: 17 additions & 7 deletions vehicle/nissan/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,18 @@ import (
"golang.org/x/oauth2"
)

// api constants
const (
refreshTimeout = 5 * time.Minute
APIVersion = "protocol=1.0,resource=2.1"
ClientID = "a-ncb-prod-android"
ClientSecret = "3LBs0yOx2XO-3m4mMRW27rKeJzskhfWF0A8KUtnim8i/qYQPl8ZItp3IaqJXaYj_"
Scope = "openid profile vehicles"
AuthBaseURL = "https://prod.eu.auth.kamereon.org/kauth"
Realm = "a-ncb-prod"
RedirectURI = "org.kamereon.service.nci:/oauth2redirect"
CarAdapterBaseURL = "https://alliance-platform-caradapter-prod.apps.eu.kamereon.io/car-adapter"
UserAdapterBaseURL = "https://alliance-platform-usersadapter-prod.apps.eu.kamereon.io/user-adapter"
UserBaseURL = "https://nci-bff-web-prod.apps.eu.kamereon.io/bff-web"
)

type API struct {
Expand Down Expand Up @@ -57,18 +67,18 @@ func (v *API) Vehicles() ([]string, error) {
}

// Battery provides battery api response
func (v *API) BatteryStatus(vin string) (Response, error) {
func (v *API) BatteryStatus(vin string) (StatusResponse, error) {
uri := fmt.Sprintf("%s/v1/cars/%s/battery-status", CarAdapterBaseURL, vin)

var res Response
var res StatusResponse
err := v.GetJSON(uri, &res)

return res, err
}

// RefreshRequest requests battery status refresh
func (v *API) RefreshRequest(vin string, typ string) (Response, error) {
var res Response
func (v *API) RefreshRequest(vin string, typ string) (ActionResponse, error) {
var res ActionResponse
uri := fmt.Sprintf("%s/v1/cars/%s/actions/refresh-battery-status", CarAdapterBaseURL, vin)

data := Request{
Expand Down Expand Up @@ -96,7 +106,7 @@ const (
)

// ChargingAction provides actions/charging-start api response
func (v *API) ChargingAction(vin string, action Action) (Response, error) {
func (v *API) ChargingAction(vin string, action Action) (ActionResponse, error) {
uri := fmt.Sprintf("%s/v1/cars/%s/actions/charging-start", CarAdapterBaseURL, vin)

data := Request{
Expand All @@ -112,7 +122,7 @@ func (v *API) ChargingAction(vin string, action Action) (Response, error) {
"Content-Type": "application/vnd.api+json",
})

var res Response
var res ActionResponse
if err == nil {
err = v.DoJSON(req, &res)
}
Expand Down
30 changes: 16 additions & 14 deletions vehicle/nissan/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"github.com/evcc-io/evcc/provider"
)

const refreshTimeout = 2 * time.Minute

// Provider is a kamereon provider
type Provider struct {
statusG func() (interface{}, error)
Expand All @@ -28,20 +30,20 @@ func NewProvider(api *API, vin string, expiry, cache time.Duration) *Provider {

impl.statusG = provider.NewCached(func() (interface{}, error) {
return impl.status(
func() (Response, error) { return api.BatteryStatus(vin) },
func() (Response, error) { return api.RefreshRequest(vin, "RefreshBatteryStatus") },
func() (StatusResponse, error) { return api.BatteryStatus(vin) },
func() (ActionResponse, error) { return api.RefreshRequest(vin, "RefreshBatteryStatus") },
)
}, cache).InterfaceGetter()

return impl
}

func (v *Provider) status(battery func() (Response, error), refresh func() (Response, error)) (Response, error) {
func (v *Provider) status(battery func() (StatusResponse, error), refresh func() (ActionResponse, error)) (StatusResponse, error) {
res, err := battery()

if err == nil {
// result valid?
if res.Data.Attributes.LastUpdateTime.Add(v.expiry).After(time.Now()) {
if time.Since(res.Attributes.LastUpdateTime.Time) < v.expiry {
v.refreshTime = time.Time{}
return res, err
}
Expand Down Expand Up @@ -83,8 +85,8 @@ var _ api.Battery = (*Provider)(nil)
func (v *Provider) SoC() (float64, error) {
res, err := v.statusG()

if res, ok := res.(Response); err == nil && ok {
return float64(res.Data.Attributes.BatteryLevel), nil
if res, ok := res.(StatusResponse); err == nil && ok {
return float64(res.Attributes.BatteryLevel), nil
}

return 0, err
Expand All @@ -97,11 +99,11 @@ func (v *Provider) Status() (api.ChargeStatus, error) {
status := api.StatusA // disconnected

res, err := v.statusG()
if res, ok := res.(Response); err == nil && ok {
if res.Data.Attributes.PlugStatus > 0 {
if res, ok := res.(StatusResponse); err == nil && ok {
if res.Attributes.PlugStatus > 0 {
status = api.StatusB
}
if res.Data.Attributes.ChargingStatus > 1.0 {
if res.Attributes.ChargeStatus > 1.0 {
status = api.StatusC
}
}
Expand All @@ -115,8 +117,8 @@ var _ api.VehicleRange = (*Provider)(nil)
func (v *Provider) Range() (int64, error) {
res, err := v.statusG()

if res, ok := res.(Response); err == nil && ok {
return int64(res.Data.Attributes.RangeHvacOff), nil
if res, ok := res.(StatusResponse); err == nil && ok {
return int64(res.Attributes.RangeHvacOff), nil
}

return 0, err
Expand All @@ -128,12 +130,12 @@ var _ api.VehicleFinishTimer = (*Provider)(nil)
func (v *Provider) FinishTime() (time.Time, error) {
res, err := v.statusG()

if res, ok := res.(Response); err == nil && ok {
if res.Data.Attributes.RemainingTime == nil {
if res, ok := res.(StatusResponse); err == nil && ok {
if res.Attributes.RemainingTime == nil {
return time.Time{}, api.ErrNotAvailable
}

return res.Data.Attributes.Timestamp.Add(time.Duration(*res.Data.Attributes.RemainingTime) * time.Minute), err
return res.Attributes.LastUpdateTime.Time.Add(time.Duration(*res.Attributes.RemainingTime) * time.Minute), err
}

return time.Time{}, err
Expand Down
48 changes: 18 additions & 30 deletions vehicle/nissan/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@ import (
"time"
)

// api constants
const (
APIVersion = "protocol=1.0,resource=2.1"
ClientID = "a-ncb-prod-android"
ClientSecret = "3LBs0yOx2XO-3m4mMRW27rKeJzskhfWF0A8KUtnim8i/qYQPl8ZItp3IaqJXaYj_"
Scope = "openid profile vehicles"
AuthBaseURL = "https://prod.eu.auth.kamereon.org/kauth"
Realm = "a-ncb-prod"
RedirectURI = "org.kamereon.service.nci:/oauth2redirect"
CarAdapterBaseURL = "https://alliance-platform-caradapter-prod.apps.eu.kamereon.io/car-adapter"
UserAdapterBaseURL = "https://alliance-platform-usersadapter-prod.apps.eu.kamereon.io/user-adapter"
UserBaseURL = "https://nci-bff-web-prod.apps.eu.kamereon.io/bff-web"
)

type Auth struct {
AuthID string `json:"authId"`
Template string `json:"template"`
Expand Down Expand Up @@ -79,34 +65,36 @@ type Payload struct {
Attributes map[string]interface{} `json:"attributes,omitempty"`
}

// Response structure for kamereon api
type Response struct {
Data struct {
Type, ID string // battery refresh
Attributes attributes `json:"attributes"`
} `json:"data"`
Errors []Error
}

type Error struct {
Status, Code, Detail string
}

type attributes struct {
Timestamp Timestamp `json:"timestamp"`
ChargingStatus float32 `json:"chargingStatus"`
InstantaneousPower int `json:"instantaneousPower"`
RangeHvacOff int `json:"rangeHvacOff"` // Nissan
BatteryAutonomy int `json:"batteryAutonomy"` // Renault
// StatusResponse structure for kamereon api
type StatusResponse struct {
ID string
Attributes
Errors []Error
}

type Attributes struct {
ChargeStatus float32 `json:"chargingStatus"`
RangeHvacOff int `json:"rangeHvacOff"`
BatteryLevel int `json:"batteryLevel"`
BatteryCapacity int `json:"batteryCapacity"` // Nissan
BatteryCapacity int `json:"batteryCapacity"`
BatteryTemperature int `json:"batteryTemperature"`
PlugStatus int `json:"plugStatus"`
LastUpdateTime Timestamp `json:"lastUpdateTime"`
ChargePower int `json:"chargePower"`
RemainingTime *int `json:"chargingRemainingTime"`
}

type ActionResponse struct {
Data struct {
Type, ID string // battery refresh
} `json:"data"`
Errors []Error
}

const timeFormat = "2006-01-02T15:04:05Z"

// Timestamp implements JSON unmarshal
Expand Down

0 comments on commit 245721c

Please sign in to comment.