Revert "Modbus: handle NaN values" (#31968)

This commit is contained in:
andig 2026-07-20 10:11:25 +02:00 • committed by GitHub
parent a1e8854df1
commit 7a95266a6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 9 additions and 26 deletions

View file

@ -9,7 +9,6 @@ import (
"strings"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/modbus"
gridx "github.com/grid-x/modbus"
@ -157,12 +156,7 @@ func (m *Modbus) FloatGetter() (func() (f float64, err error), error) {
return 0, fmt.Errorf("read failed: %w", err)
}
// a "*nan" sentinel decodes to NaN - the device reports no valid value
if res := m.scale * decode(bytes); !math.IsNaN(res) {
return res, nil
}
return 0, api.ErrNotAvailable
return m.scale * decode(bytes), nil
}, nil
}

View file

@ -5,7 +5,6 @@ import (
"encoding/hex"
"errors"
"fmt"
"math"
"slices"
"strconv"
"strings"
@ -82,7 +81,7 @@ func decodeNaN16(f func(b []byte) float64, nan ...uint16) func(b []byte) float64
return func(b []byte) float64 {
u := binary.BigEndian.Uint16(b)
if slices.Contains(nan, u) {
return math.NaN()
return 0
}
return f(b)
}
@ -92,7 +91,7 @@ func decodeNaN32(f func(b []byte) float64, nan ...uint32) func(b []byte) float64
return func(b []byte) float64 {
u := binary.BigEndian.Uint32(b)
if slices.Contains(nan, u) {
return math.NaN()
return 0
}
return f(b)
}
@ -102,7 +101,7 @@ func decodeNaN64(f func(b []byte) float64, nan ...uint64) func(b []byte) float64
return func(b []byte) float64 {
u := binary.BigEndian.Uint64(b)
if slices.Contains(nan, u) {
return math.NaN()
return 0
}
return f(b)
}

View file

@ -249,8 +249,7 @@ func (r Register) Operation() (RegisterOperation, error) {
func asFloat64[T constraints.Signed | constraints.Unsigned | constraints.Float](f func([]byte) T) func([]byte) float64 {
return func(v []byte) float64 {
res := float64(f(v))
// keep NaN so callers can map it to "not available"; sanitize Inf to 0
if math.IsInf(res, 0) {
if math.IsNaN(res) || math.IsInf(res, 0) {
res = 0
}
return res

View file

@ -71,13 +71,10 @@ func TestDecoding(t *testing.T) {
out float64
}{
{Register{Decode: "float32"}, []byte{0x4b, 0x3c, 0x61, 0x4e}, 12345678},
{Register{Decode: "float32"}, []byte{0xff, 0xff, 0xff, 0x7f}, math.NaN()}, // IEEE NaN preserved
{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}, math.NaN()}, // IEEE NaN swapped preserved
{Register{Decode: "float32nans"}, []byte{0xff, 0xff, 0xff, 0x7f}, math.NaN()},
{Register{Decode: "uint16nan"}, []byte{0xff, 0xff}, math.NaN()},
{Register{Decode: "uint32nan"}, []byte{0xff, 0xff, 0xff, 0xff}, math.NaN()},
{Register{Decode: "uint64nan"}, []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, math.NaN()},
{Register{Decode: "float32s"}, []byte{0xff, 0x7f, 0xff, 0xff}, 0}, // NaN swapped
{Register{Decode: "float32nans"}, []byte{0xff, 0xff, 0xff, 0x7f}, 0}, // NaN
{Register{Decode: "uint64"}, []byte{0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01}, 0x0004000300020001},
{Register{Decode: "uint64s"}, []byte{0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01}, 0x0001000200030004},
}
@ -85,12 +82,6 @@ func TestDecoding(t *testing.T) {
for _, tc := range tc {
fun, err := tc.r.DecodeFunc()
require.NoError(t, err, tc)
out := fun(tc.in)
if math.IsNaN(tc.out) {
require.True(t, math.IsNaN(out), tc)
continue
}
require.Equal(t, tc.out, out, tc)
require.Equal(t, tc.out, fun(tc.in), tc)
}
}