SolarEdge: workaround broken NaNs (#15464)

This commit is contained in:
andig 2024-08-18 11:36:23 +02:00 • committed by GitHub
parent 9ad7399b1d
commit dc719e4a15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 29 additions and 6 deletions

View file

@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"regexp"
"strconv"
"strings"
xj "github.com/basgys/goxml2json"
@ -140,7 +141,7 @@ func (p *Pipeline) unpackValue(value []byte) (string, error) {
// decode a hex string to a proper value
// TODO reuse similar code from Modbus
func (p *Pipeline) decodeValue(value []byte) (interface{}, error) {
func (p *Pipeline) decodeValue(value []byte) (float64, error) {
switch p.decode {
case "float32", "ieee754":
return rs485.RTUIeee754ToFloat64(value), nil
@ -164,7 +165,7 @@ func (p *Pipeline) decodeValue(value []byte) (interface{}, error) {
return rs485.RTUInt32ToFloat64Swapped(value), nil
}
return nil, fmt.Errorf("invalid decoding: %s", p.decode)
return 0, fmt.Errorf("invalid decoding: %s", p.decode)
}
func (p *Pipeline) Process(in []byte) ([]byte, error) {
@ -202,7 +203,7 @@ func (p *Pipeline) Process(in []byte) ([]byte, error) {
if err != nil {
return b, err
}
b = []byte(fmt.Sprintf("%v", v))
b = []byte(strconv.FormatFloat(v, 'f', -1, 64))
}
return b, nil

View file

@ -111,7 +111,7 @@ render: |
register:
address: 62836 # Battery 1 Instantaneous Power
type: holding
decode: float32s
decode: float32nans
{{- end }}
{{- if eq .usage "battery" }}
power:
@ -121,7 +121,7 @@ render: |
register:
address: 0xE174 # Battery 1 Instantaneous Power
type: holding
decode: float32s
decode: float32nans
scale: -1
soc:
source: modbus
@ -130,7 +130,7 @@ render: |
register:
address: 0xE184 # Battery 1 State of Energy (SOE)
type: holding
decode: float32s
decode: float32nans
batterymode:
source: watchdog
timeout: {{ .watchdog }}

View file

@ -113,6 +113,8 @@ func (r Register) DecodeFunc() (func([]byte) float64, error) {
return asFloat64(encoding.Float32), nil
case "float32s", "ieee754s":
return asFloat64(encoding.Float32LswFirst), nil
case "float32nans":
return decodeNaN32(asFloat64(encoding.Float32LswFirst), 0xffffff7f), nil
// 64 bit
case "int64":

View file

@ -63,3 +63,23 @@ func TestEncoding(t *testing.T) {
require.Equal(t, tc.out, res, tc)
}
}
func TestDecoding(t *testing.T) {
tc := []struct {
r Register
in []byte
out float64
}{
{Register{Decode: "float32"}, []byte{0x4b, 0x3c, 0x61, 0x4e}, 12345678},
{Register{Decode: "float32"}, []byte{0xff, 0xff, 0xff, 0x7f}, 0}, // NaN
{Register{Decode: "float32s"}, []byte{0x61, 0x4e, 0x4b, 0x3c}, 12345678},
{Register{Decode: "float32s"}, []byte{0xff, 0x7f, 0xff, 0xff}, 0}, // NaN swapped
{Register{Decode: "float32nans"}, []byte{0xff, 0xff, 0xff, 0x7f}, 0}, // NaN
}
for _, tc := range tc {
fun, err := tc.r.DecodeFunc()
require.NoError(t, err, tc)
require.Equal(t, tc.out, fun(tc.in), tc)
}
}