Add meter plugin (#21477)

This commit is contained in:
andig 2025-05-29 09:47:04 +02:00 • committed by GitHub
parent 5c8f101bb3
commit 02d3a362b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 196 additions and 15 deletions

View file

@ -2,14 +2,12 @@ package meter
import (
"context"
"fmt"
"strings"
"github.com/evcc-io/evcc/api"
reg "github.com/evcc-io/evcc/util/registry"
"github.com/evcc-io/evcc/meter/config"
)
var registry = reg.New[api.Meter]("meter")
var registry = config.Registry
// Types returns the list of types
func Types() []string {
@ -18,15 +16,5 @@ func Types() []string {
// NewFromConfig creates meter from configuration
func NewFromConfig(ctx context.Context, typ string, other map[string]interface{}) (api.Meter, error) {
factory, err := registry.Get(strings.ToLower(typ))
if err != nil {
return nil, err
}
v, err := factory(ctx, other)
if err != nil {
err = fmt.Errorf("cannot create meter type '%s': %w", typ, err)
}
return v, err
return config.NewFromConfig(ctx, typ, other)
}

27
meter/config/config.go Normal file
View file

@ -0,0 +1,27 @@
package config
import (
"context"
"fmt"
"strings"
"github.com/evcc-io/evcc/api"
reg "github.com/evcc-io/evcc/util/registry"
)
var Registry = reg.New[api.Meter]("meter")
// NewFromConfig creates meter from configuration
func NewFromConfig(ctx context.Context, typ string, other map[string]interface{}) (api.Meter, error) {
factory, err := Registry.Get(strings.ToLower(typ))
if err != nil {
return nil, err
}
v, err := factory(ctx, other)
if err != nil {
err = fmt.Errorf("cannot create meter type '%s': %w", typ, err)
}
return v, err
}

72
plugin/meter.go Normal file
View file

@ -0,0 +1,72 @@
package plugin
import (
"context"
"fmt"
"github.com/evcc-io/evcc/api"
meter "github.com/evcc-io/evcc/meter/config"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/config"
)
type meterPlugin struct {
meter api.Meter
method Method
}
func init() {
registry.AddCtx("meter", NewMeterFromConfig)
}
// NewMeterFromConfig creates type conversion provider
func NewMeterFromConfig(ctx context.Context, other map[string]interface{}) (Plugin, error) {
var cc struct {
Config config.Typed
Method
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
meter, err := meter.NewFromConfig(ctx, cc.Config.Type, cc.Config.Other)
if err != nil {
return nil, err
}
o := &meterPlugin{
meter: meter,
method: cc.Method,
}
return o, nil
}
var _ FloatGetter = (*meterPlugin)(nil)
func (o *meterPlugin) FloatGetter() (func() (float64, error), error) {
err := fmt.Errorf("unsupported method: %s", o.method.String())
switch o.method {
case Energy:
if _, ok := o.meter.(api.MeterEnergy); !ok {
return nil, err
}
case Soc:
if _, ok := o.meter.(api.Battery); !ok {
return nil, err
}
}
return func() (float64, error) {
switch o.method {
case Energy:
return o.meter.(api.MeterEnergy).TotalEnergy()
case Soc:
return o.meter.(api.Battery).Soc()
default:
return o.meter.CurrentPower()
}
}, nil
}

11
plugin/method.go Normal file
View file

@ -0,0 +1,11 @@
package plugin
//go:generate go tool enumer -type Method
type Method int
const (
_ Method = iota
Energy
Power
Soc
)

83
plugin/method_enumer.go Normal file
View file

@ -0,0 +1,83 @@
// Code generated by "enumer -type Method"; DO NOT EDIT.
package plugin
import (
"fmt"
"strings"
)
const _MethodName = "EnergyPowerSoc"
var _MethodIndex = [...]uint8{0, 6, 11, 14}
const _MethodLowerName = "energypowersoc"
func (i Method) String() string {
i -= 1
if i < 0 || i >= Method(len(_MethodIndex)-1) {
return fmt.Sprintf("Method(%d)", i+1)
}
return _MethodName[_MethodIndex[i]:_MethodIndex[i+1]]
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _MethodNoOp() {
var x [1]struct{}
_ = x[Energy-(1)]
_ = x[Power-(2)]
_ = x[Soc-(3)]
}
var _MethodValues = []Method{Energy, Power, Soc}
var _MethodNameToValueMap = map[string]Method{
_MethodName[0:6]: Energy,
_MethodLowerName[0:6]: Energy,
_MethodName[6:11]: Power,
_MethodLowerName[6:11]: Power,
_MethodName[11:14]: Soc,
_MethodLowerName[11:14]: Soc,
}
var _MethodNames = []string{
_MethodName[0:6],
_MethodName[6:11],
_MethodName[11:14],
}
// MethodString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func MethodString(s string) (Method, error) {
if val, ok := _MethodNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _MethodNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Method values", s)
}
// MethodValues returns all values of the enum
func MethodValues() []Method {
return _MethodValues
}
// MethodStrings returns a slice of all String values of the enum
func MethodStrings() []string {
strs := make([]string, len(_MethodNames))
copy(strs, _MethodNames)
return strs
}
// IsAMethod returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Method) IsAMethod() bool {
for _, v := range _MethodValues {
if i == v {
return true
}
}
return false
}