From cd989f7bac531fef50bec94526aeb6c0b389d20b Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Mon, 15 Aug 2022 23:27:02 +0100 Subject: [PATCH 01/14] [velux] make vanePosition channel dynamic Signed-off-by: Andrew Fiddian-Green --- bundles/org.openhab.binding.velux/README.md | 3 +- .../velux/internal/VeluxBindingConstants.java | 5 + .../internal/handler/VeluxBridgeHandler.java | 93 +++++++++++++++++++ .../velux/internal/handler/VeluxHandler.java | 17 ++++ .../resources/OH-INF/thing/rollershutter.xml | 1 - 5 files changed, 117 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.velux/README.md b/bundles/org.openhab.binding.velux/README.md index 0dfc5e258ce1c..f9b72ae43bb4e 100644 --- a/bundles/org.openhab.binding.velux/README.md +++ b/bundles/org.openhab.binding.velux/README.md @@ -176,11 +176,12 @@ The supported Channels and their associated channel types are shown below. | position | Rollershutter | Actual position of the window or device. | | limitMinimum | Rollershutter | Minimum limit position of the window or device. | | limitMaximum | Rollershutter | Maximum limit position of the window or device. | -| vanePosition | Dimmer | Vane position of a Venetian blind. | +| vanePosition | Dimmer | Vane position of a Venetian blind. (optional) | The `position`, `limitMinimum`, and `limitMaximum` are the same as described above for "window" Things. The `vanePosition` Channel only applies to Venetian blinds that have tiltable slats. +The binding detects whether the device supports a vane position, and if so, it adds the `vanePosition` Channel automatically. ### Channels for "actuator" Things diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java index 31472d73a2863..7875720a423a9 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.type.ChannelTypeUID; /** * The {@link VeluxBindingConstants} class defines common constants, which are @@ -157,4 +158,8 @@ public class VeluxBindingConstants { public static final String UNKNOWN_THING_TYPE_ID = "FAILED"; public static final String UNKNOWN_IP_ADDRESS = "xxx.xxx.xxx.xxx"; + + // Channel Type UIDs + public static final ChannelTypeUID CHANNEL_TYPE_MAIN = new ChannelTypeUID(BINDING_ID, CHANNEL_ACTUATOR_POSITION); + public static final ChannelTypeUID CHANNEL_TYPE_VANE = new ChannelTypeUID(BINDING_ID, CHANNEL_VANE_POSITION); } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index e7b02e5a97ffa..80b40b35ac38b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -12,7 +12,9 @@ */ package org.openhab.binding.velux.internal.handler; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -21,6 +23,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -61,15 +64,21 @@ import org.openhab.binding.velux.internal.utils.Localization; import org.openhab.core.common.AbstractUID; import org.openhab.core.common.NamedThreadFactory; +import org.openhab.core.library.CoreItemFactory; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandlerService; +import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.openhab.core.types.State; @@ -465,6 +474,8 @@ private void bridgeParamsUpdated() { } } + initializeVanePositionChannels(); + veluxBridgeConfiguration.hasChanged = false; logger.debug("Velux veluxBridge is online, now."); updateStatus(ThingStatus.ONLINE); @@ -957,4 +968,86 @@ public ProductBridgeIndex getProductBridgeIndex(String thingName) { } return ProductBridgeIndex.UNKNOWN; } + + /** + * Iterate over all roller shutter type things in the hub, and initialise the dynamic vane position channel if the + * respective device supports it. + */ + private void initializeVanePositionChannels() { + getThing().getThings().stream() + .filter(thing -> VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER.equals(thing.getThingTypeUID())) + .forEach(thing -> initializeVanePositionChannel(thing)); + } + + /** + * For the given roller shutter type thing, initialise the dynamic vane position channel if the respective device + * supports it. + */ + private void initializeVanePositionChannel(Thing thing) { + final ChannelUID vaneChannelUID = new ChannelUID(thing.getUID(), VeluxBindingConstants.CHANNEL_VANE_POSITION); + + final VeluxProduct product = existingProducts() + .get((new Thing2VeluxActuator(this, vaneChannelUID)).getProductBridgeIndex()); + if (product.equals(VeluxProduct.UNKNOWN)) { + // product unknown"); + return; + } + + // predicate to filter the vane position channel + final Predicate vaneChannelFilter = c -> VeluxBindingConstants.CHANNEL_TYPE_VANE + .equals(c.getChannelTypeUID()); + + // note: this is an immutable list + List channels = thing.getChannels(); + + // current and required state of the vane channel + final boolean vaneChannelExisting = channels.stream().anyMatch(vaneChannelFilter); + final boolean vaneChannelRequired = !product.supportsVanePosition(); + + logger.warn("channelExisting:{} channelRequired:{}", vaneChannelExisting, vaneChannelRequired); + + if (vaneChannelExisting == vaneChannelRequired) { + // no change needed + return; + } + + ThingHandler handler = thing.getHandler(); + if (!(handler instanceof VeluxHandler)) { + // handler is of the wrong wrong type + return; + } + VeluxHandler veluxHandler = (VeluxHandler) handler; + + // make a mutable copy of the original immutable channel list + channels = new ArrayList<>(channels); + + if (vaneChannelRequired) { + // build the vane channel + Channel newChannel = ChannelBuilder.create(vaneChannelUID).withAcceptedItemType(CoreItemFactory.DIMMER) + .withKind(ChannelKind.STATE) + .withDescription(localization.getText("channel-type.velux.vanePosition.description")) + .withLabel(localization.getText("channel-type.velux.vanePosition.label")).build(); + + // add the vane channel + if (!channels.add(newChannel)) { + // failed to add vane channel + return; + } + } else { + // remove the vane channel + if (!channels.removeIf(vaneChannelFilter)) { + // failed to remove vane channel + return; + } + } + + /* + * If we got this far then we will update the thing by building an identical copy of the target thing, except + * that it uses the newly modified channel list instead of the original one. + */ + final Thing newThing = veluxHandler.editThing().withChannels(channels).build(); + scheduler.submit(() -> { + veluxHandler.updateThing(newThing); + }); + } } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java index e38e358f55025..f0c17e240a52d 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java @@ -26,6 +26,7 @@ import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BridgeHandler; +import org.openhab.core.thing.binding.builder.ThingBuilder; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.slf4j.Logger; @@ -125,4 +126,20 @@ public void handleConfigurationUpdate(Map configurationParameter super.handleConfigurationUpdate(configurationParameters); } } + + /** + * Set public visibility on the protected super.editThing() method. + */ + @Override + public ThingBuilder editThing() { + return super.editThing(); + } + + /** + * Set public visibility on the protected super.updateThing() method. + */ + @Override + public void updateThing(Thing thing) { + super.updateThing(thing); + } } diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml index f1cd52956b4d9..ed19d77c654f3 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml @@ -19,7 +19,6 @@ - serial From d81fe2ed7b0991b25e6c5cf4960ce0257597179a Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Mon, 15 Aug 2022 23:33:56 +0100 Subject: [PATCH 02/14] [velux] remove inversion Signed-off-by: Andrew Fiddian-Green --- .../binding/velux/internal/handler/VeluxBridgeHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index 80b40b35ac38b..d67403e00fd64 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -1002,7 +1002,7 @@ private void initializeVanePositionChannel(Thing thing) { // current and required state of the vane channel final boolean vaneChannelExisting = channels.stream().anyMatch(vaneChannelFilter); - final boolean vaneChannelRequired = !product.supportsVanePosition(); + final boolean vaneChannelRequired = product.supportsVanePosition(); logger.warn("channelExisting:{} channelRequired:{}", vaneChannelExisting, vaneChannelRequired); From e879944bba7523ff72d25226a070684b36f4002f Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Mon, 15 Aug 2022 23:54:54 +0100 Subject: [PATCH 03/14] [velux] remove spurious logging Signed-off-by: Andrew Fiddian-Green --- .../binding/velux/internal/handler/VeluxBridgeHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index d67403e00fd64..ad2368f8585c9 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -1004,8 +1004,6 @@ private void initializeVanePositionChannel(Thing thing) { final boolean vaneChannelExisting = channels.stream().anyMatch(vaneChannelFilter); final boolean vaneChannelRequired = product.supportsVanePosition(); - logger.warn("channelExisting:{} channelRequired:{}", vaneChannelExisting, vaneChannelRequired); - if (vaneChannelExisting == vaneChannelRequired) { // no change needed return; From 64250737d667c0720c01ed8350175d183bb83cb4 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Mon, 15 Aug 2022 23:57:53 +0100 Subject: [PATCH 04/14] [velux] simplify lambda Signed-off-by: Andrew Fiddian-Green --- .../binding/velux/internal/handler/VeluxBridgeHandler.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index ad2368f8585c9..5e034c91006ad 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -1044,8 +1044,6 @@ private void initializeVanePositionChannel(Thing thing) { * that it uses the newly modified channel list instead of the original one. */ final Thing newThing = veluxHandler.editThing().withChannels(channels).build(); - scheduler.submit(() -> { - veluxHandler.updateThing(newThing); - }); + scheduler.submit(() -> veluxHandler.updateThing(newThing)); } } From 7c1699781ac33b7d9388d7246089d5548ce2c242 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Tue, 16 Aug 2022 11:27:13 +0100 Subject: [PATCH 05/14] [velux] adopt kind recommendations from community forum Signed-off-by: Andrew Fiddian-Green --- .../binding/velux/internal/handler/VeluxBridgeHandler.java | 4 ++-- .../src/main/resources/OH-INF/thing/rollershutter.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index 5e034c91006ad..afd89e88bf03f 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -1021,8 +1021,8 @@ private void initializeVanePositionChannel(Thing thing) { if (vaneChannelRequired) { // build the vane channel - Channel newChannel = ChannelBuilder.create(vaneChannelUID).withAcceptedItemType(CoreItemFactory.DIMMER) - .withKind(ChannelKind.STATE) + Channel newChannel = ChannelBuilder.create(vaneChannelUID).withType(VeluxBindingConstants.CHANNEL_TYPE_VANE) + .withKind(ChannelKind.STATE).withAcceptedItemType(CoreItemFactory.DIMMER) .withDescription(localization.getText("channel-type.velux.vanePosition.description")) .withLabel(localization.getText("channel-type.velux.vanePosition.label")).build(); diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml index ed19d77c654f3..26173bc8ee6fd 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml @@ -8,7 +8,7 @@ - + From 819d0033a5780922e7d0fed6a5d8b32e66866be9 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Tue, 16 Aug 2022 11:47:10 +0100 Subject: [PATCH 06/14] [velux] clean up comment Signed-off-by: Andrew Fiddian-Green --- .../binding/velux/internal/handler/VeluxBridgeHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index afd89e88bf03f..3c185a61826af 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -989,7 +989,7 @@ private void initializeVanePositionChannel(Thing thing) { final VeluxProduct product = existingProducts() .get((new Thing2VeluxActuator(this, vaneChannelUID)).getProductBridgeIndex()); if (product.equals(VeluxProduct.UNKNOWN)) { - // product unknown"); + // product unknown return; } From 785f7436ea94d661dfd4f0cdd9cc62bee4d7f7cd Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Tue, 16 Aug 2022 18:47:51 +0100 Subject: [PATCH 07/14] [velux] delete infamous 'extensible' attribute Signed-off-by: Andrew Fiddian-Green --- .../src/main/resources/OH-INF/thing/rollershutter.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml index 26173bc8ee6fd..ed19d77c654f3 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml @@ -8,7 +8,7 @@ - + From b2945c9792fd0d7becdeb362701e11933e7edb9d Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Thu, 18 Aug 2022 14:58:22 +0100 Subject: [PATCH 08/14] [velux] adopt reviewer suggestions Signed-off-by: Andrew Fiddian-Green --- .../internal/handler/VeluxBridgeHandler.java | 86 ++----------------- .../velux/internal/handler/VeluxHandler.java | 81 ++++++++++++++--- 2 files changed, 74 insertions(+), 93 deletions(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index 3c185a61826af..84e66fa16e038 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -12,9 +12,7 @@ */ package org.openhab.binding.velux.internal.handler; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -23,7 +21,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import java.util.function.Predicate; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -64,21 +61,16 @@ import org.openhab.binding.velux.internal.utils.Localization; import org.openhab.core.common.AbstractUID; import org.openhab.core.common.NamedThreadFactory; -import org.openhab.core.library.CoreItemFactory; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; import org.openhab.core.thing.Bridge; -import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; -import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandlerService; -import org.openhab.core.thing.binding.builder.ChannelBuilder; -import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.openhab.core.types.State; @@ -970,80 +962,14 @@ public ProductBridgeIndex getProductBridgeIndex(String thingName) { } /** - * Iterate over all roller shutter type things in the hub, and initialise the dynamic vane position channel if the - * respective device supports it. + * Ask all things in the hub to initialise their dynamic vane position channel if they support it. */ private void initializeVanePositionChannels() { - getThing().getThings().stream() - .filter(thing -> VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER.equals(thing.getThingTypeUID())) - .forEach(thing -> initializeVanePositionChannel(thing)); - } - - /** - * For the given roller shutter type thing, initialise the dynamic vane position channel if the respective device - * supports it. - */ - private void initializeVanePositionChannel(Thing thing) { - final ChannelUID vaneChannelUID = new ChannelUID(thing.getUID(), VeluxBindingConstants.CHANNEL_VANE_POSITION); - - final VeluxProduct product = existingProducts() - .get((new Thing2VeluxActuator(this, vaneChannelUID)).getProductBridgeIndex()); - if (product.equals(VeluxProduct.UNKNOWN)) { - // product unknown - return; - } - - // predicate to filter the vane position channel - final Predicate vaneChannelFilter = c -> VeluxBindingConstants.CHANNEL_TYPE_VANE - .equals(c.getChannelTypeUID()); - - // note: this is an immutable list - List channels = thing.getChannels(); - - // current and required state of the vane channel - final boolean vaneChannelExisting = channels.stream().anyMatch(vaneChannelFilter); - final boolean vaneChannelRequired = product.supportsVanePosition(); - - if (vaneChannelExisting == vaneChannelRequired) { - // no change needed - return; - } - - ThingHandler handler = thing.getHandler(); - if (!(handler instanceof VeluxHandler)) { - // handler is of the wrong wrong type - return; - } - VeluxHandler veluxHandler = (VeluxHandler) handler; - - // make a mutable copy of the original immutable channel list - channels = new ArrayList<>(channels); - - if (vaneChannelRequired) { - // build the vane channel - Channel newChannel = ChannelBuilder.create(vaneChannelUID).withType(VeluxBindingConstants.CHANNEL_TYPE_VANE) - .withKind(ChannelKind.STATE).withAcceptedItemType(CoreItemFactory.DIMMER) - .withDescription(localization.getText("channel-type.velux.vanePosition.description")) - .withLabel(localization.getText("channel-type.velux.vanePosition.label")).build(); - - // add the vane channel - if (!channels.add(newChannel)) { - // failed to add vane channel - return; - } - } else { - // remove the vane channel - if (!channels.removeIf(vaneChannelFilter)) { - // failed to remove vane channel - return; + getThing().getThings().stream().forEach(thing -> { + ThingHandler thingHandler = thing.getHandler(); + if (thingHandler instanceof VeluxHandler) { + ((VeluxHandler) thingHandler).initializeVanePositionChannel(this); } - } - - /* - * If we got this far then we will update the thing by building an identical copy of the target thing, except - * that it uses the newly modified channel list instead of the original one. - */ - final Thing newThing = veluxHandler.editThing().withChannels(channels).build(); - scheduler.submit(() -> veluxHandler.updateThing(newThing)); + }); } } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java index f0c17e240a52d..78d5173f6f7f6 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java @@ -12,21 +12,30 @@ */ package org.openhab.binding.velux.internal.handler; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.function.Predicate; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.velux.internal.VeluxBindingConstants; import org.openhab.binding.velux.internal.config.VeluxThingConfiguration; import org.openhab.binding.velux.internal.handler.utils.ExtendedBaseThingHandler; +import org.openhab.binding.velux.internal.handler.utils.Thing2VeluxActuator; +import org.openhab.binding.velux.internal.things.VeluxProduct; import org.openhab.binding.velux.internal.utils.Localization; import org.openhab.core.config.core.Configuration; +import org.openhab.core.library.CoreItemFactory; import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BridgeHandler; -import org.openhab.core.thing.binding.builder.ThingBuilder; +import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.slf4j.Logger; @@ -42,10 +51,12 @@ public class VeluxHandler extends ExtendedBaseThingHandler { private final Logger logger = LoggerFactory.getLogger(VeluxHandler.class); - VeluxThingConfiguration configuration = new VeluxThingConfiguration(); + private VeluxThingConfiguration configuration = new VeluxThingConfiguration(); + private final Localization localization; public VeluxHandler(Thing thing, Localization localization) { super(thing); + this.localization = localization; logger.trace("VeluxHandler(thing={},localization={}) constructor called.", thing, localization); } @@ -128,18 +139,62 @@ public void handleConfigurationUpdate(Map configurationParameter } /** - * Set public visibility on the protected super.editThing() method. + * Initialise the dynamic vane position channel if the respective device supports it. + * + * @param bridgeHandler the calling bridge handler. + * @throws IllegalStateException if something went wrong. */ - @Override - public ThingBuilder editThing() { - return super.editThing(); - } + public void initializeVanePositionChannel(VeluxBridgeHandler bridgeHandler) throws IllegalStateException { + // roller shutters are the only things allowed to have vane support + if (!VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER.equals(thing.getThingTypeUID())) { + return; + } - /** - * Set public visibility on the protected super.updateThing() method. - */ - @Override - public void updateThing(Thing thing) { - super.updateThing(thing); + ChannelUID vaneChannelUID = new ChannelUID(thing.getUID(), VeluxBindingConstants.CHANNEL_VANE_POSITION); + + VeluxProduct product = bridgeHandler.existingProducts() + .get((new Thing2VeluxActuator(bridgeHandler, vaneChannelUID)).getProductBridgeIndex()); + if (product.equals(VeluxProduct.UNKNOWN)) { + throw new IllegalStateException("initializeVanePositionChannel(): Product unknown in the bridge"); + } + + // predicate to filter the vane position channel + Predicate vaneChannelPredicate = c -> VeluxBindingConstants.CHANNEL_TYPE_VANE + .equals(c.getChannelTypeUID()); + + // note: this is initially an immutable list + List channels = thing.getChannels(); + + // current and required state of the vane channel + boolean vaneChannelExisting = channels.stream().anyMatch(vaneChannelPredicate); + boolean vaneChannelRequired = product.supportsVanePosition(); + + if (vaneChannelExisting == vaneChannelRequired) { + // no change is needed + return; + } + + // make a mutable copy of the original immutable channel list + channels = new ArrayList<>(channels); + + if (vaneChannelRequired) { + // build and add the vane channel + // @formatter:off + channels.add(ChannelBuilder.create(vaneChannelUID) + .withType(VeluxBindingConstants.CHANNEL_TYPE_VANE) + .withKind(ChannelKind.STATE) + .withAcceptedItemType(CoreItemFactory.DIMMER) + .withDescription(localization.getText("channel-type.velux.vanePosition.description")) + .withLabel(localization.getText("channel-type.velux.vanePosition.label")) + .build()); + // @formatter:on + } else { + // remove the vane channel + channels.removeIf(vaneChannelPredicate); + } + + // if we got this far, then update the thing + Thing thing = editThing().withChannels(channels).build(); + scheduler.submit(() -> updateThing(thing)); } } From 9d0e33321095316413188a33d5fd129593658894 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Fri, 19 Aug 2022 17:25:28 +0100 Subject: [PATCH 09/14] [velux] confirm no recursion, plus cosmetics Signed-off-by: Andrew Fiddian-Green --- .../binding/velux/internal/handler/VeluxBridgeHandler.java | 6 +++--- .../binding/velux/internal/handler/VeluxHandler.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index 84e66fa16e038..c7bbc209cbaf0 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -466,7 +466,7 @@ private void bridgeParamsUpdated() { } } - initializeVanePositionChannels(); + updateDynamicChannels(); veluxBridgeConfiguration.hasChanged = false; logger.debug("Velux veluxBridge is online, now."); @@ -964,11 +964,11 @@ public ProductBridgeIndex getProductBridgeIndex(String thingName) { /** * Ask all things in the hub to initialise their dynamic vane position channel if they support it. */ - private void initializeVanePositionChannels() { + private void updateDynamicChannels() { getThing().getThings().stream().forEach(thing -> { ThingHandler thingHandler = thing.getHandler(); if (thingHandler instanceof VeluxHandler) { - ((VeluxHandler) thingHandler).initializeVanePositionChannel(this); + ((VeluxHandler) thingHandler).updateDynamicChannels(this); } }); } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java index 78d5173f6f7f6..5ab16d764f926 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java @@ -144,7 +144,7 @@ public void handleConfigurationUpdate(Map configurationParameter * @param bridgeHandler the calling bridge handler. * @throws IllegalStateException if something went wrong. */ - public void initializeVanePositionChannel(VeluxBridgeHandler bridgeHandler) throws IllegalStateException { + public void updateDynamicChannels(VeluxBridgeHandler bridgeHandler) throws IllegalStateException { // roller shutters are the only things allowed to have vane support if (!VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER.equals(thing.getThingTypeUID())) { return; From 81bf48376dd2f6c3575e66996308f0654e1b174c Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Mon, 22 Aug 2022 15:07:49 +0100 Subject: [PATCH 10/14] [velux] revert from channel creation to channel removal Signed-off-by: Andrew Fiddian-Green --- .../velux/internal/VeluxBindingConstants.java | 5 -- .../velux/internal/handler/VeluxHandler.java | 63 +++++-------------- .../resources/OH-INF/thing/rollershutter.xml | 1 + 3 files changed, 15 insertions(+), 54 deletions(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java index 7875720a423a9..31472d73a2863 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java @@ -18,7 +18,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; -import org.openhab.core.thing.type.ChannelTypeUID; /** * The {@link VeluxBindingConstants} class defines common constants, which are @@ -158,8 +157,4 @@ public class VeluxBindingConstants { public static final String UNKNOWN_THING_TYPE_ID = "FAILED"; public static final String UNKNOWN_IP_ADDRESS = "xxx.xxx.xxx.xxx"; - - // Channel Type UIDs - public static final ChannelTypeUID CHANNEL_TYPE_MAIN = new ChannelTypeUID(BINDING_ID, CHANNEL_ACTUATOR_POSITION); - public static final ChannelTypeUID CHANNEL_TYPE_VANE = new ChannelTypeUID(BINDING_ID, CHANNEL_VANE_POSITION); } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java index 5ab16d764f926..a85f5b0bce649 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java @@ -12,11 +12,8 @@ */ package org.openhab.binding.velux.internal.handler; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.function.Predicate; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.velux.internal.VeluxBindingConstants; @@ -26,7 +23,6 @@ import org.openhab.binding.velux.internal.things.VeluxProduct; import org.openhab.binding.velux.internal.utils.Localization; import org.openhab.core.config.core.Configuration; -import org.openhab.core.library.CoreItemFactory; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; @@ -34,8 +30,6 @@ import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BridgeHandler; -import org.openhab.core.thing.binding.builder.ChannelBuilder; -import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.slf4j.Logger; @@ -52,11 +46,9 @@ public class VeluxHandler extends ExtendedBaseThingHandler { private final Logger logger = LoggerFactory.getLogger(VeluxHandler.class); private VeluxThingConfiguration configuration = new VeluxThingConfiguration(); - private final Localization localization; public VeluxHandler(Thing thing, Localization localization) { super(thing); - this.localization = localization; logger.trace("VeluxHandler(thing={},localization={}) constructor called.", thing, localization); } @@ -139,62 +131,35 @@ public void handleConfigurationUpdate(Map configurationParameter } /** - * Initialise the dynamic vane position channel if the respective device supports it. + * Remove previously statically created vane channel if the device does not support it. Or log a warning if it does + * support a vane and the respective channel is missing. * * @param bridgeHandler the calling bridge handler. * @throws IllegalStateException if something went wrong. */ public void updateDynamicChannels(VeluxBridgeHandler bridgeHandler) throws IllegalStateException { - // roller shutters are the only things allowed to have vane support + // roller shutters are the only things with a previously statically created vane channel if (!VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER.equals(thing.getThingTypeUID())) { return; } - ChannelUID vaneChannelUID = new ChannelUID(thing.getUID(), VeluxBindingConstants.CHANNEL_VANE_POSITION); + String id = VeluxBindingConstants.CHANNEL_VANE_POSITION; + ChannelUID uid = new ChannelUID(thing.getUID(), id); + Thing2VeluxActuator actuator = new Thing2VeluxActuator(bridgeHandler, uid); + VeluxProduct product = bridgeHandler.existingProducts().get(actuator.getProductBridgeIndex()); - VeluxProduct product = bridgeHandler.existingProducts() - .get((new Thing2VeluxActuator(bridgeHandler, vaneChannelUID)).getProductBridgeIndex()); if (product.equals(VeluxProduct.UNKNOWN)) { throw new IllegalStateException("initializeVanePositionChannel(): Product unknown in the bridge"); } - // predicate to filter the vane position channel - Predicate vaneChannelPredicate = c -> VeluxBindingConstants.CHANNEL_TYPE_VANE - .equals(c.getChannelTypeUID()); + Channel channel = thing.getChannel(id); + boolean required = product.supportsVanePosition(); - // note: this is initially an immutable list - List channels = thing.getChannels(); - - // current and required state of the vane channel - boolean vaneChannelExisting = channels.stream().anyMatch(vaneChannelPredicate); - boolean vaneChannelRequired = product.supportsVanePosition(); - - if (vaneChannelExisting == vaneChannelRequired) { - // no change is needed - return; + if (!required && channel != null) { + logger.debug("Removing unsupported channel for {}: {}", thing.getUID(), id); + scheduler.submit(() -> updateThing(editThing().withoutChannels(channel).build())); + } else if (required && channel == null) { + logger.warn("Thing {} does not have a '{}' channel => please reinitialize it", thing.getUID(), id); } - - // make a mutable copy of the original immutable channel list - channels = new ArrayList<>(channels); - - if (vaneChannelRequired) { - // build and add the vane channel - // @formatter:off - channels.add(ChannelBuilder.create(vaneChannelUID) - .withType(VeluxBindingConstants.CHANNEL_TYPE_VANE) - .withKind(ChannelKind.STATE) - .withAcceptedItemType(CoreItemFactory.DIMMER) - .withDescription(localization.getText("channel-type.velux.vanePosition.description")) - .withLabel(localization.getText("channel-type.velux.vanePosition.label")) - .build()); - // @formatter:on - } else { - // remove the vane channel - channels.removeIf(vaneChannelPredicate); - } - - // if we got this far, then update the thing - Thing thing = editThing().withChannels(channels).build(); - scheduler.submit(() -> updateThing(thing)); } } diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml index ed19d77c654f3..2918a796656f0 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/rollershutter.xml @@ -17,6 +17,7 @@ Blinds + From a988f613fc6ef7eb633778d2e73b48e060808010 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Tue, 23 Aug 2022 18:08:59 +0100 Subject: [PATCH 11/14] [velux] change category of window position from 'blinds' to 'window' Signed-off-by: Andrew Fiddian-Green --- .../src/main/resources/OH-INF/i18n/velux.properties | 2 ++ .../src/main/resources/OH-INF/thing/channels.xml | 7 +++++++ .../src/main/resources/OH-INF/thing/window.xml | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux.properties b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux.properties index 3163c66d154df..67355089c4e22 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux.properties +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux.properties @@ -133,6 +133,8 @@ channel-type.velux.scenes.description = Scenes which are configured on the Bridg channel-type.velux.check.label = Check of configuration channel-type.velux.check.description = Result of the check of current item configuration. # +channel-type.velux.windowPosition.label = Position +channel-type.velux.windowPosition.description = Device control (UP, DOWN, STOP, closure 0-100%). channel-type.velux.position.label = Position channel-type.velux.position.description = Device control (UP, DOWN, STOP, closure 0-100%). channel-type.velux.vanePosition.label = Vane Position diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml index 3a06e242c7387..be72b51e18294 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml @@ -132,6 +132,13 @@ + + Rollershutter + + @text/channel-type.velux.windowPosition.description + Window + + Rollershutter diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/window.xml b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/window.xml index d4e8f4e2f53af..baa278e0dcc89 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/window.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/window.xml @@ -16,7 +16,7 @@ @text/thing-type.velux.window.description Window - + From c98b5e6facaea7334082aec4e2b1b9ac9388804c Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Tue, 23 Aug 2022 18:17:52 +0100 Subject: [PATCH 12/14] [velux] remove vane category Signed-off-by: Andrew Fiddian-Green --- .../src/main/resources/OH-INF/thing/channels.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml index be72b51e18294..ab003a89ed709 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml @@ -150,7 +150,6 @@ Dimmer @text/channel-type.velux.vanePosition.description - Blinds From 50b1a5ed5bd02578cffdbabbce3a154121b4b6ea Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Sun, 11 Sep 2022 10:43:02 +0100 Subject: [PATCH 13/14] [velux] remove configuration; apply reviewer suggestions Signed-off-by: Andrew Fiddian-Green --- .../binding/velux/internal/handler/VeluxHandler.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java index a85f5b0bce649..15648ce0ca433 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java @@ -17,7 +17,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.velux.internal.VeluxBindingConstants; -import org.openhab.binding.velux.internal.config.VeluxThingConfiguration; import org.openhab.binding.velux.internal.handler.utils.ExtendedBaseThingHandler; import org.openhab.binding.velux.internal.handler.utils.Thing2VeluxActuator; import org.openhab.binding.velux.internal.things.VeluxProduct; @@ -45,8 +44,6 @@ public class VeluxHandler extends ExtendedBaseThingHandler { private final Logger logger = LoggerFactory.getLogger(VeluxHandler.class); - private VeluxThingConfiguration configuration = new VeluxThingConfiguration(); - public VeluxHandler(Thing thing, Localization localization) { super(thing); logger.trace("VeluxHandler(thing={},localization={}) constructor called.", thing, localization); @@ -74,7 +71,6 @@ public void initialize() { } private synchronized void initializeProperties() { - configuration = getConfigAs(VeluxThingConfiguration.class); logger.trace("initializeProperties() done."); } @@ -149,7 +145,7 @@ public void updateDynamicChannels(VeluxBridgeHandler bridgeHandler) throws Illeg VeluxProduct product = bridgeHandler.existingProducts().get(actuator.getProductBridgeIndex()); if (product.equals(VeluxProduct.UNKNOWN)) { - throw new IllegalStateException("initializeVanePositionChannel(): Product unknown in the bridge"); + throw new IllegalStateException("updateDynamicChannels(): Product unknown in the bridge"); } Channel channel = thing.getChannel(id); @@ -157,9 +153,9 @@ public void updateDynamicChannels(VeluxBridgeHandler bridgeHandler) throws Illeg if (!required && channel != null) { logger.debug("Removing unsupported channel for {}: {}", thing.getUID(), id); - scheduler.submit(() -> updateThing(editThing().withoutChannels(channel).build())); + updateThing(editThing().withoutChannels(channel).build()); } else if (required && channel == null) { - logger.warn("Thing {} does not have a '{}' channel => please reinitialize it", thing.getUID(), id); + logger.warn("Thing {} does not have a '{}' channel => please re-create it", thing.getUID(), id); } } } From b0e3bab4fb2e37703f65b161209090ea014b4d53 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Sun, 11 Sep 2022 10:43:31 +0100 Subject: [PATCH 14/14] [velux] apply reviewer suggestions Signed-off-by: Andrew Fiddian-Green --- .../src/main/resources/OH-INF/thing/channels.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml index ab003a89ed709..a65e3c08d8fd7 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/thing/channels.xml @@ -137,6 +137,7 @@ @text/channel-type.velux.windowPosition.description Window + @@ -144,6 +145,7 @@ @text/channel-type.velux.position.description Blinds + @@ -164,14 +166,14 @@ Rollershutter @text/channel-type.velux.limitMinimum.description - Blinds + Rollershutter @text/channel-type.velux.limitMaximum.description - Blinds +