This commit is contained in:
Martino Ferrari
2026-06-24 01:39:15 +02:00
parent 11120bedca
commit c0f7e662be
76 changed files with 4368 additions and 210 deletions
+13 -13
View File
@@ -218,19 +218,19 @@ func DecodeTimeValue(dbrType uint16, count uint32, payload []byte) (TimeValue, b
// CtrlDouble is the decoded form of a DBR_CTRL_DOUBLE payload.
type CtrlDouble struct {
Status int16
Severity AlarmSeverity
Precision int16
Units string
UpperDispLimit float64
LowerDispLimit float64
UpperAlarmLimit float64
UpperWarnLimit float64
LowerWarnLimit float64
LowerAlarmLimit float64
UpperCtrlLimit float64
LowerCtrlLimit float64
Value float64
Status int16
Severity AlarmSeverity
Precision int16
Units string
UpperDispLimit float64
LowerDispLimit float64
UpperAlarmLimit float64
UpperWarnLimit float64
LowerWarnLimit float64
LowerAlarmLimit float64
UpperCtrlLimit float64
LowerCtrlLimit float64
Value float64
}
// DecodeCtrlDouble decodes a DBR_CTRL_DOUBLE payload (minimum 88 bytes).
+2 -2
View File
@@ -31,8 +31,8 @@ const DefaultPort = 5064
// Search reply data_type values.
const (
SearchReply = 10 // DO_REPLY: ask server to respond
SearchNoReply = 5 // DONT_REPLY: suppress response (used by repeater)
SearchReply = 10 // DO_REPLY: ask server to respond
SearchNoReply = 5 // DONT_REPLY: suppress response (used by repeater)
)
// AccessRights bitmask values (parameter2 of CmdAccessRights message).
+163
View File
@@ -0,0 +1,163 @@
package proto_test
import (
"bytes"
"encoding/binary"
"math"
"testing"
"github.com/uopi/goca/proto"
)
// -------------------------------------------------------------------------- //
// DBR_TIME_* variants not covered by proto_test.go //
// -------------------------------------------------------------------------- //
func TestDecodeTimeFloat(t *testing.T) {
hdr := buildTimeHeader(0, 0, 0, 0)
val := make([]byte, 4)
binary.BigEndian.PutUint32(val, math.Float32bits(2.5))
tv, ok := proto.DecodeTimeValue(proto.DBRTimeFloat, 1, append(hdr, val...))
if !ok || math.Abs(float64(tv.Float)-2.5) > 1e-6 {
t.Errorf("float: ok=%v Float=%g", ok, tv.Float)
}
}
func TestDecodeTimeShort(t *testing.T) {
hdr := buildTimeHeader(0, 0, 0, 0)
val := []byte{0x00, 0x00, 0xFF, 0xD6} // 2-byte pad + int16(-42)
tv, ok := proto.DecodeTimeValue(proto.DBRTimeShort, 1, append(hdr, val...))
if !ok || tv.Short != -42 {
t.Errorf("short: ok=%v Short=%d", ok, tv.Short)
}
}
func TestDecodeTimeChar(t *testing.T) {
hdr := buildTimeHeader(0, 0, 0, 0)
val := []byte{0x00, 0x00, 0x00, 0x41} // pad0 + pad1 + value 'A'
tv, ok := proto.DecodeTimeValue(proto.DBRTimeChar, 1, append(hdr, val...))
if !ok || tv.Char != 0x41 {
t.Errorf("char: ok=%v Char=%d", ok, tv.Char)
}
}
func TestDecodeTimeUnknownType(t *testing.T) {
hdr := buildTimeHeader(0, 0, 0, 0)
if _, ok := proto.DecodeTimeValue(9999, 1, append(hdr, make([]byte, 16)...)); ok {
t.Error("unknown DBR type should return false")
}
}
// -------------------------------------------------------------------------- //
// DBR_CTRL_LONG / DBR_CTRL_STRING //
// -------------------------------------------------------------------------- //
func TestDecodeCtrlLong(t *testing.T) {
p := make([]byte, 48)
binary.BigEndian.PutUint16(p[2:], 2) // severity = Major
copy(p[4:], "counts")
i32 := func(off int, v int32) { binary.BigEndian.PutUint32(p[off:], uint32(v)) }
i32(12, 1000) // upper_disp
i32(16, -10) // lower_disp
i32(44, 777) // value
cl, ok := proto.DecodeCtrlLong(p)
if !ok {
t.Fatal("DecodeCtrlLong returned false")
}
if cl.Units != "counts" || cl.Value != 777 || cl.UpperDispLimit != 1000 || cl.LowerDispLimit != -10 {
t.Errorf("got %+v", cl)
}
if cl.Severity != proto.SeverityMajor {
t.Errorf("severity = %v, want Major", cl.Severity)
}
if _, ok := proto.DecodeCtrlLong(make([]byte, 10)); ok {
t.Error("short CtrlLong payload should return false")
}
}
func TestDecodeCtrlString(t *testing.T) {
p := make([]byte, 44)
binary.BigEndian.PutUint16(p[2:], 1) // severity = Minor
copy(p[4:], "READY")
cs, ok := proto.DecodeCtrlString(p)
if !ok {
t.Fatal("DecodeCtrlString returned false")
}
if cs.Value != "READY" || cs.Severity != proto.SeverityMinor {
t.Errorf("got %+v", cs)
}
if _, ok := proto.DecodeCtrlString(make([]byte, 10)); ok {
t.Error("short CtrlString payload should return false")
}
}
// -------------------------------------------------------------------------- //
// EncodeShort //
// -------------------------------------------------------------------------- //
func TestEncodeShort(t *testing.T) {
b := proto.EncodeShort(-7)
if len(b) != 8 {
t.Fatalf("len = %d, want 8", len(b))
}
if got := int16(binary.BigEndian.Uint16(b)); got != -7 {
t.Errorf("decoded = %d, want -7", got)
}
}
// -------------------------------------------------------------------------- //
// NativeCtrlType //
// -------------------------------------------------------------------------- //
func TestNativeCtrlType(t *testing.T) {
cases := []struct {
dbf int
want uint16
}{
{proto.DBFDouble, proto.DBRCtrlDouble},
{proto.DBFFloat, proto.DBRCtrlDouble},
{proto.DBFLong, proto.DBRCtrlLong},
{proto.DBFShort, proto.DBRCtrlLong},
{proto.DBFChar, proto.DBRCtrlLong},
{proto.DBFEnum, proto.DBRCtrlEnum},
{proto.DBFString, proto.DBRCtrlString},
{9999, proto.DBRCtrlDouble}, // default
}
for _, c := range cases {
if got := proto.NativeCtrlType(c.dbf); got != c.want {
t.Errorf("NativeCtrlType(%d) = %d, want %d", c.dbf, got, c.want)
}
}
}
// -------------------------------------------------------------------------- //
// DecodeHeader: extended encoding + error path //
// -------------------------------------------------------------------------- //
func TestDecodeHeaderExtended(t *testing.T) {
raw := make([]byte, 24)
binary.BigEndian.PutUint16(raw[0:], proto.CmdReadNotify)
binary.BigEndian.PutUint16(raw[2:], 0xFFFF) // extended marker
binary.BigEndian.PutUint16(raw[6:], 0x0000)
binary.BigEndian.PutUint32(raw[16:], 70000) // real payload size
binary.BigEndian.PutUint32(raw[20:], 5) // real count
h, n, err := proto.DecodeHeader(bytes.NewReader(raw))
if err != nil {
t.Fatal(err)
}
if n != 24 {
t.Errorf("bytes read = %d, want 24", n)
}
if h.PayloadSize != 70000 || h.DataCount != 5 {
t.Errorf("extended header = %+v", h)
}
}
func TestDecodeHeaderTruncated(t *testing.T) {
if _, _, err := proto.DecodeHeader(bytes.NewReader([]byte{0x00, 0x01})); err == nil {
t.Error("truncated header: want error")
}
}
+1 -1
View File
@@ -102,7 +102,7 @@ func TestDecodeTimeDouble(t *testing.T) {
const want = 3.14159
hdr := buildTimeHeader(0, 0, sec, nsec)
pad := make([]byte, 4) // RISC pad
pad := make([]byte, 4) // RISC pad
val := make([]byte, 8)
binary.BigEndian.PutUint64(val, math.Float64bits(want))
payload := append(append(hdr, pad...), val...)