blob: 6e70abc4634885b35716db90b4bf313e5a0adfb8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020 DFKI.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* DFKI - Volkan Gezer <volkan.gezer@dfki.de>
*
*******************************************************************************/
package org.eclipse.aas.basyx.codegen.util;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.aas.basyx.codegen.util.submodel.SubModel;
import org.eclipse.aas.basyx.codegen.util.submodel.SubModelCreator;
public class DataConnector {
private String modelUrn;
private String aasIp;
private String aasPort;
private SubModelCreator submodelCreator = new SubModelCreator();
private Project projectOperations;
public DataConnector(String modelUrn, String aasIp, String aasPort, SubModelCreator submodelCreator,
Project projectOperations) {
this.modelUrn = modelUrn;
this.aasIp = aasIp;
this.aasPort = aasPort;
this.submodelCreator = submodelCreator;
this.projectOperations = projectOperations;
}
public SubModelCreator getSubModelCreator() {
return submodelCreator;
}
public String createDataCrawler() {
String text = "package " + projectOperations.getNamespace() + ".connection;\r\n" +
"\r\n" +
"import java.util.Iterator;\r\n" +
"import java.util.Map;\r\n" +
"import java.util.Map.Entry;\r\n" +
"import java.util.concurrent.TimeUnit;\r\n" +
"\r\n" +
"import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;\r\n" +
"import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IProperty;\r\n" +
"import org.eclipse.basyx.submodel.metamodel.map.SubModel;\r\n" +
"\r\n" +
"/**\r\n" +
" * The CyclicDataCrawler provides methods for collecting data from connected\r\n" +
" * devices and updates them into selected submodel.\r\n" +
" * \r\n" +
" * By default one cycle will always be executed.\r\n" +
" *\r\n" +
" * @author DFKI\r\n" +
" *\r\n" +
" */\r\n" +
" \r\n" +
"public class DataCrawler {\r\n" +
"\r\n" +
" protected Integer cycleCounter = 1;\r\n" +
" protected Integer sleepInterval = 10;\r\n" +
" protected ConnectedDevice connectedDevice;\r\n" +
" protected String aas_submodelid;\r\n" +
"\r\n" +
" public DataCrawler(ConnectedDevice connDev) {\r\n" +
" connectedDevice = connDev;\r\n" +
" }\r\n" +
"\r\n" +
" public void setCycleConfiguration(Integer cc, Integer si) {\r\n" +
" cycleCounter = cc;\r\n" +
" sleepInterval = si;\r\n" +
" }\r\n" +
"\r\n" +
" public void collectOPCUAData(SubModel subModel) throws Exception {\r\n" +
"\r\n" +
" for (int i = 0; i < cycleCounter; i++) {\r\n" +
"\r\n" +
" String valueupdate = \"0\";\r\n" +
"\r\n" +
" aas_submodelid = subModel.getIdShort();\r\n" +
"\r\n" +
" System.out.println(\"Activated data crawler for submodel: \" + aas_submodelid);\r\n" +
"\r\n" +
" /* Take all submodel properties in a map to provide several iterations. */\r\n" +
"\r\n" +
" Map<String, IProperty> propertyMap = subModel.getProperties();\r\n" +
"\r\n" +
" Iterator<Entry<String, IProperty>> it = propertyMap.entrySet().iterator();\r\n" +
"\r\n" +
" while (it.hasNext()) {\r\n" +
" Entry<String, IProperty> pair = it.next();" +
"\r\n" +
" Property propertyupdate = (Property) propertyMap.get(pair.getKey());\r\n" +
"\r\n" +
" /* Get current values from device by using the aas-key. */\r\n" +
"\r\n" +
" if (connectedDevice.online == true) {\r\n" +
"\r\n" +
" valueupdate = connectedDevice.getSingleDeviceValueByConfig(String.valueOf(pair.getKey()));\r\n" +
" }\r\n" +
"\r\n" +
" else {\r\n" +
" valueupdate = String.valueOf(i);\r\n" +
" }\r\n" +
"\r\n" +
" /* Updating the current available submodel. */\r\n" +
"\r\n" +
" propertyupdate.set(valueupdate);\r\n" +
" subModel.getProperties().replace(String.valueOf(pair.getKey()), propertyupdate);\r\n" +
"\r\n" +
" System.out.println(\"Property-Update: \" + String.valueOf(pair.getKey()) + \" with value \"\r\n" +
" + String.valueOf(valueupdate));\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" Thread.sleep(TimeUnit.SECONDS.toMillis(sleepInterval));\r\n" +
"\r\n" +
" System.out.println(\"Processed cycles: \" + String.valueOf(i));\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
"}\r\n" +
"";
return text;
}
public String createDeviceAAS() {
String text =
"package " + projectOperations.getNamespace() + ".module.submodel;\r\n" +
"\r\n" +
"import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;\r\n" +
"import org.eclipse.basyx.aas.metamodel.map.descriptor.ModelUrn;\r\n" +
"\r\n" +
"/**\r\n" +
" * AAS header element for inputs of a floor device.\r\n" +
" * \r\n" +
" * @author DFKI\r\n" +
" * \r\n" +
" */\r\n" +
"\r\n" +
"public class DeviceAAS extends AssetAdministrationShell {\r\n" +
" private static final long serialVersionUID = 1L;\r\n" +
"\r\n" +
" // Since submodel-class refactoring, reference of inherited submodels necessary\r\n" +
" // in the aas class is no longer necessary.\r\n" +
"\r\n" +
" public DeviceAAS() {\r\n" +
"\r\n" +
" // Model URN only available as placeholder\r\n" +
"\r\n" +
" ModelUrn urn = new ModelUrn(\"" + this.modelUrn + "\");\r\n" +
" this.setIdentification(urn.getIdType(), urn.getURN());\r\n" +
"\r\n" +
" }\r\n" +
"}";
return text;
}
public String createConnectedDevice() {
return createConnectedDevice("", "", "", "", "", "");
}
public String createConnectedDevice(String sqlHostPort, String sqlDb, String sqlUser, String sqlPass, String sqlP, String sqlD) {
String text = "package " + projectOperations.getNamespace() + ".connection;\r\n" +
"\r\n" +
"import java.sql.ResultSet;\r\n" +
"import java.util.Arrays;\r\n" +
"import java.util.Collection;\r\n" +
"import java.util.LinkedList;\r\n" +
"\r\n" +
"import org.eclipse.basyx.tools.sql.driver.SQLDriver;\r\n" +
"import org.eclipse.basyx.tools.sql.driver.ISQLDriver;\r\n" +
"import org.eclipse.basyx.vab.gateway.ConnectorProviderMapper;\r\n" +
"import org.eclipse.basyx.vab.protocol.opcua.connector.OpcUaConnectorProvider;\r\n" +
"\r\n" +
"/**\r\n" +
" * This device (connector) class implements connector-interfaces that are not\r\n" +
" * yet or not strongly supported by the Virtual Automation Bus, because they\r\n" +
" * need a specific configuration (e.g. OPCUA / MQTT) to the control component.\r\n" +
" * The belonging configuration for values and methods for a specific device will\r\n" +
" * be done here, so the class has the role to provide this configuration.\r\n" +
" * \r\n" +
" * The Device must call this connection class by using database configuration\r\n" +
" * \"service registry\". The address can be saved in database tables for dynamic\r\n" +
" * endpoint calls.\r\n" +
" * \r\n" +
" * In future development, the usage of subscriptions and dependency injection\r\n" +
" * for class tests and simulation methods can be made. The connection type can\r\n" +
" * be set in an array object, to provide one or more connection types for one\r\n" +
" * single device.\r\n" +
" * \r\n" +
" * The provided connection types for a device has to be set up in a object\r\n" +
" * array, containing the connectors which can be saved in a database. Current\r\n" +
" * available is only OPCUA.\r\n" +
" * \r\n" +
" * @author DFKI\r\n" +
" *\r\n" +
" */\r\n" +
"\r\n" +
"\r\n" +
"public class ConnectedDevice {\r\n" +
"\r\n" +
" /* Definition of objects */\r\n" +
"\r\n" +
" public ConnectorProviderMapper clientMapper = new ConnectorProviderMapper();\r\n" +
" public OPCUAConnectorWrapper opcuaConnector = new OPCUAConnectorWrapper();\r\n" +
" private static String sqlHostPort = \"" + sqlHostPort + "\";\r\n" +
" private static String sqlDb = \"" + sqlDb + "\";\r\n" +
" private static String sqlUser = \"" + sqlUser + "\";\r\n" +
" private static String sqlPass = \"" + sqlPass + "\";\r\n" +
" private static String connP = \"" + sqlP + "\";\r\n" +
" private static String sqlD = \"" + sqlD + "\";\r\n" +
" \r\n" +
" /* Definition of properties */\r\n" +
"\r\n" +
" protected String devendpoint;\r\n" +
" protected String deviceid;\r\n" +
" protected String address;\r\n" +
" protected Object[] connectiontype;\r\n" +
" protected Boolean databaseinit = false;\r\n" +
" public Boolean online = false;\r\n" +
"\r\n" +
" /*\r\n" +
" * Store SQL driver reference\r\n" +
" */\r\n" +
" \r\n" +
" protected ISQLDriver sqlDriver = null;\r\n" +
"\r\n" +
" /*\r\n" +
" * The Device-Class should contain the adapters for different communication\r\n" +
" * protocols. Initialization e.g. of the connector object for OPC UA.\r\n" +
" */\r\n" +
" \r\n" +
" public ConnectedDevice(String endpoint, Object[] conntypes, String devid, Boolean initDB) {\r\n" +
" this(endpoint, conntypes, devid, initDB, ConnectedDevice.sqlHostPort, ConnectedDevice.sqlDb, ConnectedDevice.sqlUser, ConnectedDevice.sqlPass, \r\n" +
" ConnectedDevice.connP, ConnectedDevice.sqlD);\r\n" +
" }\r\n" +
"\r\n" +
" public ConnectedDevice(String endpoint, Object[] conntypes, String devid, Boolean initDB,\r\n" +
" String sqlHostPort, String sqlDb, String sqlUser, String sqlPass, String sqlConnectP, String sqlDr) {\r\n" +
" \r\n" +
" ConnectedDevice.sqlHostPort = sqlHostPort;\r\n" +
" ConnectedDevice.sqlDb = sqlDb;\r\n" +
" ConnectedDevice.sqlUser = sqlUser;\r\n" +
" ConnectedDevice.sqlPass = sqlPass;\r\n" +
" ConnectedDevice.connP = sqlConnectP;\r\n" +
" ConnectedDevice.sqlD = sqlDr;\r\n" +
" \r\n" +
"\r\n" +
" devendpoint = endpoint;\r\n" +
" deviceid = devid;\r\n" +
"\r\n" +
" /*\r\n" +
" * Set the connection type and initialize all necessary connector wrappers.\r\n" +
" */\r\n" +
"\r\n" +
" connectiontype = conntypes;\r\n" +
"\r\n" +
" if (connectiontype[0] == \"OPCUA\") {\r\n" +
" opcuaConnector.clientMapper.addConnectorProvider(\"opc.tcp\", new OpcUaConnectorProvider());\r\n" +
" }\r\n" +
"\r\n" +
" /*\r\n" +
" * Set the connection to database to enable interactions with available\r\n" +
" * configuration.\r\n" +
" */\r\n" +
"\r\n" +
" if (initDB == true) {\r\n" +
" sqlDriver = new SQLDriver(sqlHostPort + \"/\" + sqlDb, sqlUser, sqlPass, sqlConnectP,\r\n" +
" sqlDr);\r\n" +
" }\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" /**\r\n" +
" * Method getSingleDeviceValueByConfig uses a key to identify the configuration\r\n" +
" * \r\n" +
" * @param key identifier of element\r\n" +
" * \r\n" +
" * @return device value\r\n" +
" * \r\n" +
" */\r\n" +
" \r\n" +
" public String getSingleDeviceValueByConfig(String key) throws Exception {\r\n" +
"\r\n" +
" String address;\r\n" +
"\r\n" +
" if (sqlDriver == null) {\r\n" +
" return \"No Database initialized\";\r\n" +
" }\r\n" +
"\r\n" +
" /*\r\n" +
" * Set the SQL connection parameters\r\n" +
" */\r\n" +
"\r\n" +
" Collection<String> sqlQuery1Params = new LinkedList<>();\r\n" +
"\r\n" +
" sqlQuery1Params.add(\"deviceid\");\r\n" +
" sqlQuery1Params.add(deviceid);\r\n" +
" sqlQuery1Params.add(\"browsename\");\r\n" +
" sqlQuery1Params.add(key);\r\n" +
"\r\n" +
" /*\r\n" +
" * Set the SQL connection string\r\n" +
" */\r\n" +
"\r\n" +
" String sqlQuery1String = getSQLString(\"SELECT * FROM device.deviceendpoints WHERE $1='$2' AND $3='$4'\",\r\n" +
" sqlQuery1Params);\r\n" +
"\r\n" +
" System.out.println(\"SQL: \" + sqlQuery1String);\r\n" +
"\r\n" +
" /*\r\n" +
" * Get the address as SQL result string\r\n" +
" */\r\n" +
"\r\n" +
" ResultSet result1 = sqlDriver.sqlQuery(sqlQuery1String);\r\n" +
"\r\n" +
" /* Result next necessary to guarantee a data entry */\r\n" +
"\r\n" +
" if (result1.next()) {\r\n" +
"\r\n" +
" address = result1.getString(\"address\");\r\n" +
"\r\n" +
" System.out.println(\"ID : \" + address);\r\n" +
" return this.getSingleDeviceValue(address, \"OPCUA\");\r\n" +
" }\r\n" +
"\r\n" +
" return \"No configuration records available\";\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" /**\r\n" +
" * Method getSingleDeviceValue uses address call for the set connector\r\n" +
" * \r\n" +
" * @param address path of connection endpoint (e.g. opcua node)\r\n" +
" * @param conntype the connection type to access the endpoint\r\n" +
" * \r\n" +
" * @return Device value\r\n" +
" * \r\n" +
" */\r\n" +
"\r\n" +
" public String getSingleDeviceValue(String address, String conntype) throws Exception {\r\n" +
"\r\n" +
" try {\r\n" +
"\r\n" +
" /*\r\n" +
" * Execute only, if device can provide the configured connection type for the\r\n" +
" * address.\r\n" +
" */\r\n" +
"\r\n" +
" if (Arrays.stream(connectiontype).anyMatch(x -> conntype.equals(x))) {\r\n" +
"\r\n" +
" Object ret = (opcuaConnector.getOPCUANodeValue(devendpoint, address));\r\n" +
"\r\n" +
" return (String) ret;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" return null;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" catch (Exception e) {\r\n" +
" e.printStackTrace();\r\n" +
" }\r\n" +
"\r\n" +
" return null;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" /**\r\n" +
" * Method setSingleDeviceValueByConfig uses a key to identify the configuration\r\n" +
" * \r\n" +
" * @param key identifier of element\r\n" +
" * @param value value that should be set\r\n" +
" * \r\n" +
" * @return device value\r\n" +
" * \r\n" +
" */\r\n" +
"\r\n" +
" public String setSingleDeviceValueByConfig(String key, String value) throws Exception {\r\n" +
"\r\n" +
" String address;\r\n" +
"\r\n" +
" if (sqlDriver == null) {\r\n" +
" return \"No Database initialized\";\r\n" +
" }\r\n" +
"\r\n" +
" /*\r\n" +
" * Set the SQL connection parameters\r\n" +
" */\r\n" +
"\r\n" +
" Collection<String> sqlQuery1Params = new LinkedList<>();\r\n" +
"\r\n" +
" sqlQuery1Params.add(\"deviceid\");\r\n" +
" sqlQuery1Params.add(deviceid);\r\n" +
" sqlQuery1Params.add(\"browsename\");\r\n" +
" sqlQuery1Params.add(key);\r\n" +
"\r\n" +
" /*\r\n" +
" * Set the SQL connection string\r\n" +
" */\r\n" +
"\r\n" +
" String sqlQuery1String = getSQLString(\"SELECT * FROM device.deviceendpoints WHERE $1='$2' AND $3='$4'\",\r\n" +
" sqlQuery1Params);\r\n" +
"\r\n" +
" System.out.println(\"SQL: \" + sqlQuery1String);\r\n" +
"\r\n" +
" /*\r\n" +
" * Get the address as SQL result string\r\n" +
" */\r\n" +
"\r\n" +
" ResultSet result1 = sqlDriver.sqlQuery(sqlQuery1String);\r\n" +
"\r\n" +
" /* Result next necessary to guarantee a data entry */\r\n" +
"\r\n" +
" if (result1.next()) {\r\n" +
"\r\n" +
" address = result1.getString(\"address\");\r\n" +
"\r\n" +
" System.out.println(\"ID : \" + address);\r\n" +
" return this.setSingleDeviceValue(address, \"OPCUA\", value);\r\n" +
" }\r\n" +
"\r\n" +
" return \"No configuration records available\";\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" /**\r\n" +
" * Method setSingleDeviceValue uses address call for the set connector\r\n" +
" * \r\n" +
" * @param address path of connection endpoint (e.g. opcua node)\r\n" +
" * @param conntype the connection type to access the endpoint\r\n" +
" * @param value value that should be set\r\n" +
" * \r\n" +
" * @return device value\r\n" +
" * \r\n" +
" */\r\n" +
"\r\n" +
" public String setSingleDeviceValue(String address, String conntype, String value) throws Exception {\r\n" +
"\r\n" +
" try {\r\n" +
"\r\n" +
" /*\r\n" +
" * Execute only, if device can provide the configured connection type for the\r\n" +
" * address.\r\n" +
" */\r\n" +
"\r\n" +
" if (Arrays.stream(connectiontype).anyMatch(x -> conntype.equals(x))) {\r\n" +
"\r\n" +
" Object ret = (opcuaConnector.setOPCUANodeValue(devendpoint, address, value, \"Boolean\"));\r\n" +
"\r\n" +
" return (String) ret;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" catch (Exception e) {\r\n" +
" e.printStackTrace();\r\n" +
" }\r\n" +
"\r\n" +
" return null;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" /**\r\n" +
" * Method setSingleDeviceValueByConfig uses a key to identify the configuration\r\n" +
" * \r\n" +
" * @param key identifier of element\r\n" +
" * @param arguments[] arguments for method calls\r\n" +
" * \r\n" +
" * @return result of method call\r\n" +
" * \r\n" +
" */\r\n" +
"\r\n" +
" public String callOperationByConfig(String key, Object[] arguments) throws Exception {\r\n" +
"\r\n" +
" String address;\r\n" +
"\r\n" +
" if (sqlDriver == null) {\r\n" +
" return \"No Database initialized\";\r\n" +
" }\r\n" +
"\r\n" +
" /*\r\n" +
" * Set the SQL connection parameters\r\n" +
" */\r\n" +
"\r\n" +
" Collection<String> sqlQuery1Params = new LinkedList<>();\r\n" +
"\r\n" +
" sqlQuery1Params.add(\"deviceid\");\r\n" +
" sqlQuery1Params.add(deviceid);\r\n" +
" sqlQuery1Params.add(\"browsename\");\r\n" +
" sqlQuery1Params.add(key);\r\n" +
"\r\n" +
" /*\r\n" +
" * Set the SQL connection string\r\n" +
" */\r\n" +
"\r\n" +
" String sqlQuery1String = getSQLString(\"SELECT * FROM device.deviceendpoints WHERE $1='$2' AND $3='$4'\",\r\n" +
" sqlQuery1Params);\r\n" +
"\r\n" +
" System.out.println(\"SQL: \" + sqlQuery1String);\r\n" +
"\r\n" +
" /*\r\n" +
" * Get the address as SQL result string\r\n" +
" */\r\n" +
"\r\n" +
" ResultSet result1 = sqlDriver.sqlQuery(sqlQuery1String);\r\n" +
"\r\n" +
" /* Result next necessary to guarantee a data entry */\r\n" +
"\r\n" +
" if (result1.next()) {\r\n" +
"\r\n" +
" address = result1.getString(\"address\");\r\n" +
"\r\n" +
" System.out.println(\"ID : \" + address);\r\n" +
" return this.callOperation(address, \"OPCUA\", arguments);\r\n" +
" }\r\n" +
"\r\n" +
" return \"No configuration records available\";\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" /**\r\n" +
" * Method callOperation uses address call for the set connector\r\n" +
" * \r\n" +
" * @param address path of connection endpoint (e.g. opcua node)\r\n" +
" * @param conntype the connection type to access the endpoint\r\n" +
" * @param arguments[] arguments for method calls\r\n" +
" * \r\n" +
" * @return device value\r\n" +
" * \r\n" +
" */\r\n" +
"\r\n" +
" public String callOperation(String address, String conntype, Object[] arguments) throws Exception {\r\n" +
"\r\n" +
" try {\r\n" +
"\r\n" +
" /*\r\n" +
" * Execute only, if device can provide the configured connection type for the\r\n" +
" * address.\r\n" +
" */\r\n" +
"\r\n" +
" if (Arrays.stream(connectiontype).anyMatch(x -> conntype.equals(x))) {\r\n" +
"\r\n" +
" Object ret = (opcuaConnector.callOPCUAMethod(devendpoint, address, arguments));\r\n" +
"\r\n" +
" return (String) ret;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" catch (Exception e) {\r\n" +
" e.printStackTrace();\r\n" +
" }\r\n" +
"\r\n" +
" return null;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" /**\r\n" +
" * >>> Method from class \"SQLProviderTestOLD\" <<<\r\n" +
" * \r\n" +
" * Create a SQL string from an input SQL String with place holders in format $x\r\n" +
" * with x being an integer number.\r\n" +
" * \r\n" +
" * @param baseString SQL string with place holders\r\n" +
" * @param parameter Parameter values that place holders are substituted for\r\n" +
" * \r\n" +
" * @return SQL string with parameter instead of place holders\r\n" +
" */\r\n" +
"\r\n" +
" public static String getSQLString(String baseString, Collection<String> parameter) {\r\n" +
" // Resulting SQL String\r\n" +
" String result = baseString;\r\n" +
"\r\n" +
" // Replace place holders with parameter\r\n" +
" // - Counter variable\r\n" +
" int counter = 1;\r\n" +
" // - Replace all place holders\r\n" +
" for (String par : parameter) {\r\n" +
" result = result.replace(\"$\" + counter, par);\r\n" +
" counter++;\r\n" +
" }\r\n" +
"\r\n" +
" // Return SQL string with resolved parameter\r\n" +
" return result;\r\n" +
" }\r\n" +
"\r\n" +
"}\r\n" +
"";
return text;
}
public String createOPCUAConnectorWrapper() {
String text = "package " + projectOperations.getNamespace() + ".connection;\r\n" +
"\r\n" +
"import org.eclipse.basyx.vab.exception.provider.ProviderException;\r\n" +
"import org.eclipse.basyx.vab.gateway.ConnectorProviderMapper;\r\n" +
"import org.eclipse.basyx.vab.protocol.opcua.connector.OpcUaConnectorProvider;\r\n" +
"\r\n" +
"/**\r\n" +
" * This generic connector-class provides a wrapper which holds the OPC UA\r\n" +
" * clientMapper object with its functions. Aim of this wrapper class is to\r\n" +
" * provide the OPC UA clientRunner-Functions of VAB.\r\n" +
" *\r\n" +
" * @author DFKI\r\n" +
" *\r\n" +
" */\r\n" +
"\r\n" +
"public class OPCUAConnectorWrapper {\r\n" +
"\r\n" +
" protected boolean booleanValue;\r\n" +
" public ConnectorProviderMapper clientMapper = new ConnectorProviderMapper();\r\n" +
"\r\n" +
" /*\r\n" +
" * Initialize the connector object for OPC UA connection directly in the\r\n" +
" * connector wrapper class. The clientMapper-Object provides complete OPC UA\r\n" +
" * client functions from MILO package.\r\n" +
" */\r\n" +
"\r\n" +
" public OPCUAConnectorWrapper() {\r\n" +
" clientMapper.addConnectorProvider(\"opc.tcp\", new OpcUaConnectorProvider());\r\n" +
" }\r\n" +
"\r\n" +
" public String getOPCUANodeValue(String endpoint, String node_browsename) throws ProviderException {\r\n" +
"\r\n" +
" try {\r\n" +
"\r\n" +
" Object ret = clientMapper.getConnector(endpoint).getModelPropertyValue(node_browsename);\r\n" +
"\r\n" +
" return (String) ret;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" catch (final Exception e) {\r\n" +
" e.printStackTrace();\r\n" +
" return \"0\";\r\n" +
" }\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" public String setOPCUANodeValue(String endpoint, String node_browsename, String value, String datatype)\r\n" +
" throws ProviderException {\r\n" +
"\r\n" +
" try {\r\n" +
"\r\n" +
" /* TBD: DataType necessary */\r\n" +
"\r\n" +
" if (datatype == \"Boolean\") {\r\n" +
" booleanValue = Boolean.valueOf(value);\r\n" +
" }\r\n" +
"\r\n" +
" /* Set the value to opcua node */\r\n" +
" clientMapper.getConnector(endpoint).setModelPropertyValue(node_browsename, booleanValue);\r\n" +
"\r\n" +
" /* Check if value has been set correctly */\r\n" +
" Object ret = clientMapper.getConnector(endpoint).getModelPropertyValue(node_browsename);\r\n" +
"\r\n" +
" return (String) ret;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" catch (final Exception e) {\r\n" +
" e.printStackTrace();\r\n" +
" return \"0\";\r\n" +
" }\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" public String callOPCUAMethod(String endpoint, String node_browsename, Object[] methodargument)\r\n" +
" throws ProviderException {\r\n" +
"\r\n" +
" try {\r\n" +
"\r\n" +
" /* Provide method call with import parameters (can also be empty) */\r\n" +
" Object methodret = clientMapper.getConnector(endpoint).invokeOperation(node_browsename, methodargument);\r\n" +
"\r\n" +
" return (String) methodret;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" catch (Exception e) {\r\n" +
" e.printStackTrace();\r\n" +
" return null;\r\n" +
" }\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
"}\r\n" +
"";
return text;
}
public String createDeviceAASServer() {
return createDeviceAASServer(this.aasIp, this.aasPort);
}
public String createDeviceAASServer(String deviceEndPoint) {
return createDeviceAASServer(this.aasIp, this.aasPort, deviceEndPoint);
}
public String createDeviceAASServer(String aasIp, String aasPort) {
return createDeviceAASServer(aasIp, aasPort, "");
}
public String createDeviceAASServer(String aasIp, String aasPort, String deviceEndPoint) {
// Endpoint def: opc.tcp://192.168.0.37:4840
String text = "package " + projectOperations.getNamespace() + ".module;\r\n" +
"\r\n" +
"import java.util.concurrent.TimeUnit;\r\n" +
"\r\n" +
"import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;\r\n" +
"import " + projectOperations.getNamespace() + ".connection.ConnectedDevice;\r\n" +
"import org.eclipse.basyx.submodel.metamodel.connected.ConnectedSubModel;\r\n" +
"import org.eclipse.basyx.vab.coder.json.connector.JSONConnector;\r\n" +
"import org.eclipse.basyx.vab.modelprovider.VABElementProxy;\r\n" +
"import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnector;\r\n" +
"import org.eclipse.basyx.vab.protocol.http.server.AASHTTPServer;\r\n" +
"\r\n" +
"/**\r\n" +
" * A HTTP server with the asset administration shell and registry context. This\r\n" +
" * class provides the AAS with submodels over HTTP by using the given context\r\n" +
" * and provides the connected device class for the submodel connection.\r\n" +
" * \r\n" +
" * @author DFKI\r\n" +
" * \r\n" +
" */\r\n" +
"\r\n" +
"public class DeviceAASServer extends AASHTTPServer {\r\n" +
"\r\n" +
" protected static String deviceendpoint = \"" + deviceEndPoint + "/\";\r\n" +
" protected static AssetAdministrationShell AAS;\r\n" +
"\r\n" +
" /*\r\n" +
" * Setting the context in the constructor makes the context object with submodel\r\n" +
" * available.\r\n" +
" */\r\n" +
"\r\n" +
" public DeviceAASServer(DeviceContext DeviceContext) {\r\n" +
"\r\n" +
" super(DeviceContext);\r\n" +
" }\r\n" +
"\r\n" +
" public static void main(String[] args) throws Exception {\r\n" +
"\r\n" +
" /* Connected device with state machine */\r\n" +
"\r\n" +
" ConnectedDevice connectedDevice = new ConnectedDevice(deviceendpoint, new Object[] { \"OPCUA\" },\r\n" +
" \"canvaas\", false);\r\n" +
"\r\n" +
" /* Building the HTTP Server with the given context */\r\n" +
"\r\n" +
" DeviceContext deviceContext = new DeviceContext(\"" + aasIp + "\", " + aasPort + ", connectedDevice);\r\n" +
" DeviceAASServer deviceServer = new DeviceAASServer(deviceContext);\r\n" +
" deviceServer.start();\r\n" +
"\r\n" +
" /* Create a connected sub model */\r\n" +
"\r\n" +
" // ConnectedSubModel connectedControlSubModel = directlyConnectToSubmodelControl();\r\n" +
"\r\n" +
" System.out.println(\"Waiting to connect: 2 ms\");\r\n" +
" Thread.sleep(TimeUnit.SECONDS.toMillis(2));\r\n" +
"\r\n" +
" /*\r\n" +
" * Setting the connected device to true to enable interactions with the device.\r\n" +
" * Possibility in future development to set this to false for simulation mode.\r\n" +
" */\r\n" +
"\r\n" +
" connectedDevice.online = true;\r\n" +
"\r\n" +
" System.out.println(\"" + projectOperations.getProjectName() + " is online at: http://" + this.aasIp + ":" +
this.aasPort + "/" + projectOperations.getSafeProjectName() + "/aas/\");\r\n" +
"\r\n" +
" // floorserver.shutdown();\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
"// private static ConnectedSubModel directlyConnectToSubmodelControl() {\r\n" +
"// VABElementProxy proxy = new VABElementProxy(\"\",\r\n" +
"// new JSONConnector(new HTTPConnector(\"http://" + aasIp +":" + aasPort + "/"+ projectOperations.getSafeProjectName() + "/\")));\r\n" +
"// return new ConnectedSubModel(proxy.getDeepProxy(\"/aas/submodels/ControlComponent/\"));\r\n" +
"// }\r\n" +
"}\r\n" +
"";
return text;
}
public String createDeviceContext() {
String text = "package " + projectOperations.getNamespace() + ".module;\r\n" +
"\r\n" +
"import javax.servlet.http.HttpServlet;\r\n" +
"\r\n" +
"import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;\r\n" +
"import org.eclipse.basyx.aas.metamodel.map.descriptor.ModelUrn;\r\n" +
"import org.eclipse.basyx.aas.restapi.AASModelProvider;\r\n" +
"import org.eclipse.basyx.aas.metamodel.api.parts.asset.AssetKind;\r\n" +
"import org.eclipse.basyx.aas.metamodel.map.parts.Asset;\r\n" +
"import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;\r\n" +
"import org.eclipse.basyx.aas.restapi.VABMultiSubmodelProvider;\r\n" +
"import " + projectOperations.getNamespace() + ".connection.ConnectedDevice;\r\n" +
"import " + projectOperations.getNamespace() + ".module.submodel.DeviceAAS;\r\n";
for(SubModel model : submodelCreator.getSubModels()) {
text += "import " + projectOperations.getNamespace() + ".module.submodel." + model.getName().replace(" ", "") + ";\r\n";
}
text += "import org.eclipse.basyx.submodel.metamodel.map.SubModel;\r\n" +
"import org.eclipse.basyx.submodel.restapi.SubModelProvider;\r\n" +
"import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;\r\n" +
"import org.eclipse.basyx.vab.protocol.http.server.BaSyxContext;\r\n" +
"import org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface;\r\n" +
"\r\n" +
"/**\r\n" +
" * Context for the HTTP server. This class provides the device aas with its sub\r\n" +
" * models providing for http-servlets by using VAB.\r\n" +
" * \r\n" +
" * @author DFKI\r\n" +
" * \r\n" +
" */\r\n" +
"\r\n" +
"public class DeviceContext extends BaSyxContext {\r\n" +
" private static final long serialVersionUID = 5469957942186749451L;\r\n" +
"\r\n" +
" protected AssetAdministrationShell AAS;\r\n" +
"\r\n" +
" /*\r\n" +
" * The context class is necessary to build the whole model context of AAS and\r\n" +
" * provide it by HTTP.\r\n" +
" */\r\n" +
"\r\n" +
" public DeviceContext(String hostName, int port, ConnectedDevice connDevice) {\r\n" +
"\r\n" +
" /*\r\n" +
" * Create a context with the base path /basys.floor/*, a default server context\r\n" +
" * base directory (\"\") and the given host server and port. The base path must be\r\n" +
" * identical with hosted aas and its submodels. *\r\n" +
" */\r\n" +
"\r\n" +
" super(\"/" + projectOperations.getSafeProjectName() + "\", \"\", hostName, port);\r\n" +
"\r\n" +
" /*\r\n" +
" * 1. Create models. For direct method link of submodels, the submodel gets the\r\n" +
" * connected device.\r\n" +
" */\r\n" +
"\r\n" +
" AssetAdministrationShell aas = new DeviceAAS();\r\n";
for (SubModel model : submodelCreator.getSubModels()) {
String modelClass = model.getName().replaceAll(" ", "");
text += " SubModel " + modelClass.toLowerCase() + " = new " + modelClass + "(connDevice);\r\n";
text += "\r\n" +
" ModelUrn urn" + modelClass.toLowerCase() + " = new ModelUrn(\"urn:de.basyxifs:devices:" + modelClass + ":1.0:1:asset#001\");\r\n" +
" " + modelClass.toLowerCase() + ".setIdentification(urn" + modelClass.toLowerCase() + ".getIdType(), urn" + modelClass.toLowerCase() + ".getURN());\r\n" +
"\r\n";
// text += " aas.addSubModel(new SubmodelDescriptor(" + modelClass.toLowerCase() + ".getIdShort(), " + modelClass.toLowerCase() + ".getIdentification(),\r\n" +
// " \"http://" + aasIp + ":" + aasPort + "/" + projectOperations.getSafeProjectName() + "/aas/submodels/" + modelClass + "/\")); // + sm.getIdShort()\r\n" +
// " \r\n";
text += " aas.addSubModel(" + modelClass.toLowerCase() + ");\r\n";
text += " // Access to submodel via: http://" + aasIp + ":" + aasPort + "/" + projectOperations.getSafeProjectName() + "/aas/submodels/" + modelClass + "/\r\n";
}
text += " Asset asset = new Asset();\r\n" +
" \r\n" +
" /* Asset Kind can be Instance or Type */\r\n" +
" asset.setAssetKind(AssetKind.INSTANCE);\r\n" +
" asset.setIdShort(\"" + projectOperations.getProjectNameWithoutSpace() + "\");\r\n" +
" asset.setIdentification(IdentifierType.CUSTOM, \"" + projectOperations.getProjectNameWithoutSpace() + "1\");\r\n" +
"\r\n" +
" \r\n" +
" aas.setAsset(asset);\r\n" +
" aas.setIdShort(\"" + projectOperations.getProjectNameWithoutSpace() + "AAS\");\r\n" +
" /* Adding all submodels by using the submodel-descriptor functionality. */\r\n" +
" /*\r\n" +
" * 2. Wrap models in model providers\r\n" +
" */\r\n" +
"\r\n" +
" VABMultiSubmodelProvider provider = new VABMultiSubmodelProvider();\r\n" +
" provider.setAssetAdministrationShell(new AASModelProvider(aas));\r\n" +
"\r\n";
for (SubModel model : submodelCreator.getSubModels()) {
String modelClass = model.getName().replaceAll(" ", "");
text += " SubModelProvider " + modelClass + "Provider = new SubModelProvider(" + modelClass.toLowerCase() + ");\r\n" +
" provider.addSubmodel(\"" + modelClass + "\", " + modelClass + "Provider);\r\n" +
" \r\n";
}
text += " /*\r\n" +
" * 3. Create HTTP servlet for hosting with tomcat\r\n" +
" */\r\n" +
"\r\n" +
" HttpServlet servlet = new VABHTTPInterface<IModelProvider>(provider);\r\n" +
"\r\n" +
" /*\r\n" +
" * 4. Add the servlet to server context\r\n" +
" */\r\n" +
"\r\n" +
"// addServletMapping(\"/*\", servlet);\r\n" +
"// addServletMapping(\"/SQL/*\", new SQLDirectoryServlet().withParameter(\"config\",\r\n" +
"// \"/WebContent/WEB-INF/config/directory/sqldirectory/directory.properties\"));\r\n" +
"\r\n" +
" addServletMapping(\"/*\", servlet);\r\n" +
" \r\n" +
" /*\r\n" +
" * 5. Quick provide for aas and submodel elements (Possibility: Provide\r\n" +
" * availability in array)\r\n" +
" */\r\n" +
"\r\n" +
" AAS = aas;\r\n" +
"\r\n" +
" }\r\n" +
"\r\n" +
" public AssetAdministrationShell getAAS() {\r\n" +
" return AAS;\r\n" +
" }\r\n" +
"\r\n" +
"\r\n" +
"}\r\n" +
"";
return text;
}
}