Skip to content

Commit

Permalink
SolarEdge: add battery control (evcc-io#10808)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored Nov 21, 2023
1 parent ae33590 commit d01e9a8
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 9 deletions.
11 changes: 9 additions & 2 deletions meter/battery.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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))
}
}
23 changes: 17 additions & 6 deletions meter/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
53 changes: 53 additions & 0 deletions provider/map.go
Original file line number Diff line number Diff line change
@@ -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
}
18 changes: 17 additions & 1 deletion templates/definition/meter/solaredge-hybrid.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ params:
advanced: true
render: |
type: custom
power:
{{- if eq .usage "grid" }}
power:
source: modbus
{{- include "modbus" . | indent 2 }}
timeout: {{ .timeout }}
Expand All @@ -31,6 +31,7 @@ render: |
scale: -1
{{- end }}
{{- if eq .usage "pv" }}
power:
source: calc
add:
- source: modbus
Expand All @@ -47,6 +48,7 @@ render: |
decode: float32s
{{- end }}
{{- if eq .usage "battery" }}
power:
source: modbus
{{- include "modbus" . | indent 2 }}
timeout: {{ .timeout }}
Expand All @@ -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 }}
Expand Down

0 comments on commit d01e9a8

Please sign in to comment.