Keba: auto-detect optional meter (#1541)
This commit is contained in:
parent
9c32874c88
commit
ac98b8a543
3 changed files with 308 additions and 45 deletions
|
|
@ -37,6 +37,8 @@ func init() {
|
|||
registry.Add("keba", NewKebaFromConfig)
|
||||
}
|
||||
|
||||
//go:generate go run ../cmd/tools/decorate.go -f decorateKeba -b *Keba -r api.Charger -t "api.Meter,CurrentPower,func() (float64, error)" -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.ChargeRater,ChargedEnergy,func() (float64, error)" -t "api.MeterCurrent,Currents,func() (float64, float64, float64, error)"
|
||||
|
||||
// NewKebaFromConfig creates a new configurable charger
|
||||
func NewKebaFromConfig(other map[string]interface{}) (api.Charger, error) {
|
||||
cc := struct {
|
||||
|
|
@ -47,15 +49,30 @@ func NewKebaFromConfig(other map[string]interface{}) (api.Charger, error) {
|
|||
}{
|
||||
Timeout: udpTimeout,
|
||||
}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewKeba(cc.URI, cc.Serial, cc.RFID, cc.Timeout)
|
||||
k, err := NewKeba(cc.URI, cc.Serial, cc.RFID, cc.Timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
energy, err := k.totalEnergy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if energy > 0 {
|
||||
return decorateKeba(k, k.currentPower, k.totalEnergy, k.chargedEnergy, k.currents), nil
|
||||
}
|
||||
|
||||
return k, err
|
||||
}
|
||||
|
||||
// NewKeba creates a new charger
|
||||
func NewKeba(uri, serial string, rfid RFID, timeout time.Duration) (api.Charger, error) {
|
||||
func NewKeba(uri, serial string, rfid RFID, timeout time.Duration) (*Keba, error) {
|
||||
log := util.NewLogger("keba")
|
||||
|
||||
if keba.Instance == nil {
|
||||
|
|
@ -264,10 +281,8 @@ func (c *Keba) MaxCurrentMillis(current float64) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
var _ api.Meter = (*Keba)(nil)
|
||||
|
||||
// CurrentPower implements the api.Meter interface
|
||||
func (c *Keba) CurrentPower() (float64, error) {
|
||||
// currentPower implements the api.Meter interface
|
||||
func (c *Keba) currentPower() (float64, error) {
|
||||
var kr keba.Report3
|
||||
err := c.roundtrip("report", 3, &kr)
|
||||
|
||||
|
|
@ -275,10 +290,8 @@ func (c *Keba) CurrentPower() (float64, error) {
|
|||
return float64(kr.P) / 1e3, err
|
||||
}
|
||||
|
||||
var _ api.MeterEnergy = (*Keba)(nil)
|
||||
|
||||
// TotalEnergy implements the api.MeterEnergy interface
|
||||
func (c *Keba) TotalEnergy() (float64, error) {
|
||||
// totalEnergy implements the api.MeterEnergy interface
|
||||
func (c *Keba) totalEnergy() (float64, error) {
|
||||
var kr keba.Report3
|
||||
err := c.roundtrip("report", 3, &kr)
|
||||
|
||||
|
|
@ -286,10 +299,8 @@ func (c *Keba) TotalEnergy() (float64, error) {
|
|||
return float64(kr.ETotal) / 1e4, err
|
||||
}
|
||||
|
||||
var _ api.ChargeRater = (*Keba)(nil)
|
||||
|
||||
// ChargedEnergy implements the ChargeRater interface
|
||||
func (c *Keba) ChargedEnergy() (float64, error) {
|
||||
// chargedEnergy implements the ChargeRater interface
|
||||
func (c *Keba) chargedEnergy() (float64, error) {
|
||||
var kr keba.Report3
|
||||
err := c.roundtrip("report", 3, &kr)
|
||||
|
||||
|
|
@ -297,10 +308,8 @@ func (c *Keba) ChargedEnergy() (float64, error) {
|
|||
return float64(kr.EPres) / 1e4, err
|
||||
}
|
||||
|
||||
var _ api.MeterCurrent = (*Keba)(nil)
|
||||
|
||||
// Currents implements the api.MeterCurrent interface
|
||||
func (c *Keba) Currents() (float64, float64, float64, error) {
|
||||
// currents implements the api.MeterCurrent interface
|
||||
func (c *Keba) currents() (float64, float64, float64, error) {
|
||||
var kr keba.Report3
|
||||
err := c.roundtrip("report", 3, &kr)
|
||||
|
||||
|
|
|
|||
281
charger/keba_decorators.go
Normal file
281
charger/keba_decorators.go
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
package charger
|
||||
|
||||
// Code generated by github.com/andig/cmd/tools/decorate.go. DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"github.com/evcc-io/evcc/api"
|
||||
)
|
||||
|
||||
func decorateKeba(base *Keba, meter func() (float64, error), meterEnergy func() (float64, error), chargeRater func() (float64, error), meterCurrent func() (float64, float64, float64, error)) api.Charger {
|
||||
switch {
|
||||
case chargeRater == nil && meter == nil && meterCurrent == nil && meterEnergy == nil:
|
||||
return base
|
||||
|
||||
case chargeRater == nil && meter != nil && meterCurrent == nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.Meter
|
||||
}{
|
||||
Keba: base,
|
||||
Meter: &decorateKebaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater == nil && meter == nil && meterCurrent == nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Keba: base,
|
||||
MeterEnergy: &decorateKebaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater == nil && meter != nil && meterCurrent == nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Keba: base,
|
||||
Meter: &decorateKebaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterEnergy: &decorateKebaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater != nil && meter == nil && meterCurrent == nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.ChargeRater
|
||||
}{
|
||||
Keba: base,
|
||||
ChargeRater: &decorateKebaChargeRaterImpl{
|
||||
chargeRater: chargeRater,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater != nil && meter != nil && meterCurrent == nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.ChargeRater
|
||||
api.Meter
|
||||
}{
|
||||
Keba: base,
|
||||
ChargeRater: &decorateKebaChargeRaterImpl{
|
||||
chargeRater: chargeRater,
|
||||
},
|
||||
Meter: &decorateKebaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater != nil && meter == nil && meterCurrent == nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.ChargeRater
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Keba: base,
|
||||
ChargeRater: &decorateKebaChargeRaterImpl{
|
||||
chargeRater: chargeRater,
|
||||
},
|
||||
MeterEnergy: &decorateKebaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater != nil && meter != nil && meterCurrent == nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.ChargeRater
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Keba: base,
|
||||
ChargeRater: &decorateKebaChargeRaterImpl{
|
||||
chargeRater: chargeRater,
|
||||
},
|
||||
Meter: &decorateKebaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterEnergy: &decorateKebaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater == nil && meter == nil && meterCurrent != nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.MeterCurrent
|
||||
}{
|
||||
Keba: base,
|
||||
MeterCurrent: &decorateKebaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater == nil && meter != nil && meterCurrent != nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.Meter
|
||||
api.MeterCurrent
|
||||
}{
|
||||
Keba: base,
|
||||
Meter: &decorateKebaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterCurrent: &decorateKebaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater == nil && meter == nil && meterCurrent != nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.MeterCurrent
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Keba: base,
|
||||
MeterCurrent: &decorateKebaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
MeterEnergy: &decorateKebaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater == nil && meter != nil && meterCurrent != nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.Meter
|
||||
api.MeterCurrent
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Keba: base,
|
||||
Meter: &decorateKebaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterCurrent: &decorateKebaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
MeterEnergy: &decorateKebaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater != nil && meter == nil && meterCurrent != nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.ChargeRater
|
||||
api.MeterCurrent
|
||||
}{
|
||||
Keba: base,
|
||||
ChargeRater: &decorateKebaChargeRaterImpl{
|
||||
chargeRater: chargeRater,
|
||||
},
|
||||
MeterCurrent: &decorateKebaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater != nil && meter != nil && meterCurrent != nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.ChargeRater
|
||||
api.Meter
|
||||
api.MeterCurrent
|
||||
}{
|
||||
Keba: base,
|
||||
ChargeRater: &decorateKebaChargeRaterImpl{
|
||||
chargeRater: chargeRater,
|
||||
},
|
||||
Meter: &decorateKebaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterCurrent: &decorateKebaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater != nil && meter == nil && meterCurrent != nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.ChargeRater
|
||||
api.MeterCurrent
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Keba: base,
|
||||
ChargeRater: &decorateKebaChargeRaterImpl{
|
||||
chargeRater: chargeRater,
|
||||
},
|
||||
MeterCurrent: &decorateKebaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
MeterEnergy: &decorateKebaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case chargeRater != nil && meter != nil && meterCurrent != nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Keba
|
||||
api.ChargeRater
|
||||
api.Meter
|
||||
api.MeterCurrent
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Keba: base,
|
||||
ChargeRater: &decorateKebaChargeRaterImpl{
|
||||
chargeRater: chargeRater,
|
||||
},
|
||||
Meter: &decorateKebaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterCurrent: &decorateKebaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
MeterEnergy: &decorateKebaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type decorateKebaChargeRaterImpl struct {
|
||||
chargeRater func() (float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateKebaChargeRaterImpl) ChargedEnergy() (float64, error) {
|
||||
return impl.chargeRater()
|
||||
}
|
||||
|
||||
type decorateKebaMeterImpl struct {
|
||||
meter func() (float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateKebaMeterImpl) CurrentPower() (float64, error) {
|
||||
return impl.meter()
|
||||
}
|
||||
|
||||
type decorateKebaMeterCurrentImpl struct {
|
||||
meterCurrent func() (float64, float64, float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateKebaMeterCurrentImpl) Currents() (float64, float64, float64, error) {
|
||||
return impl.meterCurrent()
|
||||
}
|
||||
|
||||
type decorateKebaMeterEnergyImpl struct {
|
||||
meterEnergy func() (float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateKebaMeterEnergyImpl) TotalEnergy() (float64, error) {
|
||||
return impl.meterEnergy()
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
package charger
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
)
|
||||
|
||||
func TestKeba(t *testing.T) {
|
||||
var wb api.Charger
|
||||
wb, err := NewKeba("localhost", "bar", RFID{}, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if _, ok := wb.(api.MeterEnergy); !ok {
|
||||
t.Error("missing MeterEnergy interface")
|
||||
}
|
||||
|
||||
if _, ok := wb.(api.MeterCurrent); !ok {
|
||||
t.Error("missing MeterCurrent interface")
|
||||
}
|
||||
|
||||
if _, ok := wb.(api.ChargeRater); !ok {
|
||||
t.Error("missing ChargeRater interface")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue