Skip to content

Commit

Permalink
Add identifier api (evcc-io#947)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored May 9, 2021
1 parent 9e1e681 commit 0934a22
Show file tree
Hide file tree
Showing 24 changed files with 144 additions and 82 deletions.
6 changes: 6 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,15 @@ type ChargeRater interface {
ChargedEnergy() (float64, error)
}

// Identifier identifies a vehicle and is implemented by the charger
type Identifier interface {
Identify() (string, error)
}

// Vehicle represents the EV and it's battery
type Vehicle interface {
Battery
Identifier
Title() string
Capacity() int64
}
Expand Down
14 changes: 12 additions & 2 deletions cmd/dumper.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ func (d *dumper) Dump(name string, v interface{}) {

if v, ok := v.(api.VehicleRange); ok {
if rng, err := v.Range(); err != nil {
fmt.Fprintf(w, "Vehicle range:\t%v\n", err)
fmt.Fprintf(w, "Range:\t%v\n", err)
} else {
fmt.Fprintf(w, "Vehicle range:\t%vkm\n", rng)
fmt.Fprintf(w, "Range:\t%vkm\n", rng)
}
}

Expand All @@ -141,6 +141,16 @@ func (d *dumper) Dump(name string, v interface{}) {
}
}

// Identity

if v, ok := v.(api.Identifier); ok {
if id, err := v.Identify(); err != nil {
fmt.Fprintf(w, "Identifier:\t%v\n", err)
} else {
fmt.Fprintf(w, "Identifier:\t%s\n", id)
}
}

if v, ok := v.(api.Diagnosis); ok {
fmt.Fprintln(w, "Diagnostic dump:")
v.Diagnose()
Expand Down
51 changes: 41 additions & 10 deletions core/loadpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package core

import (
"errors"
"fmt"
"math"
"strings"
"sync"
Expand Down Expand Up @@ -424,7 +423,7 @@ func (lp *LoadPoint) Prepare(uiChan chan<- util.Param, pushChan chan<- push.Even
_ = lp.setLimit(float64(lp.MinCurrent), false)
}
} else {
lp.log.ERROR.Printf("charger error: %v", err)
lp.log.ERROR.Printf("charger: %v", err)
}

// allow charger to access loadpoint
Expand All @@ -441,7 +440,7 @@ func (lp *LoadPoint) syncCharger() {
}

if err != nil {
lp.log.ERROR.Printf("charger error: %v", err)
lp.log.ERROR.Printf("charger: %v", err)
}
}

Expand Down Expand Up @@ -580,10 +579,41 @@ func (lp *LoadPoint) setActiveVehicle(vehicle api.Vehicle) {

// findActiveVehicle validates if the active vehicle is still connected to the loadpoint
func (lp *LoadPoint) findActiveVehicle() {
// find vehicles by id
if identifier, ok := lp.charger.(api.Identifier); ok {
id, err := identifier.Identify()

if err == nil {
lp.log.DEBUG.Println("charger vehicle id:", id)

// find exact match
for _, vehicle := range lp.vehicles {
if vid, err := vehicle.Identify(); err == nil && vid == id {
lp.setActiveVehicle(vehicle)
return
}
}

// find placeholder match
for _, vehicle := range lp.vehicles {
if vid, err := vehicle.Identify(); err == nil && vid == "*" {
lp.setActiveVehicle(vehicle)
return
}
}
} else {
lp.log.ERROR.Println("charger vehicle id:", err)
}

// TODO implement removing vehicle
// lp.setActiveVehicle(nil)
}

if len(lp.vehicles) <= 1 {
return
}

// find vehicles by charge state
if vs, ok := lp.vehicle.(api.ChargeState); ok {
status, err := vs.Status()

Expand Down Expand Up @@ -614,6 +644,8 @@ func (lp *LoadPoint) findActiveVehicle() {
}
}
}
} else {
lp.log.ERROR.Println("vehicle charge state:", err)
}
}
}
Expand Down Expand Up @@ -768,8 +800,7 @@ func (lp *LoadPoint) updateChargePower() {
}, retryOptions...)

if err != nil {
err = fmt.Errorf("updating charge meter: %v", err)
lp.log.ERROR.Printf("%v", err)
lp.log.ERROR.Printf("charge meter: %v", err)
}
}

