Audi: add odometer api (#1481)

This commit is contained in:
andig 2021-09-05 14:34:55 +02:00 • committed by GitHub
parent 611b98884f
commit b54382eb6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 165 additions and 0 deletions

View file

@ -9,6 +9,7 @@ import (
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"github.com/evcc-io/evcc/vehicle/audi"
"github.com/evcc-io/evcc/vehicle/vw"
)
@ -19,6 +20,7 @@ import (
type Audi struct {
*embed
*vw.Provider // provides the api implementations
audiProvider *audi.Provider
}
func init() {
@ -78,5 +80,14 @@ func NewAudiFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}
}
audiApi := audi.NewAPI(log, identity, "Audi", "DE")
v.audiProvider = audi.NewProvider(audiApi, cc.VIN, cc.Cache)
return v, err
}
var _ api.VehicleOdometer = (*Audi)(nil)
func (v *Audi) Odometer() (float64, error) {
return v.audiProvider.Odometer()
}

65
vehicle/audi/api.go Normal file
View file

@ -0,0 +1,65 @@
package audi
import (
"fmt"
"net/http"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"golang.org/x/oauth2"
)
// DefaultBaseURI is the Audi api base URI
const DefaultBaseURI = "https://msg.audi.de/fs-car"
const StatusOdometer = "0x0101010002"
// API is the VW api client
type API struct {
*request.Helper
brand, country string
baseURI string
}
// NewAPI creates a new api client
func NewAPI(log *util.Logger, identity oauth2.TokenSource, brand, country string) *API {
v := &API{
Helper: request.NewHelper(log),
brand: brand,
country: country,
baseURI: DefaultBaseURI,
}
v.Client.Transport = &oauth2.Transport{
Source: identity,
Base: v.Client.Transport,
}
return v
}
func (v *API) getJSON(uri string, res interface{}) error {
req, err := request.New(http.MethodGet, uri, nil, map[string]string{
"Accept": request.JSONContent,
"X-App-Name": "myAudi",
"X-Country-Id": "DE",
"X-Language-Id": "de",
"X-App-Version": "3.22.0",
})
if err == nil {
err = v.DoJSON(req, &res)
}
return err
}
// Status returns the /vehicles/<vin>/status response
func (v *API) Status(vin string) (StatusResponse, error) {
var res StatusResponse
uri := fmt.Sprintf("%s/bs/vsr/v1/Audi/DE/vehicles/%s/status", DefaultBaseURI, vin)
err := v.getJSON(uri, &res)
return res, err
}

39
vehicle/audi/provider.go Normal file
View file

@ -0,0 +1,39 @@
package audi
import (
"strconv"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/provider"
)
// Provider implements the evcc vehicle api
type Provider struct {
statusG func() (interface{}, error)
}
// NewProvider provides the evcc vehicle api provider
func NewProvider(api *API, vin string, cache time.Duration) *Provider {
impl := &Provider{
statusG: provider.NewCached(func() (interface{}, error) {
return api.Status(vin)
}, cache).InterfaceGetter(),
}
return impl
}
var _ api.VehicleOdometer = (*Provider)(nil)
// Odometer implements the api.VehicleOdometer interface
func (v *Provider) Odometer() (float64, error) {
res, err := v.statusG()
if res, ok := res.(StatusResponse); err == nil && ok {
fd := res.ServiceByID(StatusOdometer).FieldByID(StatusOdometer)
if fd != nil {
return strconv.ParseFloat(fd.Value, 64)
}
}
return 0, err
}

50
vehicle/audi/types.go Normal file
View file

@ -0,0 +1,50 @@
package audi
type StatusResponse struct {
StoredVehicleDataResponse struct {
VIN string
VehicleData struct {
Data []ServiceDefinition
}
}
}
func (s *StatusResponse) ServiceByID(id string) *ServiceDefinition {
for _, d := range s.StoredVehicleDataResponse.VehicleData.Data {
if d.ID == id {
return &d
}
}
return nil
}
type ServiceDefinition struct {
ID string
Field []FieldDefinition
}
func (s *ServiceDefinition) FieldByID(id string) *FieldDefinition {
if s == nil {
return nil
}
for _, f := range s.Field {
if f.ID == id {
return &f
}
}
return nil
}
type FieldDefinition struct {
ID string // "0x0101010001",
TsCarSentUtc string // "2021-09-05T07:54:20Z",
TsCarSent string // "2021-09-05T07:54:19",
TsCarCaptured string // "2021-09-05T07:54:19",
TsTssReceivedUtc string // "2021-09-05T07:54:23Z",
MilCarCaptured int // 25009,
MilCarSent int // 25009,
Value string // "echo"
}