]> git.basschouten.com Git - openhab-addons.git/commitdiff
[knx] Correctly support state sub-types for DPTs (#16337)
authorKai Kreuzer <kai@openhab.org>
Fri, 2 Feb 2024 19:13:11 +0000 (20:13 +0100)
committerGitHub <noreply@github.com>
Fri, 2 Feb 2024 19:13:11 +0000 (20:13 +0100)
Signed-off-by: Kai Kreuzer <kai@openhab.org>
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannel.java
bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTest.java

index 4f53e6bd3f93bf9e6bf9b7f16e1ddb3b56af1610..8db0dc22fd4b8cf335c7093e673b3459aa28911d 100644 (file)
@@ -12,9 +12,8 @@
  */
 package org.openhab.binding.knx.internal.channel;
 
-import static java.util.stream.Collectors.*;
-import static org.openhab.binding.knx.internal.KNXBindingConstants.CONTROL_CHANNEL_TYPES;
-import static org.openhab.binding.knx.internal.KNXBindingConstants.GA;
+import static java.util.stream.Collectors.toList;
+import static org.openhab.binding.knx.internal.KNXBindingConstants.*;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -31,6 +30,7 @@ import org.openhab.binding.knx.internal.dpt.DPTUtil;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.types.State;
 import org.openhab.core.types.Type;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -121,11 +121,22 @@ public abstract class KNXChannel {
         logger.trace("getCommandSpec checking keys '{}' for command '{}' ({})", gaKeys, command, command.getClass());
         for (Map.Entry<String, GroupAddressConfiguration> entry : groupAddressConfigurations.entrySet()) {
             String dpt = Objects.requireNonNullElse(entry.getValue().getDPT(), getDefaultDPT(entry.getKey()));
-            Set<Class<? extends Type>> expectedTypeClass = DPTUtil.getAllowedTypes(dpt);
-            if (expectedTypeClass.contains(command.getClass())) {
-                logger.trace("getCommandSpec key '{}' has expectedTypeClass '{}', matching command '{}' and dpt '{}'",
-                        entry.getKey(), expectedTypeClass, command, dpt);
-                return new WriteSpecImpl(entry.getValue(), dpt, command);
+            Set<Class<? extends Type>> expectedTypeClasses = DPTUtil.getAllowedTypes(dpt);
+            // find the first matching type that is assignable from the command
+            for (Class<? extends Type> expectedTypeClass : expectedTypeClasses) {
+                if (expectedTypeClass.equals(command.getClass())) {
+                    logger.trace("getCommandSpec command class matches expected type class");
+                    return new WriteSpecImpl(entry.getValue(), dpt, command);
+                } else if (command instanceof State state && State.class.isAssignableFrom(expectedTypeClass)) {
+                    if (state.as(expectedTypeClass.asSubclass(State.class)) != null) {
+                        logger.trace("getCommandSpec command class is a sub-class of the expected type class");
+                        Class<? extends State> expectedTypeAsStateClass = expectedTypeClass.asSubclass(State.class);
+                        State convertedState = state.as(expectedTypeAsStateClass);
+                        if (convertedState != null) {
+                            return new WriteSpecImpl(entry.getValue(), dpt, convertedState);
+                        }
+                    }
+                }
             }
         }
         logger.trace("getCommandSpec no Spec found!");
index f251f55fd84b5264d84ed28d66f1e5b9d8c76734..a943d4288e080c57852cbe292fd381909ff7eecc 100644 (file)
@@ -24,6 +24,8 @@ import java.util.Set;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.junit.jupiter.api.Test;
 import org.openhab.core.config.core.Configuration;
+import org.openhab.core.library.items.ColorItem;
+import org.openhab.core.library.types.HSBType;
 import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.type.ChannelTypeUID;
 import org.openhab.core.types.UnDefType;
@@ -158,6 +160,18 @@ class KNXChannelTest {
         assertTrue(writeAddresses.contains(new GroupAddress("7/1/9")));
     }
 
+    @Test
+    void testSubTypeMapping() throws KNXFormatException {
+        Channel channel = Objects.requireNonNull(mock(Channel.class));
+        Configuration configuration = new Configuration(Map.of("key1", "1.001:1/2/3"));
+        when(channel.getChannelTypeUID()).thenReturn(new ChannelTypeUID("a:b:c"));
+        when(channel.getConfiguration()).thenReturn(configuration);
+        when(channel.getAcceptedItemType()).thenReturn(ColorItem.class.getName());
+        MyKNXChannel knxChannel = new MyKNXChannel(channel);
+        assertNotNull(knxChannel.getCommandSpec(new HSBType("0,100,100")));
+        assertEquals(knxChannel.getCommandSpec(new HSBType("0,100,100")).getDPT(), "1.001");
+    }
+
     private static class MyKNXChannel extends KNXChannel {
         public MyKNXChannel(Channel channel) {
             super(Set.of("key1", "key2"), List.of(UnDefType.class), channel);