Skip to content

Commit 7850a82

Browse files
Merge pull request #5 from aljoshakoecher/remove-nodeRoot
Complete rewrite of the way nodeIds are resolved + first test
2 parents acdc631 + 37b7052 commit 7850a82

21 files changed

+1971
-229
lines changed

README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,42 @@ The PLC2Skill library has to be imported into a PLC program. Skills can then be
3232
There are three different ways to use the PLC2Skill Mapper. You can either use it locally as a command line application, run it as a web-service or integrate it into your application as a library.
3333

3434
### CLI
35-
Download the current `cli-x.x.x-jar-with-dependencies.jar` from the releases into a folder of your choice. Inside that folder, open a shell and execute `java -jar cli-x.x.x-jar -f <PLCopen XML file you want to map> -e <endpointURL of your PLC> -n <root component of the PLC project>`. The mapping result will be written to a file right next to the cli.jar.<br>
35+
Download the current `cli-x.x.x-jar-with-dependencies.jar` from the releases into a folder of your choice. Inside that folder, open a shell and execute `java -jar cli-x.x.x-jar -f <PLCopen XML file you want to map> -e <endpointURL of your PLC>`. The mapping result will be written to a file right next to the cli.jar.<br>
3636
A Short description of the CLI arguments:
3737
- -f / --file: The path to the PLCopen XML file that needs to be exported in the previous step
3838
- -e / --endpointUrl: The endpointUrl of the OPC UA server running on the PLC. This is typically something like "opc.tcp://" + IP address of your PLC + ":" + Port of the UA server (default is 4840). So for UA server running on localhost with the default port, this argument would have to be set to "opc.tcp://localhost:4840".
39-
- n / --nodeIdRoot: This one is a bit more tricky than the two before. Unfortunately, PLC open XML does not preserve all information about the PLC project. Information of the root parts of the projects are not exported. This information is often used to create node IDs for UA variables. These node IDs are needed in order to execute a skill via OPC UA. So in order for the PLC2Skill Mapper to create all node IDs, the missing root part of all node IDs has to be presented. You can determine this root component by comparing your PLC project in your programming environment to the root element in the exported PLC open XML file. A more detailed guide on how to determine this root component will follow soon...
39+
- -u / --user: (Optional) OPC UA user name in case there is no anonymous access. Has to be set if the server requires authentication, otherwise the connection will fail.
40+
- p / --password: (Optional) Password for the given OPC UA user. Has to be set if the server requires authentication, otherwise the connection will fail.
41+
- n / --nodeIdRoot: (Optional) A PlcOpen XML doesn't contain complete OPC UA nodeIds. Information of the root parts of the projects are not exported. This information is often used to create node IDs for UA variables. These node IDs are needed in order to execute a skill via OPC UA. So in order for the PLC2Skill Mapper to create all node IDs, the missing root part of all node IDs has to be presented.
42+
Plc2Skill connects to the server and tries to browse for the nodes by their local names / browse names and resolve the proper nodeIds. Instead of browsing the server, you can also enter the missing prefix of the nodeIds. You can determine this root component by comparing your PLC project in your programming environment to the root element in the exported PLC open XML file. Passing `-n` can help in case you cannot connect to the server or Plc2Skill fails in resolving the nodeIds.
4043

4144
### REST-API
4245
Download the current `rest-api-x.x.x-jar-with-dependencies.jar` from the releases into a folder of your choice and from a shell, run `java -jar rest-api-x.x.x-jar-with-dependencies.jar`. This will start a web server and you can send HTTP POST request to `localhost:9191` to invoke the mapper. When creating the request, make sure to set the `Content-Type` header to `multipart/form-data`. Furthermore, the following information have to be sent inside the request body:
4346
- Key: "plc-file" - Value: The PLCopen XML file that should be mapped
4447
- Key: "endpointUrl" - Value: The endpoint URL of the PLC's OPC UA server (see above) as a string.
48+
- Key: "user" - Value: The endpoint URL of the PLC's OPC UA server (see above) as a string.
49+
- Key: "password" - Value: The endpoint URL of the PLC's OPC UA server (see above) as a string.
4550
- Key: "nodeIdRoot" - Value: The root component of all node IDs (see above) as a string.
4651

4752
The REST-API can be tested with Tools such as Postman and used e.g. by web applications. Our skill based control system interacts with the PLC2Skill Mapper via the REST API.
4853

