evcc-io/vehicle/vw/api.go

152 lines
3.9 KiB
Go

package vw
import (
"fmt"
"net/http"
"strings"
"github.com/andig/evcc/util"
"github.com/andig/evcc/util/request"
)
// BaseURI is the VW api base URI
const BaseURI = "https://msg.volkswagen.de/fs-car"
// VehiclesResponse is the /usermanagement/users/v1/%s/%s/vehicles api
type VehiclesResponse struct {
UserVehicles struct {
Vehicle []string
}
}
// TimedInt is an int value with timestamp
type TimedInt struct {
Content int
Timestamp string
}
// TimedString is a string value with timestamp
type TimedString struct {
Content string
Timestamp string
}
// ChargerResponse is the /bs/batterycharge/v1/%s/%s/vehicles/%s/charger api
type ChargerResponse struct {
Charger struct {
Status struct {
BatteryStatusData struct {
StateOfCharge TimedInt
RemainingChargingTime TimedInt
}
ChargingStatusData struct {
ChargingState TimedString // off, charging
ChargingMode TimedString // invalid, AC
ChargingReason TimedString // invalid, immediate
ExternalPowerSupplyState TimedString // unavailable, available
EnergyFlow TimedString // on, off
}
PlugStatusData struct {
PlugState TimedString // connected
}
CruisingRangeStatusData struct {
EngineTypeFirstEngine TimedString // typeIsElectric, petrolGasoline
EngineTypeSecondEngine TimedString // typeIsElectric, petrolGasoline
PrimaryEngineRange TimedInt
SecondaryEngineRange TimedInt
HybridRange TimedInt
}
}
}
}
// ClimaterResponse is the /bs/climatisation/v1/%s/%s/vehicles/%s/climater api
type ClimaterResponse struct {
Climater struct {
Settings struct {
TargetTemperature TimedInt
HeaterSource TimedString
}
Status struct {
ClimatisationStatusData struct {
ClimatisationState TimedString
ClimatisationReason TimedString
RemainingClimatisationTime TimedInt
}
TemperatureStatusData struct {
OutdoorTemperature TimedInt
}
VehicleParkingClockStatusData struct {
VehicleParkingClock TimedString
}
}
}
}
// Temp2Float converts api temp to float value
func Temp2Float(val int) float64 {
return float64(val)/10 - 273
}
// API is the VW api client
type API struct {
*request.Helper
identity *Identity
brand, country string
}
// NewAPI creates a new api client
func NewAPI(log *util.Logger, identity *Identity, brand, country string) *API {
v := &API{
Helper: request.NewHelper(log),
identity: identity,
brand: brand,
country: country,
}
return v
}
func (v *API) getJSON(uri string, res interface{}) error {
req, err := request.New(http.MethodGet, uri, nil, map[string]string{
"Accept": "application/json",
"Authorization": "Bearer " + v.identity.Token(),
})
if err == nil {
err = v.DoJSON(req, &res)
}
return err
}
// Vehicles implements the /vehicles response
func (v *API) Vehicles() ([]string, error) {
var res VehiclesResponse
uri := fmt.Sprintf("%s/usermanagement/users/v1/%s/%s/vehicles", BaseURI, v.brand, v.country)
err := v.getJSON(uri, &res)
return res.UserVehicles.Vehicle, err
}
// Charger implements the /charger response
func (v *API) Charger(vin string) (ChargerResponse, error) {
var res ChargerResponse
uri := fmt.Sprintf("%s/bs/batterycharge/v1/%s/%s/vehicles/%s/charger", BaseURI, v.brand, v.country, vin)
err := v.getJSON(uri, &res)
return res, err
}
// Climater implements the /climater response
func (v *API) Climater(vin string) (ClimaterResponse, error) {
var res ClimaterResponse
uri := fmt.Sprintf("%s/bs/climatisation/v1/%s/%s/vehicles/%s/climater", BaseURI, v.brand, v.country, vin)
err := v.getJSON(uri, &res)
return res, err
}
// Any implements any api response
func (v *API) Any(base, vin string) (interface{}, error) {
var res interface{}
uri := fmt.Sprintf("%s/"+strings.TrimLeft(base, "/"), BaseURI, v.brand, v.country, vin)
err := v.getJSON(uri, &res)
return res, err
}