SolarEdge: workaround broken NaNs (#15464)
This commit is contained in:
parent
9ad7399b1d
commit
dc719e4a15
4 changed files with 29 additions and 6 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }}
|
||||
|
|
|
|||
|
|
@ -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":
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue