BaSyx examples update
diff --git a/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/device/ControllableTCPDeviceMockup.java b/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/device/ControllableTCPDeviceMockup.java
index d1c788c..c5c02d1 100644
--- a/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/device/ControllableTCPDeviceMockup.java
+++ b/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/device/ControllableTCPDeviceMockup.java
@@ -1,9 +1,6 @@
 package org.eclipse.basyx.examples.mockup.device;

 

-import org.eclipse.basyx.components.controlcomponent.ExecutionState;

-import org.eclipse.basyx.components.device.BaseTCPDevice;

-import org.eclipse.basyx.components.netcomm.NetworkReceiver;

-import org.eclipse.basyx.components.netcomm.TCPClient;

+import org.eclipse.basyx.components.device.BaseTCPControllableDevice;

 

 

 

@@ -16,16 +13,9 @@
  * @author kuhn

  *

  */

-public class ControllableTCPDeviceMockup extends BaseTCPDevice implements NetworkReceiver {

+public class ControllableTCPDeviceMockup extends BaseTCPControllableDevice {

 

 	

-	/**

-	 * Receive thread

-	 */

-	protected Thread rxThread = null;

-	

-	

-	

 	

 	/**

 	 * Constructor

@@ -35,82 +25,17 @@
 		super(port);

 	}

 	

-	

+

 	

 	/**

-	 * Start the device

+	 * Indicate device status change to device manager

 	 */

 	@Override

-	public void start() {

+	protected void statusChange(String newStatus) {

 		// Invoke base implementation

-		super.start();

+		super.statusChange(newStatus);

 		

-		// Add this component as message listener

-		communicationClient.addTCPMessageListener(this);

-		// - Start receive thread

-		rxThread = new Thread(communicationClient);

-		// - Start receiving

-		rxThread.start();

-	}

-

-

-	/**

-	 * Stop the device

-	 */

-	@Override

-	public void stop() {

-		// Invoke base implementation

-		super.stop();

-		

-		// End communication

-		communicationClient.close();

-	}

-

-	

-	/**

-	 * Wait for end of all threads

-	 */

-	@Override

-	public void waitFor() {

-		// Invoke base implementation

-		super.waitFor();

-		

-		// Wait for end of TCP thread

-		try {rxThread.join();} catch (InterruptedException e) {e.printStackTrace();}

-	}

-

-	

-	

-	

-	/**

-	 * Changed operation mode

-	 */

-	protected void onOperationModeChange(String newOperationMode) {

-		// Do nothing

-	}

-	

-	

-	/**

-	 * State change

-	 */

-	protected void onStateChange(ExecutionState newExState) {

-		// Do nothing

-	}

-

-	

-	/**

-	 * A message has been received

-	 */

-	@Override

-	public void onReceive(byte[] message) {

-		// Convert message to String

-		String rxMessage = TCPClient.toString(message);

-		

-		// Process message

-		if (rxMessage.startsWith("state:"))  {onStateChange(ExecutionState.byValue(rxMessage.substring("state:".length()))); return;}

-		if (rxMessage.startsWith("opMode:")) {onOperationModeChange(rxMessage.substring("opMode:".length())); return;}

-		

-		// Indicate exception

-		throw new RuntimeException("Unexpected message received:"+rxMessage);

+		// Write bytes to device manager

+		communicationClient.sendMessage("status:"+newStatus+"\n");

 	}

 }

diff --git a/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/device/SmartBaSyxTCPDeviceMockup.java b/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/device/SmartBaSyxTCPDeviceMockup.java
index ad9a74f..c1c0ce9 100644
--- a/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/device/SmartBaSyxTCPDeviceMockup.java
+++ b/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/device/SmartBaSyxTCPDeviceMockup.java
@@ -84,6 +84,15 @@
 

 	

 	/**

+	 * Indicate device service end

+	 */

+	@Override

+	protected void onServiceEnd() {

+		// Do nothing

+	}

+

+	

+	/**

 	 * Smart device control component indicates an execution state change

 	 */

 	@Override

@@ -91,11 +100,6 @@
 		// Invoke base implementation

 		super.onChangedExecutionState(newExecutionState);

 		

-		// Communicate device state change to asset administration shell

-		//statusChange(newExecutionState.getValue());

-		System.out.println("Changing to:"+newExecutionState.getValue());

-		

-		

 		// Update property "properties/status" in external AAS

 		aasServerConnection.updateElementValue(lookupURN("Status").getEncodedURN()+"/properties/status", newExecutionState.getValue());

 	}

@@ -144,21 +148,16 @@
 

 		

 		// Register AAS and sub models in directory (push AAS descriptor to server)

-		// - Delete AAS registration for a fresh start - ignore if URL was not found. In this case, there was

-		//   no previous registration and the registry was clean

-		getRegistry().delete(lookupURN("AAS"));

 		// - AAS repository server URL

 		String aasRepoURL = "http://localhost:8080/basys.examples/Components/BaSys/1.0/aasServer";

-		// - Create an AAS descriptor

-		AASDescriptor deviceAASDescriptor = new AASDescriptor(lookupURN("AAS"), aasRepoURL);

-		// - Add sub model descriptors 

-		deviceAASDescriptor.addSubmodelDescriptor(lookupURN("Status"), aasRepoURL);

-		deviceAASDescriptor.addSubmodelDescriptor(lookupURN("Controller"), "basyx://127.0.0.1:"+serverPort);

-		

+		// - Build an AAS descriptor, add sub model descriptors  

+		AASDescriptor deviceAASDescriptor = new AASDescriptor(lookupURN("AAS"), aasRepoURL)

+			.addSubmodelDescriptor(lookupURN("Status"), aasRepoURL)

+			.addSubmodelDescriptor(lookupURN("Controller"), "basyx://127.0.0.1:"+serverPort);

 		// - Push AAS descriptor to server

-		getRegistry().register(deviceAASDescriptor);		

+		getRegistry().register(lookupURN("AAS"), deviceAASDescriptor);		

 	}

