diff --git a/charger/bender.go b/charger/bender.go index a6018c839..0338ac8a1 100644 --- a/charger/bender.go +++ b/charger/bender.go @@ -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 diff --git a/charger/bender_decorators.go b/charger/bender_decorators.go new file mode 100644 index 000000000..efbd54330 --- /dev/null +++ b/charger/bender_decorators.go @@ -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() +}