]> git.basschouten.com Git - openhab-addons.git/commitdiff
[knx] Code rework (#17420)
authorHolger Friedrich <mail@holger-friedrich.de>
Sun, 15 Sep 2024 20:48:34 +0000 (22:48 +0200)
committerGitHub <noreply@github.com>
Sun, 15 Sep 2024 20:48:34 +0000 (22:48 +0200)
* [knx] Code rework

Signed-off-by: Holger Friedrich <mail@holger-friedrich.de>
24 files changed:
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannel.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelFactory.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeColor.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDimmer.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInspector.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/InboundSpec.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/SerialClient.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/SerialTransportAdapter.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/console/KNXCommandExtension.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/DPTUnits.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/DPTUtil.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueDecoder.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/ValueEncoder.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/KNXBridgeBaseThingHandler.java
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/i18n/KNXTranslationProvider.java
bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelFactoryTest.java
bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/client/DummyClient.java [deleted file]
bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/DPTTest.java
bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/handler/KNXBridgeBaseThingHandlerTest.java
bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/itests/Back2BackTest.java
bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/security/KNXSecurityTest.java

index b08a309203c3913037e5829e2d7463b2b0988639..52efb9da8c6a0c780901175ac96a851f8f5bc31a 100644 (file)
@@ -131,7 +131,7 @@ public abstract class KNXChannel {
                 return new WriteSpecImpl(entry.getValue(), dpt, command);
             }
         }
-        // if we didn't find a match, check if we find a sub-type match
+        // if we didn't find a match, check if we find a subtype match
         for (Map.Entry<String, GroupAddressConfiguration> entry : groupAddressConfigurations.entrySet()) {
             String dpt = Objects.requireNonNullElse(entry.getValue().getDPT(), getDefaultDPT(entry.getKey()));
             Set<Class<? extends Type>> expectedTypeClasses = DPTUtil.getAllowedTypes(dpt);
index 0d51d174f440d025bbd3f6797e4c9cf6b546ae08..0e235e6745cb8fcb47eb3feda648ea9ae315d3cb 100644 (file)
@@ -56,7 +56,7 @@ public final class KNXChannelFactory {
                 .map(Map.Entry::getValue).findFirst()
                 .orElseThrow(() -> new IllegalArgumentException(channelTypeUID + " is not a valid channel type ID"));
 
-        // typecast to avoid warning about unsafe return type; we know that the lookup returns non null values
+        // typecast to avoid warning about unsafe return type; we know that the lookup returns non-null values
         return (KNXChannel) supplier.apply(channel);
     }
 }
index 07f2599f6af13d50611683d7d04cc69f16f25f66..8a3a872a35e36584176115dee21b046a6fc440f7 100644 (file)
@@ -46,18 +46,12 @@ class TypeColor extends KNXChannel {
 
     @Override
     protected String getDefaultDPT(String gaConfigKey) {
-        if (gaConfigKey.equals(HSB_GA)) {
-            return DPTXlatorRGB.DPT_RGB.getID();
-        }
-        if (gaConfigKey.equals(INCREASE_DECREASE_GA)) {
-            return DPTXlator3BitControlled.DPT_CONTROL_DIMMING.getID();
-        }
-        if (gaConfigKey.equals(SWITCH_GA)) {
-            return DPTXlatorBoolean.DPT_SWITCH.getID();
-        }
-        if (gaConfigKey.equals(POSITION_GA)) {
-            return DPTXlator8BitUnsigned.DPT_SCALING.getID();
-        }
-        throw new IllegalArgumentException("GA configuration '" + gaConfigKey + "' is not supported");
+        return switch (gaConfigKey) {
+            case HSB_GA -> DPTXlatorRGB.DPT_RGB.getID();
+            case INCREASE_DECREASE_GA -> DPTXlator3BitControlled.DPT_CONTROL_DIMMING.getID();
+            case SWITCH_GA -> DPTXlatorBoolean.DPT_SWITCH.getID();
+            case POSITION_GA -> DPTXlator8BitUnsigned.DPT_SCALING.getID();
+            default -> throw new IllegalArgumentException("GA configuration '" + gaConfigKey + "' is not supported");
+        };
     }
 }
index edf20832708ede8597b3ca8ff7ae4a1c5dd7b9a1..b9c994d6fb62364c53f41b024bd888af8a474d25 100644 (file)
@@ -15,7 +15,6 @@ package org.openhab.binding.knx.internal.channel;
 import static org.openhab.binding.knx.internal.KNXBindingConstants.*;
 
 import java.util.List;
-import java.util.Objects;
 import java.util.Set;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -45,15 +44,11 @@ class TypeDimmer extends KNXChannel {
 
     @Override
     protected String getDefaultDPT(String gaConfigKey) {
-        if (Objects.equals(gaConfigKey, INCREASE_DECREASE_GA)) {
-            return DPTXlator3BitControlled.DPT_CONTROL_DIMMING.getID();
-        }
-        if (Objects.equals(gaConfigKey, SWITCH_GA)) {
-            return DPTXlatorBoolean.DPT_SWITCH.getID();
-        }
-        if (Objects.equals(gaConfigKey, POSITION_GA)) {
-            return DPTXlator8BitUnsigned.DPT_SCALING.getID();
-        }
-        throw new IllegalArgumentException("GA configuration '" + gaConfigKey + "' is not supported");
+        return switch (gaConfigKey) {
+            case INCREASE_DECREASE_GA -> DPTXlator3BitControlled.DPT_CONTROL_DIMMING.getID();
+            case SWITCH_GA -> DPTXlatorBoolean.DPT_SWITCH.getID();
+            case POSITION_GA -> DPTXlator8BitUnsigned.DPT_SCALING.getID();
+            default -> throw new IllegalArgumentException("GA configuration '" + gaConfigKey + "' is not supported");
+        };
     }
 }