-	

+

 

 	/**

 	 * Stop smart device

diff --git a/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/devicemanager/BaSyxTCPControlManufacturingDeviceManager.java b/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/devicemanager/BaSyxTCPControlManufacturingDeviceManager.java
new file mode 100644
index 0000000..74ba403
--- /dev/null
+++ b/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/devicemanager/BaSyxTCPControlManufacturingDeviceManager.java
@@ -0,0 +1,187 @@
+package org.eclipse.basyx.examples.mockup.devicemanager;

+

+import java.util.HashMap;

+import java.util.Map;

+

+import org.eclipse.basyx.aas.backend.connector.http.HTTPConnectorProvider;

+import org.eclipse.basyx.aas.metamodel.hashmap.aas.AssetAdministrationShell;

+import org.eclipse.basyx.aas.metamodel.hashmap.aas.SubModel;

+import org.eclipse.basyx.components.controlcomponent.ControlComponentChangeListener;

+import org.eclipse.basyx.components.devicemanager.TCPControllableDeviceManagerComponent;

+import org.eclipse.basyx.components.proxy.registry.AASHTTPRegistryProxy;

+import org.eclipse.basyx.examples.support.directory.ExamplesPreconfiguredDirectory;

+import org.eclipse.basyx.vab.backend.server.basyx.BaSyxTCPServer;

+import org.eclipse.basyx.vab.core.VABConnectionManager;

+import org.eclipse.basyx.vab.core.proxy.VABElementProxy;

+import org.eclipse.basyx.vab.provider.hashmap.VABHashmapProvider;

+

+import basys.examples.aasdescriptor.AASDescriptor;

+import basys.examples.aasdescriptor.ModelUrn;

+

+

+

+/**

+ * Example manufacturing device manager code

+ * 

+ * This example code extends the BaSyxTCPManufacturingDeviceManager by adding a control component sub model to control the managed device.

+ * 

+ * 

+ * @author kuhn

+ *

+ */

