]> git.basschouten.com Git - openhab-addons.git/commitdiff
[knx] dynamic channel-types (#15072)
authorJ-N-K <github@klug.nrw>
Sun, 11 Jun 2023 19:04:09 +0000 (21:04 +0200)
committerGitHub <noreply@github.com>
Sun, 11 Jun 2023 19:04:09 +0000 (21:04 +0200)
Signed-off-by: Jan N. Klug <github@klug.nrw>
bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java

index 040e16a72d696ded5bb7ef71e80e9eb21f285526..2b64025292b14c7e659df75c716e4e1d66089d58 100644 (file)
@@ -27,6 +27,8 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
+import javax.measure.Unit;
+
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.knx.internal.KNXBindingConstants;
@@ -38,6 +40,7 @@ import org.openhab.binding.knx.internal.client.InboundSpec;
 import org.openhab.binding.knx.internal.client.KNXClient;
 import org.openhab.binding.knx.internal.client.OutboundSpec;
 import org.openhab.binding.knx.internal.config.DeviceConfig;
+import org.openhab.binding.knx.internal.dpt.DPTUnits;
 import org.openhab.binding.knx.internal.dpt.DPTUtil;
 import org.openhab.binding.knx.internal.dpt.ValueDecoder;
 import org.openhab.binding.knx.internal.i18n.KNXTranslationProvider;
@@ -51,11 +54,15 @@ import org.openhab.core.thing.ThingStatus;
 import org.openhab.core.thing.ThingStatusDetail;
 import org.openhab.core.thing.ThingStatusInfo;
 import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerCallback;
+import org.openhab.core.thing.binding.builder.ChannelBuilder;
+import org.openhab.core.thing.binding.builder.ThingBuilder;
 import org.openhab.core.types.Command;
 import org.openhab.core.types.RefreshType;
 import org.openhab.core.types.State;
 import org.openhab.core.types.Type;
 import org.openhab.core.types.UnDefType;
+import org.openhab.core.types.util.UnitUtils;
 import org.openhab.core.util.HexUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -99,15 +106,56 @@ public class DeviceThingHandler extends BaseThingHandler implements GroupAddress
 
     @Override
     public void initialize() {
-        attachToClient();
         DeviceConfig config = getConfigAs(DeviceConfig.class);
         readInterval = config.getReadInterval();
+
         // gather all GAs from channel configurations and create channels
-        getThing().getChannels().forEach(channel -> {
+        ThingBuilder thingBuilder = editThing();
+        boolean modified = false;
+        ThingHandlerCallback callback = getCallback();
+        if (callback == null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Framework failure: callback must not be null");
+            return;
+        }
+
+        for (Channel channel : getThing().getChannels()) {
             KNXChannel knxChannel = KNXChannelFactory.createKnxChannel(channel);
             knxChannels.put(channel.getUID(), knxChannel);
             groupAddresses.addAll(knxChannel.getAllGroupAddresses());
-        });
+
+            if (knxChannel.getChannelType().startsWith("number")) {
+                // check if we need to update the accepted item-type
+                List<InboundSpec> inboundSpecs = knxChannel.getAllGroupAddresses().stream()
+                        .map(knxChannel::getListenSpec).filter(Objects::nonNull).map(Objects::requireNonNull).toList();
+
+                String dpt = inboundSpecs.get(0).getDPT(); // there can be only one DPT on number channels
+                Unit<?> unit = UnitUtils.parseUnit(DPTUnits.getUnitForDpt(dpt));
+                String dimension = unit == null ? null : UnitUtils.getDimensionName(unit);
+                String expectedItemType = dimension == null ? "Number" : "Number:" + dimension; // unknown dimension ->
+                                                                                                // Number
+                String actualItemType = channel.getAcceptedItemType();
+                if (!expectedItemType.equals(actualItemType)) {
+                    ChannelBuilder channelBuilder = callback
+                            .createChannelBuilder(channel.getUID(), Objects.requireNonNull(channel.getChannelTypeUID()))
+                            .withAcceptedItemType(expectedItemType).withConfiguration(channel.getConfiguration());
+                    if (channel.getLabel() != null) {
+                        channelBuilder.withLabel(Objects.requireNonNull(channel.getLabel()));
+                    }
+                    if (channel.getDescription() != null) {
+                        channelBuilder.withDescription(Objects.requireNonNull(channel.getDescription()));
+                    }
+                    thingBuilder.withoutChannel(channel.getUID());
+                    thingBuilder.withChannel(channelBuilder.build());
+                    modified = true;
+                }
+            }
+        }
+
+        if (modified) {
+            updateThing(thingBuilder.build());
+        }
+
+        attachToClient();
     }
 
     @Override