index 50fdfc9b03b0dace97f16a966912d8b942031f45..d73b23ed8a5090a6bfac87dc69c38d21b521bf62 100644 (file)
@@ -15,7 +15,6 @@ package org.openhab.binding.knx.internal.channel;
 import static org.openhab.binding.knx.internal.KNXBindingConstants.*;
 
 import java.util.List;
-import java.util.Objects;
 import java.util.Set;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -45,15 +44,11 @@ class TypeRollershutter extends KNXChannel {
 
     @Override
     protected String getDefaultDPT(String gaConfigKey) {
-        if (Objects.equals(gaConfigKey, UP_DOWN_GA)) {
-            return DPTXlatorBoolean.DPT_UPDOWN.getID();
-        }
-        if (Objects.equals(gaConfigKey, STOP_MOVE_GA)) {
-            return DPTXlatorBoolean.DPT_START.getID();
-        }
-        if (Objects.equals(gaConfigKey, POSITION_GA)) {
-            return DPTXlator8BitUnsigned.DPT_SCALING.getID();
-        }
-        throw new IllegalArgumentException("GA configuration '" + gaConfigKey + "' is not supported");
+        return switch (gaConfigKey) {
+            case UP_DOWN_GA -> DPTXlatorBoolean.DPT_UPDOWN.getID();
+            case STOP_MOVE_GA -> DPTXlatorBoolean.DPT_START.getID();
+            case POSITION_GA -> DPTXlator8BitUnsigned.DPT_SCALING.getID();
+            default -> throw new IllegalArgumentException("GA configuration '" + gaConfigKey + "' is not supported");
+        };
     }
 }
index fd9a70f3a71060eaf93bce5d3e61577945e0b1e5..fc2a4c1775d9f55b6f252fc516f56350598af028 100644 (file)
@@ -234,7 +234,7 @@ public abstract class AbstractKNXClient implements NetworkLinkListener, KNXClien
             // Protected ctor using given ManagementClientImpl is available (custom class to be inherited)
             managementProcedures = new CustomManagementProceduresImpl(managementClient, tl);
 
-            // OH helper for reading device info, based on managementClient above
+            // OpenHab helper for reading device info, based on managementClient above
             deviceInfoClient = new DeviceInfoClientImpl(managementClient);
 
             // ProcessCommunicator provides main KNX communication (Calimero).