+public class BaSyxTCPControlManufacturingDeviceManager extends TCPControllableDeviceManagerComponent implements ControlComponentChangeListener {

+

+	

+	/**

+	 * AAS server connection

+	 */

+	protected VABElementProxy aasServerConnection = null;

+

+	

+	

+

+	/**

+	 * Constructor

+	 */

+	public BaSyxTCPControlManufacturingDeviceManager(int deviceTCPPort, int ctrlComponentServerPort) {

+		// Invoke base constructor

+		super(deviceTCPPort, ctrlComponentServerPort);

+		

+		

+		// Set registry that will be used by this service

+		setRegistry(new AASHTTPRegistryProxy("http://localhost:8080/basys.examples/Components/Directory/SQL"));

+		

+		

+		// Set service connection manager and create AAS server connection

+		setConnectionManager(new VABConnectionManager(new ExamplesPreconfiguredDirectory(), new HTTPConnectorProvider()));

+		// - Create AAS server connection

+		aasServerConnection = getConnectionManager().connectToHTTPVABElement("AASServer", "/aas/submodels/aasRepository/");

+		

+		

+		// Set AAS server VAB object ID, AAS server URL, and AAS server path prefix

+		setAASServerObjectID("AASServer");

+		setAASServerURL("http://localhost:8080/basys.examples/Components/BaSys/1.0/aasServer");

+		setAASServerPathPrefix("/aas/submodels/aasRepository/");

+	}

+

+	

+	/**

+	 * Initialize the device, and register it with the backend

+	 */

+	@Override 

+	public void start() {

+		// Base implementation

+		super.start();

+		

+		// Create the device AAS and sub model structure

+		createDeviceAASAndSubModels();

+		

+		// Register AAS and sub model descriptors in directory (push AAS descriptor to server)

+		getRegistry().register(lookupURN("AAS"), getAASDescriptor());

+	}

+

+	

+	

+	/**

+	 * Create the device AAS and sub model structure

+	 */

+	@SuppressWarnings("unchecked")

+	protected void createDeviceAASAndSubModels() {

+		// Register URNs of managed VAB objects

+		addShortcut("AAS",        new ModelUrn("urn:de.FHG:devices.es.iese:aas:1.0:3:x-509#001"));

+		addShortcut("Status",     new ModelUrn("urn:de.FHG:devices.es.iese:statusSM:1.0:3:x-509#001"));

+		addShortcut("Controller", new ModelUrn("urn:de.FHG:devices.es.iese:controllerSM:1.0:3:x-509#001"));

+		

+

+		// Create device AAS

+		AssetAdministrationShell aas = new AssetAdministrationShell();

+		// - Populate AAS

+		aas.setId("DeviceIDShort");

+		// - Transfer device AAS to server

+		aasServerConnection.createElement(lookupURN("AAS").toString(), aas);

+

+	

+		// The device also brings a sub model structure with an own ID that is being pushed on the server

+		// - Create generic sub model and add properties

+		SubModel statusSM = new SubModel()

+		//   - Property status: indicate device status

+				.putPath("properties/status", "offline")

+		//   - Property statistics: export invocation statistics for every service

+		//     - invocations: indicate total service invocations. Properties are not persisted in this example,

+		//                    therefore we start counting always at 0.

+				.putPath("properties/statistics/default/invocations", 0);

+		// - Transfer device sub model to server

+		aasServerConnection.createElement(lookupURN("Status").toString(), statusSM);

+

+		

+		// The device also brings a sub model structure with an own ID that is being pushed on the server

+		// - Create generic sub model 

+		SubModel controllerSM = new SubModel();

+		//   - Create sub model contents manually

+		Map<String, Object> listOfControllers = new HashMap<>();

+		((Map<String, Object>) controllerSM.get("properties")).put("controllers", listOfControllers);

+		// - Transfer device sub model to server

+		aasServerConnection.createElement(lookupURN("Controller").toString(), controllerSM);

+

+				

+		

+		// Register URNs of control component VAB object

+		addShortcut("ControlComponent", new ModelUrn("urn:de.FHG:devices.es.iese:controlComponentSM:1.0:3:x-509#001"));

+

+		

+		// Register control component as local sub model

+		// - This sub model will stay with the device

+		server = new BaSyxTCPServer<>(new VABHashmapProvider(simpleControlComponent), controlComponentServerPort);

+		// - Start local BaSyx/TCP server

+		server.start();

+	}

+	

+	

+	

+	/**

+	 * Get AAS descriptor for managed device

+	 */

+	@Override 

+	protected AASDescriptor getAASDescriptor() {

+		// Create AAS and sub model descriptors

+		AASDescriptor aasDescriptor = createAASDescriptorURI(lookupURN("AAS"));

+		addSubModelDescriptorURI(aasDescriptor, lookupURN("Status"));

+		addSubModelDescriptorURI(aasDescriptor, lookupURN("Controller"));

+		

+		// Add descriptor for control component sub model

+		aasDescriptor.addSubmodelDescriptor(lookupURN("ControlComponent"), "basyx://127.0.0.1:"+controlComponentServerPort);

+		

+		// Return AAS, sub model descriptors, and added control component sub model descriptor

+		return aasDescriptor;

+	}

+

+	

+	

+	/**

+	 * Received a string from network

+	 */

+	@Override

+	public void onReceive(byte[] rxData) {

+		// Do not process null values

+		if (rxData == null) return;

+		

+		// Convert received data to string

+		String rxStr = new String(rxData); 

+		// - Trim string to remove possibly trailing and leading white spaces

+		rxStr = rxStr.trim();

+		

+		// Check what was being received. This check is performed based on a prefix that he device has to provide);

+		// - Update of device status

+		if (hasPrefix(rxStr, "status:")) aasServerConnection.updateElementValue(lookupURN("Status").getEncodedURN()+"/properties/status", removePrefix(rxStr, "status"));

+		// - Device indicates service invocation

+		if (hasPrefix(rxStr, "invocation:")) {

+			// Read and increment invocation counter

+			int invocations = (int) aasServerConnection.readElementValue(lookupURN("Status").getEncodedURN()+"/properties/statistics/default/invocations");

+			aasServerConnection.updateElementValue(lookupURN("Status").getEncodedURN()+"/properties/statistics/default/invocations", ++invocations);

+		}

+		

+		// Let base implementation process the message

+		super.onReceive(rxData);

+	}

+}