4954
### Library
50-
You can also include the mapping library which is used in both the CLI-application and REST API in your own projects. In order to do so, import `Plc2SkillMapper` and after obtaining a new instance of the mapper, use `executeMapping(<endpointUr>,<nodeIdRoot>, <Path to your MTP file>)`. A more detailed instruction on how to use the library will follow soon.
55+
You can also include the mapping library which is used in both the CLI-application and REST API in your own projects. In order to do so, import `Plc2SkillMapper` and after create a new instance of the mapper using its builder. After creating an instance, you can simply call `executeMapping()` to get the mapping result as a String.
56+
```Java
57+
Path mappingPath = Paths.get("<path to your mapping>").toAbsolutePath();
58+
String endpointUrl = "opc.tcp://<your IP>:<your port>"; // default port of OPC UA is 4840
59+
String user = "<username>";
60+
String pw = "<password>";
61+
// Instead of letting Plc2Skill browse for the nodeIds, you can also pass the missing root part in case you know it
62+
// String nodeIdRoot = "|var|CODESYS Control Win V3 x64";
63+
64+
Plc2SkillMapper mapper = new Plc2SkillMapper.Builder(mappingPath, endpointUrl)
65+
.setUser(userName, password)
66+
// .setNodeIdRoot(nodeIdRoot) // In case you want to pass nodeIdRoot manually
67+
.build();
68+
69+
String result = mapper.executeMapping();
70+
```
5171

5272
## How to cite
5373
We are excited about everyone using PLC2Skill in their own applications. If you use PLC2Skill in research, please consider giving credit by citing the following paper:

cli/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>de.hsu-hh.ifa.plc2skill</groupId>
88
<artifactId>parent</artifactId>
9-
<version>1.0.0-SNAPSHOT</version>
9+
<version>1.1.0-SNAPSHOT</version>
1010
</parent>
1111

1212
<artifactId>plc2skill-cli</artifactId>

cli/src/main/java/cli/ConsoleApplication.java

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@
33
import java.io.BufferedWriter;
44
import java.io.FileWriter;
55
import java.io.IOException;
6+
import java.nio.file.Path;
67

78
import org.apache.commons.cli.CommandLine;
89
import org.apache.commons.cli.CommandLineParser;
910
import org.apache.commons.cli.DefaultParser;
1011
import org.apache.commons.cli.HelpFormatter;
1112
import org.apache.commons.cli.Options;
1213
import org.apache.commons.cli.ParseException;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
1316

1417
import plc2skill.mapping.Plc2SkillMapper;
1518

