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/11 15:32:08 UTC
[plc4x] 02/02: - Fine-tuned the discovery to clean up allocated
resources after finishing discovery - Made the example actually return
something - Added an "executeWithHandler" which is able to intercept
incoming events as they come in
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 6c815282637499618008008761a0fa311dad610d
Author: cdutz <ch...@c-ware.de>
AuthorDate: Sun Jul 11 17:31:49 2021 +0200
- Fine-tuned the discovery to clean up allocated resources after finishing discovery
- Made the example actually return something
- Added an "executeWithHandler" which is able to intercept incoming events as they come in
---
.../plc4x/java/api/messages/PlcDiscoveryItem.java | 3 +-
.../java/api/messages/PlcDiscoveryItemHandler.java | 7 +
.../java/api/messages/PlcDiscoveryRequest.java | 2 +
.../java/api/messages/PlcDiscoveryResponse.java | 8 +
.../apache/plc4x/java/profinet/ProfinetDriver.java | 8 +-
.../profinet/discovery/ProfinetPlcDiscoverer.java | 183 ++++++++++++---------
.../examples/hellodiscovery/HelloDiscovery.java | 22 +--
.../hello-discovery/src/main/resources/logback.xml | 2 +-
.../java/spi/messages/DefaultPlcDiscoveryItem.java | 7 +-
.../spi/messages/DefaultPlcDiscoveryRequest.java | 5 +
.../spi/messages/DefaultPlcDiscoveryResponse.java | 8 +
.../plc4x/java/spi/messages/PlcDiscoverer.java | 3 +
.../transport/rawsocket/RawSocketTransport.java | 4 +-
13 files changed, 165 insertions(+), 97 deletions(-)
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
index fddc77d..c94d513 100644
--- 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
@@ -18,7 +18,6 @@
*/
package org.apache.plc4x.java.api.messages;
-import java.net.URL;
import java.util.Map;
public interface PlcDiscoveryItem {
@@ -36,7 +35,7 @@ public interface PlcDiscoveryItem {
/**
* @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();
+ String getTransportUrl();
/**
* @return returns a map of all configuration options (usually encoded after the transport url's "?" character (rack=1&slot=1, little-endian=true, ...)
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryItemHandler.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryItemHandler.java
new file mode 100644
index 0000000..13fa882
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryItemHandler.java
@@ -0,0 +1,7 @@
+package org.apache.plc4x.java.api.messages;
+
+public interface PlcDiscoveryItemHandler {
+
+ void handle(PlcDiscoveryItem discoveryItem);
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryRequest.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryRequest.java
index 577e0bf..afe8579 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryRequest.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryRequest.java
@@ -24,6 +24,8 @@ public interface PlcDiscoveryRequest extends PlcRequest {
CompletableFuture<? extends PlcDiscoveryResponse> execute();
+ CompletableFuture<? extends PlcDiscoveryResponse> executeWithHandler(PlcDiscoveryItemHandler handler);
+
interface Builder extends PlcRequestBuilder {
@Override
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryResponse.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryResponse.java
index 85d42a7..c4db35b 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryResponse.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcDiscoveryResponse.java
@@ -18,8 +18,16 @@
*/
package org.apache.plc4x.java.api.messages;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+
+import java.util.List;
+
public interface PlcDiscoveryResponse extends PlcResponse {
PlcDiscoveryRequest getRequest();
+ PlcResponseCode getResponseCode();
+
+ List<PlcDiscoveryItem> getValues();
+
}
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 0a261f7..4354935 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
@@ -20,7 +20,6 @@ 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.discovery.ProfinetPlcDiscoverer;
@@ -32,8 +31,6 @@ 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;
@@ -41,14 +38,15 @@ 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 static final String DRIVER_CODE = "profinet";
+
@Override
public String getProtocolCode() {
- return "profinet";
+ return DRIVER_CODE;
}
@Override
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/discovery/ProfinetPlcDiscoverer.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/discovery/ProfinetPlcDiscoverer.java
index dc43f21..ba7ef24 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/discovery/ProfinetPlcDiscoverer.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/discovery/ProfinetPlcDiscoverer.java
@@ -18,8 +18,13 @@ under the License.
*/
package org.apache.plc4x.java.profinet.discovery;
+import org.apache.plc4x.java.api.exceptions.PlcException;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryItem;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryItemHandler;
import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.profinet.ProfinetDriver;
import org.apache.plc4x.java.profinet.readwrite.*;
import org.apache.plc4x.java.profinet.readwrite.io.EthernetFrameIO;
import org.apache.plc4x.java.profinet.readwrite.types.VirtualLanPriority;
@@ -27,7 +32,10 @@ import org.apache.plc4x.java.spi.generation.ParseException;
import org.apache.plc4x.java.spi.generation.ReadBuffer;
import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
import org.apache.plc4x.java.spi.generation.WriteBufferByteBased;
+import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryItem;
+import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryResponse;
import org.apache.plc4x.java.spi.messages.PlcDiscoverer;
+import org.apache.plc4x.java.transport.rawsocket.RawSocketTransport;
import org.pcap4j.core.*;
import org.pcap4j.packet.Dot1qVlanTagPacket;
import org.pcap4j.packet.EthernetPacket;
@@ -35,9 +43,10 @@ import org.pcap4j.packet.IllegalRawDataException;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.util.LinkLayerAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -46,6 +55,7 @@ public class ProfinetPlcDiscoverer implements PlcDiscoverer {
private static final EtherType PN_EtherType = EtherType.getInstance((short) 0x8892);
+ // The constants for the different block names and their actual meaning.
private static final String DEVICE_TYPE_NAME = "DEVICE_PROPERTIES_OPTION-1";
private static final String DEVICE_NAME_OF_STATION = "DEVICE_PROPERTIES_OPTION-2";
private static final String DEVICE_ID = "DEVICE_PROPERTIES_OPTION-3";
@@ -54,62 +64,110 @@ public class ProfinetPlcDiscoverer implements PlcDiscoverer {
private static final String DEVICE_INSTANCE = "DEVICE_PROPERTIES_OPTION-7";
private static final String IP_OPTION_IP = "IP_OPTION-2";
- public ProfinetPlcDiscoverer() {
- }
+ private final Logger logger = LoggerFactory.getLogger(ProfinetPlcDiscoverer.class);
@Override
public CompletableFuture<PlcDiscoveryResponse> discover(PlcDiscoveryRequest discoveryRequest) {
- Map<String, DCP_Identify_ResPDU> pnDevices = new HashMap<>();
+ return discoverWithHandler(discoveryRequest, null);
+ }
+
+ public CompletableFuture<PlcDiscoveryResponse> discoverWithHandler(PlcDiscoveryRequest discoveryRequest, PlcDiscoveryItemHandler handler) {
+ CompletableFuture<PlcDiscoveryResponse> future = new CompletableFuture<>();
+ Set<PcapHandle> openHandles = new HashSet<>();
+ List<PlcDiscoveryItem> values = new ArrayList<>();
try {
for (PcapNetworkInterface dev : Pcaps.findAllDevs()) {
- if(!dev.isLoopBack() && dev.isRunning()) {
+ if (!dev.isLoopBack() && dev.isRunning()) {
for (LinkLayerAddress linkLayerAddress : dev.getLinkLayerAddresses()) {
org.pcap4j.util.MacAddress macAddress = (org.pcap4j.util.MacAddress) linkLayerAddress;
PcapHandle handle = dev.openLive(65536, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, 10);
- PcapHandle sendHandle = dev.openLive(65536, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, 10);
+ openHandles.add(handle);
+
ExecutorService pool = Executors.newSingleThreadExecutor();
// Only react on PROFINET DCP packets targeted at our current MAC address.
- // TODO: Find out how to filter based on the ether frame type ...
handle.setFilter(
"((ether proto 0x8100) or (ether proto 0x8892)) and (ether dst " + Pcaps.toBpfString(macAddress) + ")",
BpfProgram.BpfCompileMode.OPTIMIZE);
PacketListener listener =
packet -> {
- if(packet instanceof EthernetPacket) {
+ // EthernetPacket is the highest level of abstraction we can be expecting.
+ // Everything inside this we will have to decode ourselves.
+ if (packet instanceof EthernetPacket) {
EthernetPacket ethernetPacket = (EthernetPacket) packet;
boolean isPnPacket = false;
- if(ethernetPacket.getPayload() instanceof Dot1qVlanTagPacket) {
+ // I have observed some times the ethernet packets being wrapped inside a VLAN
+ // Packet, in this case we simply unpack the content.
+ if (ethernetPacket.getPayload() instanceof Dot1qVlanTagPacket) {
Dot1qVlanTagPacket vlanPacket = (Dot1qVlanTagPacket) ethernetPacket.getPayload();
- if(PN_EtherType.equals(vlanPacket.getHeader().getType())) {
+ if (PN_EtherType.equals(vlanPacket.getHeader().getType())) {
isPnPacket = true;
}
- } else if(PN_EtherType.equals(ethernetPacket.getHeader().getType())) {
+ } else if (PN_EtherType.equals(ethernetPacket.getHeader().getType())) {
isPnPacket = true;
}
// It's a PROFINET packet.
- if(isPnPacket) {
+ if (isPnPacket) {
ReadBuffer reader = new ReadBufferByteBased(ethernetPacket.getRawData());
try {
EthernetFrame ethernetFrame = EthernetFrameIO.staticParse(reader);
- String sourceMacAddress = toMacAddressString(ethernetFrame.getSource());
DCP_PDU pdu;
- if(ethernetFrame.getPayload() instanceof VirtualLanEthernetFramePayload) {
+ // Access the pdu data (either directly or by
+ // unpacking the content of the VLAN packet.
+ if (ethernetFrame.getPayload() instanceof VirtualLanEthernetFramePayload) {
VirtualLanEthernetFramePayload vlefpl = (VirtualLanEthernetFramePayload) ethernetFrame.getPayload();
pdu = ((ProfinetEthernetFramePayload) vlefpl.getPayload()).getPdu();
} else {
pdu = ((ProfinetEthernetFramePayload) ethernetFrame.getPayload()).getPdu();
}
- if(pdu instanceof DCP_Identify_ResPDU) {
- DCP_Identify_ResPDU identify_resPDU = (DCP_Identify_ResPDU) pdu;
- if(!pnDevices.containsKey(sourceMacAddress)) {
- pnDevices.put(sourceMacAddress, identify_resPDU);
+ // Inspect the PDU itself
+ // (in this case we only process identify response packets)
+ if (pdu instanceof DCP_Identify_ResPDU) {
+ DCP_Identify_ResPDU identifyResPDU = (DCP_Identify_ResPDU) pdu;
+
+ Map<String, DCP_Block> blocks = new HashMap<>();
+ for (DCP_Block block : identifyResPDU.getBlocks()) {
+ String blockName = block.getOption().name() + "-" + block.getSuboption().toString();
+ blocks.put(blockName, block);
+ }
+
+ // The mac address of the device we found
+ org.pcap4j.util.MacAddress srcAddr = ethernetPacket.getHeader().getSrcAddr();
+ // The mac address of the local network device
+ org.pcap4j.util.MacAddress dstAddr = ethernetPacket.getHeader().getDstAddr();
+
+ String deviceTypeName = "unknown";
+ if (blocks.containsKey(DEVICE_TYPE_NAME)) {
+ DCP_BlockDevicePropertiesDeviceVendor block = (DCP_BlockDevicePropertiesDeviceVendor) blocks.get(DEVICE_TYPE_NAME);
+ deviceTypeName = new String(block.getDeviceVendorValue());
}
+ String deviceName = "unknown";
+ if (blocks.containsKey(DEVICE_NAME_OF_STATION)) {
+ DCP_BlockDevicePropertiesNameOfStation block = (DCP_BlockDevicePropertiesNameOfStation) blocks.get(DEVICE_NAME_OF_STATION);
+ deviceName = new String(block.getNameOfStation());
+ }
+
+ String transportUrl = srcAddr.toString();
+ Map<String, String> options =
+ Collections.singletonMap("localMacAddress", dstAddr.toString());
+ String name = deviceTypeName + " - " + deviceName;
+ PlcDiscoveryItem value = new DefaultPlcDiscoveryItem(
+ ProfinetDriver.DRIVER_CODE, RawSocketTransport.TRANSPORT_CODE,
+ transportUrl, options, name);
+ values.add(value);
+
+ // If we have a discovery handler, pass it to the handler callback
+ if (handler != null) {
+ handler.handle(value);
+ }
+
+ logger.debug("Found new device: '{}' with connection-url '{}'",
+ value.getName(), value.getConnectionUrl());
}
} catch (ParseException e) {
- e.printStackTrace();
+ logger.error("Got error decoding packet", e);
}
}
}
@@ -134,70 +192,46 @@ public class ProfinetPlcDiscoverer implements PlcDiscoverer {
WriteBufferByteBased buffer = new WriteBufferByteBased(34);
EthernetFrameIO.staticSerialize(buffer, identificationRequest);
Packet packet = EthernetPacket.newPacket(buffer.getData(), 0, 34);
- sendHandle.sendPacket(packet);
+ handle.sendPacket(packet);
}
}
}
- } catch (PcapNativeException | ParseException e) {
- e.printStackTrace();
- } catch (NotOpenException e) {
- e.printStackTrace();
- } catch (IllegalRawDataException e) {
- e.printStackTrace();
- }
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ } catch (IllegalRawDataException | NotOpenException | PcapNativeException | ParseException e) {
+ logger.error("Got an exception while processing raw socket data", e);
+ future.completeExceptionally(new PlcException("Got an internal error while performing discovery"));
+ for (PcapHandle openHandle : openHandles) {
+ openHandle.close();
+ }
+ return future;
}
- System.out.println(String.format("Found %d PROFINET devices:", pnDevices.size()));
- for (DCP_Identify_ResPDU pnDevice : pnDevices.values()) {
- outputPnDevice(pnDevice);
- }
+ // Create a timer that completes the future after a given time with all the responses it found till then.
+ Timer timer = new Timer("Discovery Timeout");
+ timer.schedule(new TimerTask() {
+ public void run() {
+ PlcDiscoveryResponse response =
+ new DefaultPlcDiscoveryResponse(discoveryRequest, PlcResponseCode.OK, values);
+ future.complete(response);
+ for (PcapHandle openHandle : openHandles) {
+ openHandle.close();
+ }
+ }
+ }, 5000L);
- return null;
+ return future;
}
private static MacAddress toPlc4xMacAddress(org.pcap4j.util.MacAddress pcap4jMacAddress) {
byte[] address = pcap4jMacAddress.getAddress();
- return new MacAddress(new short[]{ (short) address[0], (short) address[1], (short) address[2], (short) address[3], (short) address[4], (short) address[5]});
- }
-
- private static String toMacAddressString(MacAddress macAddress) {
- return String.format("%x2:%x2:%x2:%x2:%x2:%x2", macAddress.getAddress()[0], macAddress.getAddress()[1],
- macAddress.getAddress()[2], macAddress.getAddress()[3], macAddress.getAddress()[4], macAddress.getAddress()[5]);
- }
-
- private static void outputPnDevice(DCP_Identify_ResPDU pnDevice) {
- Map<String, DCP_Block> blocks = new HashMap<>();
- for (DCP_Block block : pnDevice.getBlocks()) {
- String blockName = block.getOption().name() + "-" + block.getSuboption().toString();
- blocks.put(blockName, block);
- }
-
- String deviceTypeName = "unknown";
- if(blocks.containsKey(DEVICE_TYPE_NAME)) {
- DCP_BlockDevicePropertiesDeviceVendor block = (DCP_BlockDevicePropertiesDeviceVendor) blocks.get(DEVICE_TYPE_NAME);
- deviceTypeName = new String(block.getDeviceVendorValue());
- }
- String deviceName = "unknown";
- if(blocks.containsKey(DEVICE_NAME_OF_STATION)) {
- DCP_BlockDevicePropertiesNameOfStation block = (DCP_BlockDevicePropertiesNameOfStation) blocks.get(DEVICE_NAME_OF_STATION);
- deviceName = new String(block.getNameOfStation());
- }
- String ipAddress = "unknown";
- if(blocks.containsKey(IP_OPTION_IP)) {
- DCP_BlockIpIpParameter block = (DCP_BlockIpIpParameter) blocks.get(IP_OPTION_IP);
- ipAddress = String.format("%d.%d.%d.%d", block.getIpAddress()[0], block.getIpAddress()[1], block.getIpAddress()[2], block.getIpAddress()[3]);
- }
- System.out.println(String.format("Found '%s' with name '%s' on IP: %s%n\t%s", deviceTypeName, deviceName, ipAddress, pnDevice));
+ return new MacAddress(new short[]{address[0], address[1], address[2], address[3], address[4], address[5]});
}
private static class Task implements Runnable {
- private PcapHandle handle;
- private PacketListener listener;
+ private final Logger logger = LoggerFactory.getLogger(Task.class);
+
+ private final PcapHandle handle;
+ private final PacketListener listener;
public Task(PcapHandle handle, PacketListener listener) {
this.handle = handle;
@@ -208,12 +242,11 @@ public class ProfinetPlcDiscoverer implements PlcDiscoverer {
public void run() {
try {
handle.loop(10, listener);
- } catch (PcapNativeException e) {
- e.printStackTrace();
} catch (InterruptedException e) {
- e.printStackTrace();
- } catch (NotOpenException e) {
- e.printStackTrace();
+ logger.error("Got error handling raw socket", e);
+ Thread.currentThread().interrupt();
+ } catch (PcapNativeException | NotOpenException e) {
+ logger.error("Got error handling raw socket", e);
}
}
}
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
index c2cfdb4..8003c28 100644
--- 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
@@ -19,19 +19,13 @@ 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.messages.*;
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 {
@@ -53,18 +47,26 @@ public class HelloDiscovery {
PlcDriverManager plcDriverManager = new PlcDriverManager();
Set<String> driverCodes = plcDriverManager.listDrivers();
for (String driverCode : driverCodes) {
- logger.info(String.format("Executing Discovery for Driver: %s", driverCode));
+ logger.info("Executing Discovery for Driver: {}", driverCode);
PlcDriver driver = plcDriverManager.getDriver(driverCode);
// Check if this driver supports discovery.
if(driver.getMetadata().canDiscover()) {
PlcDiscoveryRequest discoveryRequest = driver.discoveryRequestBuilder().build();
- discoveryRequest.execute();
+ PlcDiscoveryResponse discoveryResponse = discoveryRequest.executeWithHandler(
+ discoveryItem -> logger.info("Intercepted discovery of device with name: {} with connection url: {}",
+ discoveryItem.getName(), discoveryItem.getConnectionUrl())).get();
+ if(discoveryResponse.getResponseCode() == PlcResponseCode.OK) {
+ logger.info("Discovery finished successfully:");
+ for (PlcDiscoveryItem discoveryItem : discoveryResponse.getValues()) {
+ logger.info("Found device with name: {} with connection url: {}",
+ discoveryItem.getName(), discoveryItem.getConnectionUrl());
+ }
+ }
} 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
index a8ddebb..27d40c0 100644
--- a/plc4j/examples/hello-discovery/src/main/resources/logback.xml
+++ b/plc4j/examples/hello-discovery/src/main/resources/logback.xml
@@ -29,7 +29,7 @@
</encoder>
</appender>
- <root level="trace">
+ <root level="info">
<appender-ref ref="STDOUT" />
</root>
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
index ac1fbdf..db1174f 100644
--- 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
@@ -35,14 +35,14 @@ public class DefaultPlcDiscoveryItem implements PlcDiscoveryItem, Serializable {
private final String protocolCode;
private final String transportCode;
- private final URL transportUrl;
+ private final String 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("transportUrl") String transportUrl,
@JsonProperty("options") Map<String, String> options,
@JsonProperty("name") String name) {
this.protocolCode = protocolCode;
@@ -63,7 +63,7 @@ public class DefaultPlcDiscoveryItem implements PlcDiscoveryItem, Serializable {
}
@Override
- public URL getTransportUrl() {
+ public String getTransportUrl() {
return transportUrl;
}
@@ -85,6 +85,7 @@ public class DefaultPlcDiscoveryItem implements PlcDiscoveryItem, Serializable {
boolean first = true;
for (Map.Entry<String, String> optionEntry : options.entrySet()) {
if(first) {
+ sb.append("?");
first = false;
} else {
sb.append("&");
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
index 79334cc..1cefe38 100644
--- 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
@@ -42,6 +42,11 @@ public class DefaultPlcDiscoveryRequest implements PlcDiscoveryRequest, Serializ
}
@Override
+ public CompletableFuture<? extends PlcDiscoveryResponse> executeWithHandler(PlcDiscoveryItemHandler handler) {
+ return discoverer.discoverWithHandler(this, handler);
+ }
+
+ @Override
public void serialize(WriteBuffer writeBuffer) throws ParseException {
writeBuffer.pushContext("PlcDiscoveryRequest");
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
index c219ff9..b3f5022 100644
--- 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
@@ -20,6 +20,7 @@ package org.apache.plc4x.java.spi.messages;
import com.fasterxml.jackson.annotation.*;
import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.spi.generation.ParseException;
import org.apache.plc4x.java.spi.generation.WriteBuffer;
import org.apache.plc4x.java.spi.utils.Serializable;
@@ -30,12 +31,15 @@ import java.util.*;
public class DefaultPlcDiscoveryResponse implements PlcDiscoveryResponse, Serializable {
private final PlcDiscoveryRequest request;
+ private final PlcResponseCode responseCode;
private final List<PlcDiscoveryItem> values;
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public DefaultPlcDiscoveryResponse(@JsonProperty("request") PlcDiscoveryRequest request,
+ @JsonProperty("responseCode") PlcResponseCode responseCode,
@JsonProperty("values") List<PlcDiscoveryItem> values) {
this.request = request;
+ this.responseCode = responseCode;
this.values = values;
}
@@ -44,6 +48,10 @@ public class DefaultPlcDiscoveryResponse implements PlcDiscoveryResponse, Serial
return request;
}
+ public PlcResponseCode getResponseCode() {
+ return responseCode;
+ }
+
public List<PlcDiscoveryItem> getValues() {
return values;
}
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
index 28ace34..a7ca16a 100644
--- 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
@@ -18,6 +18,7 @@
*/
package org.apache.plc4x.java.spi.messages;
+import org.apache.plc4x.java.api.messages.PlcDiscoveryItemHandler;
import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
@@ -36,4 +37,6 @@ public interface PlcDiscoverer {
*/
CompletableFuture<PlcDiscoveryResponse> discover(PlcDiscoveryRequest discoveryRequest);
+ CompletableFuture<PlcDiscoveryResponse> discoverWithHandler(PlcDiscoveryRequest discoveryRequest, PlcDiscoveryItemHandler handler);
+
}
diff --git a/plc4j/transports/raw-socket/src/main/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransport.java b/plc4j/transports/raw-socket/src/main/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransport.java
index 5153d7a..84ccb93 100644
--- a/plc4j/transports/raw-socket/src/main/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransport.java
+++ b/plc4j/transports/raw-socket/src/main/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransport.java
@@ -24,9 +24,11 @@ import org.apache.plc4x.java.utils.rawsockets.netty.address.RawSocketAddress;
public class RawSocketTransport implements Transport {
+ public static final String TRANSPORT_CODE = "raw";
+
@Override
public String getTransportCode() {
- return "raw";
+ return TRANSPORT_CODE;
}
@Override