+

diff --git a/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/devicemanager/ManufacturingDeviceManager.java b/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/devicemanager/ManufacturingDeviceManager.java
new file mode 100644
index 0000000..c0f3dca
--- /dev/null
+++ b/examples/basys.examples/examples/org/eclipse/basyx/examples/mockup/devicemanager/ManufacturingDeviceManager.java
@@ -0,0 +1,179 @@
+package org.eclipse.basyx.examples.mockup.devicemanager;

+

+import java.util.HashMap;

+import java.util.Map;

+

+import org.eclipse.basyx.aas.backend.connector.http.HTTPConnectorProvider;

+import org.eclipse.basyx.aas.metamodel.hashmap.aas.AssetAdministrationShell;

+import org.eclipse.basyx.aas.metamodel.hashmap.aas.SubModel;

+import org.eclipse.basyx.components.devicemanager.TCPDeviceManagerComponent;

+import org.eclipse.basyx.components.proxy.registry.AASHTTPRegistryProxy;

+import org.eclipse.basyx.examples.support.directory.ExamplesPreconfiguredDirectory;

+import org.eclipse.basyx.vab.core.VABConnectionManager;

+import org.eclipse.basyx.vab.core.proxy.VABElementProxy;

+import basys.examples.aasdescriptor.AASDescriptor;

+import basys.examples.aasdescriptor.ModelUrn;

+

+

+

+/**

+ * Example manufacturing device manager code

+ * 

+ * This example code illustrates a basic device manager component. It implements the interaction between a device and the BaSyx infrastructure.

+ * This code is for example deployed on the device (in case of availability of a Java runtime environment) or to an explicit connector device.

+ * The Asset Administration Shell is not kept on the device, but transferred to an AAS server during registration. This ensures its presence also

+ * if the device itself is not available, e.g. due to a failure. Important asset data, such as manufacturer, and support contacts remain available

+ * in this case.

+ * 

+ * This code implements the following:

+ * - Registration of device the AAS and sub models with the BaSyx infrastructure

+ * - Updating of sub model properties to reflect the device status

+ * - TCP connection to legacy device

+ * 

+ * 

+ * @author kuhn

+ *

+ */

