Adds mqtt event extension for IAASRegistryService
Signed-off-by: Ashfaqul Haque <ashfaqul.haque@iese.fraunhofer.de>
Change-Id: I9bb162b31cee87ec0b5305e6e5e6114d8c39d7a7
diff --git a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mqtt/MqttSubmodelAPIFactory.java b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mqtt/MqttSubmodelAPIFactory.java
index dfac89d..bc944aa 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mqtt/MqttSubmodelAPIFactory.java
+++ b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mqtt/MqttSubmodelAPIFactory.java
@@ -3,7 +3,7 @@
import java.util.Set;
import org.eclipse.basyx.components.configuration.BaSyxMqttConfiguration;
-import org.eclipse.basyx.extensions.events.submodel.mqtt.MqttSubmodelAPI;
+import org.eclipse.basyx.extensions.submodel.mqtt.MqttSubmodelAPI;
import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable;
import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI;
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/aas/registration/mqtt/MqttAASRegistryService.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/aas/registration/mqtt/MqttAASRegistryService.java
new file mode 100644
index 0000000..d1cd947
--- /dev/null
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/aas/registration/mqtt/MqttAASRegistryService.java
@@ -0,0 +1,128 @@
+package org.eclipse.basyx.extensions.aas.registration.mqtt;
+
+import java.util.List;
+
+import org.eclipse.basyx.aas.metamodel.map.descriptor.AASDescriptor;
+import org.eclipse.basyx.aas.metamodel.map.descriptor.SubmodelDescriptor;
+import org.eclipse.basyx.aas.registration.api.IAASRegistryService;
+import org.eclipse.basyx.extensions.shared.mqtt.MqttEventService;
+import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
+import org.eclipse.basyx.vab.exception.provider.ProviderException;
+import org.eclipse.paho.client.mqttv3.MqttClient;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation variant for the AASRegistryService that triggers MQTT events for
+ * different operations on the registry. Has to be based on a backend
+ * implementation of the IAASRegistryService to forward its method calls.
+ *
+ * @author haque
+ *
+ */
+public class MqttAASRegistryService extends MqttEventService implements IAASRegistryService {
+ private static Logger logger = LoggerFactory.getLogger(MqttAASRegistryService.class);
+
+ // List of topics
+ public static final String TOPIC_REGISTERAAS = "Registry_registeredAAS";
+ public static final String TOPIC_REGISTERSUBMODEL = "Registry_registeredSubmodel";
+ public static final String TOPIC_DELETEAAS = "Registry_deletedAAS";
+ public static final String TOPIC_DELETESUBMODEL = "Registry_deletedSubmodel";
+
+ // The underlying AASRegistryService
+ protected IAASRegistryService observedRegistryService;
+
+ /**
+ * Constructor for adding this MQTT extension on top of an AASRegistryService
+ *
+ * @param observedRegistryService the underlying registry service
+ * @param serverEndpoint endpoint of mqtt broker
+ * @param clientId unique client identifier
+ * @throws MqttException
+ */
+ public MqttAASRegistryService(IAASRegistryService observedRegistryService, String serverEndpoint, String clientId) throws MqttException {
+ super(serverEndpoint, clientId);
+ logger.info("Create new MQTT AAS Registry Service for endpoint " + serverEndpoint);
+ this.observedRegistryService = observedRegistryService;
+ }
+
+ /**
+ * Constructor for adding this MQTT extension on top of an AASRegistryService
+ *
+ * @param observedRegistryService the underlying registry service
+ * @param serverEndpoint endpoint of mqtt broker
+ * @param clientId unique client identifier
+ * @param user username for authentication with broker
+ * @param pw password for authentication with broker
+ * @throws MqttException
+ */
+ public MqttAASRegistryService(IAASRegistryService observedRegistryService, String serverEndpoint, String clientId, String user, char[] pw)
+ throws MqttException {
+ super(serverEndpoint, clientId, user, pw);
+ logger.info("Create new MQTT AAS Registry Service for endpoint " + serverEndpoint);
+ this.observedRegistryService = observedRegistryService;
+ }
+
+ /**
+ * Constructor for adding this MQTT extension on top of an AASRegistryService
+ *
+ * @param observedRegistryService the underlying registry service
+ * @param client already configured client
+ * @throws MqttException
+ */
+ public MqttAASRegistryService(IAASRegistryService observedRegistryService, MqttClient client) throws MqttException {
+ super(client);
+ logger.info("Create new MQTT AAS Registry Service for endpoint " + client.getServerURI());
+ this.observedRegistryService = observedRegistryService;
+ }
+
+
+ @Override
+ public void register(AASDescriptor deviceAASDescriptor) throws ProviderException {
+ this.observedRegistryService.register(deviceAASDescriptor);
+ sendMqttMessage(TOPIC_REGISTERAAS, deviceAASDescriptor.getIdentifier().getId());
+ }
+
+ @Override
+ public void register(IIdentifier aas, SubmodelDescriptor smDescriptor) throws ProviderException {
+ this.observedRegistryService.register(aas, smDescriptor);
+ sendMqttMessage(TOPIC_REGISTERSUBMODEL, concatAasSmId(aas, smDescriptor.getIdentifier()));
+ }
+
+ @Override
+ public void delete(IIdentifier aasId) throws ProviderException {
+ this.observedRegistryService.delete(aasId);
+ sendMqttMessage(TOPIC_DELETEAAS, aasId.getId());
+ }
+
+ @Override
+ public void delete(IIdentifier aasId, IIdentifier smId) throws ProviderException {
+ this.observedRegistryService.delete(aasId, smId);
+ sendMqttMessage(TOPIC_DELETESUBMODEL, concatAasSmId(aasId, smId));
+ }
+
+ @Override
+ public AASDescriptor lookupAAS(IIdentifier aasId) throws ProviderException {
+ return this.observedRegistryService.lookupAAS(aasId);
+ }
+
+ @Override
+ public List<AASDescriptor> lookupAll() throws ProviderException {
+ return this.observedRegistryService.lookupAll();
+ }
+
+ @Override
+ public List<SubmodelDescriptor> lookupSubmodels(IIdentifier aasId) throws ProviderException {
+ return this.observedRegistryService.lookupSubmodels(aasId);
+ }
+
+ @Override
+ public SubmodelDescriptor lookupSubmodel(IIdentifier aasId, IIdentifier smId) throws ProviderException {
+ return this.observedRegistryService.lookupSubmodel(aasId, smId);
+ }
+
+ public static String concatAasSmId(IIdentifier aasId, IIdentifier smId) {
+ return "(" + aasId.getId() + "," + smId.getId() + ")";
+ }
+}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/shared/mqtt/MqttEventService.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/shared/mqtt/MqttEventService.java
new file mode 100644
index 0000000..d31019b
--- /dev/null
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/shared/mqtt/MqttEventService.java
@@ -0,0 +1,107 @@
+package org.eclipse.basyx.extensions.shared.mqtt;
+
+import org.eclipse.paho.client.mqttv3.MqttClient;
+import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
+import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of common parts of MQTT event propagation services.
+ * Extend this class to make a service MQTT extendable
+ *
+ * @author haque
+ *
+ */
+public class MqttEventService {
+ private static Logger logger = LoggerFactory.getLogger(MqttEventService.class);
+
+ // The MQTTClient
+ protected MqttClient mqttClient;
+
+ // QoS for MQTT messages (1, 2 or 3).
+ protected int qos = 1;
+
+ /**
+ * Constructor for creating an MqttClient (no authentication)
+ * @param serverEndpoint
+ * @param clientId
+ * @throws MqttException
+ */
+ public MqttEventService(String serverEndpoint, String clientId) throws MqttException {
+ this.mqttClient = new MqttClient(serverEndpoint, clientId, new MqttDefaultFilePersistence());
+ mqttClient.connect();
+ }
+
+ /**
+ * Constructor for creating an MqttClient with authentication
+ * @param serverEndpoint
+ * @param clientId
+ * @param user
+ * @param pw
+ * @throws MqttException
+ */
+ public MqttEventService(String serverEndpoint, String clientId, String user, char[] pw)
+ throws MqttException {
+ this.mqttClient = new MqttClient(serverEndpoint, clientId, new MqttDefaultFilePersistence());
+ MqttConnectOptions options = new MqttConnectOptions();
+ options.setUserName(user);
+ options.setPassword(pw);
+ mqttClient.connect(options);
+ }
+
+ /**
+ * Constructor for creating an MqttClient with existing client
+ * @param client
+ * @throws MqttException
+ */
+ public MqttEventService(MqttClient client) throws MqttException {
+ this.mqttClient = client;
+ mqttClient.connect();
+ }
+
+ /**
+ * Sets the QoS for MQTT messages
+ *
+ * @param qos
+ */
+ public void setQoS(int qos) {
+ if (qos >= 0 && qos <= 3) {
+ this.qos = qos;
+ } else {
+ throw new IllegalArgumentException("Invalid QoS: " + qos);
+ }
+ }
+
+ /**
+ * Gets the QoS for MQTT messages
+ *
+ * @param qos
+ */
+ public int getQoS() {
+ return this.qos;
+ }
+
+ /**
+ * Sends MQTT message to connected broker
+ * @param topic in which the message will be published
+ * @param payload the actual message
+ */
+ protected void sendMqttMessage(String topic, String payload) {
+ MqttMessage msg = new MqttMessage(payload.getBytes());
+ if (this.qos != 1) {
+ msg.setQos(this.qos);
+ }
+ try {
+ logger.debug("Send MQTT message to " + topic + ": " + payload);
+ mqttClient.publish(topic, msg);
+ } catch (MqttPersistenceException e) {
+ logger.error("Could not persist mqtt message", e);
+ } catch (MqttException e) {
+ logger.error("Could not send mqtt message", e);
+ }
+ }
+}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/events/submodel/mqtt/MqttSubmodelAPI.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/submodel/mqtt/MqttSubmodelAPI.java
similarity index 76%
rename from sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/events/submodel/mqtt/MqttSubmodelAPI.java
rename to sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/submodel/mqtt/MqttSubmodelAPI.java
index 04cc3b6..0bb1352 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/events/submodel/mqtt/MqttSubmodelAPI.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/extensions/submodel/mqtt/MqttSubmodelAPI.java
@@ -1,20 +1,17 @@
-package org.eclipse.basyx.extensions.events.submodel.mqtt;
+package org.eclipse.basyx.extensions.submodel.mqtt;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
+import org.eclipse.basyx.extensions.shared.mqtt.MqttEventService;
import org.eclipse.basyx.submodel.metamodel.api.ISubModel;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation;
import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
-import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,7 +23,7 @@
* @author espen
*
*/
-public class MqttSubmodelAPI implements ISubmodelAPI {
+public class MqttSubmodelAPI extends MqttEventService implements ISubmodelAPI {
private static Logger logger = LoggerFactory.getLogger(MqttSubmodelAPI.class);
// List of topics
@@ -38,16 +35,10 @@
// The underlying SubmodelAPI
protected ISubmodelAPI observedAPI;
- // The MQTTClient
- protected MqttClient mqttClient;
-
// Submodel Element whitelist for filtering
protected boolean useWhitelist = false;
protected Set<String> whitelist = new HashSet<>();
- // QoS for MQTT messages (1, 2 or 3).
- protected int qos = 1;
-
/**
* Constructor for adding this MQTT extension on top of another SubmodelAPI
*
@@ -55,10 +46,9 @@
* @throws MqttException
*/
public MqttSubmodelAPI(ISubmodelAPI observedAPI, String serverEndpoint, String clientId) throws MqttException {
+ super(serverEndpoint, clientId);
logger.info("Create new MQTT submodel for endpoint " + serverEndpoint);
this.observedAPI = observedAPI;
- this.mqttClient = new MqttClient(serverEndpoint, clientId, new MqttDefaultFilePersistence());
- mqttClient.connect();
sendMqttMessage(TOPIC_ADDSUBMODEL, observedAPI.getSubmodel().getIdentification().getId());
}
@@ -70,60 +60,26 @@
*/
public MqttSubmodelAPI(ISubmodelAPI observedAPI, String serverEndpoint, String clientId, String user, char[] pw)
throws MqttException {
+ super(serverEndpoint, clientId, user, pw);
logger.info("Create new MQTT submodel for endpoint " + serverEndpoint);
this.observedAPI = observedAPI;
- this.mqttClient = new MqttClient(serverEndpoint, clientId, new MqttDefaultFilePersistence());
- MqttConnectOptions options = new MqttConnectOptions();
- options.setUserName(user);
- options.setPassword(pw);
- mqttClient.connect(options);
sendMqttMessage(TOPIC_ADDSUBMODEL, observedAPI.getSubmodel().getIdentification().getId());
}
/**
- * Returns the connected mqttClient
- *
- * @return
- */
- public MqttClient getClient() {
- return mqttClient;
- }
-
- /**
* Constructor for adding this MQTT extension on top of another SubmodelAPI.
*
* @param observedAPI The underlying submodelAPI
* @param client An already connected mqtt client
+ * @throws MqttException
*/
- public MqttSubmodelAPI(ISubmodelAPI observedAPI, MqttClient client) {
+ public MqttSubmodelAPI(ISubmodelAPI observedAPI, MqttClient client) throws MqttException {
+ super(client);
this.observedAPI = observedAPI;
- this.mqttClient = client;
sendMqttMessage(TOPIC_ADDSUBMODEL, observedAPI.getSubmodel().getIdentification().getId());
}
/**
- * Sets the QoS for MQTT messages
- *
- * @param qos
- */
- public void setQoS(int qos) {
- if (qos >= 0 && qos <= 3) {
- this.qos = qos;
- } else {
- throw new IllegalArgumentException("Invalid QoS: " + qos);
- }
- }
-
- /**
- * Gets the QoS for MQTT messages
- *
- * @param qos
- */
- public int getQoS() {
- return this.qos;
- }
-
- /**
* Adds a submodel element to the filter whitelist. Can also be a path for nested submodel elements.
*
* @param element
@@ -237,21 +193,6 @@
return observedAPI.getOperationResult(idShort, requestId);
}
- private void sendMqttMessage(String topic, String payload) {
- MqttMessage msg = new MqttMessage(payload.getBytes());
- if (this.qos != 1) {
- msg.setQos(this.qos);
- }
- try {
- logger.debug("Send MQTT message to " + topic + ": " + payload);
- mqttClient.publish(topic, msg);
- } catch (MqttPersistenceException e) {
- logger.error("Could not persist mqtt message", e);
- } catch (MqttException e) {
- logger.error("Could not send mqtt message", e);
- }
- }
-
private boolean filter(String idShort) {
return !useWhitelist || whitelist.contains(idShort);
}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/aas/registration/mqtt/TestMqttAASRegistryService.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/aas/registration/mqtt/TestMqttAASRegistryService.java
new file mode 100644
index 0000000..cd6df8d
--- /dev/null
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/aas/registration/mqtt/TestMqttAASRegistryService.java
@@ -0,0 +1,135 @@
+package org.eclipse.basyx.testsuite.regression.extensions.aas.registration.mqtt;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.eclipse.basyx.aas.metamodel.api.parts.asset.AssetKind;
+import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;
+import org.eclipse.basyx.aas.metamodel.map.descriptor.AASDescriptor;
+import org.eclipse.basyx.aas.metamodel.map.descriptor.SubmodelDescriptor;
+import org.eclipse.basyx.aas.metamodel.map.parts.Asset;
+import org.eclipse.basyx.aas.registration.api.IAASRegistryService;
+import org.eclipse.basyx.aas.registration.memory.InMemoryRegistry;
+import org.eclipse.basyx.extensions.aas.registration.mqtt.MqttAASRegistryService;
+import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;
+import org.eclipse.basyx.submodel.metamodel.map.SubModel;
+import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier;
+import org.eclipse.basyx.testsuite.regression.extensions.shared.mqtt.MqttTestListener;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import io.moquette.broker.Server;
+import io.moquette.broker.config.ClasspathResourceLoader;
+import io.moquette.broker.config.IConfig;
+import io.moquette.broker.config.IResourceLoader;
+import io.moquette.broker.config.ResourceLoaderConfig;
+
+/**
+ * Tests events emitting with the MqttAASRegistryService
+ *
+ * @author haque
+ *
+ */
+public class TestMqttAASRegistryService {
+
+ private static final String AASID = "aasid1";
+ private static final String SUBMODELID = "submodelid1";
+ private static final String AASENDPOINT = "http://localhost:8080/aasList/" + AASID + "/aas";
+ private static final Identifier AASIDENTIFIER = new Identifier(IdentifierType.IRI, AASID);
+ private static final Identifier SUBMODELIDENTIFIER = new Identifier(IdentifierType.IRI, SUBMODELID);
+
+ private static Server mqttBroker;
+ private static MqttAASRegistryService eventAPI;
+ private MqttTestListener listener;
+
+ /**
+ * Sets up the MQTT broker and AASRegistryService for tests
+ */
+ @BeforeClass
+ public static void setUpClass() throws MqttException, IOException {
+ // Start MQTT broker
+ mqttBroker = new Server();
+ IResourceLoader classpathLoader = new ClasspathResourceLoader();
+ final IConfig classPathConfig = new ResourceLoaderConfig(classpathLoader);
+ mqttBroker.startServer(classPathConfig);
+
+ // Create underlying registry service
+ IAASRegistryService registryService = new InMemoryRegistry();
+
+ eventAPI = new MqttAASRegistryService(registryService, "tcp://localhost:1884", "testClient");
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ mqttBroker.stopServer();
+ }
+
+ @Before
+ public void setUp() {
+ AssetAdministrationShell shell = new AssetAdministrationShell(AASID, AASIDENTIFIER, new Asset("assetid1", new Identifier(IdentifierType.IRI, "assetid1"), AssetKind.INSTANCE));
+ AASDescriptor aasDescriptor = new AASDescriptor(shell, AASENDPOINT);
+ eventAPI.register(aasDescriptor);
+
+ SubModel submodel = new SubModel(SUBMODELID, SUBMODELIDENTIFIER);
+ String submodelEndpoint = AASENDPOINT + "/submodels/" + SUBMODELID + "/submodel";
+ SubmodelDescriptor submodelDescriptor = new SubmodelDescriptor(submodel, submodelEndpoint);
+ eventAPI.register(AASIDENTIFIER, submodelDescriptor);
+
+ listener = new MqttTestListener();
+ mqttBroker.addInterceptHandler(listener);
+ }
+
+ @After
+ public void tearDown() {
+ mqttBroker.removeInterceptHandler(listener);
+ }
+
+ @Test
+ public void testRegisterAAS() {
+ String newAASId = "aasid2";
+ Identifier newIdentifier = new Identifier(IdentifierType.IRI, newAASId);
+ AssetAdministrationShell shell = new AssetAdministrationShell(newAASId, newIdentifier, new Asset("assetid1", new Identifier(IdentifierType.IRI, "assetid2"), AssetKind.INSTANCE));
+ String aasEndpoint = "http://localhost:8080/aasList/" + newAASId + "/aas";
+
+ AASDescriptor aasDescriptor = new AASDescriptor(shell, aasEndpoint);
+ eventAPI.register(aasDescriptor);
+
+ assertEquals(newAASId, listener.lastPayload);
+ assertEquals(MqttAASRegistryService.TOPIC_REGISTERAAS, listener.lastTopic);
+ }
+
+ @Test
+ public void testRegisterSubmodel() {
+ String submodelid = "submodelid2";
+ Identifier newSubmodelIdentifier = new Identifier(IdentifierType.IRI, submodelid);
+ SubModel submodel = new SubModel(submodelid, newSubmodelIdentifier);
+ String submodelEndpoint = AASENDPOINT + "/submodels/" + submodelid + "/submodel";
+ SubmodelDescriptor submodelDescriptor = new SubmodelDescriptor(submodel, submodelEndpoint);
+
+ eventAPI.register(AASIDENTIFIER, submodelDescriptor);
+
+ assertEquals(MqttAASRegistryService.concatAasSmId(AASIDENTIFIER, newSubmodelIdentifier), listener.lastPayload);
+ assertEquals(MqttAASRegistryService.TOPIC_REGISTERSUBMODEL, listener.lastTopic);
+ }
+
+ @Test
+ public void testDeleteAAS() {
+ eventAPI.delete(AASIDENTIFIER);
+
+ assertEquals(AASID, listener.lastPayload);
+ assertEquals(MqttAASRegistryService.TOPIC_DELETEAAS, listener.lastTopic);
+ }
+
+ @Test
+ public void testDeleteSubmodel() {
+ eventAPI.delete(AASIDENTIFIER, SUBMODELIDENTIFIER);
+
+ assertEquals(MqttAASRegistryService.concatAasSmId(AASIDENTIFIER, SUBMODELIDENTIFIER), listener.lastPayload);
+ assertEquals(MqttAASRegistryService.TOPIC_DELETESUBMODEL, listener.lastTopic);
+ }
+}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/events/submodel/mqtt/MqttTestListener.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/shared/mqtt/MqttTestListener.java
similarity index 95%
rename from sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/events/submodel/mqtt/MqttTestListener.java
rename to sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/shared/mqtt/MqttTestListener.java
index 92ad66c..e0e297d 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/events/submodel/mqtt/MqttTestListener.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/shared/mqtt/MqttTestListener.java
@@ -1,4 +1,4 @@
-package org.eclipse.basyx.testsuite.regression.extensions.events.submodel.mqtt;
+package org.eclipse.basyx.testsuite.regression.extensions.shared.mqtt;
import java.nio.charset.StandardCharsets;
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/events/submodel/mqtt/TestMqttSubmodelAPIEvents.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/submodel/mqtt/TestMqttSubmodelAPIEvents.java
similarity index 94%
rename from sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/events/submodel/mqtt/TestMqttSubmodelAPIEvents.java
rename to sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/submodel/mqtt/TestMqttSubmodelAPIEvents.java
index 6fafffb..2eb9ca0 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/events/submodel/mqtt/TestMqttSubmodelAPIEvents.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/extensions/submodel/mqtt/TestMqttSubmodelAPIEvents.java
@@ -1,17 +1,18 @@
-package org.eclipse.basyx.testsuite.regression.extensions.events.submodel.mqtt;
+package org.eclipse.basyx.testsuite.regression.extensions.submodel.mqtt;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.io.IOException;
-import org.eclipse.basyx.extensions.events.submodel.mqtt.MqttSubmodelAPI;
+import org.eclipse.basyx.extensions.submodel.mqtt.MqttSubmodelAPI;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;
import org.eclipse.basyx.submodel.metamodel.map.SubModel;
import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
import org.eclipse.basyx.submodel.restapi.vab.VABSubmodelAPI;
+import org.eclipse.basyx.testsuite.regression.extensions.shared.mqtt.MqttTestListener;
import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.junit.After;