diff --git a/knx/dpt/formats.go b/knx/dpt/formats.go index cdc43d2..12b549e 100644 --- a/knx/dpt/formats.go +++ b/knx/dpt/formats.go @@ -208,6 +208,26 @@ func unpackV8(data []byte, i *int8) error { return nil } +func packV16(i int16) []byte { + b := make([]byte, 3) + + b[0] = 0 + b[1] = byte((i >> 8) & 0xff) + b[2] = byte(i & 0xff) + + return b +} + +func unpackV16(data []byte, i *int16) error { + if len(data) != 3 { + return ErrInvalidLength + } + + *i = int16(data[1])<<8 | int16(data[2]) + + return nil +} + func packV32(i int32) []byte { b := make([]byte, 5) diff --git a/knx/dpt/types_8.go b/knx/dpt/types_8.go new file mode 100644 index 0000000..b925ca9 --- /dev/null +++ b/knx/dpt/types_8.go @@ -0,0 +1,203 @@ +// Copyright 2017 Ole Krüger. +// Licensed under the MIT license which can be found in the LICENSE file. + +package dpt + +import ( + "fmt" +) + +// DPT_8001 represents DPT 8.001 / Counter. +type DPT_8001 int16 + +func (d DPT_8001) Pack() []byte { + return packV16(int16(d)) +} + +func (d *DPT_8001) Unpack(data []byte) error { + return unpackV16(data, (*int16)(d)) +} + +func (d DPT_8001) Unit() string { + return "pulses" +} + +func (d DPT_8001) String() string { + return fmt.Sprintf("%d pulses", int16(d)) +} + +// DPT_8002 represents DPT 8.002 / delta time ms. +type DPT_8002 int16 + +func (d DPT_8002) Pack() []byte { + return packV16(int16(d)) +} + +func (d *DPT_8002) Unpack(data []byte) error { + return unpackV16(data, (*int16)(d)) +} + +func (d DPT_8002) Unit() string { + return "ms" +} + +func (d DPT_8002) String() string { + return fmt.Sprintf("%d ms", int16(d)) +} + +// DPT_8003 represents DPT 8.003 / delta time ms (range -327.68 s ... 327.67 s) +type DPT_8003 float32 + +func (d DPT_8003) Pack() []byte { + return packV16(int16(d * 100)) +} + +func (d *DPT_8003) Unpack(data []byte) error { + var value int16 + + if err := unpackV16(data, &value); err != nil { + return err + } + + *d = DPT_8003(float32(value) / 100) + + return nil +} + +func (d DPT_8003) Unit() string { + return "ms" +} + +func (d DPT_8003) String() string { + return fmt.Sprintf("%f ms", d) +} + +// DPT_8004 represents DPT 8.004 / delta time ms (range -3276.8 s ... 3276.7 s) +type DPT_8004 float32 + +func (d DPT_8004) Pack() []byte { + return packV16(int16(d * 10)) +} + +func (d *DPT_8004) Unpack(data []byte) error { + var value int16 + + if err := unpackV16(data, &value); err != nil { + return err + } + + *d = DPT_8004(float32(value) / 10) + + return nil +} + +func (d DPT_8004) Unit() string { + return "ms" +} + +func (d DPT_8004) String() string { + return fmt.Sprintf("%f ms", d) +} + +// DPT_8005 represents DPT 8.005 / delta time seconds +type DPT_8005 int16 + +func (d DPT_8005) Pack() []byte { + return packV16(int16(d)) +} + +func (d *DPT_8005) Unpack(data []byte) error { + return unpackV16(data, (*int16)(d)) +} + +func (d DPT_8005) Unit() string { + return "s" +} + +func (d DPT_8005) String() string { + return fmt.Sprintf("%d s", int16(d)) +} + +// DPT_8006 represents DPT 8.006 / delta time minutes +type DPT_8006 int16 + +func (d DPT_8006) Pack() []byte { + return packV16(int16(d)) +} + +func (d *DPT_8006) Unpack(data []byte) error { + return unpackV16(data, (*int16)(d)) +} + +func (d DPT_8006) Unit() string { + return "min" +} + +func (d DPT_8006) String() string { + return fmt.Sprintf("%d min", int16(d)) +} + +// DPT_8007 represents DPT 8.007 / delta time hours +type DPT_8007 int16 + +func (d DPT_8007) Pack() []byte { + return packV16(int16(d)) +} + +func (d *DPT_8007) Unpack(data []byte) error { + return unpackV16(data, (*int16)(d)) +} + +func (d DPT_8007) Unit() string { + return "h" +} + +func (d DPT_8007) String() string { + return fmt.Sprintf("%d h", int16(d)) +} + +// DPT_8010 represents DPT 8.010 / percentage difference +type DPT_8010 float32 + +func (d DPT_8010) Pack() []byte { + return packV16(int16(d * 100)) +} + +func (d *DPT_8010) Unpack(data []byte) error { + var value int16 + + if err := unpackV16(data, &value); err != nil { + return err + } + + *d = DPT_8010(float32(value) / 100) + + return nil +} + +func (d DPT_8010) Unit() string { + return "%" +} + +func (d DPT_8010) String() string { + return fmt.Sprintf("%f %%", d) +} + +// DPT_8011 represents DPT 8.011 / Rotation angle °. +type DPT_8011 int16 + +func (d DPT_8011) Pack() []byte { + return packV16(int16(d)) +} + +func (d *DPT_8011) Unpack(data []byte) error { + return unpackV16(data, (*int16)(d)) +} + +func (d DPT_8011) Unit() string { + return "°" +} + +func (d DPT_8011) String() string { + return fmt.Sprintf("%d °", int16(d)) +} diff --git a/knx/dpt/types_8_test.go b/knx/dpt/types_8_test.go new file mode 100644 index 0000000..aea66fa --- /dev/null +++ b/knx/dpt/types_8_test.go @@ -0,0 +1,207 @@ +// Copyright 2017 Ole Krüger. +// Licensed under the MIT license which can be found in the LICENSE file. + +package dpt + +import ( + "testing" + + "math" + "math/rand" +) + +// Test DPT 8.001 with values within range +func TestDPT_8001(t *testing.T) { + var buf []byte + var src, dst DPT_8001 + + for i := 1; i <= 10; i++ { + value := int16(rand.Uint32() % math.MaxInt16) + + // Pack and unpack to test value + src = DPT_8001(value) + if int16(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8001! Has value \"%s\".", value, src) + } + buf = src.Pack() + dst.Unpack(buf) + if int16(dst) != value { + t.Errorf("Value \"%s\" after pack/unpack different from Original value. Was \"%v\"", dst, value) + } + } +} + +// Test DPT 8.002 with values within range +func TestDPT_8002(t *testing.T) { + var buf []byte + var src, dst DPT_8002 + + for i := 1; i <= 10; i++ { + value := int16(rand.Uint32() % math.MaxInt16) + + // Pack and unpack to test value + src = DPT_8002(value) + if int16(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8002! Has value \"%s\".", value, src) + } + buf = src.Pack() + dst.Unpack(buf) + if int16(dst) != value { + t.Errorf("Value \"%s\" after pack/unpack different from Original value. Was \"%v\"", dst, value) + } + } +} + +// Test DPT 8.003 with values within range +func TestDPT_8003(t *testing.T) { + var buf []byte + var src, dst DPT_8003 + + for i := 1; i <= 10; i++ { + value := float32(int16(rand.Int31())) / 100 + + // Pack and unpack to test value + src = DPT_8003(value) + + if float32(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8003! Has value \"%s\".", value, src) + } + + buf = src.Pack() + dst.Unpack(buf) + + if abs(float32(dst)-value) > 0.01 { + t.Errorf("Value \"%s\" after pack/unpack different from original value. Was \"%s\"", dst, src) + } + } +} + +// Test DPT 8.004 with values within range +func TestDPT_8004(t *testing.T) { + var buf []byte + var src, dst DPT_8004 + + for i := 1; i <= 10; i++ { + value := float32(int16(rand.Int31())) / 10 + + // Pack and unpack to test value + src = DPT_8004(value) + if float32(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8004! Has value \"%s\".", value, src) + } + + buf = src.Pack() + dst.Unpack(buf) + + if abs(float32(dst)-value) > 0.1 { + t.Errorf("Value \"%s\" after pack/unpack different from original value. Was \"%s\"", dst, src) + } + } +} + +// Test DPT 8.005 with values within range +func TestDPT_8005(t *testing.T) { + var buf []byte + var src, dst DPT_8005 + + for i := 1; i <= 10; i++ { + value := int16(rand.Uint32() % math.MaxInt16) + + // Pack and unpack to test value + src = DPT_8005(value) + if int16(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8005! Has value \"%s\".", value, src) + } + buf = src.Pack() + dst.Unpack(buf) + if int16(dst) != value { + t.Errorf("Value \"%s\" after pack/unpack different from Original value. Was \"%v\"", dst, value) + } + } +} + +// Test DPT 8.006 with values within range +func TestDPT_8006(t *testing.T) { + var buf []byte + var src, dst DPT_8006 + + for i := 1; i <= 10; i++ { + value := int16(rand.Uint32() % math.MaxInt16) + + // Pack and unpack to test value + src = DPT_8006(value) + if int16(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8006! Has value \"%s\".", value, src) + } + buf = src.Pack() + dst.Unpack(buf) + if int16(dst) != value { + t.Errorf("Value \"%s\" after pack/unpack different from Original value. Was \"%v\"", dst, value) + } + } +} + +// Test DPT 8.007 with values within range +func TestDPT_8007(t *testing.T) { + var buf []byte + var src, dst DPT_8007 + + for i := 1; i <= 10; i++ { + value := int16(rand.Uint32() % math.MaxInt16) + + // Pack and unpack to test value + src = DPT_8007(value) + if int16(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8007! Has value \"%s\".", value, src) + } + buf = src.Pack() + dst.Unpack(buf) + if int16(dst) != value { + t.Errorf("Value \"%s\" after pack/unpack different from Original value. Was \"%v\"", dst, value) + } + } +} + +// Test DPT 8.010 with values within range +func TestDPT_8010(t *testing.T) { + var buf []byte + var src, dst DPT_8010 + + for i := 1; i <= 10; i++ { + value := float32(int16(rand.Int31())) / 100 + + // Pack and unpack to test value + src = DPT_8010(value) + if float32(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8010! Has value \"%s\".", value, src) + } + + buf = src.Pack() + dst.Unpack(buf) + + if abs(float32(dst)-value) > 0.01 { + t.Errorf("Value \"%s\" after pack/unpack different from original value. Was \"%s\"", dst, src) + } + } +} + +// Test DPT 8.011 (°) with values within range +func TestDPT_8011(t *testing.T) { + var buf []byte + var src, dst DPT_8011 + + for i := 1; i <= 10; i++ { + value := int16(rand.Uint32() % math.MaxInt16) + + // Pack and unpack to test value + src = DPT_8011(value) + if int16(src) != value { + t.Errorf("Assignment of value \"%v\" failed for source of type DPT_8011! Has value \"%s\".", value, src) + } + buf = src.Pack() + dst.Unpack(buf) + if int16(dst) != value { + t.Errorf("Value \"%s\" after pack/unpack different from Original value. Was \"%v\"", dst, value) + } + } +} diff --git a/knx/dpt/types_registry.go b/knx/dpt/types_registry.go index 4ffb97d..71afa3a 100644 --- a/knx/dpt/types_registry.go +++ b/knx/dpt/types_registry.go @@ -58,6 +58,17 @@ var dptTypes = map[string]Datapoint{ "7.013": new(DPT_7013), "7.600": new(DPT_7600), + // 8.xxx + "8.001": new(DPT_8001), + "8.002": new(DPT_8002), + "8.003": new(DPT_8003), + "8.004": new(DPT_8004), + "8.005": new(DPT_8005), + "8.006": new(DPT_8006), + "8.007": new(DPT_8007), + "8.010": new(DPT_8010), + "8.011": new(DPT_8011), + // 9.xxx "9.001": new(DPT_9001), "9.002": new(DPT_9002),