+public class ManufacturingDeviceManager extends TCPDeviceManagerComponent {

+

+	

+	/**

+	 * AAS server connection

+	 */

+	protected VABElementProxy aasServerConnection = null;

+

+

+

+

+

+

+	/**

+	 * Constructor

+	 */

+	public ManufacturingDeviceManager(int port) {

+		// Invoke base constructor

+		super(port);

+		

+		

+		// Set registry that will be used by this service

+		setRegistry(new AASHTTPRegistryProxy("http://localhost:8080/basys.examples/Components/Directory/SQL"));

+		

+		

+		// Set service connection manager and create AAS server connection

+		setConnectionManager(new VABConnectionManager(new ExamplesPreconfiguredDirectory(), new HTTPConnectorProvider()));

+		// - Create AAS server connection

+		aasServerConnection = getConnectionManager().connectToHTTPVABElement("AASServer", "/aas/submodels/aasRepository/");

+		

+		

+		// Set AAS server VAB object ID, AAS server URL, and AAS server path prefix

+		setAASServerObjectID("AASServer");

+		setAASServerURL("http://localhost:8080/basys.examples/Components/BaSys/1.0/aasServer");

+		setAASServerPathPrefix("/aas/submodels/aasRepository/");

+	}

+

+

+

+	/**

+	 * Initialize the device, and register it with the backend

+	 */

+	@Override 

+	public void start() {

+		// Base implementation

+		super.start();

+		

+		// Create the device AAS and sub model structure

+		createDeviceAASAndSubModels();

+		

+		// Register AAS and sub model descriptors in directory (push AAS descriptor to server)

+		getRegistry().register(lookupURN("AAS"), getAASDescriptor());

+	}

+	

+	

+	/**

+	 * Get AAS descriptor for managed device

+	 */

+	@Override 

+	protected AASDescriptor getAASDescriptor() {

+		// Create AAS and sub model descriptors

+		AASDescriptor aasDescriptor = createAASDescriptorURI(lookupURN("AAS"));

+		addSubModelDescriptorURI(aasDescriptor, lookupURN("Status"));

+		addSubModelDescriptorURI(aasDescriptor, lookupURN("Controller"));

+		

+		// Return AAS and sub model descriptors

+		return aasDescriptor;

+	}

+

+	

+	

+	/**

+	 * Create the device AAS and sub model structure

+	 */

+	@SuppressWarnings("unchecked")

+	protected void createDeviceAASAndSubModels() {

+		

+		// Register URNs of managed VAB objects

+		addShortcut("AAS",        new ModelUrn("urn:de.FHG:devices.es.iese:aas:1.0:3:x-509#001"));

+		addShortcut("Status",     new ModelUrn("urn:de.FHG:devices.es.iese:statusSM:1.0:3:x-509#001"));

+		addShortcut("Controller", new ModelUrn("urn:de.FHG:devices.es.iese:controllerSM:1.0:3:x-509#001"));

+		

+

+		// Create device AAS

+		AssetAdministrationShell aas = new AssetAdministrationShell();

+		// - Populate AAS

+		aas.setId("DeviceIDShort");

+		// - Transfer device AAS to server

+		aasServerConnection.createElement(lookupURN("AAS").toString(), aas);

+

+	

+		// The device also brings a sub model structure with an own ID that is being pushed on the server

+		// - Create generic sub model and add properties

+		SubModel statusSM = new SubModel()

+		//   - Property status: indicate device status

+				.putPath("properties/status", "offline")

+		//   - Property statistics: export invocation statistics for every service

+		//     - invocations: indicate total service invocations. Properties are not persisted in this example,

+		//                    therefore we start counting always at 0.

+				.putPath("properties/statistics/default/invocations", 0);

+		// - Transfer device sub model to server

+		aasServerConnection.createElement(lookupURN("Status").toString(), statusSM);

+

+		

+		// The device also brings a sub model structure with an own ID that is being pushed on the server

+		// - Create generic sub model 

+		SubModel controllerSM = new SubModel();

+		//   - Create sub model contents manually

+		Map<String, Object> listOfControllers = new HashMap<>();

+		((Map<String, Object>) controllerSM.get("properties")).put("controllers", listOfControllers);

+		// - Transfer device sub model to server

+		aasServerConnection.createElement(lookupURN("Controller").toString(), controllerSM);

+	}

+

+

+	

+	

+	

+	

+	/**

+	 * Received a string from network

+	 */

+	@Override

+	public void onReceive(byte[] rxData) {

+		// Do not process null values

+		if (rxData == null) return;

+		

+		// Convert received data to string

+		String rxStr = new String(rxData); 

+		// - Trim string to remove possibly trailing and leading white spaces

+		rxStr = rxStr.trim();

+		

+		// Check what was being received. This check is performed based on a prefix that he device has to provide);

+		// - Update of device status

+		if (hasPrefix(rxStr, "status:")) aasServerConnection.updateElementValue(lookupURN("Status").getEncodedURN()+"/properties/status", removePrefix(rxStr, "status"));

+		// - Device indicates service invocation

+		if (hasPrefix(rxStr, "invocation:")) {

+			// Read and increment invocation counter

+			int invocations = (int) aasServerConnection.readElementValue(lookupURN("Status").getEncodedURN()+"/properties/statistics/default/invocations");

+			aasServerConnection.updateElementValue(lookupURN("Status").getEncodedURN()+"/properties/statistics/default/invocations", ++invocations);

+		}

+	}

+}

diff --git a/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/RunSimpleTCPDevice.java b/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/RunSimpleTCPDevice.java
index ba47710..0c89bdb 100644
--- a/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/RunSimpleTCPDevice.java
+++ b/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/RunSimpleTCPDevice.java
@@ -8,7 +8,7 @@
 import org.eclipse.basyx.examples.examplescenario.BaSyxExampleScenario;

 import org.eclipse.basyx.examples.mockup.application.ReceiveDeviceStatusApplication;

 import org.eclipse.basyx.examples.mockup.device.SimpleTCPDeviceMockup;

-import org.eclipse.basyx.examples.mockup.devicemanager.BaSyxTCPManufacturingDeviceManager;

+import org.eclipse.basyx.examples.mockup.devicemanager.ManufacturingDeviceManager;

 import org.eclipse.basyx.examples.support.directory.ExamplesPreconfiguredDirectory;

 import org.eclipse.basyx.vab.core.VABConnectionManager;

 import org.junit.ClassRule;

@@ -50,7 +50,7 @@
 				

 				// Simulated runnables

 				// - Manufacturing device manager, e.g. deployed to additonal device

-				new BaSyxTCPManufacturingDeviceManager(9998).setName("DeviceManager"),

+				new ManufacturingDeviceManager(9998).setName("DeviceManager"),

 				

 				// Simulated mockups

 				new SimpleTCPDeviceMockup(9998).setName("Device"),

@@ -74,48 +74,38 @@
 	public void test() throws Exception {

 		// Device updates status to ready

 		((SimpleTCPDeviceMockup) context.getRunnable("Device")).deviceInitialized();

-System.out.println("XXXXXX-1");

 		

 		// Application waits for status change

 		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("IDLE") );

 		assertTrue( ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("IDLE") );

-System.out.println("XXXXXX-2");

 

 		// Application checks invocation counter

 		assertTrue( ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceInvocationCounter() == 0 );		

