diff --git a/vehicle/nissan.go b/vehicle/nissan.go index fe1cbd9d7..2f8ea85e8 100644 --- a/vehicle/nissan.go +++ b/vehicle/nissan.go @@ -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 } diff --git a/vehicle/nissan/api.go b/vehicle/nissan/api.go index f4b13b1c6..a72525a61 100644 --- a/vehicle/nissan/api.go +++ b/vehicle/nissan/api.go @@ -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 +} diff --git a/vehicle/kamereon/api.go b/vehicle/nissan/provider.go similarity index 64% rename from vehicle/kamereon/api.go rename to vehicle/nissan/provider.go index 978e53987..29e462c3f 100644 --- a/vehicle/kamereon/api.go +++ b/vehicle/nissan/provider.go @@ -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) +} diff --git a/vehicle/nissan/types.go b/vehicle/nissan/types.go index e95b83b4a..51c4fdc87 100644 --- a/vehicle/nissan/types.go +++ b/vehicle/nissan/types.go @@ -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"` +}