Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

BaSyx / Introductory Examples / Java / Example 2

Example 2 - Remote VAB Access

In this example, the code of the previous example will be extended. The model will locally be deployed on a server and registered at the VABRegistry. Next, on the remote side, the model path is retrieved from the registry and the connection to the model is established. Finally, the same control loop as in Example 1 is implemented. As supporting component, the VABDirectoryServlet is used.

Example Code

Since the model is now potentially deployed on a separate compute node, in the following it is distinguished between the local and the remote side.

Local

The previously in Example 1 defined model is made available on a HTTP REST interface by the means of the VAB. This is done by wrapping the provider in a Servlet and providing it via e.g. an Apache Tomcat server. To enable clients to connect to this model, it is registered at the VABRegistry.

import java.util.Map;
 
import javax.servlet.http.HttpServlet;
 
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
import org.eclipse.basyx.vab.modelprovider.lambda.VABLambdaProvider;
import org.eclipse.basyx.vab.protocol.http.server.BaSyxContext;
import org.eclipse.basyx.vab.protocol.http.server.BaSyxHTTPServer;
import org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface;
import org.eclipse.basyx.vab.registry.api.IVABRegistryService;
import org.eclipse.basyx.vab.registry.memory.VABInMemoryRegistry;
import org.eclipse.basyx.vab.registry.restapi.VABRegistryModelProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * Expected console output in this HandsOn:
 * - the heater id
 * - oven is activated and deactivated multiple times
 * - temperature values between 30 and 40
 */
public class Scenario2 {
	// Initializes a logger for the output
	private static final Logger logger = LoggerFactory.getLogger(Scenario2.class);
 
	public static void main(String[] args) throws Exception {
		// First, a local model is created that is wrapped by a model provider (see first HandsOn)
		Map<String, Object> model = Scenario1.createMyOvenModel(new Oven());
		IModelProvider modelProvider = new VABLambdaProvider(model);
		// Up to this point, everything is known from the previous HandsOn
 
		// Now, the model provider is given to a HTTP servlet that gives access to the model in the next steps
		// => The model will be published using an HTTP-REST interface
		HttpServlet modelServlet = new VABHTTPInterface<IModelProvider>(modelProvider);
		logger.info("Created a servlet for the oven model");
 
		// Second, create a directory that can store endpoints for VAB models
		IVABRegistryService directory = new VABInMemoryRegistry();
 
                // Register the VAB model at the directory (locally in this case)
		directory.addMapping("oven", "http://localhost:4001/handson/oven");
                logger.info("Oven model registered!");
 
                // Similar to the IModelProvider for the local oven model, a IModelProvider for the directory is created
		IModelProvider directoryProvider = new VABRegistryModelProvider(directory);
                // Next, this model provider is given to a HTTP servlet that gives access to the directory
		HttpServlet directoryServlet = new VABHTTPInterface<IModelProvider>(directoryProvider);
		logger.info("Created a servlet for the directory");
 
		// Now, define a context to which multiple servlets can be added
		BaSyxContext context = new BaSyxContext("/handson", "", "localhost", 4001);
		// => Every servlet contained in this context is available at http://localhost:4001/handson/
		context.addServletMapping("/oven/*", modelServlet);
		// The model will be available at http://localhost:4001/handson/oven/
		context.addServletMapping("/directory/*", directoryServlet);
		// The directory will be available at http://localhost:4001/handson/directory/
		BaSyxHTTPServer server = new BaSyxHTTPServer(context);
		// Finally, the HTTP-REST server with this context is started.
		server.start();
		logger.info("HTTP server started");
	}
}

Remote

The remote side connects to the provided model. This is done by first retrieving the path of the model and then using it to connect to the model. Next, the control loop is implemented. Since the VAB abstracts from the location of the accessed model, the code for the control loop is equivalent to the code from Example 1.

import org.eclipse.basyx.vab.gateway.ConnectorProviderMapper;
import org.eclipse.basyx.vab.manager.VABConnectionManager;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
import org.eclipse.basyx.vab.protocol.basyx.connector.BaSyxConnectorFactory;
import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory;
import org.eclipse.basyx.vab.registry.proxy.VABRegistryProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * This is the connected site in the HandsOn. Although everything is executed locally in this HandsOn,
 * the connection to the model can also be established from distributed locations in the network using this code
 * (using the correct network addresses).
 * 
 */
 
public class Scenario2Connected {
	// Initializes a logger for the output
	private static final Logger logger = LoggerFactory.getLogger(Scenario2Connected.class);
 
	public static void main(String[] args) throws Exception {
		// At the connected site, no direct access to the model is possible
		// Every access is done through the network infrastructure
 
		// The Virtual Automation Bus hides network details to the connected site. Only the endpoint of the
		// directory has to be known:
		VABRegistryProxy registryProxy = new VABRegistryProxy("http://localhost:4001/handson/directory/");
 
		// The connection manager is responsible for resolving every connection attempt
		// For this, it needs:
		// - The directory at which all models are registered
		// - A provider for different types of network protocols (in this example, only HTTP-REST)
		VABConnectionManager connectionManager = new VABConnectionManager(registryProxy, new HTTPConnectorFactory());
 
		// It is now one line of code to retrieve a model provider for any registered
		// model in the network
		IModelProvider connectedOven = connectionManager.connectToVABElement("oven");
 
		// Now, implement a simple a simple bang-bang controller as it has been done in the first HandsOn
		// Note, that the IModelProvider completely abstracts from the underlying communication protocol
		for (int i = 0; i < 100; i++) {
			// Pause for 100ms
			Thread.sleep(100);
 
			// Retrieve the current temperature from the model provider
			double temperature = (double) connectedOven.getValue("/properties/temperature");
			logger.info("Current temperature: " + temperature);
 
			// Turn the oven on/off, depending on the defined temperature range
			if (temperature > 40) {
				connectedOven.invokeOperation("/operations/deactivateOven");
			} else if (temperature < 30) {
				connectedOven.invokeOperation("/operations/activateOven");
			}
		}
	}
}

Back to the top