From 10b76fbb314fcc832b2120b47379219f7faf8793 Mon Sep 17 00:00:00 2001 From: Holger Friedrich Date: Sun, 25 Feb 2024 11:59:19 +0100 Subject: [PATCH] [knx] Fix DPT 6.020 and 8.010 (#16453) Signed-off-by: Holger Friedrich Signed-off-by: Ciprian Pascu --- .../binding/knx/internal/dpt/DPTUtil.java | 2 +- .../knx/internal/dpt/ValueDecoder.java | 6 ++++++ .../knx/internal/dpt/ValueEncoder.java | 8 +++++++ .../binding/knx/internal/dpt/DPTTest.java | 21 +++++++++++++++++++ .../knx/internal/itests/Back2BackTest.java | 6 +++++- 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/DPTUtil.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/DPTUtil.java index c3c7479e377..27ec1f3e87c 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/DPTUtil.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/DPTUtil.java @@ -64,7 +64,7 @@ public class DPTUtil { Map.entry("3", Set.of(IncreaseDecreaseType.class)), // Map.entry("4", Set.of(StringType.class)), // Map.entry("5", Set.of(QuantityType.class, DecimalType.class)), // - Map.entry("6", Set.of(QuantityType.class, DecimalType.class)), // + Map.entry("6", Set.of(QuantityType.class, DecimalType.class, StringType.class)), // Map.entry("7", Set.of(QuantityType.class, DecimalType.class)), // Map.entry("8", Set.of(QuantityType.class, DecimalType.class)), // Map.entry("9", Set.of(QuantityType.class, DecimalType.class)), // diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueDecoder.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueDecoder.java index ad6cb704e35..13376f1d2f9 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueDecoder.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueDecoder.java @@ -174,6 +174,12 @@ public class ValueDecoder { return new DecimalType(decValue); case "3": return handleDpt3(subType, translator); + case "6": + if ("020".equals(subType)) { + return handleStringOrDecimal(data, value, preferredType, 8); + } else { + return handleNumericDpt(id, translator, preferredType); + } case "10": return handleDpt10(value); case "11": diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueEncoder.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueEncoder.java index 582a57d561f..232d4b85242 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueEncoder.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueEncoder.java @@ -274,6 +274,14 @@ public class ValueEncoder { } else { return "activate " + intVal; } + case "8": + if ("8.010".equals(dptId)) { + // 8.010 has a resolution of 0.01 and will be scaled. Calimero expects locale-specific separator. + return bigDecimal.stripTrailingZeros().toPlainString().replace('.', + ((DecimalFormat) DecimalFormat.getInstance()).getDecimalFormatSymbols() + .getDecimalSeparator()); + } + // fallthrough default: return bigDecimal.stripTrailingZeros().toPlainString(); } diff --git a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/DPTTest.java b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/DPTTest.java index 45ce5f8521b..d20b5504724 100644 --- a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/DPTTest.java +++ b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/DPTTest.java @@ -14,6 +14,7 @@ package org.openhab.binding.knx.internal.dpt; import static org.junit.jupiter.api.Assertions.*; +import java.text.DecimalFormat; import java.util.Map; import java.util.Objects; import java.util.regex.Matcher; @@ -29,6 +30,7 @@ import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.types.StringType; import org.openhab.core.library.unit.SIUnits; import org.openhab.core.library.unit.Units; import org.openhab.core.util.ColorUtil; @@ -95,6 +97,12 @@ class DPTTest { assertEquals("1", ValueEncoder.encode(new QuantityType<>("1000 ms"), "8.005")); assertEquals("1", ValueEncoder.encode(new QuantityType<>("60 s"), "8.006")); assertEquals("1", ValueEncoder.encode(new QuantityType<>("60 min"), "8.007")); + // 8.010 has a resolution of 0.01 and will be scaled. Calimero expects locale-specific separator. + String target = "-327.68".replace('.', + ((DecimalFormat) DecimalFormat.getInstance()).getDecimalFormatSymbols().getDecimalSeparator()); + assertEquals(target, ValueEncoder.encode(new QuantityType<>("-327.68 %"), "8.010")); + assertEquals("-327.68 %", Objects + .toString(ValueDecoder.decode("8.010", new byte[] { (byte) 0x80, (byte) 0x00 }, QuantityType.class))); assertEquals("180", ValueEncoder.encode(new QuantityType<>("180 °"), "8.011")); assertEquals("1000", ValueEncoder.encode(new QuantityType<>("1 km"), "8.012")); @@ -298,6 +306,19 @@ class DPTTest { assertEquals("42", ValueEncoder.encode(new QuantityType<>("42 varh"), "29.012")); } + @Test + public void dpt6Value() { + assertEquals("42", ValueEncoder.encode(new DecimalType(42), "6.001")); + + assertEquals("42", ValueEncoder.encode(new DecimalType(42), "6.010")); + + assertEquals("0/0/0/0/1 0", Objects.toString(ValueDecoder.decode("6.020", new byte[] { 9 }, StringType.class))); + assertEquals("0/0/0/0/0 1", Objects.toString(ValueDecoder.decode("6.020", new byte[] { 2 }, StringType.class))); + assertEquals("1/1/1/1/1 2", + Objects.toString(ValueDecoder.decode("6.020", new byte[] { (byte) 0xfc }, StringType.class))); + assertEquals("0/0/0/0/1 0", ValueEncoder.encode(StringType.valueOf("0/0/0/0/1 0"), "6.020")); + } + @Test public void dpt232RgbValue() { // input data diff --git a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/itests/Back2BackTest.java b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/itests/Back2BackTest.java index 00e12f857cb..48424413d3e 100644 --- a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/itests/Back2BackTest.java +++ b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/itests/Back2BackTest.java @@ -365,6 +365,8 @@ public class Back2BackTest { helper("6.010", new byte[] { 0 }, new DecimalType(0)); helper("6.010", new byte[] { (byte) 0x7f }, new DecimalType(127)); helper("6.010", new byte[] { (byte) 0xff }, new DecimalType(-1)); + + helper("6.020", new byte[] { 9 }, StringType.valueOf("0/0/0/0/1 0")); } @Test @@ -437,6 +439,7 @@ public class Back2BackTest { helper("8.007", new byte[] { (byte) 0x7f, (byte) 0xff }, new QuantityType<>("32767 h")); helper("8.007", new byte[] { (byte) 0x00, (byte) 0x00 }, new QuantityType<>("0 h")); + helper("8.010", new byte[] { (byte) 0x80, (byte) 0x00 }, new QuantityType<>("-327.68 %")); helper("8.011", new byte[] { (byte) 0x80, (byte) 0x00 }, new QuantityType<>("-32768 °")); helper("8.011", new byte[] { (byte) 0x7f, (byte) 0xff }, new QuantityType<>("32767 °")); helper("8.011", new byte[] { (byte) 0x00, (byte) 0x00 }, new QuantityType<>("0 °")); @@ -472,10 +475,10 @@ public class Back2BackTest { helper("9.004", new byte[] { (byte) 0x07, (byte) 0xff }, new QuantityType<>("20.47 lx")); helper("9.004", new byte[] { (byte) 0x7f, (byte) 0xfe }, new QuantityType<>("670433.28 lx")); helper("9.004", new byte[] { (byte) 0x00, (byte) 0x00 }, new QuantityType<>("0 lx")); + // no negative values allowed for DPTs 9.004-9.008 helper("9.005", new byte[] { (byte) 0x07, (byte) 0xff }, new QuantityType<>("20.47 m/s")); helper("9.005", new byte[] { (byte) 0x7f, (byte) 0xfe }, new QuantityType<>("670433.28 m/s")); helper("9.005", new byte[] { (byte) 0x00, (byte) 0x00 }, new QuantityType<>("0 m/s")); - // no negative values allowed for DPTs 9.005-9.008 helper("9.005", new byte[] { (byte) 0x07, (byte) 0xff }, new QuantityType<>("20.47 m/s")); helper("9.005", new byte[] { (byte) 0x7f, (byte) 0xfe }, new QuantityType<>("670433.28 m/s")); helper("9.005", new byte[] { (byte) 0x00, (byte) 0x00 }, new QuantityType<>("0 m/s")); @@ -804,6 +807,7 @@ public class Back2BackTest { new DateTimeType("2019-07-15T17:30:00"), new byte[0], new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }); helper("19.001", new byte[] { (byte) (2019 - 1900), 7, 15, 17, 30, 0, (byte) 0x24, (byte) 0x00 }, new DateTimeType("2019-07-15T17:30:00"), new byte[0], new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }); + // TODO add tests for incompletly filled frames (e.g. containing only date or time) } @Test