Modbus: add bytes setter (#16510)
This commit is contained in:
parent
5e482972e0
commit
11d2b8b85d
6 changed files with 97 additions and 40 deletions
|
|
@ -36,6 +36,9 @@ type (
|
|||
SetBoolProvider interface {
|
||||
BoolSetter(param string) (func(bool) error, error)
|
||||
}
|
||||
SetBytesProvider interface {
|
||||
BytesSetter(param string) (func([]byte) error, error)
|
||||
}
|
||||
)
|
||||
|
||||
// Config is the general provider config
|
||||
|
|
@ -144,3 +147,13 @@ func NewBoolSetterFromConfig(ctx context.Context, param string, config Config) (
|
|||
|
||||
return prov.BoolSetter(param)
|
||||
}
|
||||
|
||||
// NewBytesSetterFromConfig creates a BytesSetter from config
|
||||
func NewBytesSetterFromConfig(param string, config Config) (func([]byte) error, error) {
|
||||
prov, err := provider[SetBytesProvider]("bytes", config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return prov.BytesSetter(param)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package provider
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/evcc-io/evcc/provider/pipeline"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
|
|
@ -149,3 +151,23 @@ func (o *constProvider) BoolSetter(param string) (func(bool) error, error) {
|
|||
return set(val)
|
||||
}, err
|
||||
}
|
||||
|
||||
var _ SetBytesProvider = (*constProvider)(nil)
|
||||
|
||||
func (o *constProvider) BytesSetter(param string) (func([]byte) error, error) {
|
||||
set, err := NewBytesSetterFromConfig(param, o.set)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
str := strings.ReplaceAll(strings.TrimPrefix(o.str, "0x"), "_", "")
|
||||
|
||||
val, err := hex.DecodeString(str)
|
||||
if err != nil {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return func(_ []byte) error {
|
||||
return set(val)
|
||||
}, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package provider
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/evcc-io/evcc/util"
|
||||
|
|
@ -33,27 +34,40 @@ func NewConvertFromConfig(ctx context.Context, other map[string]interface{}) (Pr
|
|||
var _ SetFloatProvider = (*convertProvider)(nil)
|
||||
|
||||
func (o *convertProvider) FloatSetter(param string) (func(float64) error, error) {
|
||||
if o.Convert != "float2int" {
|
||||
switch o.Convert {
|
||||
case "float2int":
|
||||
set, err := NewIntSetterFromConfig(o.ctx, param, o.Set)
|
||||
|
||||
return func(val float64) error {
|
||||
return set(int64(val))
|
||||
}, err
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("convert: invalid conversion: %s", o.Convert)
|
||||
}
|
||||
|
||||
set, err := NewIntSetterFromConfig(o.ctx, param, o.Set)
|
||||
|
||||
return func(val float64) error {
|
||||
return set(int64(val))
|
||||
}, err
|
||||
}
|
||||
|
||||
var _ SetIntProvider = (*convertProvider)(nil)
|
||||
|
||||
func (o *convertProvider) IntSetter(param string) (func(int64) error, error) {
|
||||
if o.Convert != "int2float" {
|
||||
switch o.Convert {
|
||||
case "int2float":
|
||||
set, err := NewFloatSetterFromConfig(o.ctx, param, o.Set)
|
||||
|
||||
return func(val int64) error {
|
||||
return set(float64(val))
|
||||
}, err
|
||||
|
||||
case "int2bytes":
|
||||
set, err := NewBytesSetterFromConfig(o.ctx, param, o.Set)
|
||||
|
||||
return func(val int64) error {
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, uint64(val))
|
||||
return set(b)
|
||||
}, err
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("convert: invalid conversion: %s", o.Convert)
|
||||
}
|
||||
|
||||
set, err := NewFloatSetterFromConfig(o.ctx, param, o.Set)
|
||||
|
||||
return func(val int64) error {
|
||||
return set(float64(val))
|
||||
}, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,3 +234,24 @@ func (m *Modbus) BoolSetter(param string) (func(bool) error, error) {
|
|||
return set(ival)
|
||||
}, err
|
||||
}
|
||||
|
||||
var _ SetBytesProvider = (*Modbus)(nil)
|
||||
|
||||
// BytesSetter implements SetBytesProvider
|
||||
func (m *Modbus) BytesSetter(_ string) (func([]byte) error, error) {
|
||||
op, err := m.reg.Operation()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(val []byte) error {
|
||||
switch op.FuncCode {
|
||||
case gridx.FuncCodeWriteMultipleRegisters:
|
||||
_, err = m.conn.WriteMultipleRegisters(op.Addr, uint16(len(val)/2), val)
|
||||
return err
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid func code: %d", op.FuncCode)
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,33 +171,18 @@ render: |
|
|||
address: 0x1110
|
||||
type: writemultiple
|
||||
decode: int16
|
||||
- source: const
|
||||
value: 0
|
||||
- source: convert
|
||||
convert: int2bytes
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 0x1187
|
||||
type: writemultiple
|
||||
decode: int32
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 0x1189
|
||||
type: writemultiple
|
||||
decode: int32
|
||||
- source: const
|
||||
value: 0x7FFFFFFF
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 0x118B
|
||||
type: writemultiple
|
||||
decode: int32
|
||||
source: const
|
||||
value: '0x00000000_00000000_7FFFFFFF'
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 12 }}
|
||||
register:
|
||||
address: 0x1187
|
||||
type: writemultiple
|
||||
decode: bytes
|
||||
- case: 3 # charge (not implemented -> normal)
|
||||
set:
|
||||
source: const
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ func (r Register) Length() (uint16, error) {
|
|||
return 2, nil
|
||||
case strings.Contains(enc, "64"):
|
||||
return 4, nil
|
||||
case strings.EqualFold(enc, "bytes"):
|
||||
return 0, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid register length: %s", enc)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue