Sungrow: add battery control (#10833)
This commit is contained in:
parent
307d3d8a63
commit
bf36704b06
5 changed files with 308 additions and 1 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
96
provider/sequence.go
Normal 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
81
provider/switch.go
Normal 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
|
||||
}
|
||||
|
|
@ -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 }}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue