2 * Copyright (c) 2010-2022 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.anel.internal;
15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.hamcrest.Matchers.*;
18 import java.util.LinkedHashSet;
19 import java.util.Queue;
21 import java.util.concurrent.ConcurrentLinkedQueue;
22 import java.util.concurrent.ExecutorService;
23 import java.util.concurrent.Executors;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.junit.jupiter.api.AfterAll;
28 import org.junit.jupiter.api.BeforeAll;
29 import org.junit.jupiter.api.BeforeEach;
30 import org.junit.jupiter.api.Disabled;
31 import org.junit.jupiter.api.Test;
32 import org.openhab.binding.anel.internal.auth.AnelAuthentication;
33 import org.openhab.binding.anel.internal.auth.AnelAuthentication.AuthMethod;
36 * This test requires a physical Anel device!
38 * @author Patrick Koenemann - Initial contribution
41 @Disabled // requires a physically available device in the local network
42 public class AnelUdpConnectorTest {
45 * The IP and ports for the Anel device under test.
47 private static final String HOST = "192.168.6.63"; // 63 / 64
48 private static final int PORT_SEND = 7500; // 7500 / 75001
49 private static final int PORT_RECEIVE = 7700; // 7700 / 7701
50 private static final String USER = "user7";
51 private static final String PASSWORD = "anel";
53 /* The device may have an internal delay of 200ms, plus network latency! Should not be <1sec. */
54 private static final int WAIT_FOR_DEVICE_RESPONSE_MS = 1000;
56 private static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool();
58 private final Queue<String> receivedMessages = new ConcurrentLinkedQueue<>();
61 private static AnelUdpConnector connector;
64 public static void prepareConnector() {
65 connector = new AnelUdpConnector(HOST, PORT_RECEIVE, PORT_SEND, EXECUTOR_SERVICE);
69 @SuppressWarnings("null")
70 public static void closeConnection() {
71 connector.disconnect();
75 @SuppressWarnings("null")
76 public void connectIfNotYetConnected() throws Exception {
78 receivedMessages.clear(); // clear all previously received messages
80 if (!connector.isConnected()) {
81 connector.connect(receivedMessages::offer, false);
86 public void connectionTest() throws Exception {
87 final String response = sendAndReceiveSingle(IAnelConstants.BROADCAST_DISCOVERY_MSG);
89 * Expected example response:
90 * "NET-PwrCtrl:NET-CONTROL :192.168.0.244:255.255.255.0:192.168.0.1:0.5.163.21.4.71:Nr. 1,0:Nr. 2,1:Nr. 3,0:Nr. 4,0:Nr. 5,0:Nr. 6,0:Nr. 7,0:Nr. 8,0:248:80:NET-PWRCTRL_04.6:H:xor:"
92 assertThat(response, startsWith(IAnelConstants.STATUS_RESPONSE_PREFIX + IAnelConstants.STATUS_SEPARATOR));
96 public void toggleSwitch1() throws Exception {
101 public void toggleSwitch2() throws Exception {
106 public void toggleSwitch3() throws Exception {
111 public void toggleSwitch4() throws Exception {
116 public void toggleSwitch5() throws Exception {
121 public void toggleSwitch6() throws Exception {
126 public void toggleSwitch7() throws Exception {
131 public void toggleSwitch8() throws Exception {
135 private void toggleSwitch(int switchNr) throws Exception {
136 assertThat(switchNr, allOf(greaterThan(0), lessThan(9)));
137 final int index = 5 + switchNr;
139 // get state of switch 1
140 final String status = sendAndReceiveSingle(IAnelConstants.BROADCAST_DISCOVERY_MSG);
141 final String[] segments = status.split(IAnelConstants.STATUS_SEPARATOR);
142 assertThat(segments[5 + switchNr], anyOf(endsWith(",1"), endsWith(",0")));
143 final boolean switch1state = segments[index].endsWith(",1");
145 // toggle state of switch 1
146 final String auth = AnelAuthentication.getUserPasswordString(USER, PASSWORD, AuthMethod.of(status));
147 final String command = "Sw_" + (switch1state ? "off" : "on") + String.valueOf(switchNr) + auth;
148 final String status2 = sendAndReceiveSingle(command);
150 // assert new state of switch 1
151 assertThat(status2.trim(), not(endsWith(":Err")));
152 final String[] segments2 = status2.split(IAnelConstants.STATUS_SEPARATOR);
153 final String expectedState = segments2[index].substring(0, segments2[index].length() - 1)
154 + (switch1state ? "0" : "1");
155 assertThat(segments2[index], equalTo(expectedState));
159 public void withoutCredentials() throws Exception {
160 final String status2 = sendAndReceiveSingle("Sw_on1");
161 assertThat(status2.trim(), endsWith(":NoPass:Err"));
162 Thread.sleep(3100); // locked for 3 seconds
165 private String sendAndReceiveSingle(final String msg) throws Exception {
166 final Set<String> response = sendAndReceive(msg);
167 assertThat(response, hasSize(1));
168 return response.iterator().next();
171 @SuppressWarnings("null")
172 private Set<String> sendAndReceive(final String msg) throws Exception {
173 assertThat(receivedMessages, is(empty()));
175 Thread.sleep(WAIT_FOR_DEVICE_RESPONSE_MS);
176 final Set<String> response = new LinkedHashSet<>();
177 while (!receivedMessages.isEmpty()) {
178 final String receivedMessage = receivedMessages.poll();
179 if (receivedMessage != null) {
180 response.add(receivedMessage);