]> git.basschouten.com Git - openhab-addons.git/commitdiff
[homematic] Fix long button press handling for HM-IP devices (#11982)
authormaniac103 <dannybaumann@web.de>
Thu, 13 Jan 2022 08:09:19 +0000 (09:09 +0100)
committerGitHub <noreply@github.com>
Thu, 13 Jan 2022 08:09:19 +0000 (09:09 +0100)
* [homematic] Fix long button press handling for HM-IP devices

HM devices have the following long press cycle:
PRESS_CONT
PRESS_LONG
PRESS_CONT (N times for repetion)
PRESS_LONG_RELEASE

while (at least some) HM-IP devices use this one:
PRESS_LONG
PRESS_LONG_START
PRESS_LONG (N times for repetition)
PRESS_LONG_RELEASE

Add support for the latter case while keeping support for the former
case.

Signed-off-by: Danny Baumann <dannybaumann@web.de>
* [homematic] Track 'uses LONG_START datapoint' flag per-device

bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonVirtualDatapointHandler.java
bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java

index f3f58e83393ebb09a1b1ef822255f8fcb0eb4933..03e6019f66daf6f86c1bfc985f39c40918fe3cd3 100644 (file)
@@ -14,6 +14,8 @@ package org.openhab.binding.homematic.internal.communicator.virtual;
 
 import static org.openhab.binding.homematic.internal.misc.HomematicConstants.VIRTUAL_DATAPOINT_NAME_BUTTON;
 
+import java.util.HashSet;
+
 import org.openhab.binding.homematic.internal.misc.MiscUtils;
 import org.openhab.binding.homematic.internal.model.HmChannel;
 import org.openhab.binding.homematic.internal.model.HmDatapoint;
@@ -36,6 +38,8 @@ public class ButtonVirtualDatapointHandler extends AbstractVirtualDatapointHandl
     private static final String LONG_REPEATED_EVENT = "LONG_REPEATED";
     private static final String LONG_RELEASED_EVENT = "LONG_RELEASED";
 
+    private HashSet<String> devicesUsingLongStartEvent = new HashSet<>();
+
     @Override
     public String getName() {
         return VIRTUAL_DATAPOINT_NAME_BUTTON;
@@ -61,6 +65,7 @@ public class ButtonVirtualDatapointHandler extends AbstractVirtualDatapointHandl
     @Override
     public void handleEvent(VirtualGateway gateway, HmDatapoint dp) {
         HmChannel channel = dp.getChannel();
+        String deviceSerial = channel.getDevice().getAddress();
         HmDatapoint vdp = getVirtualDatapoint(channel);
         int usPos = dp.getName().indexOf("_");
         String pressType = usPos == -1 ? dp.getName() : dp.getName().substring(usPos + 1);
@@ -74,13 +79,20 @@ public class ButtonVirtualDatapointHandler extends AbstractVirtualDatapointHandl
                     break;
                 }
                 case "LONG":
-                    if (LONG_REPEATED_EVENT.equals(vdp.getValue())) {
-                        // Suppress long press events during an ongoing long press
+                    if (isLongPressActive) {
+                        // HM-IP devices do long press repetitions via LONG instead of CONT events,
+                        // so clear previous value to force re-triggering of event
+                        vdp.setValue(null);
                         vdp.setValue(LONG_REPEATED_EVENT);
                     } else {
+                        // HM devices start long press via LONG events
                         vdp.setValue(CommonTriggerEvents.LONG_PRESSED);
                     }
                     break;
+                case "LONG_START":
+                    vdp.setValue(CommonTriggerEvents.LONG_PRESSED);
+                    devicesUsingLongStartEvent.add(deviceSerial);
+                    break;
                 case "LONG_RELEASE":
                     // Only send release events if we sent a pressed event before
                     vdp.setValue(isLongPressActive ? LONG_RELEASED_EVENT : null);
@@ -99,7 +111,8 @@ public class ButtonVirtualDatapointHandler extends AbstractVirtualDatapointHandl
                     logger.warn("Unexpected vaule '{}' for PRESS virtual datapoint", pressType);
             }
         } else {
-            if ("LONG".equals(pressType) && LONG_REPEATED_EVENT.equals(vdp.getValue())) {
+            String usedStartEvent = devicesUsingLongStartEvent.contains(deviceSerial) ? "LONG_START" : "LONG";
+            if (usedStartEvent.equals(pressType) && LONG_REPEATED_EVENT.equals(vdp.getValue())) {
                 // If we're currently processing a repeated long-press event, don't let the initial LONG
                 // event time out the repetitions, the CONT delay handler will take care of it
                 vdp.setValue(LONG_REPEATED_EVENT);
index a22cfbb20a80350585560454854d23efb229729d..02b6bdeeb398bcd595ef708eda6a9915747f5fe1 100644 (file)
@@ -60,7 +60,7 @@ public class ButtonDatapointTest extends JavaTest {
     }
 
     @Test
-    public void testLongPress() throws IOException, HomematicClientException {
+    public void testLongPressHm() throws IOException, HomematicClientException {
         HmDatapoint longPressDp = createPressDatapoint("PRESS_LONG", Boolean.TRUE);
         HmDatapoint buttonVirtualDatapoint = getButtonVirtualDatapoint(longPressDp);
 
@@ -76,6 +76,23 @@ public class ButtonDatapointTest extends JavaTest {
         assertThat(buttonVirtualDatapoint.getValue(), is("LONG_RELEASED"));
     }
 
+    @Test
+    public void testLongPressHmIp() throws IOException, HomematicClientException {
+        HmDatapoint longPressDp = createPressDatapoint("PRESS_LONG_START", Boolean.TRUE);
+        HmDatapoint buttonVirtualDatapoint = getButtonVirtualDatapoint(longPressDp);
+
+        mockEventReceiver.eventReceived(longPressDp);
+        assertThat(buttonVirtualDatapoint.getValue(), is(CommonTriggerEvents.LONG_PRESSED));
+
+        HmDatapoint contPressDp = createPressDatapointFrom(longPressDp, "PRESS_LONG", Boolean.TRUE);
+        mockEventReceiver.eventReceived(contPressDp);
+        assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
+
+        HmDatapoint releaseDp = createPressDatapointFrom(longPressDp, "PRESS_LONG_RELEASE", Boolean.TRUE);
+        mockEventReceiver.eventReceived(releaseDp);
+        assertThat(buttonVirtualDatapoint.getValue(), is("LONG_RELEASED"));
+    }
+
     @Test
     public void testUnsupportedEvents() throws IOException, HomematicClientException {
         HmDatapoint contPressDp = createPressDatapoint("PRESS_CONT", Boolean.TRUE);