Skip to content

Commit

Permalink
[homematic] Fix duplication of LONG_REPEATED events for HM devices (o…
Browse files Browse the repository at this point in the history
…penhab#15906)

Depending on device configuration and used central [1], HM devices may
indicate long press repetition either by a single PRESS_CONT event or by
a PRESS_CONT + PRESS_LONG combination. In the latter case, make sure to
not generate a LONG_REPEATED trigger channel event for both PRESS_CONT
and PRESS_LONG, but instead keep LONG_REPEATED generation to the
PRESS_CONT handling.

[1] I'm not sure what a real CCU is doing, but for Homegear, a
    configured long press timeout of less than 1s generates only
    PRESS_CONT, while a timeout of more than 1s generates
    PRESS_CONT + PRESS_LONG ... see [2].
[2] https://github.com/Homegear/Homegear-HomeMaticBidCoS/blob/master/src/BidCoSPeer.cpp#L1711-L1716

Signed-off-by: Danny Baumann <dannybaumann@web.de>
  • Loading branch information
maniac103 authored and andrewfg committed Nov 26, 2023
1 parent 10094fd commit 9fc2938
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public void handleEvent(VirtualGateway gateway, HmDatapoint dp) {
HmDatapoint vdp = getVirtualDatapoint(channel);
int usPos = dp.getName().indexOf("_");
String pressType = usPos == -1 ? dp.getName() : dp.getName().substring(usPos + 1);
boolean usesLongStart = devicesUsingLongStartEvent.contains(deviceSerial);
boolean isLongPressActive = CommonTriggerEvents.LONG_PRESSED.equals(vdp.getValue())
|| LONG_REPEATED_EVENT.equals(vdp.getValue());
if (MiscUtils.isTrueValue(dp.getValue())) {
Expand All @@ -78,14 +79,18 @@ public void handleEvent(VirtualGateway gateway, HmDatapoint dp) {
break;
}
case "LONG":
if (isLongPressActive) {
if (usesLongStart) {
// 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);
if (isLongPressActive) {
vdp.setValue(null);
vdp.setValue(LONG_REPEATED_EVENT);
}
} else {
// HM devices start long press via LONG events
vdp.setValue(CommonTriggerEvents.LONG_PRESSED);
// HM devices start long press via LONG events, but also may keep sending them
// alongside CONT repetition events. In case a long press is already active, we just
// acknowledge those events by setting the value again, to make sure to not re-trigger events
vdp.setValue(isLongPressActive ? LONG_REPEATED_EVENT : CommonTriggerEvents.LONG_PRESSED);
}
break;
case "LONG_START":
Expand All @@ -107,10 +112,10 @@ public void handleEvent(VirtualGateway gateway, HmDatapoint dp) {
break;
default:
vdp.setValue(null);
logger.warn("Unexpected vaule '{}' for PRESS virtual datapoint", pressType);
logger.warn("Unexpected value '{}' for PRESS virtual datapoint", pressType);
}
} else {
String usedStartEvent = devicesUsingLongStartEvent.contains(deviceSerial) ? "LONG_START" : "LONG";
String usedStartEvent = usesLongStart ? "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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ public void testLongPressHm() throws IOException, HomematicClientException {
HmDatapoint contPressDp = createPressDatapointFrom(longPressDp, "PRESS_CONT", Boolean.TRUE);
mockEventReceiver.eventReceived(contPressDp);
assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
assertThat(buttonVirtualDatapoint.getPreviousValue(), nullValue());

// Receiving another LONG event during the long press should be ignored
mockEventReceiver.eventReceived(longPressDp);
assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
assertThat(buttonVirtualDatapoint.getPreviousValue(), is("LONG_REPEATED"));

HmDatapoint releaseDp = createPressDatapointFrom(longPressDp, "PRESS_LONG_RELEASE", Boolean.TRUE);
mockEventReceiver.eventReceived(releaseDp);
Expand All @@ -87,6 +93,7 @@ public void testLongPressHmIp() throws IOException, HomematicClientException {
HmDatapoint contPressDp = createPressDatapointFrom(longPressDp, "PRESS_LONG", Boolean.TRUE);
mockEventReceiver.eventReceived(contPressDp);
assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
assertThat(buttonVirtualDatapoint.getPreviousValue(), nullValue());

HmDatapoint releaseDp = createPressDatapointFrom(longPressDp, "PRESS_LONG_RELEASE", Boolean.TRUE);
mockEventReceiver.eventReceived(releaseDp);
Expand Down

0 comments on commit 9fc2938

Please sign in to comment.