diff --git a/templates/definition/meter/kostal-plenticore.yaml b/templates/definition/meter/kostal-plenticore.yaml index c641b13d7b..fcf530fbd9 100644 --- a/templates/definition/meter/kostal-plenticore.yaml +++ b/templates/definition/meter/kostal-plenticore.yaml @@ -79,7 +79,7 @@ render: | register: address: 1042 # limit soc type: writemultiple - decode: {{ if (eq .endianness "big") }}float32{{ else }}float32s{{ end }} + encoding: {{ if (eq .endianness "big") }}float32{{ else }}float32s{{ end }} capacity: {{ .capacity }} # kWh minsoc: {{ .minsoc }} # % maxsoc: {{ .maxsoc }} # % diff --git a/util/modbus/register.go b/util/modbus/register.go index 359215e7bf..c672bfaf51 100644 --- a/util/modbus/register.go +++ b/util/modbus/register.go @@ -44,10 +44,30 @@ func (r Register) encoding() string { return r.Decode } +func (r Register) Length() (uint16, error) { + enc := r.encoding() + switch { + case strings.Contains(enc, "8") || strings.Contains(enc, "16"): + return 1, nil + case strings.Contains(enc, "32") || strings.Contains(enc, "754"): + return 2, nil + case strings.Contains(enc, "64"): + return 4, nil + default: + return 0, fmt.Errorf("invalid register encoding: %s", enc) + } +} + // Operation creates a modbus operation from a register definition func (r Register) Operation() (RegisterOperation, error) { + len, err := r.Length() + if err != nil { + return RegisterOperation{}, err + } + op := RegisterOperation{ - Addr: r.Address, + Addr: r.Address, + Length: len, } switch strings.ToLower(r.Type) { @@ -72,65 +92,48 @@ func (r Register) Operation() (RegisterOperation, error) { // 8 bit (coil) case "bool8": op.Decode = decodeBool8 - op.Length = 1 // 16 bit case "int16": op.Decode = asFloat64(encoding.Int16) - op.Length = 1 case "int16nan": op.Decode = decodeNaN16(asFloat64(encoding.Int16), 1<<15, 1<<15-1) - op.Length = 1 case "uint16": op.Decode = asFloat64(encoding.Uint16) - op.Length = 1 case "uint16nan": op.Decode = decodeNaN16(asFloat64(encoding.Uint16), 1<<16-1) - op.Length = 1 case "bool16": mask, err := decodeMask(r.BitMask) if err != nil { return op, err } op.Decode = decodeBool16(mask) - op.Length = 1 // 32 bit case "int32": op.Decode = asFloat64(encoding.Int32) - op.Length = 2 case "int32nan": op.Decode = decodeNaN32(asFloat64(encoding.Int32), 1<<31, 1<<31-1) - op.Length = 2 case "int32s": op.Decode = asFloat64(encoding.Int32LswFirst) - op.Length = 2 case "uint32": op.Decode = asFloat64(encoding.Uint32) - op.Length = 2 case "uint32s": op.Decode = asFloat64(encoding.Uint32LswFirst) - op.Length = 2 case "uint32nan": op.Decode = decodeNaN32(asFloat64(encoding.Uint32), 1<<32-1) - op.Length = 2 case "float32", "ieee754": op.Decode = asFloat64(encoding.Float32) - op.Length = 2 case "float32s", "ieee754s": op.Decode = asFloat64(encoding.Float32LswFirst) - op.Length = 2 // 64 bit case "uint64": op.Decode = asFloat64(encoding.Uint64) - op.Length = 4 case "uint64nan": op.Decode = decodeNaN64(asFloat64(encoding.Uint64), 1<<64-1) - op.Length = 4 case "float64": op.Decode = encoding.Float64 - op.Length = 4 default: return RegisterOperation{}, fmt.Errorf("invalid register decoding: %s", r.Decode) diff --git a/util/modbus/register_test.go b/util/modbus/register_test.go new file mode 100644 index 0000000000..bf9eaef676 --- /dev/null +++ b/util/modbus/register_test.go @@ -0,0 +1,25 @@ +package modbus + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestLength(t *testing.T) { + tc := []struct { + value string + want uint16 + }{ + {"bool8", 1}, + {"int16", 1}, + {"float32", 2}, + {"uint64s", 4}, + } + + for _, tc := range tc { + res, err := Register{Encoding: tc.value}.Length() + require.NoError(t, err, tc) + require.Equal(t, tc.want, res, tc) + } +}