Bender: Detect meter availability (#3146)

This commit is contained in:
premultiply 2022-04-12 13:14:28 +02:00 • committed by GitHub
parent 50652f0833
commit e3a598add8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 294 additions and 12 deletions

View file

@ -26,6 +26,7 @@ package charger
import (
"encoding/binary"
"fmt"
"math"
"time"
"github.com/evcc-io/evcc/api"
@ -76,6 +77,8 @@ func NewBenderCCFromConfig(other map[string]interface{}) (api.Charger, error) {
return NewBenderCC(cc.URI, cc.ID)
}
//go:generate go run ../cmd/tools/decorate.go -f decorateBenderCC -b *BenderCC -r api.Charger -t "api.Meter,CurrentPower,func() (float64, error)" -t "api.MeterCurrent,Currents,func() (float64, float64, float64, error)" -t "api.ChargeRater,ChargedEnergy,func() (float64, error)" -t "api.MeterEnergy,TotalEnergy,func() (float64, error)"
// NewBenderCC creates BenderCC charger
func NewBenderCC(uri string, id uint8) (api.Charger, error) {
conn, err := modbus.NewConnection(uri, "", "", 0, modbus.Tcp, id)
@ -95,6 +98,12 @@ func NewBenderCC(uri string, id uint8) (api.Charger, error) {
current: 6, // assume min current
}
// check presence of metering
b, err := wb.conn.ReadHoldingRegisters(bendRegActivePower, 2)
if err == nil && (binary.BigEndian.Uint32(b) != math.MaxUint32) {
return decorateBenderCC(wb, wb.currentPower, wb.currents, wb.chargedEnergy, wb.totalEnergy), nil
}
return wb, err
}
@ -176,10 +185,8 @@ func (wb *BenderCC) ChargingTime() (time.Duration, error) {
return time.Duration(binary.BigEndian.Uint32(b)) * time.Second, nil
}
var _ api.Meter = (*BenderCC)(nil)
// CurrentPower implements the api.Meter interface
func (wb *BenderCC) CurrentPower() (float64, error) {
func (wb *BenderCC) currentPower() (float64, error) {
b, err := wb.conn.ReadHoldingRegisters(bendRegActivePower, 2)
if err != nil {
return 0, err
@ -188,10 +195,8 @@ func (wb *BenderCC) CurrentPower() (float64, error) {
return float64(binary.BigEndian.Uint32(b)), nil
}
var _ api.ChargeRater = (*BenderCC)(nil)
// ChargedEnergy implements the api.ChargeRater interface
func (wb *BenderCC) ChargedEnergy() (float64, error) {
func (wb *BenderCC) chargedEnergy() (float64, error) {
b, err := wb.conn.ReadHoldingRegisters(bendRegChargedEnergy, 2)
if err != nil {
return 0, err
@ -200,10 +205,8 @@ func (wb *BenderCC) ChargedEnergy() (float64, error) {
return float64(binary.BigEndian.Uint32(b)) / 1e3, nil
}
var _ api.MeterEnergy = (*BenderCC)(nil)
// TotalEnergy implements the api.MeterEnergy interface
func (wb *BenderCC) TotalEnergy() (float64, error) {
func (wb *BenderCC) totalEnergy() (float64, error) {
b, err := wb.conn.ReadHoldingRegisters(bendRegTotalEnergy, 2)
if err != nil {
return 0, err
@ -212,10 +215,8 @@ func (wb *BenderCC) TotalEnergy() (float64, error) {
return float64(binary.BigEndian.Uint32(b)) / 1e3, nil
}
var _ api.MeterCurrent = (*BenderCC)(nil)
// Currents implements the api.MeterCurrent interface
func (wb *BenderCC) Currents() (float64, float64, float64, error) {
func (wb *BenderCC) currents() (float64, float64, float64, error) {
b, err := wb.conn.ReadHoldingRegisters(bendRegCurrents, 6)
if err != nil {
return 0, 0, 0, err

View file

@ -0,0 +1,281 @@
package charger
// Code generated by github.com/evcc-io/evcc/cmd/tools/decorate.go. DO NOT EDIT.
import (
"github.com/evcc-io/evcc/api"
)
func decorateBenderCC(base *BenderCC, meter func() (float64, error), meterCurrent func() (float64, float64, float64, error), chargeRater func() (float64, error), meterEnergy func() (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 {
*BenderCC
api.Meter
}{
BenderCC: base,
Meter: &decorateBenderCCMeterImpl{
meter: meter,
},
}
case chargeRater == nil && meter == nil && meterCurrent != nil && meterEnergy == nil:
return &struct {
*BenderCC
api.MeterCurrent
}{
BenderCC: base,
MeterCurrent: &decorateBenderCCMeterCurrentImpl{
meterCurrent: meterCurrent,
},
}
case chargeRater == nil && meter != nil && meterCurrent != nil && meterEnergy == nil:
return &struct {
*BenderCC
api.Meter
api.MeterCurrent
}{
BenderCC: base,
Meter: &decorateBenderCCMeterImpl{
meter: meter,
},
MeterCurrent: &decorateBenderCCMeterCurrentImpl{
meterCurrent: meterCurrent,
},
}
case chargeRater != nil && meter == nil && meterCurrent == nil && meterEnergy == nil:
return &struct {
*BenderCC
api.ChargeRater
}{
BenderCC: base,
ChargeRater: &decorateBenderCCChargeRaterImpl{
chargeRater: chargeRater,
},
}
case chargeRater != nil && meter != nil && meterCurrent == nil && meterEnergy == nil:
return &struct {
*BenderCC
api.ChargeRater
api.Meter
}{
BenderCC: base,
ChargeRater: &decorateBenderCCChargeRaterImpl{
chargeRater: chargeRater,
},
Meter: &decorateBenderCCMeterImpl{
meter: meter,
},
}
case chargeRater != nil && meter == nil && meterCurrent != nil && meterEnergy == nil:
return &struct {
*BenderCC
api.ChargeRater
api.MeterCurrent
}{
BenderCC: base,
ChargeRater: &decorateBenderCCChargeRaterImpl{
chargeRater: chargeRater,
},
MeterCurrent: &decorateBenderCCMeterCurrentImpl{
meterCurrent: meterCurrent,
},
}
case chargeRater != nil && meter != nil && meterCurrent != nil && meterEnergy == nil:
return &struct {
*BenderCC
api.ChargeRater
api.Meter
api.MeterCurrent
}{
BenderCC: base,
ChargeRater: &decorateBenderCCChargeRaterImpl{
chargeRater: chargeRater,
},
Meter: &decorateBenderCCMeterImpl{
meter: meter,
},
MeterCurrent: &decorateBenderCCMeterCurrentImpl{
meterCurrent: meterCurrent,
},
}
case chargeRater == nil && meter == nil && meterCurrent == nil && meterEnergy != nil:
return &struct {
*BenderCC
api.MeterEnergy
}{
BenderCC: base,
MeterEnergy: &decorateBenderCCMeterEnergyImpl{
meterEnergy: meterEnergy,
},
}
case chargeRater == nil && meter != nil && meterCurrent == nil && meterEnergy != nil:
return &struct {
*BenderCC
api.Meter
api.MeterEnergy
}{
BenderCC: base,
Meter: &decorateBenderCCMeterImpl{
meter: meter,
},
MeterEnergy: &decorateBenderCCMeterEnergyImpl{
meterEnergy: meterEnergy,
},
}
case chargeRater == nil && meter == nil && meterCurrent != nil && meterEnergy != nil:
return &struct {
*BenderCC
api.MeterCurrent
api.MeterEnergy
}{
BenderCC: base,
MeterCurrent: &decorateBenderCCMeterCurrentImpl{
meterCurrent: meterCurrent,
},
MeterEnergy: &decorateBenderCCMeterEnergyImpl{
meterEnergy: meterEnergy,
},
}
case chargeRater == nil && meter != nil && meterCurrent != nil && meterEnergy != nil:
return &struct {
*BenderCC
api.Meter
api.MeterCurrent
api.MeterEnergy
}{
BenderCC: base,
Meter: &decorateBenderCCMeterImpl{
meter: meter,
},
MeterCurrent: &decorateBenderCCMeterCurrentImpl{
meterCurrent: meterCurrent,
},
MeterEnergy: &decorateBenderCCMeterEnergyImpl{
meterEnergy: meterEnergy,
},
}
case chargeRater != nil && meter == nil && meterCurrent == nil && meterEnergy != nil:
return &struct {
*BenderCC
api.ChargeRater
api.MeterEnergy
}{
BenderCC: base,
ChargeRater: &decorateBenderCCChargeRaterImpl{
chargeRater: chargeRater,
},
MeterEnergy: &decorateBenderCCMeterEnergyImpl{
meterEnergy: meterEnergy,
},
}
case chargeRater != nil && meter != nil && meterCurrent == nil && meterEnergy != nil:
return &struct {
*BenderCC
api.ChargeRater
api.Meter
api.MeterEnergy
}{
BenderCC: base,
ChargeRater: &decorateBenderCCChargeRaterImpl{
chargeRater: chargeRater,
},
Meter: &decorateBenderCCMeterImpl{
meter: meter,
},
MeterEnergy: &decorateBenderCCMeterEnergyImpl{
meterEnergy: meterEnergy,
},
}
case chargeRater != nil && meter == nil && meterCurrent != nil && meterEnergy != nil:
return &struct {
*BenderCC
api.ChargeRater
api.MeterCurrent
api.MeterEnergy
}{
BenderCC: base,
ChargeRater: &decorateBenderCCChargeRaterImpl{
chargeRater: chargeRater,
},
MeterCurrent: &decorateBenderCCMeterCurrentImpl{
meterCurrent: meterCurrent,
},
MeterEnergy: &decorateBenderCCMeterEnergyImpl{
meterEnergy: meterEnergy,
},
}
case chargeRater != nil && meter != nil && meterCurrent != nil && meterEnergy != nil:
return &struct {
*BenderCC
api.ChargeRater
api.Meter
api.MeterCurrent
api.MeterEnergy
}{
BenderCC: base,
ChargeRater: &decorateBenderCCChargeRaterImpl{
chargeRater: chargeRater,
},
Meter: &decorateBenderCCMeterImpl{
meter: meter,
},
MeterCurrent: &decorateBenderCCMeterCurrentImpl{
meterCurrent: meterCurrent,
},
MeterEnergy: &decorateBenderCCMeterEnergyImpl{
meterEnergy: meterEnergy,
},
}
}
return nil
}
type decorateBenderCCChargeRaterImpl struct {
chargeRater func() (float64, error)
}
func (impl *decorateBenderCCChargeRaterImpl) ChargedEnergy() (float64, error) {
return impl.chargeRater()
}
type decorateBenderCCMeterImpl struct {
meter func() (float64, error)
}
func (impl *decorateBenderCCMeterImpl) CurrentPower() (float64, error) {
return impl.meter()
}
type decorateBenderCCMeterCurrentImpl struct {
meterCurrent func() (float64, float64, float64, error)
}
func (impl *decorateBenderCCMeterCurrentImpl) Currents() (float64, float64, float64, error) {
return impl.meterCurrent()
}
type decorateBenderCCMeterEnergyImpl struct {
meterEnergy func() (float64, error)
}
func (impl *decorateBenderCCMeterEnergyImpl) TotalEnergy() (float64, error) {
return impl.meterEnergy()
}