Skip to content

Commit

Permalink
SolarEdge: workaround broken NaNs (#15464)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored Aug 18, 2024
1 parent 9ad7399 commit dc719e4
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 6 deletions.
7 changes: 4 additions & 3 deletions provider/pipeline/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"regexp"
"strconv"
"strings"

xj "github.com/basgys/goxml2json"
Expand Down Expand Up @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions templates/definition/meter/solaredge-hybrid.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ render: |
register:
address: 62836 # Battery 1 Instantaneous Power
type: holding
decode: float32s
decode: float32nans
{{- end }}
{{- if eq .usage "battery" }}
power:
Expand All @@ -121,7 +121,7 @@ render: |
register:
address: 0xE174 # Battery 1 Instantaneous Power
type: holding
decode: float32s
decode: float32nans
scale: -1
soc:
source: modbus
Expand All @@ -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 }}
Expand Down
2 changes: 2 additions & 0 deletions util/modbus/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down
20 changes: 20 additions & 0 deletions util/modbus/register_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

0 comments on commit dc719e4

Please sign in to comment.