Skip to content

Commit

Permalink
Kostal: add battery control (evcc-io#10807)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored Nov 18, 2023
1 parent eb98e08 commit 8da3db2
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 27 deletions.
91 changes: 71 additions & 20 deletions provider/modbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,37 +266,88 @@ func (m *Modbus) BoolGetter() func() (bool, error) {
}
}

// FloatSetter executes configured modbus write operation and implements SetFloatProvider
func (m *Modbus) FloatSetter(_ string) func(float64) error {
return func(val float64) error {
op := m.op.MBMD
if op.FuncCode == 0 {
return errors.New("modbus plugin does not support writing to sunspec")
}

// if funccode is configured, execute the read directly
if op.FuncCode != gridx.FuncCodeWriteMultipleRegisters {
return fmt.Errorf("invalid write function code: %d", op.FuncCode)
}

val = m.scale * val

var err error
switch op.ReadLen {
case 2:
var b [4]byte
binary.BigEndian.PutUint32(b[:], math.Float32bits(float32(val)))
_, err = m.conn.WriteMultipleRegisters(op.OpCode, 2, b[:])

case 4:
var b [8]byte
binary.BigEndian.PutUint64(b[:], math.Float64bits(val))
_, err = m.conn.WriteMultipleRegisters(op.OpCode, 4, b[:])

default:
err = fmt.Errorf("invalid write length: %d", op.ReadLen)
}

return err
}
}

// IntSetter executes configured modbus write operation and implements SetIntProvider
func (m *Modbus) IntSetter(param string) func(int64) error {
func (m *Modbus) IntSetter(_ string) func(int64) error {
return func(val int64) error {
var err error
op := m.op.MBMD
if op.FuncCode == 0 {
return errors.New("modbus plugin does not support writing to sunspec")
}

// if funccode is configured, execute the read directly
if op := m.op.MBMD; op.FuncCode != 0 {
uval := uint16(m.scale * float64(val))
ival := int64(m.scale * float64(val))

switch op.FuncCode {
case gridx.FuncCodeWriteSingleRegister:
_, err = m.conn.WriteSingleRegister(op.OpCode, uval)
// if funccode is configured, execute the read directly
var err error
switch op.FuncCode {
case gridx.FuncCodeWriteSingleRegister:
_, err = m.conn.WriteSingleRegister(op.OpCode, uint16(ival))

case gridx.FuncCodeWriteMultipleRegisters:
case gridx.FuncCodeWriteMultipleRegisters:
switch op.ReadLen {
case 1:
var b [2]byte
binary.BigEndian.PutUint16(b[:], uval)
binary.BigEndian.PutUint16(b[:], uint16(ival))
_, err = m.conn.WriteMultipleRegisters(op.OpCode, 1, b[:])

case gridx.FuncCodeWriteSingleCoil:
if uval != 0 {
// Modbus protocol requires 0xFF00 for ON
// and 0x0000 for OFF
uval = 0xFF00
}
_, err = m.conn.WriteSingleCoil(op.OpCode, uval)
case 2:
var b [4]byte
binary.BigEndian.PutUint32(b[:], uint32(ival))
_, err = m.conn.WriteMultipleRegisters(op.OpCode, 2, b[:])

case 4:
var b [8]byte
binary.BigEndian.PutUint64(b[:], uint64(ival))
_, err = m.conn.WriteMultipleRegisters(op.OpCode, 4, b[:])

default:
err = fmt.Errorf("invalid write function code: %d", op.FuncCode)
err = fmt.Errorf("invalid write length: %d", op.ReadLen)
}
} else {
err = errors.New("modbus plugin does not support writing to sunspec")

case gridx.FuncCodeWriteSingleCoil:
if ival != 0 {
// Modbus protocol requires 0xFF00 for ON
// and 0x0000 for OFF
ival = 0xFF00
}
_, err = m.conn.WriteSingleCoil(op.OpCode, uint16(ival))

default:
err = fmt.Errorf("invalid write function code: %d", op.FuncCode)
}

return err
Expand Down
36 changes: 29 additions & 7 deletions templates/definition/meter/kostal-plenticore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ params:
port: 1502
- name: capacity
advanced: true
# battery control
- name: minsoc
type: number
advanced: true
- name: maxsoc
type: number
advanced: true
render: |
{{- if eq .usage "pv" }}
type: custom
Expand All @@ -39,12 +46,27 @@ render: |
value: 160:3:DCW # string 3
{{- end }}
{{- if eq .usage "battery" }}
type: modbus
{{- include "modbus" . }}
model: sunspec
power: 802:W # sunspec model 802 battery
soc: 802:SoC # sunspec model 802 battery
{{- if .capacity }}
type: custom
power:
source: modbus
{{- include "modbus" . | indent 2 }}
model: sunspec
value: 802:W # 802 battery control
soc:
source: modbus
{{- include "modbus" . | indent 2 }}
model: sunspec
value: 802:SoC # 802 battery control
limitsoc:
source: float2int
set:
source: modbus
{{- include "modbus" . | indent 4 }}
register:
address: 1042 # limit soc
type: writesingle
decode: uint16
capacity: {{ .capacity }} # kWh
{{- end }}
minsoc: {{ .minsoc }} # %
maxsoc: {{ .maxsoc }} # %
{{- end }}

0 comments on commit 8da3db2

Please sign in to comment.