- reserve-network-port
+ reserve-mqtt-broker-port
reserve-network-port
process-resources
- mqttembeddedbroker.port
+ mqttbroker.port
diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/Constants.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/Constants.java
deleted file mode 100644
index f9f59254570..00000000000
--- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/Constants.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright (c) 2010-2022 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.mqtt;
-
-/**
- * MQTT embedded broker constants
- *
- * @author David Graeff - Initial contribution
- */
-public class Constants {
- /**
- * The broker connection client ID. You can request the embedded broker connection via the MqttService:
- *
- *
- * MqttBrokerConnection c = mqttService.getBrokerConnection(Constants.CLIENTID);
- *
- */
- public static final String CLIENTID = "embedded-mqtt-broker";
-
- /**
- * The broker persistent identifier used for identifying configurations.
- */
- public static final String PID = "org.openhab.core.mqttembeddedbroker";
-
- /**
- * The configuration key used for configuring the embedded broker port.
- */
- public static final String PORT = "port";
-}
diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/EmbeddedBrokerTools.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/EmbeddedBrokerTools.java
deleted file mode 100644
index f7e10c4681d..00000000000
--- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/EmbeddedBrokerTools.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Copyright (c) 2010-2022 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.mqtt;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.IOException;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
-import org.openhab.core.io.transport.mqtt.MqttConnectionObserver;
-import org.openhab.core.io.transport.mqtt.MqttConnectionState;
-import org.openhab.core.io.transport.mqtt.MqttService;
-import org.openhab.core.io.transport.mqtt.MqttServiceObserver;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-/**
- * A full implementation test, that starts the embedded MQTT broker and publishes a homeassistant MQTT discovery device
- * tree.
- *
- * @author David Graeff - Initial contribution
- * @author Wouter Born - Support running MQTT itests in parallel by reconfiguring embedded broker port
- */
-@NonNullByDefault
-public class EmbeddedBrokerTools {
-
- private static final int BROKER_PORT = Integer.getInteger("mqttembeddedbroker.port", 1883);
-
- private final ConfigurationAdmin configurationAdmin;
- private final MqttService mqttService;
-
- public @Nullable MqttBrokerConnection embeddedConnection;
-
- public EmbeddedBrokerTools(ConfigurationAdmin configurationAdmin, MqttService mqttService) {
- this.configurationAdmin = configurationAdmin;
- this.mqttService = mqttService;
- }
-
- /**
- * Request the embedded broker connection from the {@link MqttService} and wait for a connection to be established.
- *
- * @throws InterruptedException
- * @throws IOException
- */
- public MqttBrokerConnection waitForConnection() throws InterruptedException, IOException {
- reconfigurePort();
-
- embeddedConnection = mqttService.getBrokerConnection(Constants.CLIENTID);
- if (embeddedConnection == null) {
- Semaphore semaphore = new Semaphore(1);
- semaphore.acquire();
- MqttServiceObserver observer = new MqttServiceObserver() {
-
- @Override
- public void brokerAdded(String brokerID, MqttBrokerConnection broker) {
- if (brokerID.equals(Constants.CLIENTID)) {
- embeddedConnection = broker;
- semaphore.release();
- }
- }
-
- @Override
- public void brokerRemoved(String brokerID, MqttBrokerConnection broker) {
- }
- };
- mqttService.addBrokersListener(observer);
- assertTrue(semaphore.tryAcquire(5, TimeUnit.SECONDS), "Wait for embedded connection client failed");
- }
- MqttBrokerConnection embeddedConnection = this.embeddedConnection;
- if (embeddedConnection == null) {
- throw new IllegalStateException();
- }
-
- Semaphore semaphore = new Semaphore(1);
- semaphore.acquire();
- MqttConnectionObserver mqttConnectionObserver = (state, error) -> {
- if (state == MqttConnectionState.CONNECTED) {
- semaphore.release();
- }
- };
- embeddedConnection.addConnectionObserver(mqttConnectionObserver);
- if (embeddedConnection.connectionState() == MqttConnectionState.CONNECTED) {
- semaphore.release();
- }
- assertTrue(semaphore.tryAcquire(5, TimeUnit.SECONDS), "Connection " + embeddedConnection.getClientId()
- + " failed. State: " + embeddedConnection.connectionState());
- return embeddedConnection;
- }
-
- public void reconfigurePort() throws IOException {
- Configuration configuration = configurationAdmin.getConfiguration(Constants.PID, null);
-
- Dictionary properties = configuration.getProperties();
- if (properties == null) {
- properties = new Hashtable<>();
- }
-
- Integer currentPort = (Integer) properties.get(Constants.PORT);
- if (currentPort == null || currentPort.intValue() != BROKER_PORT) {
- properties.put(Constants.PORT, BROKER_PORT);
- configuration.update(properties);
- // Remove the connection to make sure the test waits for the new connection to become available
- mqttService.removeBrokerConnection(Constants.CLIENTID);
- }
- }
-}
diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/DiscoverComponentsTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/DiscoverComponentsTest.java
similarity index 95%
rename from itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/DiscoverComponentsTest.java
rename to itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/DiscoverComponentsTest.java
index e94f2358100..170f0e439ab 100644
--- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/DiscoverComponentsTest.java
+++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/DiscoverComponentsTest.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.mqtt;
+package org.openhab.binding.mqtt.homeassistant;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@@ -37,11 +37,11 @@ import org.mockito.quality.Strictness;
import org.openhab.binding.mqtt.generic.AvailabilityTracker;
import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener;
import org.openhab.binding.mqtt.generic.TransformationServiceProvider;
-import org.openhab.binding.mqtt.homeassistant.internal.ChannelConfigurationTypeAdapterFactory;
import org.openhab.binding.mqtt.homeassistant.internal.DiscoverComponents;
import org.openhab.binding.mqtt.homeassistant.internal.DiscoverComponents.ComponentDiscovered;
import org.openhab.binding.mqtt.homeassistant.internal.HaID;
import org.openhab.binding.mqtt.homeassistant.internal.HandlerConfiguration;
+import org.openhab.binding.mqtt.homeassistant.internal.config.ChannelConfigurationTypeAdapterFactory;
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
import org.openhab.core.test.java.JavaOSGiTest;
@@ -83,7 +83,7 @@ public class DiscoverComponentsTest extends JavaOSGiTest {
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ChannelConfigurationTypeAdapterFactory()).create();
- DiscoverComponents discover = spy(new DiscoverComponents(ThingChannelConstants.testHomeAssistantThing,
+ DiscoverComponents discover = spy(new DiscoverComponents(ThingChannelConstants.TEST_HOME_ASSISTANT_THING,
scheduler, channelStateUpdateListener, availabilityTracker, gson, transformationServiceProvider));
HandlerConfiguration config = new HandlerConfiguration("homeassistant",
diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/HomeAssistantMQTTImplementationTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java
similarity index 65%
rename from itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/HomeAssistantMQTTImplementationTest.java
rename to itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java
index 0cf38fb2f55..dde840756c0 100644
--- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/HomeAssistantMQTTImplementationTest.java
+++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.mqtt;
+package org.openhab.binding.mqtt.homeassistant;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -25,11 +25,9 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@@ -45,22 +43,19 @@ import org.openhab.binding.mqtt.generic.AvailabilityTracker;
import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener;
import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider;
import org.openhab.binding.mqtt.generic.TransformationServiceProvider;
-import org.openhab.binding.mqtt.homeassistant.internal.AbstractComponent;
-import org.openhab.binding.mqtt.homeassistant.internal.ChannelConfigurationTypeAdapterFactory;
-import org.openhab.binding.mqtt.homeassistant.internal.ComponentSwitch;
import org.openhab.binding.mqtt.homeassistant.internal.DiscoverComponents;
import org.openhab.binding.mqtt.homeassistant.internal.DiscoverComponents.ComponentDiscovered;
import org.openhab.binding.mqtt.homeassistant.internal.HaID;
+import org.openhab.binding.mqtt.homeassistant.internal.component.AbstractComponent;
+import org.openhab.binding.mqtt.homeassistant.internal.component.Switch;
+import org.openhab.binding.mqtt.homeassistant.internal.config.ChannelConfigurationTypeAdapterFactory;
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
import org.openhab.core.io.transport.mqtt.MqttConnectionObserver;
import org.openhab.core.io.transport.mqtt.MqttConnectionState;
-import org.openhab.core.io.transport.mqtt.MqttService;
import org.openhab.core.library.types.OnOffType;
-import org.openhab.core.test.java.JavaOSGiTest;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
import org.openhab.core.util.UIDUtils;
-import org.osgi.service.cm.ConfigurationAdmin;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -74,11 +69,9 @@ import com.google.gson.GsonBuilder;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
@NonNullByDefault
-public class HomeAssistantMQTTImplementationTest extends JavaOSGiTest {
- private @NonNullByDefault({}) ConfigurationAdmin configurationAdmin;
- private @NonNullByDefault({}) MqttService mqttService;
- private @NonNullByDefault({}) MqttBrokerConnection embeddedConnection;
- private @NonNullByDefault({}) MqttBrokerConnection connection;
+public class HomeAssistantMQTTImplementationTest extends MqttOSGiTest {
+
+ private @NonNullByDefault({}) MqttBrokerConnection haConnection;
private int registeredTopics = 100;
private @Nullable Throwable failure;
@@ -93,24 +86,17 @@ public class HomeAssistantMQTTImplementationTest extends JavaOSGiTest {
private final MqttConnectionObserver failIfChange = (state, error) -> assertThat(state,
is(MqttConnectionState.CONNECTED));
private final String testObjectTopic = "homeassistant/switch/node/"
- + ThingChannelConstants.testHomeAssistantThing.getId();
+ + ThingChannelConstants.TEST_HOME_ASSISTANT_THING.getId();
+ @Override
@BeforeEach
public void beforeEach() throws Exception {
- registerVolatileStorageService();
- configurationAdmin = getService(ConfigurationAdmin.class);
- mqttService = getService(MqttService.class);
+ super.beforeEach();
- // Wait for the EmbeddedBrokerService internal connection to be connected
- embeddedConnection = new EmbeddedBrokerTools(configurationAdmin, mqttService).waitForConnection();
-
- connection = new MqttBrokerConnection(embeddedConnection.getHost(), embeddedConnection.getPort(),
- embeddedConnection.isSecure(), "ha_mqtt");
- connection.start().get(2, TimeUnit.SECONDS);
- assertThat(connection.connectionState(), is(MqttConnectionState.CONNECTED));
+ haConnection = createBrokerConnection("ha_mqtt");
// If the connection state changes in between -> fail
- connection.addConnectionObserver(failIfChange);
+ haConnection.addConnectionObserver(failIfChange);
// Create topic string and config for one example HA component (a Switch)
final String config = "{'name':'testname','state_topic':'" + testObjectTopic + "/state','command_topic':'"
@@ -118,8 +104,8 @@ public class HomeAssistantMQTTImplementationTest extends JavaOSGiTest {
// Publish component configurations and component states to MQTT
List> futures = new ArrayList<>();
- futures.add(embeddedConnection.publish(testObjectTopic + "/config", config.getBytes(), 0, true));
- futures.add(embeddedConnection.publish(testObjectTopic + "/state", "ON".getBytes(), 0, true));
+ futures.add(publish(testObjectTopic + "/config", config));
+ futures.add(publish(testObjectTopic + "/state", "ON"));
registeredTopics = futures.size();
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(2, TimeUnit.SECONDS);
@@ -129,41 +115,42 @@ public class HomeAssistantMQTTImplementationTest extends JavaOSGiTest {
doReturn(null).when(transformationServiceProvider).getTransformationService(any());
}
+ @Override
@AfterEach
public void afterEach() throws Exception {
- if (connection != null) {
- connection.removeConnectionObserver(failIfChange);
- connection.stop().get(2, TimeUnit.SECONDS);
+ if (haConnection != null) {
+ haConnection.removeConnectionObserver(failIfChange);
+ haConnection.stop().get(5, TimeUnit.SECONDS);
}
+
+ super.afterEach();
}
@Test
- public void reconnectTest() throws InterruptedException, ExecutionException, TimeoutException {
- connection.removeConnectionObserver(failIfChange);
- connection.stop().get(2, TimeUnit.SECONDS);
- connection = new MqttBrokerConnection(embeddedConnection.getHost(), embeddedConnection.getPort(),
- embeddedConnection.isSecure(), "ha_mqtt");
- connection.start().get(2, TimeUnit.SECONDS);
+ public void reconnectTest() throws Exception {
+ haConnection.removeConnectionObserver(failIfChange);
+ haConnection.stop().get(5, TimeUnit.SECONDS);
+ haConnection = createBrokerConnection("ha_mqtt");
}
@Test
- public void retrieveAllTopics() throws InterruptedException, ExecutionException, TimeoutException {
+ public void retrieveAllTopics() throws Exception {
CountDownLatch c = new CountDownLatch(registeredTopics);
- connection.subscribe("homeassistant/+/+/" + ThingChannelConstants.testHomeAssistantThing.getId() + "/#",
- (topic, payload) -> c.countDown()).get(2, TimeUnit.SECONDS);
+ haConnection.subscribe("homeassistant/+/+/" + ThingChannelConstants.TEST_HOME_ASSISTANT_THING.getId() + "/#",
+ (topic, payload) -> c.countDown()).get(5, TimeUnit.SECONDS);
assertTrue(c.await(2, TimeUnit.SECONDS),
- "Connection " + connection.getClientId() + " not retrieving all topics");
+ "Connection " + haConnection.getClientId() + " not retrieving all topics");
}
@Test
- public void parseHATree() throws InterruptedException, ExecutionException, TimeoutException {
+ public void parseHATree() throws Exception {
MqttChannelTypeProvider channelTypeProvider = mock(MqttChannelTypeProvider.class);
final Map> haComponents = new HashMap<>();
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ChannelConfigurationTypeAdapterFactory()).create();
ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(4);
- DiscoverComponents discover = spy(new DiscoverComponents(ThingChannelConstants.testHomeAssistantThing,
+ DiscoverComponents discover = spy(new DiscoverComponents(ThingChannelConstants.TEST_HOME_ASSISTANT_THING,
scheduler, channelStateUpdateListener, availabilityTracker, gson, transformationServiceProvider));
// The DiscoverComponents object calls ComponentDiscovered callbacks.
@@ -171,15 +158,15 @@ public class HomeAssistantMQTTImplementationTest extends JavaOSGiTest {
// and add the types to the channelTypeProvider, like in the real Thing handler.
final CountDownLatch latch = new CountDownLatch(1);
ComponentDiscovered cd = (haID, c) -> {
- haComponents.put(c.uid().getId(), c);
+ haComponents.put(c.getGroupUID().getId(), c);
c.addChannelTypes(channelTypeProvider);
- channelTypeProvider.setChannelGroupType(c.groupTypeUID(), c.type());
+ channelTypeProvider.setChannelGroupType(c.getGroupTypeUID(), c.getType());
latch.countDown();
};
// Start the discovery for 2000ms. Forced timeout after 4000ms.
HaID haID = new HaID(testObjectTopic + "/config");
- CompletableFuture future = discover.startDiscovery(connection, 2000, Collections.singleton(haID), cd)
+ CompletableFuture future = discover.startDiscovery(haConnection, 2000, Collections.singleton(haID), cd)
.thenRun(() -> {
}).exceptionally(e -> {
failure = e;
@@ -187,7 +174,7 @@ public class HomeAssistantMQTTImplementationTest extends JavaOSGiTest {
});
assertTrue(latch.await(4, TimeUnit.SECONDS));
- future.get(2, TimeUnit.SECONDS);
+ future.get(5, TimeUnit.SECONDS);
// No failure expected and one discovered result
assertNull(failure);
@@ -199,13 +186,13 @@ public class HomeAssistantMQTTImplementationTest extends JavaOSGiTest {
verify(channelTypeProvider, times(1)).setChannelType(any(), any());
String channelGroupId = UIDUtils
- .encode("node_" + ThingChannelConstants.testHomeAssistantThing.getId() + "_switch");
+ .encode("node_" + ThingChannelConstants.TEST_HOME_ASSISTANT_THING.getId() + "_switch");
- State value = haComponents.get(channelGroupId).channelTypes().get(ComponentSwitch.switchChannelID).getState()
- .getCache().getChannelState();
+ State value = haComponents.get(channelGroupId).getChannel(Switch.SWITCH_CHANNEL_ID).getState().getCache()
+ .getChannelState();
assertThat(value, is(UnDefType.UNDEF));
- haComponents.values().stream().map(e -> e.start(connection, scheduler, 100))
+ haComponents.values().stream().map(e -> e.start(haConnection, scheduler, 100))
.reduce(CompletableFuture.completedFuture(null), (a, v) -> a.thenCompose(b -> v)).exceptionally(e -> {
failure = e;
return null;
@@ -215,8 +202,8 @@ public class HomeAssistantMQTTImplementationTest extends JavaOSGiTest {
verify(channelStateUpdateListener, timeout(4000).times(1)).updateChannelState(any(), any());
// Value should be ON now.
- value = haComponents.get(channelGroupId).channelTypes().get(ComponentSwitch.switchChannelID).getState()
- .getCache().getChannelState();
+ value = haComponents.get(channelGroupId).getChannel(Switch.SWITCH_CHANNEL_ID).getState().getCache()
+ .getChannelState();
assertThat(value, is(OnOffType.ON));
}
}
diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/MqttOSGiTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/MqttOSGiTest.java
new file mode 100644
index 00000000000..79415f70aab
--- /dev/null
+++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/MqttOSGiTest.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2010-2022 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.homeassistant;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
+import org.openhab.core.io.transport.mqtt.MqttConnectionState;
+import org.openhab.core.test.java.JavaOSGiTest;
+
+import io.moquette.BrokerConstants;
+import io.moquette.broker.Server;
+
+/**
+ * Creates a Moquette MQTT broker instance and a {@link MqttBrokerConnection} for testing MQTT bindings.
+ *
+ * @author Wouter Born - Initial contribution
+ */
+@NonNullByDefault
+public class MqttOSGiTest extends JavaOSGiTest {
+
+ private static final String BROKER_ID = "test-broker";
+ private static final int BROKER_PORT = Integer.getInteger("mqttbroker.port", 1883);
+
+ protected @NonNullByDefault({}) MqttBrokerConnection brokerConnection;
+
+ private Server moquetteServer = new Server();
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ registerVolatileStorageService();
+
+ moquetteServer = new Server();
+ moquetteServer.startServer(brokerProperties());
+
+ brokerConnection = createBrokerConnection(BROKER_ID);
+ }
+
+ @AfterEach
+ public void afterEach() throws Exception {
+ brokerConnection.stop().get(5, TimeUnit.SECONDS);
+ moquetteServer.stopServer();
+ }
+
+ private Properties brokerProperties() {
+ Properties properties = new Properties();
+ properties.put(BrokerConstants.HOST_PROPERTY_NAME, BrokerConstants.HOST);
+ properties.put(BrokerConstants.PORT_PROPERTY_NAME, String.valueOf(BROKER_PORT));
+ properties.put(BrokerConstants.SSL_PORT_PROPERTY_NAME, BrokerConstants.DISABLED_PORT_BIND);
+ properties.put(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, BrokerConstants.DISABLED_PORT_BIND);
+ properties.put(BrokerConstants.WSS_PORT_PROPERTY_NAME, BrokerConstants.DISABLED_PORT_BIND);
+ return properties;
+ }
+
+ protected MqttBrokerConnection createBrokerConnection(String clientId) throws Exception {
+ MqttBrokerConnection connection = new MqttBrokerConnection(BrokerConstants.HOST, BROKER_PORT, false, clientId);
+ connection.setQos(1);
+ connection.start().get(5, TimeUnit.SECONDS);
+
+ waitForAssert(() -> assertThat(connection.connectionState(), is(MqttConnectionState.CONNECTED)));
+
+ return connection;
+ }
+
+ protected CompletableFuture publish(String topic, String message) {
+ return brokerConnection.publish(topic, message.getBytes(StandardCharsets.UTF_8), 1, true);
+ }
+}
diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/ThingChannelConstants.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/ThingChannelConstants.java
similarity index 83%
rename from itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/ThingChannelConstants.java
rename to itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/ThingChannelConstants.java
index 2c9c856cb1c..5d69d00ee4c 100644
--- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/ThingChannelConstants.java
+++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/ThingChannelConstants.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.mqtt;
+package org.openhab.binding.mqtt.homeassistant;
import static org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants.HOMEASSISTANT_MQTT_THING;
@@ -25,5 +25,5 @@ import org.openhab.core.thing.ThingUID;
@NonNullByDefault
public class ThingChannelConstants {
// Common ThingUID and ChannelUIDs
- public static final ThingUID testHomeAssistantThing = new ThingUID(HOMEASSISTANT_MQTT_THING, "device234");
+ public static final ThingUID TEST_HOME_ASSISTANT_THING = new ThingUID(HOMEASSISTANT_MQTT_THING, "device234");
}
diff --git a/itests/org.openhab.binding.mqtt.homie.tests/itest.bndrun b/itests/org.openhab.binding.mqtt.homie.tests/itest.bndrun
index 2c862325e96..304906cf254 100644
--- a/itests/org.openhab.binding.mqtt.homie.tests/itest.bndrun
+++ b/itests/org.openhab.binding.mqtt.homie.tests/itest.bndrun
@@ -3,93 +3,111 @@
Bundle-SymbolicName: ${project.artifactId}
Fragment-Host: org.openhab.binding.mqtt.homie
+Import-Package: \
+ com.bugsnag.*;resolution:=optional,\
+ com.librato.metrics.reporter.*;resolution:=optional,\
+ *
+
+-includeresource: \
+ moquette-broker-[0-9.]*.jar;lib:=true
+
-runrequires: \
bnd.identity;id='org.openhab.binding.mqtt.homie.tests',\
bnd.identity;id='org.openhab.core.binding.xml',\
- bnd.identity;id='org.openhab.core.thing.xml',\
- bnd.identity;id='org.openhab.io.mqttembeddedbroker'
+ bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
-runblacklist: \
bnd.identity;id='org.openhab.core.storage.json'
--runvm: \
+-runvm.mqtt: \
-Dio.netty.noUnsafe=true,\
- -Dmqttembeddedbroker.port=${mqttembeddedbroker.port}
+ -Dmqttbroker.port=${mqttbroker.port}
#
# done
#
-runbundles: \
- ch.qos.logback.core;version='[1.2.3,1.2.4)',\
- com.google.gson;version='[2.8.2,2.8.3)',\
- javax.measure.unit-api;version='[1.0.0,1.0.1)',\
- org.apache.commons.lang;version='[2.6.0,2.6.1)',\
- org.apache.felix.configadmin;version='[1.9.8,1.9.9)',\
org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
- org.apache.felix.scr;version='[2.1.10,2.1.11)',\
org.eclipse.equinox.event;version='[1.4.300,1.4.301)',\
- org.objenesis;version='[2.6.0,2.6.1)',\
org.osgi.service.event;version='[1.4.0,1.4.1)',\
- slf4j.api;version='[1.7.25,1.7.26)',\
- org.apache.servicemix.bundles.xstream;version='[1.4.7,1.4.8)',\
- com.h2database.mvstore;version='[1.4.199,1.4.200)',\
- io.netty.buffer;version='[4.1.42,4.1.43)',\
- io.netty.codec;version='[4.1.42,4.1.43)',\
- io.netty.codec-mqtt;version='[4.1.42,4.1.43)',\
- io.netty.common;version='[4.1.42,4.1.43)',\
- io.netty.handler;version='[4.1.42,4.1.43)',\
- io.netty.resolver;version='[4.1.42,4.1.43)',\
- io.netty.transport;version='[4.1.42,4.1.43)',\
- tec.uom.lib.uom-lib-common;version='[1.0.3,1.0.4)',\
- tec.uom.se;version='[1.0.10,1.0.11)',\
- ch.qos.logback.classic;version='[1.2.3,1.2.4)',\
- biz.aQute.tester.junit-platform;version='[5.1.2,5.1.3)',\
- com.google.dagger;version='[2.20.0,2.20.1)',\
- com.hivemq.client.mqtt;version='[1.1.2,1.1.3)',\
- io.netty.codec-http;version='[4.1.34,4.1.35)',\
- io.netty.transport-native-epoll;version='[4.1.34,4.1.35)',\
- io.netty.transport-native-unix-common;version='[4.1.34,4.1.35)',\
- io.reactivex.rxjava2.rxjava;version='[2.2.5,2.2.6)',\
- junit-jupiter-api;version='[5.6.2,5.6.3)',\
- junit-jupiter-engine;version='[5.6.2,5.6.3)',\
- junit-platform-commons;version='[1.6.2,1.6.3)',\
- junit-platform-engine;version='[1.6.2,1.6.3)',\
- junit-platform-launcher;version='[1.6.2,1.6.3)',\
- net.bytebuddy.byte-buddy;version='[1.10.13,1.10.14)',\
- net.bytebuddy.byte-buddy-agent;version='[1.10.13,1.10.14)',\
- org.apache.aries.javax.jax.rs-api;version='[1.0.0,1.0.1)',\
- org.apache.commons.codec;version='[1.10.0,1.10.1)',\
- org.eclipse.jetty.http;version='[9.4.20,9.4.21)',\
- org.eclipse.jetty.io;version='[9.4.20,9.4.21)',\
- org.eclipse.jetty.security;version='[9.4.20,9.4.21)',\
- org.eclipse.jetty.server;version='[9.4.20,9.4.21)',\
- org.eclipse.jetty.servlet;version='[9.4.20,9.4.21)',\
- org.eclipse.jetty.util;version='[9.4.20,9.4.21)',\
org.glassfish.hk2.external.javax.inject;version='[2.4.0,2.4.1)',\
org.hamcrest;version='[2.2.0,2.2.1)',\
org.jctools.core;version='[2.1.2,2.1.3)',\
- org.mockito.mockito-core;version='[3.4.6,3.4.7)',\
- org.openhab.binding.mqtt;version='[3.0.0,3.0.1)',\
- org.openhab.binding.mqtt.generic;version='[3.0.0,3.0.1)',\
- org.openhab.binding.mqtt.homie;version='[3.0.0,3.0.1)',\
- org.openhab.binding.mqtt.homie.tests;version='[3.0.0,3.0.1)',\
- org.openhab.core;version='[3.0.0,3.0.1)',\
- org.openhab.core.binding.xml;version='[3.0.0,3.0.1)',\
- org.openhab.core.config.core;version='[3.0.0,3.0.1)',\
- org.openhab.core.config.discovery;version='[3.0.0,3.0.1)',\
- org.openhab.core.config.xml;version='[3.0.0,3.0.1)',\
- org.openhab.core.io.console;version='[3.0.0,3.0.1)',\
- org.openhab.core.io.transport.mqtt;version='[3.0.0,3.0.1)',\
- org.openhab.core.test;version='[3.0.0,3.0.1)',\
- org.openhab.core.thing;version='[3.0.0,3.0.1)',\
- org.openhab.core.thing.xml;version='[3.0.0,3.0.1)',\
- org.openhab.core.transform;version='[3.0.0,3.0.1)',\
- org.openhab.io.mqttembeddedbroker;version='[3.0.0,3.0.1)',\
org.opentest4j;version='[1.2.0,1.2.1)',\
- org.reactivestreams.reactive-streams;version='[1.0.2,1.0.3)',\
jakarta.xml.bind-api;version='[2.3.3,2.3.4)',\
com.sun.xml.bind.jaxb-osgi;version='[2.3.3,2.3.4)',\
- org.glassfish.hk2.osgi-resource-locator;version='[1.0.1,1.0.2)',\
- org.apache.servicemix.specs.activation-api-1.2.1;version='[1.2.1,1.2.2)'
+ org.apache.servicemix.specs.activation-api-1.2.1;version='[1.2.1,1.2.2)',\
+ com.google.dagger;version='[2.27.0,2.27.1)',\
+ com.google.gson;version='[2.8.9,2.8.10)',\
+ com.hivemq.client.mqtt;version='[1.2.2,1.2.3)',\
+ io.netty.buffer;version='[4.1.72,4.1.73)',\
+ io.netty.codec;version='[4.1.72,4.1.73)',\
+ io.netty.codec-http;version='[4.1.59,4.1.60)',\
+ io.netty.codec-socks;version='[4.1.72,4.1.73)',\
+ io.netty.common;version='[4.1.72,4.1.73)',\
+ io.netty.handler;version='[4.1.72,4.1.73)',\
+ io.netty.handler-proxy;version='[4.1.72,4.1.73)',\
+ io.netty.resolver;version='[4.1.72,4.1.73)',\
+ io.netty.tcnative-classes;version='[2.0.46,2.0.47)',\
+ io.netty.transport;version='[4.1.72,4.1.73)',\
+ io.netty.transport-native-epoll;version='[4.1.59,4.1.60)',\
+ io.netty.transport-native-unix-common;version='[4.1.59,4.1.60)',\
+ io.reactivex.rxjava2.rxjava;version='[2.2.19,2.2.20)',\
+ jakarta.annotation-api;version='[2.0.0,2.0.1)',\
+ jakarta.inject.jakarta.inject-api;version='[2.0.0,2.0.1)',\
+ javax.measure.unit-api;version='[2.1.2,2.1.3)',\
+ junit-jupiter-api;version='[5.8.1,5.8.2)',\
+ junit-jupiter-engine;version='[5.8.1,5.8.2)',\
+ junit-platform-commons;version='[1.8.1,1.8.2)',\
+ junit-platform-engine;version='[1.8.1,1.8.2)',\
+ junit-platform-launcher;version='[1.8.1,1.8.2)',\
+ net.bytebuddy.byte-buddy;version='[1.12.1,1.12.2)',\
+ net.bytebuddy.byte-buddy-agent;version='[1.12.1,1.12.2)',\
+ org.apache.aries.javax.jax.rs-api;version='[1.0.1,1.0.2)',\
+ org.apache.felix.configadmin;version='[1.9.22,1.9.23)',\
+ org.apache.felix.scr;version='[2.1.30,2.1.31)',\
+ org.eclipse.jetty.http;version='[9.4.43,9.4.44)',\
+ org.eclipse.jetty.io;version='[9.4.43,9.4.44)',\
+ org.eclipse.jetty.security;version='[9.4.43,9.4.44)',\
+ org.eclipse.jetty.server;version='[9.4.43,9.4.44)',\
+ org.eclipse.jetty.servlet;version='[9.4.43,9.4.44)',\
+ org.eclipse.jetty.util;version='[9.4.43,9.4.44)',\
+ org.eclipse.jetty.util.ajax;version='[9.4.43,9.4.44)',\
+ org.glassfish.hk2.osgi-resource-locator;version='[1.0.3,1.0.4)',\
+ org.jsr-305;version='[3.0.2,3.0.3)',\
+ org.mockito.junit-jupiter;version='[4.1.0,4.1.1)',\
+ org.mockito.mockito-core;version='[4.1.0,4.1.1)',\
+ org.objenesis;version='[3.2.0,3.2.1)',\
+ org.openhab.binding.mqtt;version='[3.3.0,3.3.1)',\
+ org.openhab.binding.mqtt.generic;version='[3.3.0,3.3.1)',\
+ org.openhab.binding.mqtt.homie;version='[3.3.0,3.3.1)',\
+ org.openhab.binding.mqtt.homie.tests;version='[3.3.0,3.3.1)',\
+ org.openhab.core;version='[3.3.0,3.3.1)',\
+ org.openhab.core.binding.xml;version='[3.3.0,3.3.1)',\
+ org.openhab.core.config.core;version='[3.3.0,3.3.1)',\
+ org.openhab.core.config.discovery;version='[3.3.0,3.3.1)',\
+ org.openhab.core.config.xml;version='[3.3.0,3.3.1)',\
+ org.openhab.core.io.console;version='[3.3.0,3.3.1)',\
+ org.openhab.core.io.transport.mqtt;version='[3.3.0,3.3.1)',\
+ org.openhab.core.test;version='[3.3.0,3.3.1)',\
+ org.openhab.core.thing;version='[3.3.0,3.3.1)',\
+ org.openhab.core.thing.xml;version='[3.3.0,3.3.1)',\
+ org.openhab.core.transform;version='[3.3.0,3.3.1)',\
+ org.ops4j.pax.logging.pax-logging-api;version='[2.0.14,2.0.15)',\
+ org.osgi.service.cm;version='[1.6.0,1.6.1)',\
+ org.osgi.util.function;version='[1.2.0,1.2.1)',\
+ org.osgi.util.promise;version='[1.2.0,1.2.1)',\
+ org.reactivestreams.reactive-streams;version='[1.0.3,1.0.4)',\
+ si-units;version='[2.1.0,2.1.1)',\
+ si.uom.si-quantity;version='[2.1.0,2.1.1)',\
+ tech.units.indriya;version='[2.1.2,2.1.3)',\
+ uom-lib-common;version='[2.1.0,2.1.1)',\
+ xstream;version='[1.4.19,1.4.20)',\
+ com.h2database.mvstore;version='[1.4.199,1.4.200)',\
+ com.zaxxer.HikariCP;version='[2.4.7,2.4.8)',\
+ io.dropwizard.metrics.core;version='[3.2.2,3.2.3)',\
+ io.netty.codec-mqtt;version='[4.1.72,4.1.73)',\
+ org.apache.commons.codec;version='[1.10.0,1.10.1)',\
+ biz.aQute.tester.junit-platform;version='[6.2.0,6.2.1)'
diff --git a/itests/org.openhab.binding.mqtt.homie.tests/pom.xml b/itests/org.openhab.binding.mqtt.homie.tests/pom.xml
index a77c9bc7667..a6aa0a365ce 100644
--- a/itests/org.openhab.binding.mqtt.homie.tests/pom.xml
+++ b/itests/org.openhab.binding.mqtt.homie.tests/pom.xml
@@ -7,13 +7,17 @@
org.openhab.addons.itests
org.openhab.addons.reactor.itests
- 3.1.0-SNAPSHOT
+ 3.3.0-SNAPSHOT
org.openhab.binding.mqtt.homie.tests
openHAB Add-ons :: Integration Tests :: MQTT Homie Tests
+
+ 1883
+
+
org.openhab.addons.bundles
@@ -31,52 +35,43 @@
${project.version}
- com.github.j-n-k
- moquette-broker
- 0.13.0.OH2
-
-
- org.slf4j
- slf4j-api
-
-
- org.slf4j
- slf4j-log4j12
-
-
- org.mockito
- mockito-core
-
-
+ com.h2database
+ h2-mvstore
+ 1.4.199
- io.netty
- netty-common
- ${netty.version}
+ io.moquette
+ moquette-broker
+ 0.15
io.netty
netty-buffer
${netty.version}
-
- io.netty
- netty-transport
- ${netty.version}
-
io.netty
netty-codec
${netty.version}
- com.h2database
- h2-mvstore
- 1.4.199
+ io.netty
+ netty-codec-mqtt
+ ${netty.version}
io.netty
- netty-codec-mqtt
+ netty-common
+ ${netty.version}
+
+
+ io.netty
+ netty-handler
+ ${netty.version}
+
+
+ io.netty
+ netty-handler-proxy
${netty.version}
@@ -86,7 +81,7 @@
io.netty
- netty-handler
+ netty-transport
${netty.version}
@@ -98,14 +93,14 @@
build-helper-maven-plugin
- reserve-network-port
+ reserve-mqtt-broker-port
reserve-network-port
process-resources
- mqttembeddedbroker.port
+ mqttbroker.port
diff --git a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/Constants.java b/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/Constants.java
deleted file mode 100644
index f9f59254570..00000000000
--- a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/Constants.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright (c) 2010-2022 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.mqtt;
-
-/**
- * MQTT embedded broker constants
- *
- * @author David Graeff - Initial contribution
- */
-public class Constants {
- /**
- * The broker connection client ID. You can request the embedded broker connection via the MqttService:
- *
- *
- * MqttBrokerConnection c = mqttService.getBrokerConnection(Constants.CLIENTID);
- *
- */
- public static final String CLIENTID = "embedded-mqtt-broker";
-
- /**
- * The broker persistent identifier used for identifying configurations.
- */
- public static final String PID = "org.openhab.core.mqttembeddedbroker";
-
- /**
- * The configuration key used for configuring the embedded broker port.
- */
- public static final String PORT = "port";
-}
diff --git a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/EmbeddedBrokerTools.java b/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/EmbeddedBrokerTools.java
deleted file mode 100644
index f7e10c4681d..00000000000
--- a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/EmbeddedBrokerTools.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Copyright (c) 2010-2022 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.mqtt;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.IOException;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
-import org.openhab.core.io.transport.mqtt.MqttConnectionObserver;
-import org.openhab.core.io.transport.mqtt.MqttConnectionState;
-import org.openhab.core.io.transport.mqtt.MqttService;
-import org.openhab.core.io.transport.mqtt.MqttServiceObserver;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-/**
- * A full implementation test, that starts the embedded MQTT broker and publishes a homeassistant MQTT discovery device
- * tree.
- *
- * @author David Graeff - Initial contribution
- * @author Wouter Born - Support running MQTT itests in parallel by reconfiguring embedded broker port
- */
-@NonNullByDefault
-public class EmbeddedBrokerTools {
-
- private static final int BROKER_PORT = Integer.getInteger("mqttembeddedbroker.port", 1883);
-
- private final ConfigurationAdmin configurationAdmin;
- private final MqttService mqttService;
-
- public @Nullable MqttBrokerConnection embeddedConnection;
-
- public EmbeddedBrokerTools(ConfigurationAdmin configurationAdmin, MqttService mqttService) {
- this.configurationAdmin = configurationAdmin;
- this.mqttService = mqttService;
- }
-
- /**
- * Request the embedded broker connection from the {@link MqttService} and wait for a connection to be established.
- *
- * @throws InterruptedException
- * @throws IOException
- */
- public MqttBrokerConnection waitForConnection() throws InterruptedException, IOException {
- reconfigurePort();
-
- embeddedConnection = mqttService.getBrokerConnection(Constants.CLIENTID);
- if (embeddedConnection == null) {
- Semaphore semaphore = new Semaphore(1);
- semaphore.acquire();
- MqttServiceObserver observer = new MqttServiceObserver() {
-
- @Override
- public void brokerAdded(String brokerID, MqttBrokerConnection broker) {
- if (brokerID.equals(Constants.CLIENTID)) {
- embeddedConnection = broker;
- semaphore.release();
- }
- }
-
- @Override
- public void brokerRemoved(String brokerID, MqttBrokerConnection broker) {
- }
- };
- mqttService.addBrokersListener(observer);
- assertTrue(semaphore.tryAcquire(5, TimeUnit.SECONDS), "Wait for embedded connection client failed");
- }
- MqttBrokerConnection embeddedConnection = this.embeddedConnection;
- if (embeddedConnection == null) {
- throw new IllegalStateException();
- }
-
- Semaphore semaphore = new Semaphore(1);
- semaphore.acquire();
- MqttConnectionObserver mqttConnectionObserver = (state, error) -> {
- if (state == MqttConnectionState.CONNECTED) {
- semaphore.release();
- }
- };
- embeddedConnection.addConnectionObserver(mqttConnectionObserver);
- if (embeddedConnection.connectionState() == MqttConnectionState.CONNECTED) {
- semaphore.release();
- }
- assertTrue(semaphore.tryAcquire(5, TimeUnit.SECONDS), "Connection " + embeddedConnection.getClientId()
- + " failed. State: " + embeddedConnection.connectionState());
- return embeddedConnection;
- }
-
- public void reconfigurePort() throws IOException {
- Configuration configuration = configurationAdmin.getConfiguration(Constants.PID, null);
-
- Dictionary properties = configuration.getProperties();
- if (properties == null) {
- properties = new Hashtable<>();
- }
-
- Integer currentPort = (Integer) properties.get(Constants.PORT);
- if (currentPort == null || currentPort.intValue() != BROKER_PORT) {
- properties.put(Constants.PORT, BROKER_PORT);
- configuration.update(properties);
- // Remove the connection to make sure the test waits for the new connection to become available
- mqttService.removeBrokerConnection(Constants.CLIENTID);
- }
- }
-}
diff --git a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/HomieImplementationTest.java b/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/HomieImplementationTest.java
similarity index 78%
rename from itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/HomieImplementationTest.java
rename to itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/HomieImplementationTest.java
index be6873179bc..2ff5f27db90 100644
--- a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/HomieImplementationTest.java
+++ b/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/HomieImplementationTest.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.mqtt;
+package org.openhab.binding.mqtt.homie;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -18,17 +18,14 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.AfterEach;
@@ -57,12 +54,10 @@ import org.openhab.binding.mqtt.homie.internal.homie300.PropertyHelper;
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
import org.openhab.core.io.transport.mqtt.MqttConnectionObserver;
import org.openhab.core.io.transport.mqtt.MqttConnectionState;
-import org.openhab.core.io.transport.mqtt.MqttService;
-import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
-import org.openhab.core.test.java.JavaOSGiTest;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.types.UnDefType;
-import org.osgi.service.cm.ConfigurationAdmin;
/**
* A full implementation test, that starts the embedded MQTT broker and publishes a homie device tree.
@@ -72,15 +67,12 @@ import org.osgi.service.cm.ConfigurationAdmin;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
@NonNullByDefault
-public class HomieImplementationTest extends JavaOSGiTest {
+public class HomieImplementationTest extends MqttOSGiTest {
private static final String BASE_TOPIC = "homie";
- private static final String DEVICE_ID = ThingChannelConstants.testHomieThing.getId();
+ private static final String DEVICE_ID = ThingChannelConstants.TEST_HOME_THING.getId();
private static final String DEVICE_TOPIC = BASE_TOPIC + "/" + DEVICE_ID;
- private @NonNullByDefault({}) ConfigurationAdmin configurationAdmin;
- private @NonNullByDefault({}) MqttService mqttService;
- private @NonNullByDefault({}) MqttBrokerConnection embeddedConnection;
- private @NonNullByDefault({}) MqttBrokerConnection connection;
+ private @NonNullByDefault({}) MqttBrokerConnection homieConnection;
private int registeredTopics = 100;
// The handler is not tested here, so just mock the callback
@@ -100,23 +92,15 @@ public class HomieImplementationTest extends JavaOSGiTest {
private String propertyTestTopic = "";
+ @Override
@BeforeEach
public void beforeEach() throws Exception {
- registerVolatileStorageService();
- configurationAdmin = getService(ConfigurationAdmin.class);
- mqttService = getService(MqttService.class);
+ super.beforeEach();
- // Wait for the EmbeddedBrokerService internal connection to be connected
- embeddedConnection = new EmbeddedBrokerTools(configurationAdmin, mqttService).waitForConnection();
- embeddedConnection.setQos(1);
+ homieConnection = createBrokerConnection("homie");
- connection = new MqttBrokerConnection(embeddedConnection.getHost(), embeddedConnection.getPort(),
- embeddedConnection.isSecure(), "homie");
- connection.setQos(1);
- connection.start().get(5, TimeUnit.SECONDS);
- assertThat(connection.connectionState(), is(MqttConnectionState.CONNECTED));
// If the connection state changes in between -> fail
- connection.addConnectionObserver(failIfChange);
+ homieConnection.addConnectionObserver(failIfChange);
List> futures = new ArrayList<>();
futures.add(publish(DEVICE_TOPIC + "/$homie", "3.0"));
@@ -152,47 +136,46 @@ public class HomieImplementationTest extends JavaOSGiTest {
futures.add(publish(propertyTestTopic + "/$datatype", "boolean"));
registeredTopics = futures.size();
- CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(2, TimeUnit.SECONDS);
+ CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(5, TimeUnit.SECONDS);
scheduler = new ScheduledThreadPoolExecutor(6);
}
- private CompletableFuture publish(String topic, String message) {
- return embeddedConnection.publish(topic, message.getBytes(StandardCharsets.UTF_8), 0, true);
- }
-
+ @Override
@AfterEach
public void afterEach() throws Exception {
- if (connection != null) {
- connection.removeConnectionObserver(failIfChange);
- connection.stop().get(2, TimeUnit.SECONDS);
+ if (homieConnection != null) {
+ homieConnection.removeConnectionObserver(failIfChange);
+ homieConnection.stop().get(5, TimeUnit.SECONDS);
}
if (scheduler != null) {
scheduler.shutdownNow();
}
+ super.afterEach();
}
@Test
- public void retrieveAllTopics() throws InterruptedException, ExecutionException, TimeoutException {
+ public void retrieveAllTopics() throws Exception {
// four topics are not under /testnode !
CountDownLatch c = new CountDownLatch(registeredTopics - 4);
- connection.subscribe(DEVICE_TOPIC + "/testnode/#", (topic, payload) -> c.countDown()).get(5, TimeUnit.SECONDS);
+ homieConnection.subscribe(DEVICE_TOPIC + "/testnode/#", (topic, payload) -> c.countDown()).get(5,
+ TimeUnit.SECONDS);
assertTrue(c.await(5, TimeUnit.SECONDS),
- "Connection " + connection.getClientId() + " not retrieving all topics ");
+ "Connection " + homieConnection.getClientId() + " not retrieving all topics ");
}
@Test
- public void retrieveOneAttribute() throws InterruptedException, ExecutionException {
- WaitForTopicValue watcher = new WaitForTopicValue(connection, DEVICE_TOPIC + "/$homie");
+ public void retrieveOneAttribute() throws Exception {
+ WaitForTopicValue watcher = new WaitForTopicValue(homieConnection, DEVICE_TOPIC + "/$homie");
assertThat(watcher.waitForTopicValue(1000), is("3.0"));
}
@SuppressWarnings("null")
@Test
- public void retrieveAttributes() throws InterruptedException, ExecutionException {
- assertThat(connection.hasSubscribers(), is(false));
+ public void retrieveAttributes() throws Exception {
+ assertThat(homieConnection.hasSubscribers(), is(false));
- Node node = new Node(DEVICE_TOPIC, "testnode", ThingChannelConstants.testHomieThing, callback,
+ Node node = new Node(DEVICE_TOPIC, "testnode", ThingChannelConstants.TEST_HOME_THING, callback,
new NodeAttributes());
Property property = spy(
new Property(DEVICE_TOPIC + "/testnode", node, "temperature", callback, new PropertyAttributes()));
@@ -200,7 +183,7 @@ public class HomieImplementationTest extends JavaOSGiTest {
// Create a scheduler
ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(4);
- property.subscribe(connection, scheduler, 500).get();
+ property.subscribe(homieConnection, scheduler, 500).get();
assertThat(property.attributes.settable, is(true));
assertThat(property.attributes.retained, is(true));
@@ -214,15 +197,16 @@ public class HomieImplementationTest extends JavaOSGiTest {
ChannelState channelState = spy(property.getChannelState());
PropertyHelper.setChannelState(property, channelState);
- property.startChannel(connection, scheduler, 500).get();
+ property.startChannel(homieConnection, scheduler, 500).get();
verify(channelState).start(any(), any(), anyInt());
verify(channelState, timeout(500)).processMessage(any(), any());
verify(callback).updateChannelState(any(), any());
- assertThat(property.getChannelState().getCache().getChannelState(), is(new DecimalType(10)));
+ assertThat(property.getChannelState().getCache().getChannelState(),
+ is(new QuantityType<>(10, SIUnits.CELSIUS)));
property.stop().get();
- assertThat(connection.hasSubscribers(), is(false));
+ assertThat(homieConnection.hasSubscribers(), is(false));
}
// Inject a spy'ed property
@@ -245,19 +229,19 @@ public class HomieImplementationTest extends JavaOSGiTest {
@SuppressWarnings("null")
@Test
- public void parseHomieTree() throws InterruptedException, ExecutionException, TimeoutException {
+ public void parseHomieTree() throws Exception {
// Create a Homie Device object. Because spied Nodes are required for call verification,
// the full Device constructor need to be used and a ChildMap object need to be created manually.
ChildMap nodeMap = new ChildMap<>();
Device device = spy(
- new Device(ThingChannelConstants.testHomieThing, callback, new DeviceAttributes(), nodeMap));
+ new Device(ThingChannelConstants.TEST_HOME_THING, callback, new DeviceAttributes(), nodeMap));
// Intercept creating a node in initialize()->start() and inject a spy'ed node.
doAnswer(this::createSpyNode).when(device).createNode(any());
// initialize the device, subscribe and wait.
device.initialize(BASE_TOPIC, DEVICE_ID, Collections.emptyList());
- device.subscribe(connection, scheduler, 1500).get();
+ device.subscribe(homieConnection, scheduler, 1500).get();
assertThat(device.isInitialized(), is(true));
@@ -306,22 +290,23 @@ public class HomieImplementationTest extends JavaOSGiTest {
assertThat(propertyBell.attributes.datatype, is(DataTypeEnum.boolean_));
// The device->node->property tree is ready. Now subscribe to property values.
- device.startChannels(connection, scheduler, 50, handler).get();
+ device.startChannels(homieConnection, scheduler, 50, handler).get();
assertThat(propertyBell.getChannelState().isStateful(), is(false));
assertThat(propertyBell.getChannelState().getCache().getChannelState(), is(UnDefType.UNDEF));
- assertThat(property.getChannelState().getCache().getChannelState(), is(new DecimalType(10)));
+ assertThat(property.getChannelState().getCache().getChannelState(),
+ is(new QuantityType<>(10, SIUnits.CELSIUS)));
property = node.properties.get("testRetain");
- WaitForTopicValue watcher = new WaitForTopicValue(embeddedConnection, propertyTestTopic + "/set");
+ WaitForTopicValue watcher = new WaitForTopicValue(brokerConnection, propertyTestTopic + "/set");
// Watch the topic. Publish a retain=false value to MQTT
property.getChannelState().publishValue(OnOffType.OFF).get();
- assertThat(watcher.waitForTopicValue(1000), is("false"));
+ assertThat(watcher.waitForTopicValue(10000), is("false"));
// Publish a retain=false value to MQTT.
property.getChannelState().publishValue(OnOffType.ON).get();
// No value is expected to be retained on this MQTT topic
waitForAssert(() -> {
- WaitForTopicValue w = new WaitForTopicValue(embeddedConnection, propertyTestTopic + "/set");
+ WaitForTopicValue w = new WaitForTopicValue(brokerConnection, propertyTestTopic + "/set");
assertNull(w.waitForTopicValue(50));
}, 500, 100);
}
diff --git a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/MqttOSGiTest.java b/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/MqttOSGiTest.java
new file mode 100644
index 00000000000..64ae708ad15
--- /dev/null
+++ b/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/MqttOSGiTest.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2010-2022 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.homie;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
+import org.openhab.core.io.transport.mqtt.MqttConnectionState;
+import org.openhab.core.test.java.JavaOSGiTest;
+
+import io.moquette.BrokerConstants;
+import io.moquette.broker.Server;
+
+/**
+ * Creates a Moquette MQTT broker instance and a {@link MqttBrokerConnection} for testing MQTT bindings.
+ *
+ * @author Wouter Born - Initial contribution
+ */
+@NonNullByDefault
+public class MqttOSGiTest extends JavaOSGiTest {
+
+ private static final String BROKER_ID = "test-broker";
+ private static final int BROKER_PORT = Integer.getInteger("mqttbroker.port", 1883);
+
+ protected @NonNullByDefault({}) MqttBrokerConnection brokerConnection;
+
+ private Server moquetteServer = new Server();
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ registerVolatileStorageService();
+
+ moquetteServer = new Server();
+ moquetteServer.startServer(brokerProperties());
+
+ brokerConnection = createBrokerConnection(BROKER_ID);
+ }
+
+ @AfterEach
+ public void afterEach() throws Exception {
+ brokerConnection.stop().get(5, TimeUnit.SECONDS);
+ moquetteServer.stopServer();
+ }
+
+ private Properties brokerProperties() {
+ Properties properties = new Properties();
+ properties.put(BrokerConstants.HOST_PROPERTY_NAME, BrokerConstants.HOST);
+ properties.put(BrokerConstants.PORT_PROPERTY_NAME, String.valueOf(BROKER_PORT));
+ properties.put(BrokerConstants.SSL_PORT_PROPERTY_NAME, BrokerConstants.DISABLED_PORT_BIND);
+ properties.put(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, BrokerConstants.DISABLED_PORT_BIND);
+ properties.put(BrokerConstants.WSS_PORT_PROPERTY_NAME, BrokerConstants.DISABLED_PORT_BIND);
+ return properties;
+ }
+
+ protected MqttBrokerConnection createBrokerConnection(String clientId) throws Exception {
+ MqttBrokerConnection connection = new MqttBrokerConnection(BrokerConstants.HOST, BROKER_PORT, false, clientId);
+ connection.setQos(1);
+ connection.start().get(5, TimeUnit.SECONDS);
+
+ waitForAssert(() -> assertThat(connection.connectionState(), is(MqttConnectionState.CONNECTED)));
+
+ return connection;
+ }
+
+ protected CompletableFuture publish(String topic, String message) {
+ return brokerConnection.publish(topic, message.getBytes(StandardCharsets.UTF_8), 1, true);
+ }
+}
diff --git a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/ThingChannelConstants.java b/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/ThingChannelConstants.java
similarity index 85%
rename from itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/ThingChannelConstants.java
rename to itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/ThingChannelConstants.java
index b254837c48f..60646acba24 100644
--- a/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/ThingChannelConstants.java
+++ b/itests/org.openhab.binding.mqtt.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/ThingChannelConstants.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.mqtt;
+package org.openhab.binding.mqtt.homie;
import static org.openhab.binding.mqtt.homie.generic.internal.MqttBindingConstants.HOMIE300_MQTT_THING;
@@ -25,5 +25,5 @@ import org.openhab.core.thing.ThingUID;
@NonNullByDefault
public class ThingChannelConstants {
// Common ThingUID and ChannelUIDs
- public final static ThingUID testHomieThing = new ThingUID(HOMIE300_MQTT_THING, "device123");
+ public static final ThingUID TEST_HOME_THING = new ThingUID(HOMIE300_MQTT_THING, "device123");
}
diff --git a/itests/pom.xml b/itests/pom.xml
index d5cb682fa9c..f58c4d9a7dc 100644
--- a/itests/pom.xml
+++ b/itests/pom.xml
@@ -24,10 +24,8 @@
org.openhab.binding.max.tests
org.openhab.binding.mielecloud.tests
org.openhab.binding.modbus.tests
-
+ org.openhab.binding.mqtt.homeassistant.tests
+ org.openhab.binding.mqtt.homie.tests
org.openhab.binding.nest.tests
org.openhab.binding.ntp.tests
org.openhab.binding.systeminfo.tests