Curtailment devices: new device class for feed-in limitation (BC) (#32416)
This commit is contained in:
parent
7c0ddf1828
commit
8661c66fc7
40 changed files with 819 additions and 149 deletions
28
curtailer/curtailer.go
Normal file
28
curtailer/curtailer.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package curtailer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
reg "github.com/evcc-io/evcc/util/registry"
|
||||
)
|
||||
|
||||
var registry = reg.New[api.Curtailer]("curtailer")
|
||||
|
||||
// NewFromConfig creates curtailer from configuration
|
||||
func NewFromConfig(ctx context.Context, typ string, other map[string]any) (api.Curtailer, 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 curtailer type '%s': %w", util.TypeWithTemplateName(typ, other), err)
|
||||
}
|
||||
|
||||
return v, err
|
||||
}
|
||||
45
curtailer/custom.go
Normal file
45
curtailer/custom.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package curtailer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/api/implement"
|
||||
"github.com/evcc-io/evcc/meter/measurement"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddCtx(api.Custom, NewConfigurableFromConfig)
|
||||
}
|
||||
|
||||
// NewConfigurableFromConfig creates a curtailer from config
|
||||
func NewConfigurableFromConfig(ctx context.Context, other map[string]any) (api.Curtailer, error) {
|
||||
cc := struct {
|
||||
measurement.Curtailer `mapstructure:",squash"`
|
||||
}{}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
curtailS, curtailedG, err := cc.Curtailer.Configure(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if curtailS == nil {
|
||||
return nil, errors.New("missing curtail")
|
||||
}
|
||||
|
||||
return implement.Curtailer(
|
||||
func() (int, error) {
|
||||
percent, err := curtailedG()
|
||||
return int(percent), err
|
||||
},
|
||||
func(percent int) error {
|
||||
return curtailS(int64(percent))
|
||||
},
|
||||
), nil
|
||||
}
|
||||
21
curtailer/template.go
Normal file
21
curtailer/template.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package curtailer
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/util/templates"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddCtx("template", NewFromTemplateConfig)
|
||||
}
|
||||
|
||||
func NewFromTemplateConfig(ctx context.Context, other map[string]any) (api.Curtailer, error) {
|
||||
instance, err := templates.RenderInstance(templates.Curtailer, other)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewFromConfig(ctx, instance.Type, instance.Other)
|
||||
}
|
||||
21
curtailer/template_test.go
Normal file
21
curtailer/template_test.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package curtailer
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/evcc-io/evcc/util/templates"
|
||||
"github.com/evcc-io/evcc/util/test"
|
||||
)
|
||||
|
||||
var acceptable = []string{}
|
||||
|
||||
func TestTemplates(t *testing.T) {
|
||||
templates.TestClass(t, templates.Curtailer, func(t *testing.T, values map[string]any) {
|
||||
t.Helper()
|
||||
|
||||
if _, err := NewFromConfig(t.Context(), "template", values); err != nil && !test.Acceptable(err, acceptable) {
|
||||
t.Log(values)
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue