2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.homematic.internal.communicator.virtual;
15 import static org.hamcrest.CoreMatchers.*;
16 import static org.hamcrest.MatcherAssert.assertThat;
18 import java.io.IOException;
20 import org.junit.jupiter.api.BeforeEach;
21 import org.junit.jupiter.api.Test;
22 import org.openhab.binding.homematic.internal.misc.HomematicClientException;
23 import org.openhab.binding.homematic.internal.misc.HomematicConstants;
24 import org.openhab.binding.homematic.internal.misc.MiscUtils;
25 import org.openhab.binding.homematic.internal.model.HmChannel;
26 import org.openhab.binding.homematic.internal.model.HmDatapoint;
27 import org.openhab.binding.homematic.internal.model.HmDevice;
28 import org.openhab.binding.homematic.internal.model.HmInterface;
29 import org.openhab.binding.homematic.internal.model.HmParamsetType;
30 import org.openhab.binding.homematic.internal.model.HmValueType;
31 import org.openhab.core.test.java.JavaTest;
32 import org.openhab.core.thing.CommonTriggerEvents;
35 * Tests for {@link ButtonVirtualDatapointHandler}.
37 * @author Michael Reitler - Initial Contribution
40 public class ButtonDatapointTest extends JavaTest {
42 private static final int DISABLE_DATAPOINT_DELAY = 50;
44 private MockEventReceiver mockEventReceiver;
45 private final ButtonVirtualDatapointHandler bvdpHandler = new ButtonVirtualDatapointHandler();
48 public void setup() throws IOException {
49 this.mockEventReceiver = new MockEventReceiver();
53 public void testShortPress() throws IOException, HomematicClientException {
54 HmDatapoint shortPressDp = createPressDatapoint("PRESS_SHORT", Boolean.TRUE);
55 HmDatapoint buttonVirtualDatapoint = getButtonVirtualDatapoint(shortPressDp);
57 mockEventReceiver.eventReceived(shortPressDp);
59 assertThat(buttonVirtualDatapoint.getValue(), is(CommonTriggerEvents.SHORT_PRESSED));
63 public void testLongPressHm() throws IOException, HomematicClientException {
64 HmDatapoint longPressDp = createPressDatapoint("PRESS_LONG", Boolean.TRUE);
65 HmDatapoint buttonVirtualDatapoint = getButtonVirtualDatapoint(longPressDp);
67 mockEventReceiver.eventReceived(longPressDp);
68 assertThat(buttonVirtualDatapoint.getValue(), is(CommonTriggerEvents.LONG_PRESSED));
70 HmDatapoint contPressDp = createPressDatapointFrom(longPressDp, "PRESS_CONT", Boolean.TRUE);
71 mockEventReceiver.eventReceived(contPressDp);
72 assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
73 assertThat(buttonVirtualDatapoint.getPreviousValue(), nullValue());
75 // Receiving another LONG event during the long press should be ignored
76 mockEventReceiver.eventReceived(longPressDp);
77 assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
78 assertThat(buttonVirtualDatapoint.getPreviousValue(), is("LONG_REPEATED"));
80 HmDatapoint releaseDp = createPressDatapointFrom(longPressDp, "PRESS_LONG_RELEASE", Boolean.TRUE);
81 mockEventReceiver.eventReceived(releaseDp);
82 assertThat(buttonVirtualDatapoint.getValue(), is("LONG_RELEASED"));
86 public void testLongPressHmIp() throws IOException, HomematicClientException {
87 HmDatapoint longPressDp = createPressDatapoint("PRESS_LONG_START", Boolean.TRUE);
88 HmDatapoint buttonVirtualDatapoint = getButtonVirtualDatapoint(longPressDp);
90 mockEventReceiver.eventReceived(longPressDp);
91 assertThat(buttonVirtualDatapoint.getValue(), is(CommonTriggerEvents.LONG_PRESSED));
93 HmDatapoint contPressDp = createPressDatapointFrom(longPressDp, "PRESS_LONG", Boolean.TRUE);
94 mockEventReceiver.eventReceived(contPressDp);
95 assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
96 assertThat(buttonVirtualDatapoint.getPreviousValue(), nullValue());
98 HmDatapoint releaseDp = createPressDatapointFrom(longPressDp, "PRESS_LONG_RELEASE", Boolean.TRUE);
99 mockEventReceiver.eventReceived(releaseDp);
100 assertThat(buttonVirtualDatapoint.getValue(), is("LONG_RELEASED"));
104 public void testUnsupportedEvents() throws IOException, HomematicClientException {
105 HmDatapoint contPressDp = createPressDatapoint("PRESS_CONT", Boolean.TRUE);
106 HmDatapoint contButtonVirtualDatapoint = getButtonVirtualDatapoint(contPressDp);
108 mockEventReceiver.eventReceived(contPressDp);
110 HmDatapoint releaseDp = createPressDatapoint("PRESS_LONG_RELEASE", Boolean.TRUE);
111 HmDatapoint releaseButtonVirtualDatapoint = getButtonVirtualDatapoint(releaseDp);
113 mockEventReceiver.eventReceived(releaseDp);
115 HmDatapoint crapDp = createPressDatapoint("CRAP", Boolean.TRUE);
116 HmDatapoint crapButtonVirtualDatapoint = getButtonVirtualDatapoint(crapDp);
118 mockEventReceiver.eventReceived(crapDp);
120 // CONT and LONG_RELEASE events without previous LONG event are supposed to yield no trigger
121 assertThat(contButtonVirtualDatapoint.getValue(), nullValue());
122 assertThat(releaseButtonVirtualDatapoint.getValue(), nullValue());
123 assertThat(crapButtonVirtualDatapoint, nullValue());
126 private HmDatapoint createPressDatapoint(String channelName, Object value) {
127 HmDatapoint pressDp = new HmDatapoint(channelName, "", HmValueType.ACTION, value, true, HmParamsetType.VALUES);
128 HmChannel hmChannel = new HmChannel(channelName, 1);
129 HmDevice device = new HmDevice("ABC12345", HmInterface.RF, "HM-MOCK", "mockid", "mockid", "mockfw");
130 hmChannel.setDevice(device);
131 device.addChannel(hmChannel);
132 hmChannel.addDatapoint(pressDp);
133 pressDp.setChannel(hmChannel);
134 bvdpHandler.initialize(device);
139 private HmDatapoint createPressDatapointFrom(HmDatapoint originalDatapoint, String channelName, Object value) {
140 HmDatapoint pressDp = new HmDatapoint(channelName, "", HmValueType.ACTION, value, true, HmParamsetType.VALUES);
141 HmChannel hmChannel = originalDatapoint.getChannel();
142 hmChannel.addDatapoint(pressDp);
143 pressDp.setChannel(hmChannel);
148 private HmDatapoint getButtonVirtualDatapoint(HmDatapoint originalDatapoint) {
149 return originalDatapoint.getChannel().getDatapoints().stream()
150 .filter(dp -> HomematicConstants.VIRTUAL_DATAPOINT_NAME_BUTTON.equals(dp.getName())).findFirst()
155 * Mock parts of {@linkplain org.openhab.binding.homematic.internal.communicator.AbstractHomematicGateway}
157 private class MockEventReceiver {
159 public void eventReceived(HmDatapoint dp) throws IOException, HomematicClientException {
160 if (bvdpHandler.canHandleEvent(dp)) {
161 bvdpHandler.handleEvent(null, dp);
163 if (dp.isPressDatapoint() && MiscUtils.isTrueValue(dp.getValue())) {
164 disableDatapoint(dp);
168 private void disableDatapoint(HmDatapoint dp) {
171 Thread.sleep(DISABLE_DATAPOINT_DELAY);
172 dp.setValue(Boolean.FALSE);
173 } catch (InterruptedException e) {