-System.out.println("XXXXXX-3");

 

 		// Device updates status to running

 		// - The device indicates that a process step is running

 		((SimpleTCPDeviceMockup) context.getRunnable("Device")).serviceRunning();

-System.out.println("XXXXXX-4");

 		

 		// Application waits for status change

 		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("EXECUTE") );

 		assertTrue( ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("EXECUTE") );

-System.out.println("XXXXXX-5");

 

 		// Device updates status to complete

 		// - The device indicates that process step did finish

 		((SimpleTCPDeviceMockup) context.getRunnable("Device")).serviceCompleted();

-System.out.println("XXXXXX-6");

 		

 		// Application waits for status change

 		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("COMPLETE") );

 		assertTrue( ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("COMPLETE") );

-System.out.println("XXXXXX-7");

 

 		// Device updates status to ready again, next process step may be invoked

 		((SimpleTCPDeviceMockup) context.getRunnable("Device")).resetCompleted();

-System.out.println("XXXXXX-8");

 		

 		// Application waits for status change

 		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("IDLE") );

 		assertTrue( ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("IDLE") );

-System.out.println("XXXXXX-9");

 

 		// Application checks invocation counter

 		assertTrue( ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceInvocationCounter() == 1 );

-System.out.println("XXXXXX-10");

 	}

 }

diff --git a/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/controllable/RunExampleSimpleControllableTCPDevice.java b/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/controllable/RunExampleSimpleControllableTCPDevice.java
new file mode 100644
index 0000000..2c628d2
--- /dev/null
+++ b/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/controllable/RunExampleSimpleControllableTCPDevice.java
@@ -0,0 +1,142 @@
+package org.eclipse.basyx.examples.scenarios.device.controllable;

+

+import static org.junit.Assert.assertTrue;

+

+import org.eclipse.basyx.aas.backend.connector.JSONConnector;

+import org.eclipse.basyx.aas.backend.connector.basyx.BaSyxConnector;

+import org.eclipse.basyx.aas.backend.connector.http.HTTPConnectorProvider;

+import org.eclipse.basyx.components.controlcomponent.ExecutionState;

+import org.eclipse.basyx.examples.contexts.BaSyxExamplesContext_1MemoryAASServer_1SQLDirectory;

+import org.eclipse.basyx.examples.deployment.BaSyxDeployment;

+import org.eclipse.basyx.examples.examplescenario.BaSyxExampleScenario;

+import org.eclipse.basyx.examples.mockup.application.ReceiveDeviceStatusApplication;

+import org.eclipse.basyx.examples.mockup.device.ControllableTCPDeviceMockup;

+import org.eclipse.basyx.examples.mockup.devicemanager.BaSyxTCPControlManufacturingDeviceManager;

+import org.eclipse.basyx.examples.support.directory.ExamplesPreconfiguredDirectory;

+import org.eclipse.basyx.vab.core.VABConnectionManager;

+import org.junit.ClassRule;

+import org.junit.Test;

+

+

+

+/**

+ * Run example for controllable device

+ * 

+ * @author kuhn

+ *

+ */

+public class RunExampleSimpleControllableTCPDevice extends BaSyxExampleScenario {

+

+	

+	/**

+	 * VAB connection manager backend

+	 */

+	protected VABConnectionManager connManager = new VABConnectionManager(new ExamplesPreconfiguredDirectory(), new HTTPConnectorProvider());

+

+	

+	/**

+	 * BaSyx connector instance

+	 */

+	protected BaSyxConnector basyxConnector = null;

+	

+	

+	/**

+	 * Communication stream to connected device control component

+	 */

+	protected JSONConnector toControlComponent = null;

+

+

+

+

+	/**

+	 * Instantiate and start context elements for this example. BaSyxDeployment contexts instantiate all

+	 * components on the IP address of the host. Therefore, all components use the same IP address. 

+	 */

+	@ClassRule

+	public static BaSyxDeployment context = new BaSyxDeployment(

+				// BaSyx infrastructure

+				// - BaSys topology with one AAS Server and one SQL directory

+				new BaSyxExamplesContext_1MemoryAASServer_1SQLDirectory(),

+				

+				// Simulated runnables

+				// - Manufacturing device manager, e.g. deployed to additonal device

+				new BaSyxTCPControlManufacturingDeviceManager(9998, 9997).setName("DeviceManager"),

+

+				// Device mockups

+				new ControllableTCPDeviceMockup(9998).setName("Device"),

+				

+				// Application mockups

+				new ReceiveDeviceStatusApplication().setName("Application")

+			);

+

+

+

+	/**

+	 * Test sequence: 

+	 * - Device status update

+	 * - Read device status from AAS

+	 */

+	@Test 

+	public void test() throws Exception {

+		// Create connection to device control component on smart device

+		// - Create BaSyx connector to connect with the device manager

+		basyxConnector = new BaSyxConnector("localhost", 9997);

+		// - Create connection to device control component

+		toControlComponent = new JSONConnector(basyxConnector);

+

+

+		

+		// Device finishes initialization and moves to idle state

+		((ControllableTCPDeviceMockup) context.getRunnable("Device")).deviceInitialized();

+		

+		// Application waits for status change

+		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("IDLE") );

+		// - Validate device status

+		waitfor( () -> ((ControllableTCPDeviceMockup) context.getRunnable("Device")).exState == ExecutionState.IDLE );

+

+		

+		// Change device operation mode

+		toControlComponent.setModelPropertyValue("status/opMode", "RegularMilling");

+		// - Validate device operation mode

+		waitfor( () -> ((ControllableTCPDeviceMockup) context.getRunnable("Device")).opMode.equals("RegularMilling") );

+

+		// Application checks invocation counter

+		assertTrue( ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceInvocationCounter() == 0 );		

+

+		

+		// Start device service

+		toControlComponent.setModelPropertyValue("cmd", "start");

+		// - Application waits for status change

+		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("EXECUTE") );

