Sungrow: add battery control (#10833)

This commit is contained in:
andig 2023-11-21 10:47:11 +01:00 • committed by GitHub
parent 307d3d8a63
commit bf36704b06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 308 additions and 1 deletions

View file

@ -9,6 +9,7 @@ import (
type constProvider struct {
str string
set Config
}
func init() {
@ -20,6 +21,7 @@ func NewConstFromConfig(other map[string]interface{}) (Provider, error) {
var cc struct {
Value string
pipeline.Settings `mapstructure:",squash"`
Set Config
}
if err := util.DecodeOther(other, &cc); err != nil {
@ -38,6 +40,7 @@ func NewConstFromConfig(other map[string]interface{}) (Provider, error) {
o := &constProvider{
str: string(b),
set: cc.Set,
}
return o, nil
@ -68,3 +71,54 @@ func (o *constProvider) FloatGetter() (func() (float64, error), error) {
return val, err
}, err
}
var _ BoolProvider = (*constProvider)(nil)
func (o *constProvider) BoolGetter() (func() (bool, error), error) {
val, err := strconv.ParseBool(o.str)
return func() (bool, error) {
return val, err
}, err
}
var _ SetIntProvider = (*constProvider)(nil)
func (o *constProvider) IntSetter(param string) (func(int64) error, error) {
set, err := NewIntSetterFromConfig(param, o.set)
if err != nil {
return nil, err
}
val, err := strconv.ParseInt(o.str, 10, 64)
return func(_ int64) error {
return set(val)
}, err
}
var _ SetFloatProvider = (*constProvider)(nil)
func (o *constProvider) FloatSetter(param string) (func(float64) error, error) {
set, err := NewFloatSetterFromConfig(param, o.set)
if err != nil {
return nil, err
}
val, err := strconv.ParseFloat(o.str, 64)
return func(_ float64) error {
return set(val)
}, err
}
var _ SetBoolProvider = (*constProvider)(nil)
func (o *constProvider) BoolSetter(param string) (func(bool) error, error) {
set, err := NewBoolSetterFromConfig(param, o.set)
if err != nil {
return nil, err
}
val, err := strconv.ParseBool(o.str)
return func(_ bool) error {
return set(val)
}, err
}

View file

@ -46,7 +46,7 @@ func (o *mapProvider) IntSetter(param string) (func(int64) error, error) {
return func(val int64) error {
m, ok := o.values[val]
if !ok {
return fmt.Errorf("value %d not found", val)
return fmt.Errorf("map: value not found: %d", val)
}
return set(m)
}, err

96
provider/sequence.go Normal file
View file

@ -0,0 +1,96 @@
package provider
import (
"github.com/evcc-io/evcc/util"
)
type sequenceProvider struct {
set []Config
}
func init() {
registry.Add("sequence", NewSequenceFromConfig)
}
// NewSequenceFromConfig creates sequence provider
func NewSequenceFromConfig(other map[string]interface{}) (Provider, error) {
var cc struct {
Set []Config
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
o := &sequenceProvider{
set: cc.Set,
}
return o, nil
}
var _ SetIntProvider = (*sequenceProvider)(nil)
func (o *sequenceProvider) IntSetter(param string) (func(int64) error, error) {
set := make([]func(int64) error, 0, len(o.set))
for _, cc := range o.set {
s, err := NewIntSetterFromConfig(param, cc)
if err != nil {
return nil, err
}
set = append(set, s)
}
return func(val int64) error {
for _, s := range set {
if err := s(val); err != nil {
return err
}
}
return nil
}, nil
}
var _ SetFloatProvider = (*sequenceProvider)(nil)
func (o *sequenceProvider) FloatSetter(param string) (func(float64) error, error) {
set := make([]func(float64) error, 0, len(o.set))
for _, cc := range o.set {
s, err := NewFloatSetterFromConfig(param, cc)
if err != nil {
return nil, err
}
set = append(set, s)
}
return func(val float64) error {
for _, s := range set {
if err := s(val); err != nil {
return err
}
}
return nil
}, nil
}
var _ SetBoolProvider = (*sequenceProvider)(nil)
func (o *sequenceProvider) BoolSetter(param string) (func(bool) error, error) {
set := make([]func(bool) error, 0, len(o.set))
for _, cc := range o.set {
s, err := NewBoolSetterFromConfig(param, cc)
if err != nil {
return nil, err
}
set = append(set, s)
}
return func(val bool) error {
for _, s := range set {
if err := s(val); err != nil {
return err
}
}
return nil
}, nil
}

81
provider/switch.go Normal file
View file

@ -0,0 +1,81 @@
package provider
import (
"fmt"
"strconv"
"github.com/evcc-io/evcc/util"
)
type Case struct {
Case string
Set Config
}
type switchProvider struct {
cases []Case
dflt *Config
}
func init() {
registry.Add("switch", NewSwitchFromConfig)
}
// NewSwitchFromConfig creates switch provider
func NewSwitchFromConfig(other map[string]interface{}) (Provider, error) {
var cc struct {
Switch []Case
Default *Config
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
o := &switchProvider{
cases: cc.Switch,
dflt: cc.Default,
}
return o, nil
}
var _ SetIntProvider = (*switchProvider)(nil)
func (o *switchProvider) IntSetter(param string) (func(int64) error, error) {
set := make([]func(int64) error, 0, len(o.cases))
for _, cc := range o.cases {
s, err := NewIntSetterFromConfig(param, cc.Set)
if err != nil {
return nil, err
}
set = append(set, s)
}
var dflt func(int64) error
if o.dflt != nil {
var err error
if dflt, err = NewIntSetterFromConfig(param, *o.dflt); err != nil {
return nil, err
}
}
return func(val int64) error {
for i, s := range o.cases {
ival, err := strconv.ParseInt(s.Case, 10, 64)
if err != nil {
return err
}
if ival == val {
return set[i](val)
}
}
if dflt != nil {
return dflt(val)
}
return fmt.Errorf("switch: value not found: %d", val)
}, nil
}

View file

@ -15,6 +15,7 @@ params:
- name: modbus
choice: ["rs485", "tcpip"]
baudrate: 9600
- name: timeout
- name: capacity
advanced: true
render: |
@ -97,6 +98,81 @@ render: |
type: input
decode: int16
scale: 0.1
batterymode:
source: switch
switch:
- case: 1 # normal
set:
source: sequence
set:
- source: const
value: 0 # self consumption
set:
source: modbus
{{- include "modbus" . | indent 10 }}
timeout: {{ .timeout }}
register:
address: 13049 # EMS mode
type: writesingle
decode: uint16
- source: const
value: 0xCC # stop
set:
source: modbus
{{- include "modbus" . | indent 10 }}
timeout: {{ .timeout }}
register:
address: 13050 # Forced mode
type: writesingle
decode: uint16
- case: 2 # hold
set:
source: sequence
set:
- source: const
value: 2 # forced mode
set:
source: modbus
{{- include "modbus" . | indent 10 }}
timeout: {{ .timeout }}
register:
address: 13049 # EMS mode
type: writesingle
decode: uint16
- source: const
value: 0xCC
set:
source: modbus
{{- include "modbus" . | indent 10 }}
timeout: {{ .timeout }}
register:
address: 13050 # Forced mode
type: writesingle
decode: uint16
- case: 2 # charge
set:
source: sequence
set:
- source: const
value: 2 # forced mode
set:
source: modbus
{{- include "modbus" . | indent 10 }}
timeout: {{ .timeout }}
register:
address: 13049 # EMS mode
type: writesingle
decode: uint16
- source: const
value: 0xAA
set:
source: modbus
{{- include "modbus" . | indent 10 }}
timeout: {{ .timeout }}
register:
address: 13050 # Forced mode
type: writesingle
decode: uint16
{{- if .capacity }}
capacity: {{ .capacity }} # kWh
{{- end }}