Expand All @@ -783,7 +814,7 @@ func (lp *LoadPoint) updateChargeCurrents() {

i1, i2, i3, err := phaseMeter.Currents()
if err != nil {
lp.log.ERROR.Printf("charge meter error: %v", err)
lp.log.ERROR.Printf("charge meter: %v", err)
return
}

Expand Down Expand Up @@ -813,13 +844,13 @@ func (lp *LoadPoint) publishChargeProgress() {
if f, err := lp.chargeRater.ChargedEnergy(); err == nil {
lp.chargedEnergy = 1e3 * f // convert to Wh
} else {
lp.log.ERROR.Printf("charge rater error: %v", err)
lp.log.ERROR.Printf("charge rater: %v", err)
}

if d, err := lp.chargeTimer.ChargingTime(); err == nil {
lp.chargeDuration = d.Round(time.Second)
} else {
lp.log.ERROR.Printf("charge timer error: %v", err)
lp.log.ERROR.Printf("charge timer: %v", err)
}

lp.publish("chargedEnergy", lp.chargedEnergy)
Expand Down Expand Up @@ -870,7 +901,7 @@ func (lp *LoadPoint) publishSoCAndRange() {
// we need a value- so retry on error
lp.socUpdated = lp.clock.Now()

lp.log.ERROR.Printf("vehicle error: %v", err)
lp.log.ERROR.Printf("vehicle: %v", err)
}

// range
Expand Down Expand Up @@ -912,7 +943,7 @@ func (lp *LoadPoint) Update(sitePower float64) {

// read and publish status
if err := lp.updateChargerStatus(); err != nil {
lp.log.ERROR.Printf("charger error: %v", err)
lp.log.ERROR.Printf("charger: %v", err)
return
}

Expand Down
13 changes: 12 additions & 1 deletion internal/charger/keba.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,18 @@ func (c *Keba) Currents() (float64, float64, float64, error) {
return float64(kr.I1) / 1e3, float64(kr.I2) / 1e3, float64(kr.I3) / 1e3, err
}

// Diagnose implements the Diagnosis interface
var _ api.Identifier = (*Keba)(nil)

// Identify implements the api.Identifier interface
func (c *Keba) Identify() (string, error) {
var kr keba.Report100
err := c.roundtrip("report", 100, &kr)
return kr.RFIDTag, err
}

var _ api.Diagnosis = (*Keba)(nil)

// Diagnose implements the api.Diagnosis interface
func (c *Keba) Diagnose() {
var kr keba.Report100
if err := c.roundtrip("report", 100, &kr); err == nil {
Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/audi.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ func init() {
// NewAudiFromConfig creates a new vehicle
func NewAudiFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password, VIN string
Cache time.Duration
}{
Expand All @@ -40,7 +39,7 @@ func NewAudiFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}

v := &Audi{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
}

log := util.NewLogger("audi")
Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/bmw.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ func init() {
// NewBMWFromConfig creates a new vehicle
func NewBMWFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password, VIN string
Cache time.Duration
}{
Expand All @@ -62,7 +61,7 @@ func NewBMWFromConfig(other map[string]interface{}) (api.Vehicle, error) {
log := util.NewLogger("bmw")

v := &BMW{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
Helper: request.NewHelper(log),
user: cc.User,
password: cc.Password,
Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/carwings.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ func init() {
// NewCarWingsFromConfig creates a new vehicle
func NewCarWingsFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password, Region string
Cache time.Duration
}{
Expand All @@ -41,7 +40,7 @@ func NewCarWingsFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}

v := &CarWings{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
user: cc.User,
password: cc.Password,
region: cc.Region,
Expand Down
13 changes: 6 additions & 7 deletions internal/vehicle/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ func init() {
// NewCloudFromConfig creates a new vehicle
func NewCloudFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Token string
Title string
Capacity int64
Brand string
Other map[string]string `mapstructure:",remain"`
Cache time.Duration
Token string
embed `mapstructure:",squash"`
Brand string
Other map[string]string `mapstructure:",remain"`
Cache time.Duration
}{
Cache: interval,
}
Expand All @@ -56,7 +55,7 @@ func NewCloudFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}

v := &Cloud{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
token: cc.Token,
brand: cc.Brand,
config: cc.Other,
Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/ford.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ func init() {
// NewFordFromConfig creates a new vehicle
func NewFordFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password, VIN string
Cache time.Duration
}{
Expand All @@ -61,7 +60,7 @@ func NewFordFromConfig(other map[string]interface{}) (api.Vehicle, error) {
log := util.NewLogger("ford")

v := &Ford{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
Helper: request.NewHelper(log),
log: log,
user: cc.User,
Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/hyundai.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ func init() {
// NewHyundaiFromConfig creates a new Vehicle
func NewHyundaiFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password string
VIN string
Cache time.Duration
Expand Down Expand Up @@ -80,7 +79,7 @@ func NewHyundaiFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}

v := &Hyundai{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
API: api,
}

Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ func init() {
// NewIDFromConfig creates a new vehicle
func NewIDFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password, VIN string
Cache time.Duration
}{
Expand All @@ -40,7 +39,7 @@ func NewIDFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}

v := &ID{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
}

log := util.NewLogger("id")
Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/kia.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ func init() {
// NewKiaFromConfig creates a new Vehicle
func NewKiaFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password string
VIN string
Cache time.Duration
Expand Down Expand Up @@ -80,7 +79,7 @@ func NewKiaFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}

v := &Kia{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
API: api,
}

Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/nissan.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ func init() {
// NewNissanFromConfig creates a new vehicle
func NewNissanFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password, Region, VIN string
Cache time.Duration
}{
Expand All @@ -72,7 +71,7 @@ func NewNissanFromConfig(other map[string]interface{}) (api.Vehicle, error) {
log := util.NewLogger("nissan")

v := &Nissan{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
Helper: request.NewHelper(log),
log: log,
user: cc.User,
Expand Down
5 changes: 2 additions & 3 deletions internal/vehicle/niu.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ func init() {
// NewFordFromConfig creates a new vehicle
func NewNiuFromConfig(other map[string]interface{}) (api.Vehicle, error) {
cc := struct {
Title string
Capacity int64
embed `mapstructure:",squash"`
User, Password, Serial string
Cache time.Duration
}{
Expand All @@ -52,7 +51,7 @@ func NewNiuFromConfig(other map[string]interface{}) (api.Vehicle, error) {
log := util.NewLogger("niu")

v := &Niu{
embed: &embed{cc.Title, cc.Capacity},
embed: &cc.embed,
Helper: request.NewHelper(log),
user: cc.User,
password: cc.Password,
Expand Down
Loading

0 comments on commit 0934a22

Please sign in to comment.