+		// - Validate device status

+		waitfor( () -> ((ControllableTCPDeviceMockup) context.getRunnable("Device")).exState == ExecutionState.EXECUTE );

+

+		

+		// Device indicates service end

+		((ControllableTCPDeviceMockup) context.getRunnable("Device")).serviceCompleted();

+		// - Application waits for status change

+		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("COMPLETE") );

+		// - Validate device status

+		waitfor( () -> ((ControllableTCPDeviceMockup) context.getRunnable("Device")).exState == ExecutionState.COMPLETE );

+

+

+		// Reset device to enable subsequent service calls

+		toControlComponent.setModelPropertyValue("cmd", "reset");

+		// - Application waits for status change

+		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("RESETTING") );

+		// - Validate device status

+		waitfor( () -> ((ControllableTCPDeviceMockup) context.getRunnable("Device")).exState == ExecutionState.RESETTING );

+

+		

+		// Device finishes reset and moves to idle state

+		((ControllableTCPDeviceMockup) context.getRunnable("Device")).resetCompleted();

+		// - Application waits for status change

+		waitfor( () -> ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceStatus().equals("IDLE") );

+		// - Validate device status

+		waitfor( () -> ((ControllableTCPDeviceMockup) context.getRunnable("Device")).exState == ExecutionState.IDLE );

+

+		

+		// Application checks invocation counter

+		assertTrue( ((ReceiveDeviceStatusApplication) context.getRunnable("Application")).getDeviceInvocationCounter() == 1 );

+	}

+}

diff --git a/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/controllable/RunExampleSimpleSmartDevice.java b/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/controllable/RunExampleSimpleSmartDevice.java
index c357999..49c6296 100644
--- a/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/controllable/RunExampleSimpleSmartDevice.java
+++ b/examples/basys.examples/examples/org/eclipse/basyx/examples/scenarios/device/controllable/RunExampleSimpleSmartDevice.java
@@ -40,9 +40,9 @@
 	

 	

 	/**

-	 * Communication stream to connected device manager

+	 * Communication stream to connected device control component

 	 */

-	protected JSONConnector toDeviceManager = null;

+	protected JSONConnector toControlComponent = null;

 

 

 

@@ -76,8 +76,8 @@
 		// Create connection to device control component on smart device

 		// - Create BaSyx connector to connect with the device manager

 		basyxConnector = new BaSyxConnector("localhost", 9997);

-		// - Create connection to device manager

-		toDeviceManager = new JSONConnector(basyxConnector);

+		// - Create connection to device control component

+		toControlComponent = new JSONConnector(basyxConnector);

 

 

 		

@@ -89,7 +89,7 @@
 		

 		

 		// Change device operation mode

-		((SmartBaSyxTCPDeviceMockup) context.getRunnable("Device")).getControlComponent().setOperationMode("RegularMilling");

+		toControlComponent.setModelPropertyValue("status/opMode", "RegularMilling");

 		// - Validate device control component operation mode

 		waitfor( () -> ((SmartBaSyxTCPDeviceMockup) context.getRunnable("Device")).getControlComponent().getOperationMode().equals("RegularMilling") );

 

@@ -98,7 +98,7 @@
 

 

 		// Start device service

-		((SmartBaSyxTCPDeviceMockup) context.getRunnable("Device")).getControlComponent().setCommand("start");

+		toControlComponent.setModelPropertyValue("cmd", "start");

 		// - Validate control component status

 		waitfor( () -> ((SmartBaSyxTCPDeviceMockup) context.getRunnable("Device")).getControlComponent().getExecutionState().equals(ExecutionState.EXECUTE.getValue()) );

 		// - Indicate service end

