[homematic] Fix long button press handling for HM-IP devices (#11982)

* [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
This commit is contained in:
maniac103 2022-01-13 09:09:19 +01:00 committed by GitHub
parent a1e6a4e35c
commit a4c579b753
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 4 deletions

View 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);

View 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);