diff --git a/util/request/helper.go b/util/request/helper.go index a3c67c36d..4506de4cb 100644 --- a/util/request/helper.go +++ b/util/request/helper.go @@ -58,7 +58,8 @@ func decodeJSON(resp *http.Response, res interface{}) error { return json.NewDecoder(resp.Body).Decode(&res) } -// DoJSON executes HTTP request and decodes JSON response. It returns a StatusError on response codes other than HTTP 2xx. +// DoJSON executes HTTP request and decodes JSON response. +// It returns a StatusError on response codes other than HTTP 2xx. func (r *Helper) DoJSON(req *http.Request, res interface{}) error { resp, err := r.Do(req) if err == nil { @@ -68,12 +69,12 @@ func (r *Helper) DoJSON(req *http.Request, res interface{}) error { return err } -// GetJSON executes HTTP GET request and decodes JSON response. It returns a StatusError on response codes other than HTTP 2xx. +// GetJSON executes HTTP GET request and decodes JSON response. +// It returns a StatusError on response codes other than HTTP 2xx. func (r *Helper) GetJSON(url string, res interface{}) error { - resp, err := r.Get(url) + req, err := New(http.MethodGet, url, nil, AcceptJSON) if err == nil { - defer resp.Body.Close() - err = decodeJSON(resp, &res) + err = r.DoJSON(req, &res) } return err } diff --git a/vehicle/skoda/api.go b/vehicle/skoda/api.go index 839987b6c..e1a0af2ea 100644 --- a/vehicle/skoda/api.go +++ b/vehicle/skoda/api.go @@ -30,36 +30,12 @@ func NewAPI(log *util.Logger, ts oauth2.TokenSource) *API { return v } -func (v *API) getJSON(uri string, res interface{}) error { - req, err := request.New(http.MethodGet, uri, nil, request.AcceptJSON) - - if err == nil { - err = v.DoJSON(req, &res) - } - - return err -} - -// Vehicle is the /v2/garage/vehicles api -type Vehicle struct { - ID, VIN string - LastUpdatedAt string - Specification struct { - Title, Brand, Model string - Battery struct { - CapacityInKWh int - } - } - // Connectivities - // Capabilities -} - // Vehicles implements the /vehicles response func (v *API) Vehicles() ([]string, error) { - var res []Vehicle + var res VehiclesResponse uri := fmt.Sprintf("%s/v2/garage/vehicles", BaseURI) - err := v.getJSON(uri, &res) + err := v.GetJSON(uri, &res) var vehicles []string if err == nil { @@ -71,30 +47,36 @@ func (v *API) Vehicles() ([]string, error) { return vehicles, err } -// ChargerResponse is the /v1/charging//status api -type ChargerResponse struct { - Plug struct { - ConnectionState string // Connected - LockState string // Unlocked - } - Charging struct { - State string // Error - RemainingToCompleteInSeconds int64 - ChargingPowerInWatts float64 - ChargingRateInKilometersPerHour float64 - ChargingType string // Invalid - ChargeMode string // MANUAL - } - Battery struct { - CruisingRangeElectricInMeters int64 - StateOfChargeInPercent int - } -} - // Charger implements the /v1/charging//status response func (v *API) Charger(vin string) (ChargerResponse, error) { var res ChargerResponse uri := fmt.Sprintf("%s/v1/charging/%s/status", BaseURI, vin) - err := v.getJSON(uri, &res) + err := v.GetJSON(uri, &res) return res, err } + +const ( + ActionCharge = "charging" + ActionChargeStart = "Start" + ActionChargeStop = "Stop" +) + +// Action executes a vehicle action +func (v *API) Action(vin, action, value string) error { + var res map[string]interface{} + uri := fmt.Sprintf("%s/v1/%s/operation-requests?vin=%s", BaseURI, action, vin) + + data := struct { + Typ string `json:"type"` + }{ + Typ: value, + } + + req, err := request.New(http.MethodPost, uri, request.MarshalJSON(data), request.JSONEncoding) + if err == nil { + // {"id":"61991908906fa40af9a5cba4","status":"InProgress","deeplink":""} + err = v.DoJSON(req, &res) + } + + return err +} diff --git a/vehicle/skoda/provider.go b/vehicle/skoda/provider.go index f10f8560f..421c653dc 100644 --- a/vehicle/skoda/provider.go +++ b/vehicle/skoda/provider.go @@ -10,8 +10,7 @@ import ( // Provider implements the evcc vehicle api type Provider struct { chargerG func() (interface{}, error) - // climateG func() (interface{}, error) - // action func(action, value string) error + action func(action, value string) error } // NewProvider provides the evcc vehicle api provider @@ -23,9 +22,9 @@ func NewProvider(api *API, vin string, cache time.Duration) *Provider { // climateG: provider.NewCached(func() (interface{}, error) { // return api.Climater(vin) // }, cache).InterfaceGetter(), - // action: func(action, value string) error { - // return api.Action(vin, action, value) - // }, + action: func(action, value string) error { + return api.Action(vin, action, value) + }, } return impl } @@ -114,16 +113,16 @@ func (v *Provider) Range() (rng int64, err error) { // return active, outsideTemp, targetTemp, err // } -// var _ api.VehicleStartCharge = (*Provider)(nil) +var _ api.VehicleStartCharge = (*Provider)(nil) -// // StartCharge implements the api.VehicleStartCharge interface -// func (v *Provider) StartCharge() error { -// return v.action(ActionCharge, ActionChargeStart) -// } +// StartCharge implements the api.VehicleStartCharge interface +func (v *Provider) StartCharge() error { + return v.action(ActionCharge, ActionChargeStart) +} -// var _ api.VehicleStopCharge = (*Provider)(nil) +var _ api.VehicleStopCharge = (*Provider)(nil) -// // StopCharge implements the api.VehicleStopCharge interface -// func (v *Provider) StopCharge() error { -// return v.action(ActionCharge, ActionChargeStop) -// } +// StopCharge implements the api.VehicleStopCharge interface +func (v *Provider) StopCharge() error { + return v.action(ActionCharge, ActionChargeStop) +} diff --git a/vehicle/skoda/types.go b/vehicle/skoda/types.go new file mode 100644 index 000000000..3d8d19d9b --- /dev/null +++ b/vehicle/skoda/types.go @@ -0,0 +1,37 @@ +package skoda + +// VehiclesResponse is the /v2/garage/vehicles api +type VehiclesResponse []Vehicle + +type Vehicle struct { + ID, VIN string + LastUpdatedAt string + Specification struct { + Title, Brand, Model string + Battery struct { + CapacityInKWh int + } + } + // Connectivities + // Capabilities +} + +// ChargerResponse is the /v1/charging//status api +type ChargerResponse struct { + Plug struct { + ConnectionState string // Connected + LockState string // Unlocked + } + Charging struct { + State string // Error + RemainingToCompleteInSeconds int64 + ChargingPowerInWatts float64 + ChargingRateInKilometersPerHour float64 + ChargingType string // Invalid + ChargeMode string // MANUAL + } + Battery struct { + CruisingRangeElectricInMeters int64 + StateOfChargeInPercent int + } +}