SolarEdge: add battery control (#10808)

This commit is contained in:
andig 2023-11-21 09:19:36 +01:00 • committed by GitHub
parent ae33590e6b
commit d01e9a85d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 9 deletions

View file

@ -8,8 +8,8 @@ type battery struct {
MinSoc, MaxSoc float64
}
// Decorator returns an api.BatteryController decorator
func (m *battery) BatteryController(socG func() (float64, error), limitSocS func(float64) error) func(api.BatteryMode) error {
// LimitController returns an api.BatteryController decorator
func (m *battery) LimitController(socG func() (float64, error), limitSocS func(float64) error) func(api.BatteryMode) error {
return func(mode api.BatteryMode) error {
switch mode {
case api.BatteryNormal:
@ -30,3 +30,10 @@ func (m *battery) BatteryController(socG func() (float64, error), limitSocS func
}
}
}
// ModeController returns an api.BatteryController decorator
func (m *battery) ModeController(modeS func(int64) error) func(api.BatteryMode) error {
return func(mode api.BatteryMode) error {
return modeS(int64(mode))
}
}

View file

@ -25,10 +25,11 @@ func NewConfigurableFromConfig(other map[string]interface{}) (api.Meter, error)
Powers []provider.Config // optional
// battery
capacity `mapstructure:",squash"`
battery `mapstructure:",squash"`
Soc *provider.Config // optional
LimitSoc *provider.Config // optional
capacity `mapstructure:",squash"`
battery `mapstructure:",squash"`
Soc *provider.Config // optional
LimitSoc *provider.Config // optional
BatteryMode *provider.Config // optional
}{
battery: battery{
MinSoc: 20,
@ -84,13 +85,23 @@ func NewConfigurableFromConfig(other map[string]interface{}) (api.Meter, error)
}
var batModeS func(api.BatteryMode) error
if cc.Soc != nil && cc.LimitSoc != nil {
switch {
case cc.Soc != nil && cc.LimitSoc != nil:
limitSocS, err := provider.NewFloatSetterFromConfig("limitSoc", *cc.LimitSoc)
if err != nil {
return nil, fmt.Errorf("battery limit soc: %w", err)
}
batModeS = cc.battery.BatteryController(socG, limitSocS)
batModeS = cc.battery.LimitController(socG, limitSocS)
case cc.BatteryMode != nil:
modeS, err := provider.NewIntSetterFromConfig("mode", *cc.BatteryMode)
if err != nil {
return nil, fmt.Errorf("battery mode: %w", err)
}
batModeS = cc.battery.ModeController(modeS)
}
res := m.Decorate(totalEnergyG, currentsG, voltagesG, powersG, socG, cc.capacity.Decorator(), batModeS)

53
provider/map.go Normal file
View file

@ -0,0 +1,53 @@
package provider
import (
"fmt"
"github.com/evcc-io/evcc/util"
)
type mapProvider struct {
values map[int64]int64
set Config
}
func init() {
registry.Add("map", NewMapFromConfig)
}
// NewMapFromConfig creates type conversion provider
func NewMapFromConfig(other map[string]interface{}) (Provider, error) {
var cc struct {
Values map[int64]int64
Set Config
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
if len(cc.Values) == 0 {
return nil, fmt.Errorf("missing values")
}
o := &mapProvider{
set: cc.Set,
values: cc.Values,
}
return o, nil
}
var _ SetIntProvider = (*mapProvider)(nil)
func (o *mapProvider) IntSetter(param string) (func(int64) error, error) {
set, err := NewIntSetterFromConfig(param, o.set)
return func(val int64) error {
m, ok := o.values[val]
if !ok {
return fmt.Errorf("value %d not found", val)
}
return set(m)
}, err
}

View file

@ -20,8 +20,8 @@ params:
advanced: true
render: |
type: custom
power:
{{- if eq .usage "grid" }}
power:
source: modbus
{{- include "modbus" . | indent 2 }}
timeout: {{ .timeout }}
@ -31,6 +31,7 @@ render: |
scale: -1
{{- end }}
{{- if eq .usage "pv" }}
power:
source: calc
add:
- source: modbus
@ -47,6 +48,7 @@ render: |
decode: float32s
{{- end }}
{{- if eq .usage "battery" }}
power:
source: modbus
{{- include "modbus" . | indent 2 }}
timeout: {{ .timeout }}
@ -63,6 +65,20 @@ render: |
address: 62852 # Battery 1 State of Energy (SOE)
type: holding
decode: float32s
batterymode:
source: map
values:
1: 7 # normal
2: 1 # hold
3: 3 # charge
set:
source: modbus
{{- include "modbus" . | indent 4 }}
timeout: {{ .timeout }}
register:
address: 0xE00A # Battery mode
type: writesingle
decode: uint16
{{- if .capacity }}
capacity: {{ .capacity }} # kWh
{{- end }}