index 5781d1192bf8bf19d84ba59ef3302b6ba629d571..89938adefbbe9bb42613c074019347376e522fd8 100644 (file)
@@ -51,23 +51,7 @@ public class DeviceInspector {
     private final DeviceInfoClient client;
     private final IndividualAddress address;
 
-    public static class Result {
-        private final Map<String, String> properties;
-        private final Set<GroupAddress> groupAddresses;
-
-        public Result(Map<String, String> properties, Set<GroupAddress> groupAddresses) {
-            super();
-            this.properties = properties;
-            this.groupAddresses = groupAddresses;
-        }
-
-        public Map<String, String> getProperties() {
-            return properties;
-        }
-
-        public Set<GroupAddress> getGroupAddresses() {
-            return groupAddresses;
-        }
+    public record Result(Map<String, String> properties, Set<GroupAddress> groupAddresses) {
     }
 
     public DeviceInspector(DeviceInfoClient client, IndividualAddress address) {
@@ -114,7 +98,7 @@ public class DeviceInspector {
      *           task immediately on connection loss or thing deconstruction.
      *
      * @param address Individual address of KNX device
-     * @return List of device properties
+     * @return Map of device properties
      * @throws InterruptedException
      */
     private Map<String, String> readDeviceProperties(IndividualAddress address) throws InterruptedException {
@@ -179,7 +163,7 @@ public class DeviceInspector {
             if (!maxApdu.isEmpty()) {
                 logger.trace("Max APDU of device {} is {} bytes (routing)", address, maxApdu);
             } else {
-                // fallback: MAX_APDU_LENGTH; if availble set the default is 14 according to spec
+                // fallback: MAX_APDU_LENGTH; if available set the default is 14 according to spec
                 Thread.sleep(OPERATION_INTERVAL);
                 try {
                     byte[] result = getClient().readDeviceProperties(address, ADDRESS_TABLE_OBJECT,
@@ -247,7 +231,7 @@ public class DeviceInspector {
                         logger.debug("Identified device {} as \"{}\"", address, result);
                         ret.put(FRIENDLY_NAME, result);
                     } else {
-                        // this is due to devices which have a buggy implememtation (and show a broken string also
+                        // this is due to devices which have a buggy implementation (and show a broken string also
                         // in ETS tool)
                         logger.debug("Ignoring FRIENDLY_NAME of device {} as it contains non-printable characters",
                                 address);
@@ -288,7 +272,7 @@ public class DeviceInspector {
      *           Currently only data from DD0 is returned; DD2 is just logged in debug mode.
      *
      * @param address Individual address of KNX device
-     * @return List of device properties
+     * @return Map of device properties
      * @throws InterruptedException
      */
     private Map<String, String> readDeviceDescription(IndividualAddress address) throws InterruptedException {
@@ -315,7 +299,7 @@ public class DeviceInspector {
             if (data != null) {
                 try {
                     final DD2 dd = DeviceDescriptor.DD2.from(data);
-                    logger.debug("The device with address {} is has DD2 {}", address, dd.toString());
+                    logger.debug("The device with address {} is has DD2 {}", address, dd);
                 } catch (KNXIllegalArgumentException e) {
                     logger.warn("Can not parse device descriptor 2 of device with address {}: {}", address,
                             e.getMessage());
@@ -342,21 +326,14 @@ public class DeviceInspector {
     }
 
     private static String getMediumType(int type) {
-        switch (type) {
-            case 0:
-                return "TP";
-            case 1:
-                return "PL";
-            case 2:
-                return "RF";
-            case 3:
-                return "TP0 (deprecated)";
-            case 4:
-                return "PL123 (deprecated)";
-            case 5:
-                return "IP";
-            default:
-                return "unknown (" + type + ")";
-        }
+        return switch (type) {
+            case 0 -> "TP";
+            case 1 -> "PL";
+            case 2 -> "RF";
+            case 3 -> "TP0 (deprecated)";
+            case 4 -> "PL123 (deprecated)";
+            case 5 -> "IP";
+            default -> "unknown (" + type + ")";
+        };
     }
 }
index aabbc9cb358bb939447519d656fd404a3a86e544..8df8f75969ec69e50aeca47938be858daf9367dc 100644 (file)
@@ -37,7 +37,7 @@ public interface InboundSpec {
     /**
      * Get the affected group addresses.
      *
-     * @return a list of group addresses.
+     * @return a Set of group addresses.
      */
     Set<GroupAddress> getGroupAddresses();
 }
index 49d3e3306ed316a0875644d24afb43897595c024..e5213bd0903218feec11dbcb65c96d4fb634e899 100644 (file)
@@ -66,7 +66,7 @@ public class SerialClient extends AbstractKNXClient {
     /**
      * try automatic detection of cEMI devices via the PEI identification frame
      *
-     * @implNote This is based on an vendor specific extension and may not work for other devices.
+     * @implNote This is based on a vendor specific extension and may not work for other devices.
      */
     protected boolean detectCemi() throws InterruptedException {
         final byte[] peiIdentifyReqFrame = { (byte) 0xa7 };
index ef455e24b6fa787d93274c8f46b5e83fa69605da..c04a4a4aeceb40177ec26913a5c34c6f47340459 100644 (file)
@@ -42,7 +42,7 @@ import tuwien.auto.calimero.serial.spi.SerialCom;
  * {@literal @}ServiceProvider annotation (biz.aQute.bnd.annotation) automatically creates the file
  * /META-INF/services/tuwien.auto.calimero.serial.spi.SerialCom
  * to register SerialTransportAdapter to the service loader.
- * Additional attributes for SerialTansportAdapter can be specified as well, e.g.
+ * Additional attributes for SerialTransportAdapter can be specified as well, e.g.
  * attribute = { "position=1" }
  * and will be part of MANIFEST.MF
  * 
index 8968e1fe6c068e78450cfe6da410299cd0949b7b..fe1b6d2590cbd516820501803cfc9d2680637b32 100644 (file)
@@ -54,7 +54,7 @@ public class KNXCommandExtension extends AbstractConsoleCommandExtension impleme
         if (args.length == 1 && CMD_LIST_UNKNOWN_GA.equalsIgnoreCase(args[0])) {
             for (KNXBridgeBaseThingHandler bridgeHandler : knxHandlerFactory.getBridges()) {
                 console.println("KNX bridge \"" + bridgeHandler.getThing().getLabel()
-                        + "\": group address, type, number of bytes, and number of occurence since last reload of binding:");
+                        + "\": group address, type, number of bytes, and number of occurrence since last reload of binding:");
                 for (Entry<String, Long> entry : bridgeHandler.getCommandExtensionData().unknownGA().entrySet()) {
                     console.println(entry.getKey() + " " + entry.getValue());
                 }
index d199e3482d612f874b44f40a7e29a8c364fec403..6bc57d818bdbddab4c04257dd2bbe3252b8b6ccb 100644 (file)
@@ -144,7 +144,7 @@ public class DPTUnits {
         DPT_UNIT_MAP.put(DPTXlator4ByteFloat.DPT_ELECTROMAGNETIC_MOMENT.getID(),
                 Units.AMPERE.multiply(SIUnits.SQUARE_METRE).toString());
 
-        // 64 bit signed (DPT 29)
+        // 64-bit signed (DPT 29)
         DPT_UNIT_MAP.put(DPTXlator64BitSigned.DPT_REACTIVE_ENERGY.getID(), Units.VAR_HOUR.toString());
     }
 }
index 27ec1f3e87c1bc1e03a72fc7fa4b2f76a21d00d8..5b3f2ff6fec8636b67099909785fb6bccf09d55e 100644 (file)
@@ -50,7 +50,7 @@ import tuwien.auto.calimero.dptxlator.DPTXlatorString;
 public class DPTUtil {
     private static final Logger LOGGER = LoggerFactory.getLogger(DPTUtil.class);
 
-    // DPT: "123.001", 1-3 digits main type (no leading zero), optional sub-type 3-4 digits (leading zeros allowed)
+    // DPT: "123.001", 1-3 digits main type (no leading zero), optional subtype 3-4 digits (leading zeros allowed)
     public static final Pattern DPT_PATTERN = Pattern.compile("^(?<main>[1-9][0-9]{0,2})(?:\\.(?<sub>\\d{3,5}))?$");
 
     // used to map vendor-specific data to standard DPT
index 11c4e7fa51dacd3eaa5aa2fd2ce183efe3cc028c..bef244ff46a69e69fff328d3126ac3d203f32360 100644 (file)
@@ -241,32 +241,34 @@ public class ValueDecoder {
 
     private static Type handleDpt1(String subType, DPTXlator translator, Class<? extends Type> preferredType) {
         DPTXlatorBoolean translatorBoolean = (DPTXlatorBoolean) translator;
-        switch (subType) {
-            case "008":
-                return translatorBoolean.getValueBoolean() ? UpDownType.DOWN : UpDownType.UP;
-            case "009":
-            case "019":
+        return switch (subType) {
+            case "008" -> translatorBoolean.getValueBoolean() ? UpDownType.DOWN : UpDownType.UP;
+            case "009", "019" -> {
                 // default is OpenClosedType (Contact), but it may be mapped to OnOffType as well
                 if (OnOffType.class.equals(preferredType)) {
-                    return OnOffType.from(translatorBoolean.getValueBoolean());
+                    yield OnOffType.from(translatorBoolean.getValueBoolean());
                 }
 
                 // This is wrong for DPT 1.009. It should be true -> CLOSE, false -> OPEN, but unfortunately
                 // can't be fixed without breaking a lot of working installations.
                 // The documentation has been updated to reflect that. / @J-N-K
-                return translatorBoolean.getValueBoolean() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
-            case "010":
-                return translatorBoolean.getValueBoolean() ? StopMoveType.MOVE : StopMoveType.STOP;
-            case "022":
-                return DecimalType.valueOf(translatorBoolean.getValueBoolean() ? "1" : "0");
-            default:
+                yield translatorBoolean.getValueBoolean() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
+
+                // This is wrong for DPT 1.009. It should be true -> CLOSE, false -> OPEN, but unfortunately
+                // can't be fixed without breaking a lot of working installations.
+                // The documentation has been updated to reflect that. / @J-N-K
+            }
+            case "010" -> translatorBoolean.getValueBoolean() ? StopMoveType.MOVE : StopMoveType.STOP;
+            case "022" -> DecimalType.valueOf(translatorBoolean.getValueBoolean() ? "1" : "0");
+            default -> {
                 // default is OnOffType (Switch), but it may be mapped to OpenClosedType as well
                 if (OpenClosedType.class.equals(preferredType)) {
-                    return translatorBoolean.getValueBoolean() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
+                    yield translatorBoolean.getValueBoolean() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
                 }
 
-                return OnOffType.from(translatorBoolean.getValueBoolean());
-        }
+                yield OnOffType.from(translatorBoolean.getValueBoolean());
+            }
+        };
     }
 
     private static @Nullable Type handleDpt3(String subType, DPTXlator translator) {
@@ -275,17 +277,16 @@ public class ValueDecoder {
             LOGGER.debug("convertRawDataToType: KNX DPT_Control_Dimming: break received.");
             return UnDefType.NULL;
         }
-        switch (subType) {
-            case "007":
-                return translator3BitControlled.getControlBit() ? IncreaseDecreaseType.INCREASE
-                        : IncreaseDecreaseType.DECREASE;
-            case "008":
-                return translator3BitControlled.getControlBit() ? UpDownType.DOWN : UpDownType.UP;
-            default:
+        return switch (subType) {
+            case "007" -> translator3BitControlled.getControlBit() ? IncreaseDecreaseType.INCREASE
+                    : IncreaseDecreaseType.DECREASE;
+            case "008" -> translator3BitControlled.getControlBit() ? UpDownType.DOWN : UpDownType.UP;
+            default -> {
                 // should never happen unless Calimero introduces new subtypes
                 LOGGER.warn("DPT3, subtype '{}' is unknown. Please open an issue.", subType);
-                return null;
-        }
+                yield null;
+            }
+        };
     }
 
     private static Type handleDpt10(String value) throws ParseException {
index beac917a99c8b91fc4e57a953886bf6d900041ab..e0d0a9f7e7473b031ddf01ac49ea7430c008fdfc 100644 (file)
@@ -198,14 +198,14 @@ public class ValueEncoder {
             if (DPTXlator2ByteFloat.DPT_TEMPERATURE_DIFFERENCE.getID().equals(dptId)
                     || DPTXlator2ByteFloat.DPT_TEMPERATURE_GRADIENT.getID().equals(dptId)
                     || DPTXlator2ByteFloat.DPT_KELVIN_PER_PERCENT.getID().equals(dptId)) {
-                // match unicode character or Â°C
+                // match Unicode character or Â°C
                 if (value.toString().contains(SIUnits.CELSIUS.getSymbol()) || value.toString().contains("°C")) {
                     if (unit != null) {
                         unit = unit.replace("K", "°C");
                     }
                 } else if (value.toString().contains("°F")) {
-                    // an new approach to handle temperature differences was introduced to core
-                    // after 4.0, stripping the unit and and creating a new QuantityType works
+                    // A new approach to handle temperature differences was introduced to core
+                    // after 4.0, stripping the unit and creating a new QuantityType works
                     // both with core release 4.0 and current snapshot
                     boolean perPercent = value.toString().contains("/%");
                     value = new QuantityType<>(((QuantityType<?>) value).doubleValue() * 5.0 / 9.0, Units.KELVIN);
@@ -248,16 +248,12 @@ public class ValueEncoder {
                 return bigDecimal.stripTrailingZeros().toPlainString();
             case "2":
                 DPT valueDPT = ((DPTXlator1BitControlled.DPT1BitControlled) dpt).getValueDPT();
-                switch (bigDecimal.intValue()) {
-                    case 0:
-                        return "0 " + valueDPT.getLowerValue();
-                    case 1:
-                        return "0 " + valueDPT.getUpperValue();
-                    case 2:
-                        return "1 " + valueDPT.getLowerValue();
-                    default:
-                        return "1 " + valueDPT.getUpperValue();
-                }
+                return switch (bigDecimal.intValue()) {
+                    case 0 -> "0 " + valueDPT.getLowerValue();
+                    case 1 -> "0 " + valueDPT.getUpperValue();
+                    case 2 -> "1 " + valueDPT.getLowerValue();
+                    default -> "1 " + valueDPT.getUpperValue();
+                };
             case "18":
                 int intVal = bigDecimal.intValue();
                 if (intVal > 63) {
@@ -281,7 +277,7 @@ public class ValueEncoder {
     /**
      * convert 0...100% to 1 byte 0..255
      *
-     * @param percent
+     * @param percent percentage 0..1
      * @return int 0..255
      */
     private static int convertPercentToByte(PercentType percent) {
index 4c69b73e229aa02f23f8e853a86e20a362d8d72f..2d0525088e6b3f16119f5f2ff6a922107f5525ae 100644 (file)
@@ -370,9 +370,8 @@ public class DeviceThingHandler extends BaseThingHandler implements GroupAddress
                 logger.trace(
                         "onGroupWrite Thing '{}' processes a GroupValueWrite telegram for destination '{}' for channel '{}'",
                         getThing().getUID(), destination, knxChannel.getChannelUID());
-                /**
-                 * Remember current KNXIO outboundSpec only if it is a control channel.
-                 */
+
+                // Remember current KNXIO outboundSpec only if it is a control channel
                 if (knxChannel.isControl()) {
                     logger.trace("onGroupWrite isControl");
                     Type value = ValueDecoder.decode(listenSpec.getDPT(), asdu, knxChannel.preferredType());
@@ -478,7 +477,7 @@ public class DeviceThingHandler extends BaseThingHandler implements GroupAddress
         DeviceInspector.Result result = inspector.readDeviceInfo();
         if (result != null) {
             Map<String, String> properties = editProperties();
-            properties.putAll(result.getProperties());
+            properties.putAll(result.properties());
             updateProperties(properties);
             return true;
         }
index ed2e8111ac33f97f46d04dd478962103c902f099..a2ab8573d4e5f11888f1438c440d00a49426a2b8 100644 (file)
@@ -367,7 +367,7 @@ public abstract class KNXBridgeBaseThingHandler extends BaseBridgeHandler implem
     /***
      * Show all secure group addresses and surrogates. A surrogate is the device which is asked to carry out an indirect
      * read/write request.
-     * Simpler approach w/o surrogates: Security.defaultInstallation().groupSenders().toString());
+     * Simpler approach w/o surrogates: Security.defaultInstallation().groupSenders().toString();
      */
     public static String secHelperGetSecureGroupAddresses(final Security openhabSecurity) {
         Map<GroupAddress, Set<String>> groupSendersWithSurrogate = new HashMap<GroupAddress, Set<String>>();
@@ -379,7 +379,7 @@ public abstract class KNXBridgeBaseThingHandler extends BaseBridgeHandler implem
             IndividualAddress surrogate = null;
             try {
                 surrogate = senders.getOrDefault(ga, Set.of()).stream().findAny().get();
-            } catch (NoSuchElementException e) {
+            } catch (NoSuchElementException ignored) {
             }
             Set<String> devices = new HashSet<String>();
             for (var device : entry.getValue()) {
index 2ad00e5968f7c004f9b44bc62ea47b34ba07fa35..2458f933c11e2942986ea78912c4737945cc048b 100644 (file)
@@ -26,7 +26,7 @@ import org.osgi.framework.FrameworkUtil;
  * This class provides translations. It is a helper class for i18n / localization efforts.
  *
  * @implNote It is implemented as a static singleton, enforced by the single-element enum pattern.
- * @apiNote {@link #setProvider(LocaleProvider, TranslationProvider)} must be called to provide tanslation service,
+ * @apiNote {@link #setProvider(LocaleProvider, TranslationProvider)} must be called to provide translation service,
  *          otherwise all functions will return untranslated text.
  *          Thread safety is ensured.
  * @author Holger Friedrich - Initial contribution
@@ -38,9 +38,9 @@ public enum KNXTranslationProvider {
 
     private @Nullable LocaleProvider localeProvider;
     private @Nullable TranslationProvider translationProvider;
-    private Bundle bundle;
+    private final Bundle bundle;
 
-    private KNXTranslationProvider() {
+    KNXTranslationProvider() {
         localeProvider = null;
         translationProvider = null;
         bundle = FrameworkUtil.getBundle(this.getClass());
@@ -59,7 +59,7 @@ public enum KNXTranslationProvider {
         final TranslationProvider translationProvider = this.translationProvider;
         final LocaleProvider localeProvider = this.localeProvider;
         if (translationProvider != null) {
-            // localeProvider might be null, but if not, getLocale will return NonNull Locale
+            // localeProvider might be null, but if not, getLocale will return NonNull Locale;
             // locale cannot be cached, as getLocale() will return different result once locale is changed by user
             final Locale locale = (localeProvider != null) ? localeProvider.getLocale() : Locale.getDefault();
             final String res = translationProvider.getText(bundle, text, text, locale, arguments);
@@ -67,7 +67,7 @@ public enum KNXTranslationProvider {
                 return res;
             }
         }
-        // translating not possible, we still have the original text without any subsititutions
+        // translating not possible, we still have the original text without any substitutions
         if (arguments == null || arguments.length == 0) {
             return text;
         }
@@ -80,14 +80,14 @@ public enum KNXTranslationProvider {
      *
      * @param e any exception
      * @return localized message in form [description (translated)] [class name], [e.getLocalizedMessage (not
-     *         translated)]), empty string for null. May possibly change in further releases.
+     *         translated)], empty string for null. May change in further releases.
      */
     public String getLocalizedException(final Throwable e) {
         StringBuilder res = new StringBuilder();
         final String exName = e.getClass().getSimpleName();
         final String key = "exception." + exName;
         final String translatedDescription = KNXTranslationProvider.I18N.get(key);
-        Boolean foundTranslation = !key.equals(translatedDescription);
+        boolean foundTranslation = !key.equals(translatedDescription);
         // detailed message cannot be translated, e.getLocalizedMessage will likely return English
         String detail = e.getLocalizedMessage();
         if (detail == null) {
index 905fb895864b68868cbb2e87c33f8f03d38549df..0c3431903f6645e41d22e9be607f223ba9af993e 100644 (file)
@@ -45,9 +45,7 @@ class KNXChannelFactoryTest {
     public void testNullChannelUidFails() {
         Channel channel = Objects.requireNonNull(mock(Channel.class));
 
-        assertThrows(IllegalArgumentException.class, () -> {
-            KNXChannelFactory.createKnxChannel(channel);
-        });
+        assertThrows(IllegalArgumentException.class, () -> KNXChannelFactory.createKnxChannel(channel));
     }
 
     @Test
@@ -55,9 +53,7 @@ class KNXChannelFactoryTest {
         Channel channel = Objects.requireNonNull(mock(Channel.class));
         when(channel.getChannelTypeUID()).thenReturn(new ChannelTypeUID("a:b:c"));
 
-        assertThrows(IllegalArgumentException.class, () -> {
-            KNXChannelFactory.createKnxChannel(channel);
-        });
+        assertThrows(IllegalArgumentException.class, () -> KNXChannelFactory.createKnxChannel(channel));
     }
 
     @ParameterizedTest
@@ -65,11 +61,11 @@ class KNXChannelFactoryTest {
             CHANNEL_DATETIME, CHANNEL_DATETIME_CONTROL, CHANNEL_DIMMER, CHANNEL_DIMMER_CONTROL, CHANNEL_NUMBER,
             CHANNEL_NUMBER_CONTROL, CHANNEL_ROLLERSHUTTER, CHANNEL_ROLLERSHUTTER_CONTROL, CHANNEL_STRING,
             CHANNEL_STRING_CONTROL, CHANNEL_SWITCH, CHANNEL_SWITCH_CONTROL })
-    public void testSuccess(String channeltype) {
+    public void testSuccess(String channelType) {
         Channel channel = Objects.requireNonNull(mock(Channel.class));
         Configuration configuration = new Configuration(
                 Map.of("key1", "5.001:<1/2/3+4/5/6+1/5/6", "key2", "1.001:7/1/9+1/1/2"));
-        when(channel.getChannelTypeUID()).thenReturn(new ChannelTypeUID("knx:" + channeltype));
+        when(channel.getChannelTypeUID()).thenReturn(new ChannelTypeUID("knx:" + channelType));
         when(channel.getConfiguration()).thenReturn(configuration);
         when(channel.getAcceptedItemType()).thenReturn("none");
 
diff --git a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/client/DummyClient.java b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/client/DummyClient.java
deleted file mode 100644 (file)
index 3a1beef..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Copyright (c) 2010-2024 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.knx.internal.client;
-
-import java.util.Collections;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.knx.internal.handler.KNXBridgeBaseThingHandler.CommandExtensionData;
-import org.openhab.core.thing.ThingUID;
-
-import tuwien.auto.calimero.KNXException;
-import tuwien.auto.calimero.link.KNXNetworkLink;
-
-/**
- * {@link AbstractKNXClient} implementation for test, using {@link DummyKNXNetworkLink}.
- *
- * @author Holger Friedrich - initial contribution and API.
- *
- */
-@NonNullByDefault
-public class DummyClient extends AbstractKNXClient {
-
-    public DummyClient() {
-        super(0, new ThingUID("dummy connection"), 0, 0, 0, null, new CommandExtensionData(Collections.emptyMap()),
-                null, null);
-    }
-
-    @Override
-    protected KNXNetworkLink establishConnection() throws KNXException, InterruptedException {
-        return new DummyKNXNetworkLink();
-    }
-}
index 6b73fc12ec26906f02e90a8230a24dc20e0527d7..e58a8e881a0a2a3feb915e5fef7fa88dded8af39 100644 (file)
@@ -26,7 +26,6 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
-import org.openhab.binding.knx.internal.itests.Back2BackTest;
 import org.openhab.core.library.types.DateTimeType;
 import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.HSBType;
@@ -36,8 +35,6 @@ 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;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import tuwien.auto.calimero.dptxlator.DPTXlator2ByteUnsigned;
 import tuwien.auto.calimero.dptxlator.DPTXlator4ByteFloat;
@@ -54,8 +51,6 @@ import tuwien.auto.calimero.dptxlator.DptXlator2ByteSigned;
  */
 @NonNullByDefault
 class DPTTest {
-    public static final Logger LOGGER = LoggerFactory.getLogger(Back2BackTest.class);
-
     @Test
     void testDptBroken() {
         assertNull(ValueEncoder.encode(new DecimalType(), "9.042.1"));
@@ -529,7 +524,7 @@ class DPTTest {
         assertNotEquals(DPTXlator4ByteFloat.DPT_ELECTROMAGNETIC_MOMENT.getUnit(),
                 Units.AMPERE.multiply(SIUnits.SQUARE_METRE).toString());
 
-        // 64 bit signed (DPT 29)
+        // 64-bit signed (DPT 29)
         assertNotEquals(DPTXlator64BitSigned.DPT_REACTIVE_ENERGY.getUnit(), Units.VAR_HOUR.toString());
     }
 
index 4c331a812b8f6c923be09ea5c77569bc9d0365ea..f702ef28b70c9e0210deb6d4fee28420fcfc01c2 100644 (file)
@@ -58,28 +58,21 @@ class KNXBridgeBaseThingHandlerTest {
         // router password configured, length must be 16 bytes in hex notation
         assertTrue(handler.initializeSecurity("", "", "D947B12DDECAD528B1D5A88FD347F284", "", "", "", ""));
         assertTrue(handler.initializeSecurity("", "", "0xD947B12DDECAD528B1D5A88FD347F284", "", "", "", ""));
-        assertThrows(KnxSecureException.class, () -> {
-            handler.initializeSecurity("", "", "wrongLength", "", "", "", "");
-        });
+        assertThrows(KnxSecureException.class, () -> handler.initializeSecurity("", "", "wrongLength", "", "", "", ""));
 
         // tunnel configuration
         assertTrue(handler.initializeSecurity("", "", "", "da", "1", "pw", ""));
         // cTunnelUser is restricted to a number >0
-        assertThrows(KnxSecureException.class, () -> {
-            handler.initializeSecurity("", "", "", "da", "0", "pw", "");
-        });
-        assertThrows(KnxSecureException.class, () -> {
-            handler.initializeSecurity("", "", "", "da", "eins", "pw", "");
-        });
+        assertThrows(KnxSecureException.class, () -> handler.initializeSecurity("", "", "", "da", "0", "pw", ""));
+        assertThrows(KnxSecureException.class, () -> handler.initializeSecurity("", "", "", "da", "eins", "pw", ""));
         // at least one setting for tunnel is given, count as try to configure secure tunnel
         // plausibility is checked during initialize()
         assertTrue(handler.initializeSecurity("", "", "", "da", "", "", ""));
         assertTrue(handler.initializeSecurity("", "", "", "", "1", "", ""));
         assertTrue(handler.initializeSecurity("", "", "", "", "", "pw", ""));
 
-        assertThrows(KnxSecureException.class, () -> {
-            handler.initializeSecurity("nonExistingFile.xml", "", "", "", "", "", "");
-        });
+        assertThrows(KnxSecureException.class,
+                () -> handler.initializeSecurity("nonExistingFile.xml", "", "", "", "", "", ""));
 
         Properties pBackup = new Properties(System.getProperties());
         try {
@@ -91,12 +84,12 @@ class KNXBridgeBaseThingHandlerTest {
             p.put(OpenHAB.CONFIG_DIR_PROG_ARGUMENT, testFile.getParent().replaceAll("misc$", ""));
             System.setProperties(p);
 
-            assertTrue(handler.initializeSecurity(testFile.getName().toString(), passwordString, "", "", "", "pw", ""));
+            assertTrue(handler.initializeSecurity(testFile.getName(), passwordString, "", "", "", "pw", ""));
 
-            assertThrows(KnxSecureException.class, () -> {
-                assertTrue(handler.initializeSecurity(testFile.getName().toString(), "wrong", "", "", "", "pw", ""));
-            });
+            assertThrows(KnxSecureException.class,
+                    () -> assertTrue(handler.initializeSecurity(testFile.getName(), "wrong", "", "", "", "pw", "")));
         } catch (URISyntaxException e) {
+            fail("should never happen");
         } finally {
             // properties are not persistent, but change may interference with other tests -> restore
             System.setProperties(pBackup);
index 7c633bf8dd5de5519c284d00fcc9821e9f939b6e..033aaf756ba28092eb22992f1354b3620733e84c 100644 (file)
  */
 package org.openhab.binding.knx.internal.itests;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -71,7 +68,6 @@ import tuwien.auto.calimero.process.ProcessCommunicatorImpl;
  * handled by this test. However, new subtypes are not detected.
  *
  * @see DummyKNXNetworkLink
- * @see DummyClient
  * @author Holger Friedrich - Initial contribution
  *
  */
@@ -80,7 +76,6 @@ public class Back2BackTest {
     public static final Logger LOGGER = LoggerFactory.getLogger(Back2BackTest.class);
     static Set<Integer> dptTested = new HashSet<>();
     static final byte[] F32_MINUS_ONE = new byte[] { (byte) 0xbf, (byte) 0x80, 0, 0 };
-    boolean testsMissing = false;
 
     /**
      * helper method for integration tests
@@ -90,7 +85,7 @@ public class Back2BackTest {
      * @param ohReferenceData OpenHAB data type, initialized to known good value
      * @param maxDistance byte array containing maximal deviations when comparing byte arrays (rawData against created
      *            KNX frame), may be empty if no deviation is considered
-     * @param bitmask to mask certain bits in the raw to raw comparison, required for multi-valued KNX frames
+     * @param bitmask to mask certain bits in the raw to raw comparison, required for multivalued KNX frames
      */
     void helper(String dpt, byte[] rawData, Type ohReferenceData, byte[] maxDistance, byte[] bitmask) {
         try {
@@ -104,7 +99,7 @@ public class Back2BackTest {
                     DPTUtil.NORMALIZED_DPT.getOrDefault(dpt, dpt));
 
             // 0) check usage of helper()
-            assertEquals(true, rawData.length > 0);
+            assertTrue(rawData.length > 0);
             if (maxDistance.length == 0) {
                 maxDistance = new byte[rawData.length];
             }
@@ -115,7 +110,7 @@ public class Back2BackTest {
             }
             assertEquals(rawData.length, bitmask.length, "incorrect length of bitmask array");
             int mainType = Integer.parseUnsignedInt(dpt.substring(0, dpt.indexOf('.')));
-            dptTested.add(Integer.valueOf(mainType));
+            dptTested.add(mainType);
             // check if OH would be able to send out a frame, given the type
             Set<Integer> knownWorking = Set.of(1, 3, 5);
             if (!knownWorking.contains(mainType)) {
@@ -146,7 +141,8 @@ public class Back2BackTest {
 
             // 2) check the encoding (ohData to raw data)
             //
-            // Test approach is to a) encode the value into String format using ValueEncoder.encode(),
+            // Test approach is to
+            // a) encode the value into String format using ValueEncoder.encode(),
             // b) pass it to Calimero for conversion into a raw representation, and
             // c) finally grab raw data bytes from a custom KNXNetworkLink implementation
             String enc = ValueEncoder.encode(ohData, dpt);
@@ -178,7 +174,7 @@ public class Back2BackTest {
 
             pc.close();
         } catch (KNXException e) {
-            LOGGER.warn("exception occurred", e.toString());
+            LOGGER.warn("exception occurred: {}", e.toString());
             assertEquals("", e.toString());
         }
     }
@@ -949,10 +945,10 @@ public class Back2BackTest {
         };
         TranslatorTypes.getAllMainTypes().forEach((i, t) -> {
             if (!dptTested.contains(i)) {
-                LOGGER.warn("missing tests for main DPT type " + i);
+                LOGGER.warn("missing tests for main DPT type {}", i);
                 wrapper.testsMissing = true;
             }
         });
-        assertEquals(false, wrapper.testsMissing, "add tests for new DPT main types");
+        assertFalse(wrapper.testsMissing, "add tests for new DPT main types");
     }
 }
index 29f3648956ad823b8db51d7e662cc16e87882b84..f871bdb29b39b85315f2a7749c0d524de65273e7 100644 (file)
@@ -138,18 +138,15 @@ public class KNXSecurityTest {
         Security openhabSecurity = Security.newSecurity();
         openhabSecurity.useKeyring(keys, password);
 
-        assertThrows(KnxSecureException.class, () -> {
-            KNXBridgeBaseThingHandler.secHelperReadBackboneKey(Optional.empty(), passwordString);
-        });
+        assertThrows(KnxSecureException.class,
+                () -> KNXBridgeBaseThingHandler.secHelperReadBackboneKey(Optional.empty(), passwordString));
         assertTrue(KNXBridgeBaseThingHandler.secHelperReadBackboneKey(Optional.ofNullable(keys), passwordString)
                 .isPresent());
 
         // now check tunnel (expected to fail, not included)
         IndividualAddress secureTunnelSourceAddr = new IndividualAddress(2, 8, 20);
-        assertThrows(KnxSecureException.class, () -> {
-            KNXBridgeBaseThingHandler.secHelperReadTunnelConfig(Optional.empty(), passwordString,
-                    secureTunnelSourceAddr);
-        });
+        assertThrows(KnxSecureException.class, () -> KNXBridgeBaseThingHandler
+                .secHelperReadTunnelConfig(Optional.empty(), passwordString, secureTunnelSourceAddr));
         assertTrue(KNXBridgeBaseThingHandler
                 .secHelperReadTunnelConfig(Optional.ofNullable(keys), passwordString, secureTunnelSourceAddr)
                 .isEmpty());
@@ -170,18 +167,15 @@ public class KNXSecurityTest {
         Security openhabSecurity = Security.newSecurity();
         openhabSecurity.useKeyring(keys, password);
 
-        assertThrows(KnxSecureException.class, () -> {
-            KNXBridgeBaseThingHandler.secHelperReadBackboneKey(Optional.empty(), passwordString);
-        });
+        assertThrows(KnxSecureException.class,
+                () -> KNXBridgeBaseThingHandler.secHelperReadBackboneKey(Optional.empty(), passwordString));
         assertTrue(KNXBridgeBaseThingHandler.secHelperReadBackboneKey(Optional.ofNullable(keys), passwordString)
                 .isEmpty());
 
         // now check tunnel
         IndividualAddress secureTunnelSourceAddr = new IndividualAddress(1, 1, 2);
-        assertThrows(KnxSecureException.class, () -> {
-            KNXBridgeBaseThingHandler.secHelperReadTunnelConfig(Optional.empty(), passwordString,
-                    secureTunnelSourceAddr);
-        });
+        assertThrows(KnxSecureException.class, () -> KNXBridgeBaseThingHandler
+                .secHelperReadTunnelConfig(Optional.empty(), passwordString, secureTunnelSourceAddr));
         assertTrue(KNXBridgeBaseThingHandler
                 .secHelperReadTunnelConfig(Optional.ofNullable(keys), passwordString, secureTunnelSourceAddr)
                 .isPresent());
@@ -205,9 +199,8 @@ public class KNXSecurityTest {
         openhabSecurity.useKeyring(keys, password);
 
         // now check router settings:
-        assertThrows(KnxSecureException.class, () -> {
-            KNXBridgeBaseThingHandler.secHelperReadBackboneKey(Optional.empty(), passwordString);
-        });
+        assertThrows(KnxSecureException.class,
+                () -> KNXBridgeBaseThingHandler.secHelperReadBackboneKey(Optional.empty(), passwordString));
         String bbKeyHex = "D947B12DDECAD528B1D5A88FD347F284";
         byte[] bbKeyParsedLower = KNXBridgeBaseThingHandler.secHelperParseBackboneKey(bbKeyHex.toLowerCase());
         byte[] bbKeyParsedUpper = KNXBridgeBaseThingHandler.secHelperParseBackboneKey(bbKeyHex);
@@ -225,10 +218,8 @@ public class KNXSecurityTest {
         // now check tunnel settings:
         IndividualAddress secureTunnelSourceAddr = new IndividualAddress(1, 1, 2);
         IndividualAddress noSecureTunnelSourceAddr = new IndividualAddress(2, 8, 20);
-        assertThrows(KnxSecureException.class, () -> {
-            KNXBridgeBaseThingHandler.secHelperReadTunnelConfig(Optional.empty(), passwordString,
-                    secureTunnelSourceAddr);
-        });
+        assertThrows(KnxSecureException.class, () -> KNXBridgeBaseThingHandler
+                .secHelperReadTunnelConfig(Optional.empty(), passwordString, secureTunnelSourceAddr));
         assertTrue(KNXBridgeBaseThingHandler
                 .secHelperReadTunnelConfig(Optional.ofNullable(keys), passwordString, noSecureTunnelSourceAddr)
                 .isEmpty());