Modbus: add bool16 type and supporting bitmask (#2196)
This commit is contained in:
parent
3bac55c494
commit
20a8acb365
2 changed files with 54 additions and 1 deletions
|
|
@ -1,6 +1,12 @@
|
|||
package modbus
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ReadingName formats MBMD reading names
|
||||
func ReadingName(val string) string {
|
||||
|
|
@ -9,3 +15,42 @@ func ReadingName(val string) string {
|
|||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// decodeMask converts a bit mask in decimal or hex format to uint64
|
||||
func decodeMask(mask string) (uint64, error) {
|
||||
mask = strings.ToLower(mask)
|
||||
|
||||
if strings.HasPrefix(mask, "0x") {
|
||||
if len(mask) < 3 {
|
||||
return 0, fmt.Errorf("invalid mask: %s", mask)
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(mask[2:])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid mask: %w", err)
|
||||
}
|
||||
|
||||
var u uint64
|
||||
for _, v := range b {
|
||||
u = u<<8 | uint64(v)
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
return strconv.ParseUint(mask, 10, 64)
|
||||
}
|
||||
|
||||
// decodeBool16 converts a masked uint16 to a bool
|
||||
func decodeBool16(mask uint64) func(b []byte) float64 {
|
||||
return func(b []byte) float64 {
|
||||
u := binary.BigEndian.Uint16(b)
|
||||
if mask > 0 {
|
||||
u = u & uint16(mask)
|
||||
}
|
||||
if u > 0 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ type Register struct {
|
|||
Address uint16 // Length uint16
|
||||
Type string
|
||||
Decode string
|
||||
BitMask string
|
||||
}
|
||||
|
||||
// RegisterOperation creates a read operation from a register definition
|
||||
|
|
@ -288,6 +289,13 @@ func RegisterOperation(r Register) (rs485.Operation, error) {
|
|||
op.Transform = rs485.RTUInt32ToFloat64
|
||||
case "int32s":
|
||||
op.Transform = rs485.RTUInt32ToFloat64Swapped
|
||||
case "bool16":
|
||||
mask, err := decodeMask(r.BitMask)
|
||||
if err != nil {
|
||||
return op, err
|
||||
}
|
||||
op.Transform = decodeBool16(mask)
|
||||
op.ReadLen = 1
|
||||
default:
|
||||
return rs485.Operation{}, fmt.Errorf("invalid register decoding: %s", r.Decode)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue