diff --git a/cmd/config.go b/cmd/config.go index f78aba344..ae40111c7 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -6,6 +6,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/charger" "github.com/andig/evcc/core" + "github.com/andig/evcc/meter" "github.com/andig/evcc/push" "github.com/andig/evcc/server" "github.com/andig/evcc/vehicle" @@ -19,7 +20,7 @@ type config struct { Influx influxConfig Menu []server.MenuConfig Messaging messagingConfig - Meters []namedConfig + Meters []qualifiedConfig Chargers []qualifiedConfig Vehicles []qualifiedConfig LoadPoints []core.Config @@ -30,11 +31,6 @@ type qualifiedConfig struct { Other map[string]interface{} `mapstructure:",remain"` } -type namedConfig struct { - Name string - Other map[string]interface{} `mapstructure:",remain"` -} - type typedConfig struct { Type string Other map[string]interface{} `mapstructure:",remain"` @@ -102,7 +98,7 @@ func (c *ConfigProvider) configure(conf config) { func (c *ConfigProvider) configureMeters(conf config) { c.meters = make(map[string]api.Meter) for _, cc := range conf.Meters { - c.meters[cc.Name] = core.NewMeterFromConfig(log, cc.Other) + c.meters[cc.Name] = meter.NewFromConfig(log, cc.Type, cc.Other) } } diff --git a/core/api.go b/core/api.go index bd24dcc0d..5d07f1530 100644 --- a/core/api.go +++ b/core/api.go @@ -154,7 +154,7 @@ func (lp *LoadPoint) publishSoC() { if lp.connected() { f, err := lp.vehicle.ChargeState() if err == nil { - log.DEBUG.Printf("%s vehicle charge: %.1f%%", lp.Name, f) + log.DEBUG.Printf("%s vehicle soc: %.1f%%", lp.Name, f) lp.publish("socCharge", f) lp.publish("chargeEstimate", lp.remainingChargeDuration(f)) return diff --git a/core/config.go b/core/config.go deleted file mode 100644 index 44eb5bd0a..000000000 --- a/core/config.go +++ /dev/null @@ -1,28 +0,0 @@ -package core - -import ( - "github.com/andig/evcc/api" - "github.com/andig/evcc/core/wrapper" - "github.com/andig/evcc/provider" -) - -// NewMeterFromConfig creates api.Meter from config -func NewMeterFromConfig(log *api.Logger, other map[string]interface{}) api.Meter { - cc := struct { - Power provider.Config - Energy *provider.Config // optional - }{} - api.DecodeOther(log, other, &cc) - - m := NewMeter(provider.NewFloatGetterFromConfig(log, cc.Power)) - - // decorate Meter with MeterEnergy - if cc.Energy != nil { - m = &wrapper.CompositeMeter{ - Meter: m, - MeterEnergy: NewMeterEnergy(provider.NewFloatGetterFromConfig(log, *cc.Energy)), - } - } - - return m -} diff --git a/core/loadpoint_test.go b/core/loadpoint_test.go index 56d65e121..39059b702 100644 --- a/core/loadpoint_test.go +++ b/core/loadpoint_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/andig/evcc/api" + "github.com/andig/evcc/meter" "github.com/andig/evcc/mock" "github.com/andig/evcc/provider" "github.com/andig/evcc/push" @@ -121,13 +122,13 @@ func TestMeterConfigurations(t *testing.T) { var gm, pm, cm api.Meter if tc.gm { - gm = NewMeter(fg) + gm = meter.NewConfigurable(fg) } if tc.cm { - cm = NewMeter(fg) + cm = meter.NewConfigurable(fg) } if tc.pm { - pm = NewMeter(fg) + pm = meter.NewConfigurable(fg) } ctrl := gomock.NewController(t) diff --git a/core/wrapper/chargemeter.go b/core/wrapper/chargemeter.go index 1da95efd1..d905a6d43 100644 --- a/core/wrapper/chargemeter.go +++ b/core/wrapper/chargemeter.go @@ -2,16 +2,8 @@ package wrapper import ( "sync" - - "github.com/andig/evcc/api" ) -// CompositeMeter decorates a Meter with MeterEnergy. -type CompositeMeter struct { - api.Meter - api.MeterEnergy -} - // ChargeMeter is a replacement for a physical charge meter. // It uses the charger's actual or max current to calculate power consumption. type ChargeMeter struct { diff --git a/core/wrapper/chargerater_test.go b/core/wrapper/chargerater_test.go index b0e517a7e..88c41b937 100644 --- a/core/wrapper/chargerater_test.go +++ b/core/wrapper/chargerater_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/andig/evcc/meter" "github.com/andig/evcc/mock" "github.com/benbjohnson/clock" "github.com/golang/mock/gomock" @@ -43,7 +44,7 @@ func TestWrappedMeter(t *testing.T) { mm := mock.NewMockMeter(ctrl) me := mock.NewMockMeterEnergy(ctrl) - cm := &CompositeMeter{mm, me} + cm := &meter.CompositeMeter{Meter: mm, MeterEnergy: me} me.EXPECT(). TotalEnergy(). diff --git a/evcc.dist.yaml b/evcc.dist.yaml index 6faa3bb91..ee27ebd3a 100644 --- a/evcc.dist.yaml +++ b/evcc.dist.yaml @@ -44,16 +44,19 @@ messaging: # meters meters: - name: grid + type: default power: # power reading type: mqtt # use mqtt topic: mbmd/sdm1-1/Power # mqtt topic timeout: 10s # don't use older values - name: pv + type: default power: type: mqtt topic: mbmd/sdm1-2/Power timeout: 10s # don't use older values - name: charge + type: default power: type: script # use script cmd: /bin/sh -c "echo 0" # actual command diff --git a/meter/config.go b/meter/config.go new file mode 100644 index 000000000..cb9af6da7 --- /dev/null +++ b/meter/config.go @@ -0,0 +1,21 @@ +package meter + +import ( + "strings" + + "github.com/andig/evcc/api" +) + +// NewFromConfig creates meter from configuration +func NewFromConfig(log *api.Logger, typ string, other map[string]interface{}) api.Meter { + var c api.Meter + + switch strings.ToLower(typ) { + case "default", "configurable": + c = NewConfigurableFromConfig(log, other) + default: + log.FATAL.Fatalf("invalid meter type '%s'", typ) + } + + return c +} diff --git a/core/meter.go b/meter/meter.go similarity index 52% rename from core/meter.go rename to meter/meter.go index d01a69ba8..cad10614a 100644 --- a/core/meter.go +++ b/meter/meter.go @@ -1,22 +1,49 @@ -package core +package meter import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" ) -// Meter is an api.Meter implementation with configurable getters and setters. -type Meter struct { - currentPowerG provider.FloatGetter +// CompositeMeter decorates a Meter with MeterEnergy. +type CompositeMeter struct { + api.Meter + api.MeterEnergy } -// NewMeter creates a new charger -func NewMeter(currentPowerG provider.FloatGetter) api.Meter { +// NewConfigurableFromConfig creates api.Meter from config +func NewConfigurableFromConfig(log *api.Logger, other map[string]interface{}) api.Meter { + cc := struct { + Power provider.Config + Energy *provider.Config // optional + }{} + api.DecodeOther(log, other, &cc) + + m := NewConfigurable(provider.NewFloatGetterFromConfig(log, cc.Power)) + + // decorate Meter with MeterEnergy + if cc.Energy != nil { + m = &CompositeMeter{ + Meter: m, + MeterEnergy: NewMeterEnergy(provider.NewFloatGetterFromConfig(log, *cc.Energy)), + } + } + + return m +} + +// NewConfigurable creates a new charger +func NewConfigurable(currentPowerG provider.FloatGetter) api.Meter { return &Meter{ currentPowerG: currentPowerG, } } +// Meter is an api.Meter implementation with configurable getters and setters. +type Meter struct { + currentPowerG provider.FloatGetter +} + // CurrentPower implements the Meter.CurrentPower interface func (m *Meter) CurrentPower() (float64, error) { return m.currentPowerG()