1619
public class ConsoleApplication {
17-
Plc2SkillMapper mapping = new Plc2SkillMapper();
20+
21+
private final Logger logger = LoggerFactory.getLogger(getClass());
1822
String outputFilename = "MappingOutput.ttl";
1923

2024
public void run(String[] args) {
@@ -25,16 +29,23 @@ public void run(String[] args) {
2529
return;
2630
}
2731

28-
if (line.hasOption("filename") && line.hasOption("endpointUrl") && line.hasOption("nodeIdRoot")) {
29-
System.out.println("Started PLC-Code Mapping to Skills");
30-
String path = line.getOptionValue("filename");
32+
// fileName and endpointUrl are required, rest is optional
33+
if (line.hasOption("filename") && line.hasOption("endpointUrl")) {
34+
logger.info("Started PLC-Code Mapping to Skills");
35+
Path plcOpenPath = Path.of(line.getOptionValue("filename"));
3136
String endpointUrl = line.getOptionValue("endpointUrl");
37+
String user = line.getOptionValue("user");
38+
String password = line.getOptionValue("password");
3239
String nodeIdRoot = line.getOptionValue("nodeIdRoot");
33-
System.out.println("fileName: " + path + "\nendpointUrl: " + endpointUrl + "\nnodeIdRoot: " + nodeIdRoot);
34-
String result = mapping.executeMapping(endpointUrl, nodeIdRoot, path);
40+
logger.info("fileName: " + plcOpenPath + "\nendpointUrl: " + endpointUrl + "\nnodeIdRoot: " + nodeIdRoot);
41+
Plc2SkillMapper mapper = new Plc2SkillMapper.Builder(plcOpenPath, endpointUrl)
42+
.setUser(user, password)
43+
.setNodeIdRoot(nodeIdRoot)
44+
.build();
45+
String result = mapper.executeMapping();
3546
writeFile(result, outputFilename);
3647
} else {
37-
System.out.println("Missing one or more of the parameters -f, -e and -n...");
48+
logger.error("Missing one or both mandatory parameters -f and -e...");
3849
printHelp();
3950
}
4051
}
@@ -49,10 +60,8 @@ private CommandLine parseArguments(String[] args) {
4960
line = parser.parse(options, args);
5061

5162
} catch (ParseException ex) {
52-
53-
System.err.println("Failed to parse command line arguments");
54-
System.err.println(ex.toString());
55-
63+
logger.error("Failed to parse command line arguments");
64+
logger.error(ex.toString());
5665
System.exit(1);
5766
}
5867
return line;
@@ -61,9 +70,11 @@ private CommandLine parseArguments(String[] args) {
6170
private Options getOptions() {
6271
Options options = new Options();
6372
options.addOption("h", "help", false, "Print help");
64-
options.addOption("f", "filename", true, "File name of the PLCopen XML file that should be mapped");
65-
options.addOption("e", "endpointUrl", true, "EndpointUrl of this skills UA Server");
66-
options.addOption("n", "nodeIdRoot", true, "Root component of this UA Server's node IDs");
73+
options.addRequiredOption("f", "filename", true, "File name of the PLCopen XML file that should be mapped");
74+
options.addRequiredOption("e", "endpointUrl", true, "EndpointUrl of this skills OPC UA Server");
75+
options.addOption("u", "user", true, "Username of the OPC UA Server");
76+
options.addOption("p", "password", true, "Password of the OPC UA Server");
77+
options.addOption("n", "nodeIdRoot", true, "Root component of this OPC UA Server's node IDs");
6778

6879
return options;
6980
}
@@ -80,7 +91,7 @@ private void writeFile(String mappedModel, String filePath) {
8091
writer.write(mappedModel);
8192
writer.close();
8293
} catch (IOException e) {
83-
System.out.println("Error while writing the file");
94+
logger.error("Error while writing the file");
8495
e.printStackTrace();
8596
}
8697
}

lib/pom.xml

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>de.hsu-hh.ifa.plc2skill</groupId>
88
<artifactId>parent</artifactId>
9-
<version>1.0.0-SNAPSHOT</version>
9+
<version>1.1.0-SNAPSHOT</version>
1010
</parent>
1111

1212
<artifactId>plc2skill-lib</artifactId>
@@ -19,19 +19,86 @@
1919
<artifactId>maven-compiler-plugin</artifactId>
2020
<version>3.8.0</version>
2121
<configuration>
22-
<source>1.8</source> <!-- Note that this is still @Java 8 as there is a dependency conflict when using Java >= 9 -->
22+
<source>1.8</source> <!-- Note that this is still @Java 8 as there is a dependency conflict when
23+
using Java >= 9 -->
2324
<target>1.8</target>
2425
<!-- <release>14</release> -->
2526
</configuration>
2627
</plugin>
28+
<plugin>
29+
<groupId>org.apache.maven.plugins</groupId>
30+
<artifactId>maven-surefire-plugin</artifactId>
31+
<version>2.21.0</version>
32+
<dependencies>
33+
<dependency>
34+
<groupId>org.junit.platform</groupId>
35+
<artifactId>junit-platform-surefire-provider</artifactId>
36+
<version>1.2.0-M1</version>
37+
</dependency>
38+
<dependency>
39+
<groupId>org.junit.jupiter</groupId>
40+
<artifactId>junit-jupiter-engine</artifactId>
41+
<version>5.2.0-M1</version>
42+
</dependency>
43+
</dependencies>
44+
</plugin>
2745
</plugins>
2846
</build>
2947

3048
<dependencies>
49+
<dependency>
50+
<groupId>org.eclipse.milo</groupId>
51+
<artifactId>sdk-client</artifactId>
52+
<version>0.6.8</version>
53+
</dependency>
3154
<dependency>
3255
<groupId>be.ugent.rml</groupId>
3356
<artifactId>rmlmapper</artifactId>
34-
<version>4.9.1</version>
57+
<version>6.0.0</version>
58+
</dependency>
59+
<dependency>
60+
<groupId>org.slf4j</groupId>
61+
<artifactId>slf4j-api</artifactId>
62+
<version>1.7.36</version>
63+
</dependency>
64+
<dependency>
65+
<groupId>org.slf4j</groupId>
66+
<artifactId>slf4j-log4j12</artifactId>
67+
<version>1.7.36</version>
68+
</dependency>
69+
70+
<!-- Test dependencies -->
71+
<dependency>
72+
<groupId>org.junit.jupiter</groupId>
73+
<artifactId>junit-jupiter-api</artifactId>
74+
<version>5.6.0</version>
75+
<scope>test</scope>
76+
</dependency>
77+
<dependency>
78+
<groupId>org.junit.jupiter</groupId>
79+
<artifactId>junit-jupiter-engine</artifactId>
80+
<version>5.6.0</version>
81+
<scope>test</scope>
82+
</dependency>
83+
<dependency>
84+
<groupId>org.junit.jupiter</groupId>
85+
<artifactId>junit-jupiter-params</artifactId>
86+
<version>5.2.0</version>
87+
<scope>test</scope>
88+
</dependency>
89+
<dependency>
90+
<groupId>org.assertj</groupId>
91+
<artifactId>assertj-core</artifactId>
92+
<!-- use 2.9.1 for Java 7 projects -->
93+
<version>3.11.1</version>
94+
<scope>test</scope>
95+
</dependency>
96+
<dependency>
97+
<groupId>org.apache.jena</groupId>
98+
<artifactId>apache-jena-libs</artifactId>
99+
<type>pom</type>
100+
<version>3.8.0</version>
101+
<scope>test</scope>
35102
</dependency>
36103
</dependencies>
37104
</project>

0 commit comments

Comments
 (0)