From 6878384df9cbc5589f50002d300725ecac82df56 Mon Sep 17 00:00:00 2001 From: Boris Krivonog Date: Thu, 4 Feb 2021 22:59:44 +0100 Subject: [PATCH] [nikobus] added option to reverse rollershutter commands (#10047) * Added option to reverse rollershutter commands - UP -> DOWN and DOWN -> UP - might happen if rollershuter module's output is wired differently. * Fixed PR comments. Signed-off-by: Boris Krivonog --- bundles/org.openhab.binding.nikobus/README.md | 2 + .../handler/NikobusDimmerModuleHandler.java | 6 +- .../handler/NikobusModuleHandler.java | 8 +-- .../NikobusRollershutterModuleHandler.java | 55 +++++++++++++++---- .../handler/NikobusSwitchModuleHandler.java | 4 +- .../main/resources/OH-INF/config/config.xml | 4 ++ 6 files changed, 59 insertions(+), 20 deletions(-) diff --git a/bundles/org.openhab.binding.nikobus/README.md b/bundles/org.openhab.binding.nikobus/README.md index b75868e5f..76a57cf0a 100644 --- a/bundles/org.openhab.binding.nikobus/README.md +++ b/bundles/org.openhab.binding.nikobus/README.md @@ -131,6 +131,8 @@ Defines a `rollershutter-module` with address `4C6C`. | output-5 | Rollershutter | Output 5 | | output-6 | Rollershutter | Output 6 | +In case rollershutters are moving in the oposite direction when sending `UP` or `DOWN` commands, there is a `reverse` parameter, which can be set to `true` in this case to reverse the rollershutter's direction. Defaults to `false`. + ##### Estimating Position Nikobus rollershuter module does not provide information about rollershutter's position. In order to bridge this gap, an optional parameter `duration` can be set per channel, describing the amount of time needed by a rollershutter to get from open to closed state (or vice-versa). diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusDimmerModuleHandler.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusDimmerModuleHandler.java index cf2f3cb69..45fe86060 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusDimmerModuleHandler.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusDimmerModuleHandler.java @@ -53,16 +53,16 @@ public class NikobusDimmerModuleHandler extends NikobusSwitchModuleHandler { } @Override - protected int valueFromCommand(Command command) { + protected int valueFromCommand(String channelId, Command command) { if (command instanceof PercentType) { return Math.round(((PercentType) command).floatValue() / 100f * 255f); } - return super.valueFromCommand(command); + return super.valueFromCommand(channelId, command); } @Override - protected State stateFromValue(int value) { + protected State stateFromValue(String channelId, int value) { int result = Math.round(value * 100f / 255f); return new PercentType(result); } diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusModuleHandler.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusModuleHandler.java index 07c0bdddd..5a7762fba 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusModuleHandler.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusModuleHandler.java @@ -182,7 +182,7 @@ abstract class NikobusModuleHandler extends NikobusBaseThingHandler { } if (previousValue == null || previousValue.intValue() != value) { - updateState(channelId, stateFromValue(value)); + updateState(channelId, stateFromValue(channelId, value)); } } @@ -195,7 +195,7 @@ abstract class NikobusModuleHandler extends NikobusBaseThingHandler { Integer digits; if (channelId.equals(channelUID.getId())) { - digits = valueFromCommand(command); + digits = valueFromCommand(channelId, command); updateStateAndCacheValue(channelId, digits.intValue()); } else { synchronized (cachedStates) { @@ -233,7 +233,7 @@ abstract class NikobusModuleHandler extends NikobusBaseThingHandler { } } - protected abstract int valueFromCommand(Command command); + protected abstract int valueFromCommand(String channelId, Command command); - protected abstract State stateFromValue(int value); + protected abstract State stateFromValue(String channelId, int value); } diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusRollershutterModuleHandler.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusRollershutterModuleHandler.java index 95a986c62..963755763 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusRollershutterModuleHandler.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusRollershutterModuleHandler.java @@ -13,6 +13,8 @@ package org.openhab.binding.nikobus.internal.handler; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -44,6 +46,8 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler { private final Logger logger = LoggerFactory.getLogger(NikobusRollershutterModuleHandler.class); private final List positionEstimators = new CopyOnWriteArrayList<>(); + private final Map directionConfigurations = new ConcurrentHashMap<>(); + public NikobusRollershutterModuleHandler(Thing thing) { super(thing); } @@ -57,43 +61,50 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler { } positionEstimators.clear(); + directionConfigurations.clear(); for (Channel channel : thing.getChannels()) { PositionEstimatorConfig config = channel.getConfiguration().as(PositionEstimatorConfig.class); if (config.delay >= 0 && config.duration > 0) { positionEstimators.add(new PositionEstimator(channel.getUID(), config)); } + + DirectionConfiguration configuration = config.reverse ? DirectionConfiguration.REVERSED + : DirectionConfiguration.NORMAL; + directionConfigurations.put(channel.getUID().getId(), configuration); } logger.debug("Position estimators for {} = {}", thing.getUID(), positionEstimators); } @Override - protected int valueFromCommand(Command command) { - if (command == UpDownType.DOWN || command == StopMoveType.MOVE) { - return 0x02; - } - if (command == UpDownType.UP) { - return 0x01; - } + protected int valueFromCommand(String channelId, Command command) { if (command == StopMoveType.STOP) { return 0x00; } - + if (command == UpDownType.DOWN || command == StopMoveType.MOVE) { + return getDirectionConfiguration(channelId).down; + } + if (command == UpDownType.UP) { + return getDirectionConfiguration(channelId).up; + } throw new IllegalArgumentException("Command '" + command + "' not supported"); } @Override - protected State stateFromValue(int value) { + protected State stateFromValue(String channelId, int value) { if (value == 0x00) { return OnOffType.OFF; } - if (value == 0x01) { + + DirectionConfiguration configuration = getDirectionConfiguration(channelId); + if (value == configuration.up) { return UpDownType.UP; } - if (value == 0x02) { + if (value == configuration.down) { return UpDownType.DOWN; } + throw new IllegalArgumentException("Unexpected value " + value + " received"); } @@ -119,9 +130,18 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler { super.updateState(channelUID, new PercentType(percent)); } + private DirectionConfiguration getDirectionConfiguration(String channelId) { + DirectionConfiguration configuration = directionConfigurations.get(channelId); + if (configuration == null) { + throw new IllegalArgumentException("Direction configuration not found for " + channelId); + } + return configuration; + } + public static class PositionEstimatorConfig { public int duration = -1; public int delay = 5; + public boolean reverse = false; } private class PositionEstimator { @@ -203,4 +223,17 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler { + delayInMillis + "ms)"; } } + + private static class DirectionConfiguration { + final int up; + final int down; + + final static DirectionConfiguration NORMAL = new DirectionConfiguration(1, 2); + final static DirectionConfiguration REVERSED = new DirectionConfiguration(2, 1); + + private DirectionConfiguration(int up, int down) { + this.up = up; + this.down = down; + } + } } diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusSwitchModuleHandler.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusSwitchModuleHandler.java index d23cc467a..449f2ae78 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusSwitchModuleHandler.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusSwitchModuleHandler.java @@ -30,7 +30,7 @@ public class NikobusSwitchModuleHandler extends NikobusModuleHandler { } @Override - protected int valueFromCommand(Command command) { + protected int valueFromCommand(String channelId, Command command) { if (command == OnOffType.ON) { return 0xff; } @@ -43,7 +43,7 @@ public class NikobusSwitchModuleHandler extends NikobusModuleHandler { } @Override - protected State stateFromValue(int value) { + protected State stateFromValue(String channelId, int value) { return value != 0 ? OnOffType.ON : OnOffType.OFF; } } diff --git a/bundles/org.openhab.binding.nikobus/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.nikobus/src/main/resources/OH-INF/config/config.xml index c7353d3e5..eb767784f 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.nikobus/src/main/resources/OH-INF/config/config.xml @@ -44,6 +44,10 @@ Delay specifying how many seconds after duration module's output is set to OFF. Defaults to 5 seconds + + + Reverse direction of rollershutters. Defaults to false +