@@ -108,7 +108,7 @@
 

 		

 		// Reset device to enable subsequent service calls

-		((SmartBaSyxTCPDeviceMockup) context.getRunnable("Device")).getControlComponent().setCommand("reset");

+		toControlComponent.setModelPropertyValue("cmd", "reset");

 		// - Device finishes reset and moves to idle state

 		((SmartBaSyxTCPDeviceMockup) context.getRunnable("Device")).resetCompleted();

 		

diff --git a/examples/basys.examples/src/org/eclipse/basyx/components/devicemanager/DeviceManagerComponent.java b/examples/basys.examples/src/org/eclipse/basyx/components/devicemanager/DeviceManagerComponent.java
index bdabb71..d94b1fb 100644
--- a/examples/basys.examples/src/org/eclipse/basyx/components/devicemanager/DeviceManagerComponent.java
+++ b/examples/basys.examples/src/org/eclipse/basyx/components/devicemanager/DeviceManagerComponent.java
@@ -103,6 +103,13 @@
 		return aasServerPrefix;

 	}

 

+	

+	

+	/**

+	 * Get AAS descriptor for managed device

+	 */

+	protected abstract AASDescriptor getAASDescriptor();

+	

 

 	

 	

diff --git a/examples/basys.examples/src/org/eclipse/basyx/components/netcomm/TCPCommunicator.java b/examples/basys.examples/src/org/eclipse/basyx/components/netcomm/TCPCommunicator.java
index b686915..5332032 100644
--- a/examples/basys.examples/src/org/eclipse/basyx/components/netcomm/TCPCommunicator.java
+++ b/examples/basys.examples/src/org/eclipse/basyx/components/netcomm/TCPCommunicator.java
@@ -138,6 +138,9 @@
 	 * Buffer must point to where transmission should start

 	 */

 	public void sendMessage(ByteBuffer messageBuffer) {

+		// Only continue if client is connected

+		if (communicationToClient == null) return;

+

 		// Transmit frame

 		try {communicationToClient.write(messageBuffer);} catch (IOException e) {e.printStackTrace();}

 	}

diff --git a/examples/basys.examples/src/org/eclipse/basyx/components/proxy/registry/AASHTTPRegistryProxy.java b/examples/basys.examples/src/org/eclipse/basyx/components/proxy/registry/AASHTTPRegistryProxy.java
index 557c6c5..acd08c3 100644
--- a/examples/basys.examples/src/org/eclipse/basyx/components/proxy/registry/AASHTTPRegistryProxy.java
+++ b/examples/basys.examples/src/org/eclipse/basyx/components/proxy/registry/AASHTTPRegistryProxy.java
@@ -58,10 +58,23 @@
 	

 	

 	/**

+	 * Register AAS descriptor in registry, delete old registration

+	 */

+	@Override

+	public void register(ModelUrn aasID, AASDescriptor deviceAASDescriptor) {

+		// Invoke delete operation of AAS registry

+		try {client.delete(aasRegistryURL+"/api/v1/registry/"+URLEncoder.encode(aasID.getURN(), "UTF-8"));} catch (Exception e) {e.printStackTrace();}

+

+		// Perform web service call to registry

+		client.post(aasRegistryURL+"/api/v1/registry", serializer.getJsonString(serializer.serialize(deviceAASDescriptor)));

+	}

+

+	

+	/**

 	 * Register AAS descriptor in registry

 	 */

 	@Override

-	public void register(AASDescriptor deviceAASDescriptor) {

+	public void registerOnly(AASDescriptor deviceAASDescriptor) {

 		// Perform web service call to registry

 		client.post(aasRegistryURL+"/api/v1/registry", serializer.getJsonString(serializer.serialize(deviceAASDescriptor)));

 	}

diff --git a/examples/basys.examples/src/org/eclipse/basyx/components/proxy/registry/AASRegistryProxyIF.java b/examples/basys.examples/src/org/eclipse/basyx/components/proxy/registry/AASRegistryProxyIF.java
index d986976..3f538f9 100644
--- a/examples/basys.examples/src/org/eclipse/basyx/components/proxy/registry/AASRegistryProxyIF.java
+++ b/examples/basys.examples/src/org/eclipse/basyx/components/proxy/registry/AASRegistryProxyIF.java
@@ -16,10 +16,16 @@
 	

 	

 	/**

-	 * Register AAS descriptor in registry

+	 * Register AAS descriptor in registry, delete old registration

 	 */

-	public void register(AASDescriptor deviceAASDescriptor);

+	public void register(ModelUrn aasID, AASDescriptor deviceAASDescriptor);

+

 	

+	/**

+	 * Only register AAS descriptor in registry

+	 */

+	public void registerOnly(AASDescriptor deviceAASDescriptor);

+

 	

 	/**

 	 * Delete AAS descriptor from registry