You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2021/07/02 13:50:47 UTC
[plc4x] 03/05: - Worked on implementing the basics of Discovery in
API and SPI - Refactored the driver.getDriver function to operate on the
driver-code and added a second getDriverForUrl
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/profinet-chris
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit ad9580309f592419743deb619026bdec11ca271a
Author: cdutz <ch...@c-ware.de>
AuthorDate: Fri Jul 2 10:16:33 2021 +0200
- Worked on implementing the basics of Discovery in API and SPI
- Refactored the driver.getDriver function to operate on the driver-code and added a second getDriverForUrl
---
.../org/apache/plc4x/java/PlcDriverManager.java | 36 ++++--
.../java/org/apache/plc4x/java/api/PlcDriver.java | 14 +++
.../plc4x/java/api/messages/PlcDiscoveryItem.java | 38 ++++++
.../plc4x/java/api/metadata/PlcDriverMetadata.java | 31 +++++
.../apache/plc4x/java/profinet/ProfinetDriver.java | 29 ++++-
plc4j/examples/hello-discovery/pom.xml | 79 ++++++++++++
.../java/examples/hellodiscovery/CliOptions.java | 73 +++++++++++
.../examples/hellodiscovery/HelloDiscovery.java | 70 +++++++++++
.../hello-discovery/src/main/resources/logback.xml | 36 ++++++
plc4j/examples/pom.xml | 8 ++
.../java/org/apache/plc4x/kafka/config/Sink.java | 2 +-
.../java/org/apache/plc4x/kafka/config/Source.java | 2 +-
.../opcuaserver/backend/Plc4xCommunication.java | 2 +-
.../java/spi/messages/DefaultPlcDiscoveryItem.java | 133 +++++++++++++++++++++
.../spi/messages/DefaultPlcDiscoveryRequest.java | 67 +++++++++++
.../spi/messages/DefaultPlcDiscoveryResponse.java | 68 +++++++++++
.../plc4x/java/spi/messages/PlcDiscoverer.java | 39 ++++++
.../triggerhandler/TriggerConfiguration.java | 2 +-
18 files changed, 715 insertions(+), 14 deletions(-)
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java b/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java
index 7b3652c..af4ee11 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java
@@ -31,6 +31,7 @@ import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
+import java.util.Set;
public class PlcDriverManager {
@@ -91,21 +92,38 @@ public class PlcDriverManager {
}
/**
- * Returns suitble driver for protocol or throws an Exception.
- * @param url Uri to use
+ * Returns the codes of all of the drivers which are currently registered at the PlcDriverManager
+ * @return Set of driver codes for all drivers registered
+ */
+ public Set<String> listDrivers() {
+ return driverMap.keySet();
+ }
+
+ /**
+ * Returns suitable driver for protocol or throws an Exception.
+ * @param protocolCode protocol code identifying the driver
* @return Driver instance for the given protocol
* @throws PlcConnectionException If no Suitable Driver can be found
*/
- @Experimental
- public PlcDriver getDriver(String url) throws PlcConnectionException {
+ public PlcDriver getDriver(String protocolCode) throws PlcConnectionException {
+ PlcDriver driver = driverMap.get(protocolCode);
+ if (driver == null) {
+ throw new PlcConnectionException("Unable to find driver for protocol '" + protocolCode + "'");
+ }
+ return driver;
+ }
+
+ /**
+ * Returns suitable driver for a given plc4x connection url or throws an Exception.
+ * @param url Uri to use
+ * @return Driver instance for the given url
+ * @throws PlcConnectionException If no Suitable Driver can be found
+ */
+ public PlcDriver getDriverForUrl(String url) throws PlcConnectionException {
try {
URI connectionUri = new URI(url);
String protocol = connectionUri.getScheme();
- PlcDriver driver = driverMap.get(protocol);
- if (driver == null) {
- throw new PlcConnectionException("Unable to find driver for protocol '" + protocol + "'");
- }
- return driver;
+ return getDriver(protocol);
} catch (URISyntaxException e) {
throw new PlcConnectionException("Invalid plc4j connection string '" + url + "'", e);
}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java
index bc8c0b3..6d99d17 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java
@@ -23,6 +23,8 @@ import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
import org.apache.plc4x.java.api.exceptions.PlcNotImplementedException;
import org.apache.plc4x.java.api.exceptions.PlcUnsupportedOperationException;
import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
+import org.apache.plc4x.java.api.metadata.PlcConnectionMetadata;
+import org.apache.plc4x.java.api.metadata.PlcDriverMetadata;
import org.apache.plc4x.java.api.model.PlcField;
/**
@@ -45,6 +47,18 @@ public interface PlcDriver {
String getProtocolName();
/**
+ * Provides driver metadata.
+ */
+ default PlcDriverMetadata getMetadata() {
+ return new PlcDriverMetadata() {
+ @Override
+ public boolean canDiscover() {
+ return false;
+ }
+ };
+ }
+
+ /**
* Connects to a PLC using the given plc connection string.
*
* @param url plc connection string.
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryItem.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryItem.java
new file mode 100644
index 0000000..b0692e0
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryItem.java
@@ -0,0 +1,38 @@
+package org.apache.plc4x.java.api.messages;
+
+import java.net.URL;
+import java.util.Map;
+
+public interface PlcDiscoveryItem {
+
+ /**
+ * @return returns the protocol-code part of the url (s7, modbus, ads, ...)
+ */
+ String getProtocolCode();
+
+ /**
+ * @return returns the transport part of the url (tcp, udp, serial, raw, ...)
+ */
+ String getTransportCode();
+
+ /**
+ * @return returns the part of the url, the given transport needs in order to connect (plc.mycompany.de, 192.168.42.23, /dev/serial, COM1)
+ */
+ URL getTransportUrl();
+
+ /**
+ * @return returns a map of all configuration options (usually encoded after the transport url's "?" character (rack=1&slot=1, little-endian=true, ...)
+ */
+ Map<String, String> getOptions();
+
+ /**
+ * @return returns something I bet made sense some time, but I have forgotten why I added it to plc4go ;-)
+ */
+ String getName();
+
+ /**
+ * @return returns a plc4x connection string that can be used in any PLC4X driver to connect to the given device (Generally just a concatenation of the other parts of this object)
+ */
+ String getConnectionUrl();
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/PlcDriverMetadata.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/PlcDriverMetadata.java
new file mode 100644
index 0000000..63b6f4e
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/PlcDriverMetadata.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.api.metadata;
+
+/**
+ * Information about driver capabilities.
+ */
+public interface PlcDriverMetadata {
+
+ /**
+ * Indicates that the driver supports discovery.
+ */
+ boolean canDiscover();
+
+}
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java
index b47d1bd..055b147 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java
@@ -19,6 +19,9 @@ under the License.
package org.apache.plc4x.java.profinet;
import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
+import org.apache.plc4x.java.api.metadata.PlcDriverMetadata;
import org.apache.plc4x.java.profinet.config.ProfinetConfiguration;
import org.apache.plc4x.java.profinet.field.ProfinetField;
import org.apache.plc4x.java.profinet.field.ProfinetFieldHandler;
@@ -27,6 +30,9 @@ import org.apache.plc4x.java.profinet.readwrite.EthernetFrame;
import org.apache.plc4x.java.profinet.readwrite.io.EthernetFrameIO;
import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
+import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
+import org.apache.plc4x.java.spi.messages.PlcDiscoverer;
import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
import org.apache.plc4x.java.api.value.PlcValueHandler;
import org.apache.plc4x.java.spi.configuration.Configuration;
@@ -34,9 +40,10 @@ import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
import org.apache.plc4x.java.spi.optimizer.SingleFieldOptimizer;
+import java.util.concurrent.CompletableFuture;
import java.util.function.ToIntFunction;
-public class ProfinetDriver extends GeneratedDriverBase<EthernetFrame> {
+public class ProfinetDriver extends GeneratedDriverBase<EthernetFrame> implements PlcDiscoverer {
@Override
public String getProtocolCode() {
@@ -49,6 +56,21 @@ public class ProfinetDriver extends GeneratedDriverBase<EthernetFrame> {
}
@Override
+ public PlcDriverMetadata getMetadata() {
+ return new PlcDriverMetadata() {
+ @Override
+ public boolean canDiscover() {
+ return true;
+ }
+ };
+ }
+
+ @Override
+ public PlcDiscoveryRequest.Builder discoveryRequestBuilder() {
+ return new DefaultPlcDiscoveryRequest.Builder(this);
+ }
+
+ @Override
protected Class<? extends Configuration> getConfigurationType() {
return ProfinetConfiguration.class;
}
@@ -127,4 +149,9 @@ public class ProfinetDriver extends GeneratedDriverBase<EthernetFrame> {
return ProfinetField.of(query);
}
+ @Override
+ public CompletableFuture<PlcDiscoveryResponse> discover(PlcDiscoveryRequest discoveryRequest) {
+ return null;
+ }
+
}
diff --git a/plc4j/examples/hello-discovery/pom.xml b/plc4j/examples/hello-discovery/pom.xml
new file mode 100644
index 0000000..18e4dd0
--- /dev/null
+++ b/plc4j/examples/hello-discovery/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.plc4x.examples</groupId>
+ <artifactId>plc4j-examples</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>plc4j-hello-discovery</artifactId>
+ <name>PLC4J: Examples: Hello Discovery</name>
+ <description>Hello world application for PLC4X demonstrating the Discovery API.</description>
+
+ <properties>
+ <app.main.class>org.apache.plc4x.java.examples.hellodiscovery.HelloDiscovery</app.main.class>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-api</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <version>1.7.25</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <configuration>
+ <usedDependencies combine.children="append">
+ <usedDependency>org.slf4j:log4j-over-slf4j</usedDependency>
+ </usedDependencies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git a/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/CliOptions.java b/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/CliOptions.java
new file mode 100644
index 0000000..78e20ca
--- /dev/null
+++ b/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/CliOptions.java
@@ -0,0 +1,73 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.java.examples.hellodiscovery;
+
+import org.apache.commons.cli.*;
+
+public class CliOptions {
+
+ private static Options options;
+
+ public static CliOptions fromArgs(String[] args) {
+ options = new Options();
+ // Required arguments
+/*
+ options.addOption(
+ Option.builder()
+ .type(String.class)
+ .longOpt("connection-string")
+ .hasArg()
+ .desc("Connection String")
+ .required()
+ .build());
+ options.addOption(
+ Option.builder()
+ .type(String.class)
+ .longOpt("field-addresses")
+ .hasArgs()
+ .desc("Field Addresses (Space separated).")
+ .required()
+ .build());
+*/
+
+ CommandLineParser parser = new DefaultParser();
+ CommandLine commandLine;
+ try {
+ commandLine = parser.parse(options, args);
+
+/* String connectionString = commandLine.getOptionValue("connection-string");
+ String[] fieldAddress = commandLine.getOptionValues("field-addresses");
+*/
+ return new CliOptions(/*connectionString, fieldAddress*/);
+ } catch (ParseException e) {
+ System.err.println(e.getMessage());
+ return null;
+ }
+ }
+
+ public static void printHelp() {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("HelloPlc4x", options);
+ }
+
+ public CliOptions() {
+ }
+
+}
diff --git a/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/HelloDiscovery.java b/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/HelloDiscovery.java
new file mode 100644
index 0000000..c2cfdb4
--- /dev/null
+++ b/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/HelloDiscovery.java
@@ -0,0 +1,70 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.examples.hellodiscovery;
+
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriver;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+public class HelloDiscovery {
+
+ private static final Logger logger = LoggerFactory.getLogger(HelloDiscovery.class);
+
+ /**
+ * Example code do demonstrate using PLC4X's discovery API.
+ *
+ * @param args ignored.
+ */
+ public static void main(String[] args) throws Exception {
+ CliOptions options = CliOptions.fromArgs(args);
+ if (options == null) {
+ CliOptions.printHelp();
+ // Could not parse.
+ System.exit(1);
+ }
+
+ PlcDriverManager plcDriverManager = new PlcDriverManager();
+ Set<String> driverCodes = plcDriverManager.listDrivers();
+ for (String driverCode : driverCodes) {
+ logger.info(String.format("Executing Discovery for Driver: %s", driverCode));
+ PlcDriver driver = plcDriverManager.getDriver(driverCode);
+
+ // Check if this driver supports discovery.
+ if(driver.getMetadata().canDiscover()) {
+ PlcDiscoveryRequest discoveryRequest = driver.discoveryRequestBuilder().build();
+ discoveryRequest.execute();
+ } else {
+ logger.info("This driver doesn't support discovery");
+ }
+ }
+
+ }
+
+}
diff --git a/plc4j/examples/hello-discovery/src/main/resources/logback.xml b/plc4j/examples/hello-discovery/src/main/resources/logback.xml
new file mode 100644
index 0000000..a8ddebb
--- /dev/null
+++ b/plc4j/examples/hello-discovery/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<configuration xmlns="http://ch.qos.logback/xml/ns/logback"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ch.qos.logback/xml/ns/logback https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="trace">
+ <appender-ref ref="STDOUT" />
+ </root>
+
+</configuration>
\ No newline at end of file
diff --git a/plc4j/examples/pom.xml b/plc4j/examples/pom.xml
index 5a974cb..e9a8145 100644
--- a/plc4j/examples/pom.xml
+++ b/plc4j/examples/pom.xml
@@ -43,6 +43,7 @@
<module>hello-cloud-azure</module>
<module>hello-cloud-google</module>
<module>hello-connectivity-kafka</module>
+ <module>hello-discovery</module>
<module>hello-connectivity-mqtt</module>
<module>hello-influx-data-collection</module>
<module>hello-integration-edgent</module>
@@ -101,6 +102,7 @@
<usedDependency>org.apache.plc4x:plc4j-driver-knxnetip</usedDependency>
<usedDependency>org.apache.plc4x:plc4j-driver-modbus</usedDependency>
<usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency>
+ <usedDependency>org.apache.plc4x:plc4j-driver-profinet</usedDependency>
<usedDependency>org.apache.plc4x:plc4j-driver-s7</usedDependency>
<usedDependency>org.apache.plc4x:plc4j-driver-simulated</usedDependency>
</usedDependencies>
@@ -191,6 +193,12 @@
</dependency>
<dependency>
<groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-driver-profinet</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
<artifactId>plc4j-driver-s7</artifactId>
<version>0.9.0-SNAPSHOT</version>
<scope>runtime</scope>
diff --git a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Sink.java b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Sink.java
index 72edcc4..60a1abd 100644
--- a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Sink.java
+++ b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Sink.java
@@ -58,7 +58,7 @@ public class Sink extends AbstractConfig{
String.format("Connection string shouldn't be null for source %s ", this.name));
}
try {
- new PlcDriverManager().getDriver(connectionString);
+ new PlcDriverManager().getDriverForUrl(connectionString);
} catch (Exception e) {
throw new ConfigException(
String.format("Connection String format is incorrect %s ", Constants.SINKS_CONFIG + "." + this.name + "." + Constants.CONNECTION_STRING_CONFIG + "=" + connectionString));
diff --git a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Source.java b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Source.java
index 42dc14a..aab9b3f 100644
--- a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Source.java
+++ b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Source.java
@@ -73,7 +73,7 @@ public class Source extends AbstractConfig{
String.format("Connection string shouldn't be null for source %s ", this.name));
}
try {
- new PlcDriverManager().getDriver(connectionString);
+ new PlcDriverManager().getDriverForUrl(connectionString);
} catch (Exception e) {
throw new ConfigException(
String.format("Connection String format is incorrect %s ", SOURCES_CONFIG + "." + this.name + "." + CONNECTION_STRING_CONFIG + "=" + connectionString));
diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
index 6740d45..14814f2 100644
--- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
+++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
@@ -94,7 +94,7 @@ public class Plc4xCommunication extends AbstractLifecycle {
}
public PlcField getField(String tag, String connectionString) throws PlcConnectionException {
- return driverManager.getDriver(connectionString).prepareField(tag);
+ return driverManager.getDriverForUrl(connectionString).prepareField(tag);
}
public void addField(DataItem item) {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryItem.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryItem.java
new file mode 100644
index 0000000..1516793
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryItem.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.spi.messages;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryItem;
+import org.apache.plc4x.java.spi.utils.XmlSerializable;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.net.URL;
+import java.util.Map;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
+public class DefaultPlcDiscoveryItem implements PlcDiscoveryItem, XmlSerializable {
+
+ private final String protocolCode;
+ private final String transportCode;
+ private final URL transportUrl;
+ private final Map<String, String> options;
+ private final String name;
+
+ @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+ public DefaultPlcDiscoveryItem(@JsonProperty("protocolCode") String protocolCode,
+ @JsonProperty("transportCode") String transportCode,
+ @JsonProperty("transportUrl") URL transportUrl,
+ @JsonProperty("options") Map<String, String> options,
+ @JsonProperty("name") String name) {
+ this.protocolCode = protocolCode;
+ this.transportCode = transportCode;
+ this.transportUrl = transportUrl;
+ this.options = options;
+ this.name = name;
+ }
+
+ @Override
+ public String getProtocolCode() {
+ return protocolCode;
+ }
+
+ @Override
+ public String getTransportCode() {
+ return transportCode;
+ }
+
+ @Override
+ public URL getTransportUrl() {
+ return transportUrl;
+ }
+
+ @Override
+ public Map<String, String> getOptions() {
+ return options;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getConnectionUrl() {
+ StringBuilder sb = new StringBuilder(String.format("%s:%s://%s",
+ protocolCode, transportCode, transportUrl.toString()));
+ if(options != null && !options.isEmpty()) {
+ boolean first = true;
+ for (Map.Entry<String, String> optionEntry : options.entrySet()) {
+ if(first) {
+ first = false;
+ } else {
+ sb.append("&");
+ }
+ sb.append(optionEntry.getKey()).append("=").append(optionEntry.getValue());
+ }
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public void xmlSerialize(Element parent) {
+ Document doc = parent.getOwnerDocument();
+ Element messageElement = doc.createElement("PlcDiscoveryItem");
+
+ Element protocolCodeElement = doc.createElement("protocolCode");
+ protocolCodeElement.appendChild(doc.createTextNode(protocolCode));
+ messageElement.appendChild(protocolCodeElement);
+
+ Element transportCodeElement = doc.createElement("transportCode");
+ transportCodeElement.appendChild(doc.createTextNode(transportCode));
+ messageElement.appendChild(transportCodeElement);
+
+ Element transportUrlElement = doc.createElement("transportUrl");
+ transportUrlElement.appendChild(doc.createTextNode(transportUrl.toString()));
+ messageElement.appendChild(transportUrlElement);
+
+ if(options != null && !options.isEmpty()) {
+ Element optionsElement = doc.createElement("options");
+ for (Map.Entry<String, String> optionEntry : options.entrySet()) {
+ Element optionElement = doc.createElement(optionEntry.getKey());
+ optionElement.appendChild(doc.createTextNode(optionEntry.getValue()));
+ optionsElement.appendChild(optionElement);
+ }
+ messageElement.appendChild(optionsElement);
+ }
+
+ if(name != null && !name.isEmpty()) {
+ Element nameElement = doc.createElement("name");
+ nameElement.appendChild(doc.createTextNode(name));
+ messageElement.appendChild(nameElement);
+ }
+
+ parent.appendChild(messageElement);
+ }
+
+}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryRequest.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryRequest.java
new file mode 100644
index 0000000..fa97866
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryRequest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.spi.messages;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.spi.utils.XmlSerializable;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.concurrent.CompletableFuture;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
+public class DefaultPlcDiscoveryRequest implements PlcDiscoveryRequest, XmlSerializable {
+
+ private final PlcDiscoverer discoverer;
+
+ @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+ public DefaultPlcDiscoveryRequest(@JsonProperty("discoverer") PlcDiscoverer discoverer) {
+ this.discoverer = discoverer;
+ }
+
+ @Override
+ public CompletableFuture<? extends PlcDiscoveryResponse> execute() {
+ return discoverer.discover(this);
+ }
+
+ @Override
+ public void xmlSerialize(Element parent) {
+ Document doc = parent.getOwnerDocument();
+ Element messageElement = doc.createElement("PlcDiscoveryRequest");
+ parent.appendChild(messageElement);
+ // TODO: Implement
+ }
+
+ public static class Builder implements PlcDiscoveryRequest.Builder {
+
+ private final PlcDiscoverer discoverer;
+
+ public Builder(PlcDiscoverer discoverer) {
+ this.discoverer = discoverer;
+ }
+
+ @Override
+ public PlcDiscoveryRequest build() {
+ return new DefaultPlcDiscoveryRequest(discoverer);
+ }
+
+ }
+
+}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryResponse.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryResponse.java
new file mode 100644
index 0000000..8b0a59e
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcDiscoveryResponse.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.spi.messages;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.spi.utils.XmlSerializable;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.*;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
+public class DefaultPlcDiscoveryResponse implements PlcDiscoveryResponse, XmlSerializable {
+
+ private final PlcDiscoveryRequest request;
+ private final List<PlcDiscoveryItem> values;
+
+ @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+ public DefaultPlcDiscoveryResponse(@JsonProperty("request") PlcDiscoveryRequest request,
+ @JsonProperty("values") List<PlcDiscoveryItem> values) {
+ this.request = request;
+ this.values = values;
+ }
+
+ @Override
+ public PlcDiscoveryRequest getRequest() {
+ return request;
+ }
+
+ public List<PlcDiscoveryItem> getValues() {
+ return values;
+ }
+
+ @Override
+ public void xmlSerialize(Element parent) {
+ Document doc = parent.getOwnerDocument();
+ Element messageElement = doc.createElement("PlcDiscoveryResponse");
+ if(request instanceof XmlSerializable) {
+ ((XmlSerializable) request).xmlSerialize(messageElement);
+ }
+ Element valuesElement = doc.createElement("values");
+ messageElement.appendChild(valuesElement);
+ for (PlcDiscoveryItem value : values) {
+ if(value instanceof XmlSerializable) {
+ ((XmlSerializable) value).xmlSerialize(messageElement);
+ }
+ }
+ parent.appendChild(messageElement);
+ }
+
+}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcDiscoverer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcDiscoverer.java
new file mode 100644
index 0000000..28ace34
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcDiscoverer.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.spi.messages;
+
+import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Interface implemented by all PlcConnections that are able to read from remote resources.
+ */
+public interface PlcDiscoverer {
+
+ /**
+ * Executes a discovery operation
+ *
+ * @param discoveryRequest object describing the parameters of the discovery.
+ * @return a {@link CompletableFuture} giving async access to the returned value.
+ */
+ CompletableFuture<PlcDiscoveryResponse> discover(PlcDiscoveryRequest discoveryRequest);
+
+}
diff --git a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
index 8035270..7291613 100644
--- a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
+++ b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
@@ -561,7 +561,7 @@ public class TriggerConfiguration{
//So I need to create the field using the connection string here
private PlcField prepareField(String fieldQuery) throws PlcConnectionException {
PlcDriverManager driverManager = new PlcDriverManager();
- PlcDriver driver = driverManager.getDriver(plcConnectionString);
+ PlcDriver driver = driverManager.getDriverForUrl(plcConnectionString);
return driver.prepareField(fieldQuery);
}