Nissan: add start/stop actions (#1366)
This commit is contained in:
parent
363c7b8c94
commit
edc1b3efc6
4 changed files with 102 additions and 41 deletions
|
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/andig/evcc/api"
|
||||
"github.com/andig/evcc/util"
|
||||
"github.com/andig/evcc/vehicle/kamereon"
|
||||
"github.com/andig/evcc/vehicle/nissan"
|
||||
)
|
||||
|
||||
|
|
@ -22,7 +21,7 @@ import (
|
|||
// Nissan is an api.Vehicle implementation for Nissan cars
|
||||
type Nissan struct {
|
||||
*embed
|
||||
*kamereon.Provider
|
||||
*nissan.Provider
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
@ -64,7 +63,7 @@ func NewNissanFromConfig(other map[string]interface{}) (api.Vehicle, error) {
|
|||
}
|
||||
}
|
||||
|
||||
v.Provider = kamereon.NewProvider(api.Battery, cc.Cache)
|
||||
v.Provider = nissan.NewProvider(api, cc.Cache)
|
||||
|
||||
return v, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/andig/evcc/api"
|
||||
"github.com/andig/evcc/util"
|
||||
"github.com/andig/evcc/util/request"
|
||||
"github.com/andig/evcc/vehicle/kamereon"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
|
|
@ -65,12 +63,14 @@ func (v *API) Vehicles() ([]string, error) {
|
|||
return vehicles, err
|
||||
}
|
||||
|
||||
const timeFormat = "2006-01-02T15:04:05Z"
|
||||
|
||||
// Battery provides battery api response
|
||||
func (v *API) Battery() (kamereon.Response, error) {
|
||||
func (v *API) Battery() (Response, error) {
|
||||
// request battery status
|
||||
uri := fmt.Sprintf("%s/v1/cars/%s/battery-status", CarAdapterBaseURL, v.VIN)
|
||||
|
||||
var res kamereon.Response
|
||||
var res Response
|
||||
err := v.GetJSON(uri, &res)
|
||||
|
||||
var ts time.Time
|
||||
|
|
@ -111,12 +111,17 @@ func (v *API) Battery() (kamereon.Response, error) {
|
|||
func (v *API) refreshRequest() error {
|
||||
uri := fmt.Sprintf("%s/v1/cars/%s/actions/refresh-battery-status", CarAdapterBaseURL, v.VIN)
|
||||
|
||||
data := strings.NewReader(`{"data": {"type": "RefreshBatteryStatus"}}`)
|
||||
req, err := request.New(http.MethodPost, uri, data, map[string]string{
|
||||
data := Request{
|
||||
Data: Payload{
|
||||
Type: "RefreshBatteryStatus",
|
||||
},
|
||||
}
|
||||
|
||||
req, err := request.New(http.MethodPost, uri, request.MarshalJSON(data), map[string]string{
|
||||
"Content-Type": "application/vnd.api+json",
|
||||
})
|
||||
|
||||
var res kamereon.Response
|
||||
var res Response
|
||||
if err == nil {
|
||||
err = v.DoJSON(req, &res)
|
||||
}
|
||||
|
|
@ -132,3 +137,35 @@ func (v *API) refreshRequest() error {
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
type Action string
|
||||
|
||||
const (
|
||||
ActionChargeStart Action = "start"
|
||||
ActionChargeStop Action = "stop"
|
||||
)
|
||||
|
||||
// ChargingAction provides actions/charging-start api response
|
||||
func (v *API) ChargingAction(action Action) (Response, error) {
|
||||
uri := fmt.Sprintf("%s/v1/cars/%s/actions/charging-start", CarAdapterBaseURL, v.VIN)
|
||||
|
||||
data := Request{
|
||||
Data: Payload{
|
||||
Type: "ChargingStart",
|
||||
Attributes: map[string]interface{}{
|
||||
"action": action,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
req, err := request.New(http.MethodPost, uri, request.MarshalJSON(data), map[string]string{
|
||||
"Content-Type": "application/vnd.api+json",
|
||||
})
|
||||
|
||||
var res Response
|
||||
if err == nil {
|
||||
err = v.DoJSON(req, &res)
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package kamereon
|
||||
package nissan
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
|
@ -7,42 +7,22 @@ import (
|
|||
"github.com/andig/evcc/provider"
|
||||
)
|
||||
|
||||
// Response structure for kamereon api
|
||||
type Response struct {
|
||||
Data data `json:"data"`
|
||||
}
|
||||
|
||||
type data struct {
|
||||
Type, ID string // battery refresh
|
||||
Attributes attributes `json:"attributes"`
|
||||
}
|
||||
|
||||
type attributes struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
ChargingStatus float32 `json:"chargingStatus"`
|
||||
InstantaneousPower int `json:"instantaneousPower"`
|
||||
RangeHvacOff int `json:"rangeHvacOff"` // Nissan
|
||||
BatteryAutonomy int `json:"batteryAutonomy"` // Renault
|
||||
BatteryLevel int `json:"batteryLevel"`
|
||||
BatteryCapacity int `json:"batteryCapacity"` // Nissan
|
||||
BatteryTemperature int `json:"batteryTemperature"`
|
||||
PlugStatus int `json:"plugStatus"`
|
||||
LastUpdateTime string `json:"lastUpdateTime"`
|
||||
ChargePower int `json:"chargePower"`
|
||||
RemainingTime *int `json:"chargingRemainingTime"`
|
||||
}
|
||||
|
||||
// Provider is a kamereon provider
|
||||
type Provider struct {
|
||||
apiG func() (interface{}, error)
|
||||
apiG func() (interface{}, error)
|
||||
action func(value Action) error
|
||||
}
|
||||
|
||||
// NewProvider returns a kamereon provider
|
||||
func NewProvider(respG func() (Response, error), cache time.Duration) *Provider {
|
||||
func NewProvider(api *API, cache time.Duration) *Provider {
|
||||
return &Provider{
|
||||
apiG: provider.NewCached(func() (interface{}, error) {
|
||||
return respG()
|
||||
return api.Battery()
|
||||
}, cache).InterfaceGetter(),
|
||||
action: func(value Action) error {
|
||||
_, err := api.ChargingAction(value)
|
||||
return err
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,3 +89,17 @@ func (v *Provider) FinishTime() (time.Time, error) {
|
|||
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
var _ api.VehicleStartCharge = (*Provider)(nil)
|
||||
|
||||
// StartCharge implements the api.VehicleStartCharge interface
|
||||
func (v *Provider) StartCharge() error {
|
||||
return v.action(ActionChargeStart)
|
||||
}
|
||||
|
||||
var _ api.VehicleStopCharge = (*Provider)(nil)
|
||||
|
||||
// StopCharge implements the api.VehicleStopCharge interface
|
||||
func (v *Provider) StopCharge() error {
|
||||
return v.action(ActionChargeStop)
|
||||
}
|
||||
|
|
@ -14,8 +14,6 @@ const (
|
|||
UserBaseURL = "https://nci-bff-web-prod.apps.eu.kamereon.io/bff-web"
|
||||
)
|
||||
|
||||
const timeFormat = "2006-01-02T15:04:05Z"
|
||||
|
||||
type Auth struct {
|
||||
AuthID string `json:"authId"`
|
||||
Template string `json:"template"`
|
||||
|
|
@ -50,3 +48,36 @@ type Vehicle struct {
|
|||
ModelName string
|
||||
PictureURL string
|
||||
}
|
||||
|
||||
// Request structure for kamereon api
|
||||
type Request struct {
|
||||
Data Payload `json:"data"`
|
||||
}
|
||||
|
||||
type Payload struct {
|
||||
Type string `json:"type"`
|
||||
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"`
|
||||
}
|
||||
|
||||
type attributes struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
ChargingStatus float32 `json:"chargingStatus"`
|
||||
InstantaneousPower int `json:"instantaneousPower"`
|
||||
RangeHvacOff int `json:"rangeHvacOff"` // Nissan
|
||||
BatteryAutonomy int `json:"batteryAutonomy"` // Renault
|
||||
BatteryLevel int `json:"batteryLevel"`
|
||||
BatteryCapacity int `json:"batteryCapacity"` // Nissan
|
||||
BatteryTemperature int `json:"batteryTemperature"`
|
||||
PlugStatus int `json:"plugStatus"`
|
||||
LastUpdateTime string `json:"lastUpdateTime"`
|
||||
ChargePower int `json:"chargePower"`
|
||||
RemainingTime *int `json:"chargingRemainingTime"`
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue