]> git.basschouten.com Git - openhab-addons.git/commitdiff
[velbus] Add new functionality PRESSED and LONG PRESSED (#10664)
authorDaniel Rosengarten <rosengarten01@hotmail.com>
Sat, 29 May 2021 18:23:29 +0000 (20:23 +0200)
committerGitHub <noreply@github.com>
Sat, 29 May 2021 18:23:29 +0000 (20:23 +0200)
* [velbus] Add new functionality PRESSED and LONG PRESSED and fix bug

New functionality:
Add the the possibility to simulate the PRESSED and LONG PRESSED message of an input.

Module supported with button simulation :
VMB1RYS (button : CH6)
VMB6IN (buttons : CH1 ... CH6)
VMB2PBN, VMB6PBN, VMB7IN, VMB8IR, VMB8PB, VMB8PBU, VMBEL1, VMBEL2, VMBEL4, VMBGP1, VMBGP1-2, VMBGP2, VMBGP2-2, VMBGP4, VMBGP4-2, VMBGP4PIR, VMBGP4PIR-2 (buttons : CH1 ... CH8)
VMBELO, VMBGPOD, VMBGPOD-2 (buttons : CH1 ... CH32)

Fix bug:
The channels names were not correctly assigned to the thing properties. The last channel had the default name, not the one retrieved from the module.

Also-by: cedricboon <cedric.boon@hotmail.com>
Signed-off-by: Daniel Rosengarten <github@praetorians.be>
bundles/org.openhab.binding.velbus/README.md
bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/VelbusHandlerFactory.java
bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/VelbusModule.java
bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/discovery/VelbusThingDiscoveryService.java
bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusRelayHandler.java
bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusRelayWithInputHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusSensorHandler.java
bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusButtonPacket.java [new file with mode: 0644]
bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/thing/thing-types.xml

index 001c2859bfc2330ca3f208a6c9f8cd01013dd6ec..d6ae71b34a07040a6c4b3a7b032627ef94095750 100644 (file)
@@ -152,18 +152,30 @@ OnOff command types are supported.
 For thing type `vmb4ry` 4 channels are available `CH1` ... `CH4`.
 OnOff command types are supported.
 
-For thing types `vmb1ryno`, `vmb1rynos`, `vmb1rys`, `vmb4ryld` and `vmb4ryno` 5 channels are available `CH1` ... `CH5`.
+For thing types `vmb1ryno`, `vmb1rynos`, `vmb4ryld` and `vmb4ryno` 5 channels are available `CH1` ... `CH5`.
 OnOff command types are supported.
 
+For thing types `vmb1rys` 6 channels are available `CH1` ... `CH6`.
+OnOff command types are supported on channels `CH1` ... `CH5`.
+Pressed and Long_Pressed command types are supported on channel `CH6`.
+1 trigger channel on `CH6t`.
+
 The module `vmb1ts` has a number of channels to set the module's thermostat (`thermostat:currentTemperatureSetpoint`, `thermostat:heatingModeComfortTemperatureSetpoint`, `thermostat:heatingModeDayTemperatureSetpoint`, `thermostat:heatingModeNightTemperatureSetpoint`, `thermostat:heatingModeAntiFrostTemperatureSetpoint`, `thermostat:coolingModeComfortTemperatureSetpoint`, `thermostat:coolingModeDayTemperatureSetpoint`, `thermostat:coolingModeNightTemperatureSetpoint`, `thermostat:coolingModeSafeTemperatureSetpoint`, `operatingMode` and `thermostat:mode`) and thermostat trigger channels: `thermostat:heater`, `thermostat:boost`, `thermostat:pump`, `thermostat:cooler`, `thermostat:alarm1`, `thermostat:alarm2`, `thermostat:alarm3`, `thermostat:alarm4`.
 
 For thing types `vmb2bl` and `vmb2ble` the supported channels are `CH1` and `CH2`. UpDown, StopMove and Percent command types are supported.
 
-Thing type `vmb6in` has 6 trigger channels `input#CH1` ... `input#CH6`.
+For thing type `vmb6in` 6 channels are available `CH1` ... `CH6`.
+Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH6`.
+6 trigger channels on channels `input#CH1` ... `input#CH6`.
+
+For thing type `vmb7in` 8 channels are available `CH1` ... `CH8`.
+Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH8`.
+8 trigger channels on channels `input#CH1` ... `input#CH8`.
 
-Thing type `vmb7in` has 8 trigger channels `input#CH1` ... `input#CH8`.
+For thing types `vmb2pbn`, `vmb6pbn`, `vmb7in`, `vmb8ir`, `vmb8pb`, `vmb8pbu`, `vmbrfr8s` and `vmbvp1`  8 channels are available `CH1` ... `CH8`.
+Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH8`.
+8 trigger channels on channels `input:CH1` ... `input:CH8`.
 
-Thing types `vmb2pbn`, `vmb6pbn`, `vmb7in`, `vmb8ir`, `vmb8pb`, `vmb8pbu`, `vmbrfr8s` and `vmbvp1` have 8 trigger channels (`input:CH1` ... `input:CH8`).
 Thing types `vmb2pbn`, `vmb6pbn`, `vmb7in`, `vmb8pb`, `vmb8pbu`, `vmbrfr8s` and `vmbvp1` also have and 2 channels to steer the button LED feedback (`feedback:CH1` and `feedback:CH2`).
 Additionally, the modules `vmb2pbn`, `vmb6pbn`, `vmb7in`, `vmb8pbu`, `vmbrfr8s` and `vmbvp1` have a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
 
@@ -181,6 +193,7 @@ For thing type `vmb4ry` 4 channels are available `CH1` ... `CH4`.
 OnOff command types are supported.
 
 Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4`, `vmbgp4pir` and `vmbpiro` have 8 trigger channels `input:CH1` ... `input:CH8` and one temperature channel `input:CH9`.
+Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH8`.
 The thing types `vmbel1` and `vmbgp1` have one channel to steer the button LED feedback `feedback:CH1`.
 The thing types `vmbel2` and `vmbgp2` have two channels to steer the button LED feedback `feedback:CH1` and `feedback:CH2`.
 The thing types `vmbel4`, `vmbgp4` and `vmbgp4pir` have four channels to steer the button LED feedback `feedback:CH1` ... `feedback:CH4`.
@@ -189,6 +202,7 @@ Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4` and `vmbg
 Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4` and `vmbgp4pir` also have a number of channels to set the module's thermostat (`thermostat:currentTemperatureSetpoint`, `thermostat:heatingModeComfortTemperatureSetpoint`, `thermostat:heatingModeDayTemperatureSetpoint`, `thermostat:heatingModeNightTemperatureSetpoint`, `thermostat:heatingModeAntiFrostTemperatureSetpoint`, `thermostat:coolingModeComfortTemperatureSetpoint`, `thermostat:coolingModeDayTemperatureSetpoint`, `thermostat:coolingModeNightTemperatureSetpoint`, `thermostat:coolingModeSafeTemperatureSetpoint`, `operatingMode` and `thermostat:mode`) and thermostat trigger channels: `thermostat:heater`, `thermostat:boost`, `thermostat:pump`, `thermostat:cooler`, `thermostat:alarm1`, `thermostat:alarm2`, `thermostat:alarm3`, `thermostat:alarm4`.
 
 Thing types `vmbelo`, `vmbgpo` and `vmbgpod` have 32 trigger channels `input:CH1` ... `input:CH32` and one temperature channel `input:CH33`.
+Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH32`.
 They have have 32 channels to steer the button LED feedback `feedback:CH1` ... `feedback:CH32`.
 They have a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
 They have a number of channels to set the module's thermostat thermostat (`thermostat:currentTemperatureSetpoint`, `thermostat:heatingModeComfortTemperatureSetpoint`, `thermostat:heatingModeDayTemperatureSetpoint`, `thermostat:heatingModeNightTemperatureSetpoint`, `thermostat:heatingModeAntiFrostTemperatureSetpoint`, `thermostat:coolingModeComfortTemperatureSetpoint`, `thermostat:coolingModeDayTemperatureSetpoint`, `thermostat:coolingModeNightTemperatureSetpoint`, `thermostat:coolingModeSafeTemperatureSetpoint`, `operatingMode` and `thermostat:mode`) and thermostat trigger channels: `thermostat:heater`, `thermostat:boost`, `thermostat:pump`, `thermostat:cooler`, `thermostat:alarm1`, `thermostat:alarm2`, `thermostat:alarm3`, `thermostat:alarm4`.
@@ -203,6 +217,9 @@ Additionally, these modules have a number of channels to set the module's alarms
 
 The trigger channels can be used as a trigger to rules. The event message can be `PRESSED`, `RELEASED`or `LONG_PRESSED`.
 
+To remove the state of the Item in the Sitemap for a `button` channel.
+Go to the Items list, select the Item, add a State Description Metadata, and set the Pattern value to a blank space.
+
 ## Full Example
 
 .things:
@@ -230,6 +247,7 @@ Bridge velbus:bridge:1 [ port="COM1"] {
 
 ```
 Switch LivingRoom           {channel="velbus:vmb4ryld:1:06:CH1"}                # Switch for onOff type action
+Switch KitchenButton        {velbus:vmb2pbn:1:05:button#CH1}                    # Switch for Pressed and Long_Pressed type actions
 Dimmer TVRoom               {channel="velbus:vmb4dc:1:07:CH2"}                  # Changing brightness dimmer type action
 Rollershutter Kitchen       {channel="velbus:vmb2ble:1:01"}                     # Controlling rollershutter or blind type action
 
@@ -245,6 +263,12 @@ Switch item=LivingRoom
 Slider item=TVRoom
 Switch item=TVRoom          # allows switching dimmer item off or on
 Rollershutter item=Kitchen
+
+Switch item=KitchenButton # Press and Long_Pressed message are available
+# or
+Switch item=KitchenButton mappings=[PRESSED="Push"] # only the Pressed message is send on the bus
+# or
+Switch item=KitchenButton mappings=[LONG_PRESSED="Push"] # only the Long_Pressed message is send on the bus
 ```
 
 Example trigger rule:
index 8c7b1cdefb1c2cf6aec37de941f73c7dc726c745..f603a20542054008d5590c187845a96c2d930943 100644 (file)
@@ -21,6 +21,7 @@ import org.openhab.binding.velbus.internal.handler.VelbusBridgeHandler;
 import org.openhab.binding.velbus.internal.handler.VelbusDimmerHandler;
 import org.openhab.binding.velbus.internal.handler.VelbusNetworkBridgeHandler;
 import org.openhab.binding.velbus.internal.handler.VelbusRelayHandler;
+import org.openhab.binding.velbus.internal.handler.VelbusRelayWithInputHandler;
 import org.openhab.binding.velbus.internal.handler.VelbusSensorHandler;
 import org.openhab.binding.velbus.internal.handler.VelbusSensorWithAlarmClockHandler;
 import org.openhab.binding.velbus.internal.handler.VelbusSerialBridgeHandler;
@@ -77,6 +78,8 @@ public class VelbusHandlerFactory extends BaseThingHandlerFactory {
             thingHandler = velbusBridgeHandler;
         } else if (VelbusRelayHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
             thingHandler = new VelbusRelayHandler(thing);
+        } else if (VelbusRelayWithInputHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
+            thingHandler = new VelbusRelayWithInputHandler(thing);
         } else if (VelbusDimmerHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
             thingHandler = new VelbusDimmerHandler(thing);
         } else if (VelbusBlindsHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
index 49f9faa4b33338c84538c048f4f1949fd5c4428d..7037f3fcf5aaf6d632a93dd6d587d274f781e9b1 100644 (file)
@@ -94,7 +94,7 @@ public class VelbusModule {
     protected String getChannelName(int channelIndex) {
         String channelName = "";
 
-        Integer key = channelIndex - 1;
+        Integer key = channelIndex;
         if (channelNames.containsKey(key)) {
             for (int i = 0; i < 3; i++) {
                 String channelNamePart = channelNames.get(key)[i];
@@ -147,7 +147,7 @@ public class VelbusModule {
         for (Integer key : keys) {
             String channelName = getChannelName(key);
             if (channelName.length() > 0) {
-                properties.put(CHANNEL + key, channelName);
+                properties.put(CHANNEL + (key + 1), channelName);
             }
         }
 
index 417b8188685724d57620c19178f1c9cea799e586..65f32e9a6a4d2b349069ab5916fa8be0f98e934e 100644 (file)
@@ -32,7 +32,6 @@ import org.openhab.binding.velbus.internal.packets.VelbusScanPacket;
 import org.openhab.core.config.discovery.AbstractDiscoveryService;
 import org.openhab.core.config.discovery.DiscoveryResult;
 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
-import org.openhab.core.config.discovery.DiscoveryService;
 import org.openhab.core.thing.ThingUID;
 import org.openhab.core.thing.binding.ThingHandler;
 import org.openhab.core.thing.binding.ThingHandlerService;
@@ -48,7 +47,7 @@ import org.slf4j.LoggerFactory;
  */
 @NonNullByDefault
 public class VelbusThingDiscoveryService extends AbstractDiscoveryService
-        implements DiscoveryService, ThingHandlerService, VelbusPacketListener {
+        implements ThingHandlerService, VelbusPacketListener {
     private static final int SEARCH_TIME = 60;
 
     private final Logger logger = LoggerFactory.getLogger(VelbusThingDiscoveryService.class);
index 196a775b95219e9f21d5281431a8eeafa827508b..9137fbe36361fbd11cc76e5bda2f3d5aff1f4026 100644 (file)
@@ -40,9 +40,8 @@ import org.openhab.core.types.RefreshType;
  */
 @NonNullByDefault
 public class VelbusRelayHandler extends VelbusThingHandler {
-    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
-            Arrays.asList(THING_TYPE_VMB1RY, THING_TYPE_VMB1RYNO, THING_TYPE_VMB1RYNOS, THING_TYPE_VMB1RYS,
-                    THING_TYPE_VMB4RY, THING_TYPE_VMB4RYLD, THING_TYPE_VMB4RYNO));
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB1RY,
+            THING_TYPE_VMB1RYNO, THING_TYPE_VMB1RYNOS, THING_TYPE_VMB4RY, THING_TYPE_VMB4RYLD, THING_TYPE_VMB4RYNO));
 
     public VelbusRelayHandler(Thing thing) {
         super(thing, 0);
diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusRelayWithInputHandler.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusRelayWithInputHandler.java
new file mode 100644 (file)
index 0000000..feca2df
--- /dev/null
@@ -0,0 +1,128 @@
+/**
+ * Copyright (c) 2010-2021 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.velbus.internal.handler;
+
+import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
+import org.openhab.binding.velbus.internal.packets.VelbusButtonPacket;
+import org.openhab.binding.velbus.internal.packets.VelbusPacket;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.CommonTriggerEvents;
+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.types.Command;
+
+/**
+ * The {@link VelbusRelayWithInputHandler} is responsible for handling commands, which are
+ * sent to one of the channels.
+ *
+ * @author Daniel Rosengarten - Initial contribution
+ */
+@NonNullByDefault
+public class VelbusRelayWithInputHandler extends VelbusRelayHandler {
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB1RYS));
+
+    private static final StringType PRESSED = new StringType("PRESSED");
+    private static final StringType LONG_PRESSED = new StringType("LONG_PRESSED");
+
+    public VelbusRelayWithInputHandler(Thing thing) {
+        super(thing);
+    }
+
+    @Override
+    public void handleCommand(ChannelUID channelUID, Command command) {
+        super.handleCommand(channelUID, command);
+
+        VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
+        if (velbusBridgeHandler == null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
+            return;
+        }
+
+        if (isButtonChannel(channelUID) && command instanceof StringType) {
+            StringType stringTypeCommand = (StringType) command;
+
+            if (stringTypeCommand.equals(PRESSED) || stringTypeCommand.equals(LONG_PRESSED)) {
+                VelbusButtonPacket packet = new VelbusButtonPacket(getModuleAddress().getChannelIdentifier(channelUID));
+
+                packet.Pressed();
+                velbusBridgeHandler.sendPacket(packet.getBytes());
+                triggerChannel("CH6t", CommonTriggerEvents.PRESSED);
+
+                if (stringTypeCommand.equals(LONG_PRESSED)) {
+                    packet.LongPressed();
+                    velbusBridgeHandler.sendPacket(packet.getBytes());
+                    triggerChannel("CH6t", CommonTriggerEvents.LONG_PRESSED);
+                }
+
+                packet.Released();
+                velbusBridgeHandler.sendPacket(packet.getBytes());
+                triggerChannel("CH6t", CommonTriggerEvents.RELEASED);
+            } else {
+                throw new UnsupportedOperationException(
+                        "The command '" + command + "' is not supported on channel '" + channelUID + "'.");
+            }
+        }
+    }
+
+    private boolean isButtonChannel(ChannelUID channelUID) {
+        return "CH6".equals(channelUID.toString().substring(channelUID.toString().length() - 3));
+    }
+
+    private boolean isTriggerChannel(byte address, byte channel) {
+        VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address, channel);
+
+        if (getModuleAddress().getChannelNumber(velbusChannelIdentifier) == 6) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public void onPacketReceived(byte[] packet) {
+        super.onPacketReceived(packet);
+
+        if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
+            byte command = packet[4];
+
+            if (command == COMMAND_PUSH_BUTTON_STATUS && packet.length >= 6) {
+                byte address = packet[2];
+
+                byte channelJustPressed = packet[5];
+                if (isTriggerChannel(address, channelJustPressed)) {
+                    triggerChannel("CH6t", CommonTriggerEvents.PRESSED);
+                }
+
+                byte channelJustReleased = packet[6];
+                if (isTriggerChannel(address, channelJustReleased)) {
+                    triggerChannel("CH6t", CommonTriggerEvents.RELEASED);
+                }
+
+                byte channelLongPressed = packet[7];
+                if (isTriggerChannel(address, channelLongPressed)) {
+                    triggerChannel("CH6t", CommonTriggerEvents.LONG_PRESSED);
+                }
+            }
+        }
+    }
+}
index aa7c13f9fbe08a9ec3f776a4f2a8c7f8d7a02b2b..852625925b45613d9d8a988f644021c28773007a 100644 (file)
@@ -20,6 +20,7 @@ import java.util.Set;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
+import org.openhab.binding.velbus.internal.packets.VelbusButtonPacket;
 import org.openhab.binding.velbus.internal.packets.VelbusFeedbackLEDPacket;
 import org.openhab.binding.velbus.internal.packets.VelbusPacket;
 import org.openhab.core.library.types.StringType;
@@ -36,6 +37,7 @@ import org.openhab.core.types.Command;
  * sent to one of the channels.
  *
  * @author Cedric Boon - Initial contribution
+ * @author Daniel Rosengarten - Add button simulation
  */
 @NonNullByDefault
 public class VelbusSensorHandler extends VelbusThingHandler {
@@ -48,6 +50,9 @@ public class VelbusSensorHandler extends VelbusThingHandler {
     private static final StringType VERY_FAST_BLINK_LED = new StringType("VERY_FAST_BLINK_LED");
     private static final StringType CLEAR_LED = new StringType("CLEAR_LED");
 
+    private static final StringType PRESSED = new StringType("PRESSED");
+    private static final StringType LONG_PRESSED = new StringType("LONG_PRESSED");
+
     public VelbusSensorHandler(Thing thing) {
         this(thing, 0);
     }
@@ -89,12 +94,44 @@ public class VelbusSensorHandler extends VelbusThingHandler {
             byte[] packetBytes = packet.getBytes();
             velbusBridgeHandler.sendPacket(packetBytes);
         }
+
+        if (isButtonChannel(channelUID) && command instanceof StringType) {
+            StringType stringTypeCommand = (StringType) command;
+
+            if (stringTypeCommand.equals(PRESSED) || stringTypeCommand.equals(LONG_PRESSED)) {
+                VelbusButtonPacket packet = new VelbusButtonPacket(getModuleAddress().getChannelIdentifier(channelUID));
+
+                packet.Pressed();
+                velbusBridgeHandler.sendPacket(packet.getBytes());
+                triggerChannel("input#CH" + getModuleAddress().getChannelNumber(channelUID),
+                        CommonTriggerEvents.PRESSED);
+
+                if (stringTypeCommand.equals(LONG_PRESSED)) {
+                    packet.LongPressed();
+                    velbusBridgeHandler.sendPacket(packet.getBytes());
+                    triggerChannel("input#CH" + getModuleAddress().getChannelNumber(channelUID),
+                            CommonTriggerEvents.LONG_PRESSED);
+                }
+
+                packet.Released();
+                velbusBridgeHandler.sendPacket(packet.getBytes());
+                triggerChannel("input#CH" + getModuleAddress().getChannelNumber(channelUID),
+                        CommonTriggerEvents.RELEASED);
+            } else {
+                throw new UnsupportedOperationException(
+                        "The command '" + command + "' is not supported on channel '" + channelUID + "'.");
+            }
+        }
     }
 
     private boolean isFeedbackChannel(ChannelUID channelUID) {
         return "feedback".equals(channelUID.getGroupId());
     }
 
+    private boolean isButtonChannel(ChannelUID channelUID) {
+        return "button".equals(channelUID.getGroupId());
+    }
+
     @Override
     public void onPacketReceived(byte[] packet) {
         logger.trace("onPacketReceived() was called");
diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusButtonPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusButtonPacket.java
new file mode 100644 (file)
index 0000000..11cccee
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2010-2021 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.velbus.internal.packets;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.velbus.internal.VelbusBindingConstants;
+import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
+
+/**
+ * The {@link VelbusButtonPacket} represents a Velbus packet that can be used to
+ * simulate a pushed button.
+ *
+ * @author Daniel Rosengarten - Initial contribution
+ */
+@NonNullByDefault
+public class VelbusButtonPacket extends VelbusPacket {
+    private byte channel;
+    private byte[] data;
+
+    public VelbusButtonPacket(VelbusChannelIdentifier velbusChannelIdentifier) {
+        super(velbusChannelIdentifier.getAddress(), PRIO_HI, false);
+
+        this.channel = velbusChannelIdentifier.getChannelByte();
+        this.data = new byte[] { VelbusBindingConstants.COMMAND_PUSH_BUTTON_STATUS, (byte) 0x00, (byte) 0x00,
+                (byte) 0x00 };
+    }
+
+    public void Pressed() {
+        data = new byte[] { VelbusBindingConstants.COMMAND_PUSH_BUTTON_STATUS, channel, (byte) 0x00, (byte) 0x00 };
+    }
+
+    public void LongPressed() {
+        data = new byte[] { VelbusBindingConstants.COMMAND_PUSH_BUTTON_STATUS, (byte) 0x00, (byte) 0x00, channel };
+    }
+
+    public void Released() {
+        data = new byte[] { VelbusBindingConstants.COMMAND_PUSH_BUTTON_STATUS, (byte) 0x00, channel, (byte) 0x00 };
+    }
+
+    @Override
+    protected byte[] getDataBytes() {
+        return data;
+    }
+}
index cf6b6133b81a634e6af71d9f5f5f5157437a31c6..e754617dfa740f60181d633ea3f5bd6a2b42046f 100644 (file)
                </supported-bridge-type-refs>
 
                <label>VMB1RYS</label>
-               <description>1-channel relay module</description>
+               <description>1-channel relay module with input</description>
                <channels>
                        <channel id="CH1" typeId="switch"/>
                        <channel id="CH2" typeId="switch"/>
                        <channel id="CH3" typeId="switch"/>
                        <channel id="CH4" typeId="switch"/>
                        <channel id="CH5" typeId="switch"/>
+                       <channel id="CH6" typeId="button-channel"/>
+                       <channel id="CH6t" typeId="trigger-channel"/>
                </channels>
 
-               <config-description-ref uri="thing-type:velbus:5channelDevice"/>
+               <config-description-ref uri="thing-type:velbus:6channelDevice"/>
        </thing-type>
 
        <thing-type id="vmb1ts">
                <description>Push-button interface for Niko 1- or 2-fold push-buttons</description>
                <channel-groups>
                        <channel-group id="input" typeId="8channelInputModule"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="2channelFeedbackModule"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                </channel-groups>
                <description>6-channel input module</description>
                <channel-groups>
                        <channel-group id="input" typeId="6channelInputModule"/>
+                       <channel-group id="button" typeId="6channelButtonModule"/>
                </channel-groups>
 
                <config-description-ref uri="thing-type:velbus:6channelDevice"/>
                <description>Push-button interface module for Niko 4- or 6-fold push-button</description>
                <channel-groups>
                        <channel-group id="input" typeId="8channelInputModule"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="6channelFeedbackModule"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                </channel-groups>
                <description>7-channel input module (potentialfree + pulse)</description>
                <channel-groups>
                        <channel-group id="input" typeId="8channelInputModule"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="counter" typeId="4channelCounterModule"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                </channel-groups>
                <description>Infrared remote control receiver module</description>
                <channel-groups>
                        <channel-group id="input" typeId="8channelInputModule"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                </channel-groups>
 
                <config-description-ref uri="thing-type:velbus:8channelDevice"/>
                <description>8-Channel Push Button module</description>
                <channel-groups>
                        <channel-group id="input" typeId="8channelInputModule"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="8channelFeedbackModule"/>
                </channel-groups>
 
                <description>Push-button interface with 8 channels for universal mounting</description>
                <channel-groups>
                        <channel-group id="input" typeId="8channelInputModule"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="8channelFeedbackModule"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                </channel-groups>
                <description>Edge-lit one touch button module</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="1channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Edge-lit two touch buttons module</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="2channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Edge-lit four touch buttons module</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="4channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Edge-lit touch panel with Oled display</description>
                <channel-groups>
                        <channel-group id="input" typeId="33channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="32channelButtonModule"/>
                        <channel-group id="feedback" typeId="32channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with 1 touch key</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="1channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with 1 touch key (Edition 2)</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="1channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with 2 touch keys</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="2channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with 2 touch keys (Edition 2)</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="2channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with 4 touch keys</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="4channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with 4 touch keys (Edition 2)</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="4channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with 4 touch keys and built-in motion and twilight sensor</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="4channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with 4 touch keys and built-in motion and twilight sensor (Edition 2)</description>
                <channel-groups>
                        <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="8channelButtonModule"/>
                        <channel-group id="feedback" typeId="4channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with oled display</description>
                <channel-groups>
                        <channel-group id="input" typeId="33channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="32channelButtonModule"/>
                        <channel-group id="feedback" typeId="32channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with oled display and temperature controller</description>
                <channel-groups>
                        <channel-group id="input" typeId="33channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="32channelButtonModule"/>
                        <channel-group id="feedback" typeId="32channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Glass control module with oled display and temperature controller (Edition 2)</description>
                <channel-groups>
                        <channel-group id="input" typeId="33channelInputModuleWithTemperatureSensor"/>
+                       <channel-group id="button" typeId="32channelButtonModule"/>
                        <channel-group id="feedback" typeId="32channelFeedbackModule"/>
                        <channel-group id="thermostat" typeId="thermostat"/>
                        <channel-group id="clockAlarm" typeId="clockAlarm"/>
                <description>Switch control for action in Velbus</description>
                <category>Switch</category>
        </channel-type>
+       <channel-type id="button-channel">
+               <item-type>String</item-type>
+               <label>Button Channel</label>
+               <category>Switch</category>
+               <command>
+                       <options>
+                               <option value="PRESSED">pressed</option>
+                               <option value="LONG_PRESSED">long pressed</option>
+                       </options>
+               </command>
+       </channel-type>
        <channel-type id="brightness">
                <item-type>Dimmer</item-type>
                <label>Brightness</label>
                        <channel id="CH32" typeId="ledFeedback"/>
                </channels>
        </channel-group-type>
+       <channel-group-type id="6channelButtonModule">
+               <label>Button</label>
+               <description>
+                       This is a generic module with 6 button channels.
+               </description>
+               <channels>
+                       <channel id="CH1" typeId="button-channel"/>
+                       <channel id="CH2" typeId="button-channel"/>
+                       <channel id="CH3" typeId="button-channel"/>
+                       <channel id="CH4" typeId="button-channel"/>
+                       <channel id="CH5" typeId="button-channel"/>
+                       <channel id="CH6" typeId="button-channel"/>
+               </channels>
+       </channel-group-type>
+       <channel-group-type id="8channelButtonModule">
+               <label>Button</label>
+               <description>
+                       This is a generic module with 8 button channels.
+               </description>
+               <channels>
+                       <channel id="CH1" typeId="button-channel"/>
+                       <channel id="CH2" typeId="button-channel"/>
+                       <channel id="CH3" typeId="button-channel"/>
+                       <channel id="CH4" typeId="button-channel"/>
+                       <channel id="CH5" typeId="button-channel"/>
+                       <channel id="CH6" typeId="button-channel"/>
+                       <channel id="CH7" typeId="button-channel"/>
+                       <channel id="CH8" typeId="button-channel"/>
+               </channels>
+       </channel-group-type>
+       <channel-group-type id="32channelButtonModule">
+               <label>Button</label>
+               <description>
+                       This is a generic module with 32 button channels.
+               </description>
+               <channels>
+                       <channel id="CH1" typeId="button-channel"/>
+                       <channel id="CH2" typeId="button-channel"/>
+                       <channel id="CH3" typeId="button-channel"/>
+                       <channel id="CH4" typeId="button-channel"/>
+                       <channel id="CH5" typeId="button-channel"/>
+                       <channel id="CH6" typeId="button-channel"/>
+                       <channel id="CH7" typeId="button-channel"/>
+                       <channel id="CH8" typeId="button-channel"/>
+                       <channel id="CH9" typeId="button-channel"/>
+                       <channel id="CH10" typeId="button-channel"/>
+                       <channel id="CH11" typeId="button-channel"/>
+                       <channel id="CH12" typeId="button-channel"/>
+                       <channel id="CH13" typeId="button-channel"/>
+                       <channel id="CH14" typeId="button-channel"/>
+                       <channel id="CH15" typeId="button-channel"/>
+                       <channel id="CH16" typeId="button-channel"/>
+                       <channel id="CH17" typeId="button-channel"/>
+                       <channel id="CH18" typeId="button-channel"/>
+                       <channel id="CH19" typeId="button-channel"/>
+                       <channel id="CH20" typeId="button-channel"/>
+                       <channel id="CH21" typeId="button-channel"/>
+                       <channel id="CH22" typeId="button-channel"/>
+                       <channel id="CH23" typeId="button-channel"/>
+                       <channel id="CH24" typeId="button-channel"/>
+                       <channel id="CH25" typeId="button-channel"/>
+                       <channel id="CH26" typeId="button-channel"/>
+                       <channel id="CH27" typeId="button-channel"/>
+                       <channel id="CH28" typeId="button-channel"/>
+                       <channel id="CH29" typeId="button-channel"/>
+                       <channel id="CH30" typeId="button-channel"/>
+                       <channel id="CH31" typeId="button-channel"/>
+                       <channel id="CH32" typeId="button-channel"/>
+               </channels>
+       </channel-group-type>
        <channel-group-type id="oledDisplay">
                <label>O-LED Display</label>
                <channels>