diff --git a/core/wrapper/chargerater_test.go b/core/wrapper/chargerater_test.go index 0f7580982..74e81493a 100644 --- a/core/wrapper/chargerater_test.go +++ b/core/wrapper/chargerater_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/andig/evcc/meter" + "github.com/andig/evcc/api" "github.com/andig/evcc/mock" "github.com/andig/evcc/util" "github.com/benbjohnson/clock" @@ -45,7 +45,13 @@ func TestWrappedMeter(t *testing.T) { mm := mock.NewMockMeter(ctrl) me := mock.NewMockMeterEnergy(ctrl) - cm := &meter.EnergyDecorator{Meter: mm, MeterEnergy: me} + + type EnergyDecorator struct { + api.Meter + api.MeterEnergy + } + + cm := &EnergyDecorator{Meter: mm, MeterEnergy: me} me.EXPECT(). TotalEnergy(). diff --git a/meter/meter.go b/meter/meter.go index f6ee63ac6..b90943c9d 100644 --- a/meter/meter.go +++ b/meter/meter.go @@ -1,6 +1,7 @@ package meter import ( + "errors" "fmt" "github.com/andig/evcc/api" @@ -8,17 +9,12 @@ import ( "github.com/andig/evcc/util" ) -// EnergyDecorator decorates an api.Meter with api.MeterEnergy -type EnergyDecorator struct { - api.Meter - api.MeterEnergy -} - // NewConfigurableFromConfig creates api.Meter from config func NewConfigurableFromConfig(other map[string]interface{}) (api.Meter, error) { cc := struct { - Power provider.Config - Energy *provider.Config // optional + Power provider.Config + Energy *provider.Config // optional + Currents []provider.Config // optional }{} if err := util.DecodeOther(other, &cc); err != nil { @@ -40,14 +36,54 @@ func NewConfigurableFromConfig(other map[string]interface{}) (api.Meter, error) // decorate Meter with MeterEnergy if cc.Energy != nil { - energy, err := provider.NewFloatGetterFromConfig(*cc.Energy) + energy, err := NewMeterEnergy(*cc.Energy) if err != nil { return nil, err } + type EnergyDecorator struct { + api.Meter + api.MeterEnergy + } + m = &EnergyDecorator{ Meter: m, - MeterEnergy: NewMeterEnergy(energy), + MeterEnergy: energy, + } + } + + // decorate Meter with MeterCurrent + if len(cc.Currents) > 0 { + currents, err := NewCurrents(cc.Currents) + if err != nil { + return nil, err + } + + type PowerEnergy interface { + api.Meter + api.MeterEnergy + } + + if pe, ok := m.(PowerEnergy); ok { + type CurrentDecorator struct { + PowerEnergy + api.MeterCurrent + } + + m = &CurrentDecorator{ + PowerEnergy: pe, + MeterCurrent: currents, + } + } else { + type CurrentDecorator struct { + api.Meter + api.MeterCurrent + } + + m = &CurrentDecorator{ + Meter: m, + MeterCurrent: currents, + } } } @@ -77,14 +113,64 @@ type MeterEnergy struct { totalEnergyG func() (float64, error) } -// NewMeterEnergy creates a new charger -func NewMeterEnergy(totalEnergyG func() (float64, error)) api.MeterEnergy { - return &MeterEnergy{ +// NewMeterEnergy creates a new api.MeterEnergy +func NewMeterEnergy(ccEnergy provider.Config) (api.MeterEnergy, error) { + totalEnergyG, err := provider.NewFloatGetterFromConfig(ccEnergy) + if err != nil { + return nil, err + } + + e := &MeterEnergy{ totalEnergyG: totalEnergyG, } + + return e, nil } // TotalEnergy implements the Meter.TotalEnergy interface func (m *MeterEnergy) TotalEnergy() (float64, error) { return m.totalEnergyG() } + +// Currents is an api.MeterCurrent implementation +type Currents struct { + currentsG []func() (float64, error) +} + +// NewCurrents creates a new api.MeterCurrent +func NewCurrents(ccCurrents []provider.Config) (api.MeterCurrent, error) { + if len(ccCurrents) != 3 { + return nil, errors.New("need 3 currents") + } + + var currentsG []func() (float64, error) + for _, cc := range ccCurrents { + c, err := provider.NewFloatGetterFromConfig(cc) + if err != nil { + return nil, err + } + + currentsG = append(currentsG, c) + } + + c := &Currents{ + currentsG: currentsG, + } + + return c, nil +} + +// Currents implements the api.Currents interface +func (c *Currents) Currents() (float64, float64, float64, error) { + var currents []float64 + for _, currentG := range c.currentsG { + c, err := currentG() + if err != nil { + return 0, 0, 0, err + } + + currents = append(currents, c) + } + + return currents[0], currents[1], currents[2], nil +}