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 2022/08/31 08:12:02 UTC

[plc4x] branch develop updated: fix(plc4j/ads): Updated the ADS connect logic to be a bit more asynchronous (At least on an API level)

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 6fb1dea1f fix(plc4j/ads): Updated the ADS connect logic to be a bit more asynchronous (At least on an API level)
6fb1dea1f is described below

commit 6fb1dea1ff8e6776c974794de02a1e640b676be3
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Aug 31 10:11:44 2022 +0200

    fix(plc4j/ads): Updated the ADS connect logic to be a bit more asynchronous (At least on an API level)
---
 .../java/ads/configuration/AdsConfiguration.java   | 13 ++++
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  | 82 ++++++++++++++--------
 2 files changed, 67 insertions(+), 28 deletions(-)

diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/configuration/AdsConfiguration.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/configuration/AdsConfiguration.java
index 5a1134dc2..2d74033c8 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/configuration/AdsConfiguration.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/configuration/AdsConfiguration.java
@@ -26,6 +26,7 @@ import org.apache.plc4x.java.spi.configuration.ConfigurationParameterConverter;
 import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.spi.configuration.annotations.ParameterConverter;
 import org.apache.plc4x.java.spi.configuration.annotations.Required;
+import org.apache.plc4x.java.spi.configuration.annotations.defaults.BooleanDefaultValue;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.transport.serial.SerialTransportConfiguration;
 import org.apache.plc4x.java.transport.tcp.TcpTransportConfiguration;
@@ -64,6 +65,10 @@ public class AdsConfiguration implements Configuration, TcpTransportConfiguratio
     @IntDefaultValue(4000)
     protected int timeoutRequest;
 
+    @ConfigurationParameter("load-symbol-and-data-type-tables")
+    @BooleanDefaultValue(true)
+    protected boolean loadSymbolAndDataTypeTables;
+
     public AmsNetId getTargetAmsNetId() {
         return targetAmsNetId;
     }
@@ -112,6 +117,14 @@ public class AdsConfiguration implements Configuration, TcpTransportConfiguratio
         this.timeoutRequest = timeoutRequest;
     }
 
+    public boolean isLoadSymbolAndDataTypeTables() {
+        return loadSymbolAndDataTypeTables;
+    }
+
+    public void setLoadSymbolAndDataTypeTables(boolean loadSymbolAndDataTypeTables) {
+        this.loadSymbolAndDataTypeTables = loadSymbolAndDataTypeTables;
+    }
+
     @Override
     public int getDefaultPort() {
         return AdsConstants.ADSTCPDEFAULTPORT;
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
index 4f905e39c..3f2c09a9c 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
@@ -104,10 +104,10 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
 
     @Override
     public void onConnect(ConversationContext<AmsTCPPacket> context) {
-        LOGGER.debug("Fetching sizes of symbol and datatype table sizes.");
         final CompletableFuture<Void> future = new CompletableFuture<>();
 
         // If we have connection credentials available, try to set up the AMS routes.
+        CompletableFuture<Void> setupAmsRouteFuture;
         if(context.getAuthentication() != null) {
             if(!(context.getAuthentication() instanceof PlcUsernamePasswordAuthentication)) {
                 future.completeExceptionally(new PlcConnectionException(
@@ -117,8 +117,40 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
             PlcUsernamePasswordAuthentication usernamePasswordAuthentication =
                 (PlcUsernamePasswordAuthentication) context.getAuthentication();
 
-            // Prepre the request message.
-            org.apache.plc4x.java.ads.discovery.readwrite.AmsNetId sourceAmsNetId = new AmsNetId(
+            setupAmsRouteFuture = setupAmsRoute(usernamePasswordAuthentication);
+        } else {
+            setupAmsRouteFuture = CompletableFuture.completedFuture(null);
+        }
+
+        // If the configuration asks us to load the symbol and data type tables, do so,
+        // otherwise just mark the connection as completed instantly.
+        setupAmsRouteFuture.whenComplete((unused, throwable) -> {
+            if(configuration.isLoadSymbolAndDataTypeTables()) {
+                LOGGER.debug("Fetching sizes of symbol and datatype table sizes.");
+                CompletableFuture<Void> readSymbolTableFuture = readSymbolTableAndDatatypeTable(context);
+                readSymbolTableFuture.whenComplete((unused2, throwable2) -> {
+                    if (throwable2 != null) {
+                        LOGGER.error("Error fetching symbol and datatype table sizes");
+                    } else {
+                        context.fireConnected();
+                    }
+                });
+            } else {
+                context.fireConnected();
+            }
+        });
+    }
+
+    protected CompletableFuture<Void> setupAmsRoute(PlcUsernamePasswordAuthentication authentication) {
+        CompletableFuture<Void> future = new CompletableFuture<>();
+
+        new Thread(() -> {
+            LOGGER.debug("Setting up remote AMS routes.");
+            SocketAddress localSocketAddress = context.getChannel().localAddress();
+            InetAddress localAddress = ((InetSocketAddress) localSocketAddress).getAddress();
+
+            // Prepare the request message.
+            AmsNetId sourceAmsNetId = new AmsNetId(
                 configuration.getSourceAmsNetId().getOctet1(), configuration.getSourceAmsNetId().getOctet2(),
                 configuration.getSourceAmsNetId().getOctet3(), configuration.getSourceAmsNetId().getOctet4(),
                 configuration.getSourceAmsNetId().getOctet5(), configuration.getSourceAmsNetId().getOctet6());
@@ -129,9 +161,9 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                 sourceAmsNetId, AdsPortNumbers.SYSTEM_SERVICE,
                 Arrays.asList(new AdsDiscoveryBlockRouteName(new AmsString(routeName)),
                     new AdsDiscoveryBlockAmsNetId(sourceAmsNetId),
-                    new AdsDiscoveryBlockUserName(new AmsString(usernamePasswordAuthentication.getUsername())),
-                    new AdsDiscoveryBlockPassword(new AmsString(usernamePasswordAuthentication.getPassword())),
-                    new AdsDiscoveryBlockHostName(new AmsString("host-name-or-ip"))));
+                    new AdsDiscoveryBlockUserName(new AmsString(authentication.getUsername())),
+                    new AdsDiscoveryBlockPassword(new AmsString(authentication.getPassword())),
+                    new AdsDiscoveryBlockHostName(new AmsString(localAddress.getHostAddress()))));
 
             // Send the request to the PLC using a UDP socket.
             try (DatagramSocket adsDiscoverySocket = new DatagramSocket(AdsDiscoveryConstants.ADSDISCOVERYUDPDEFAULTPORT)) {
@@ -163,22 +195,28 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                 // Check if adding the route was successful
                 if (addOrUpdateRouteResponse.getRequestId() == 1) {
                     for (AdsDiscoveryBlock block : addOrUpdateRouteResponse.getBlocks()) {
-                        if(block.getBlockType() == AdsDiscoveryBlockType.STATUS) {
+                        if (block.getBlockType() == AdsDiscoveryBlockType.STATUS) {
                             AdsDiscoveryBlockStatus statusBlock = (AdsDiscoveryBlockStatus) block;
-                            if(statusBlock.getStatus() != Status.SUCCESS) {
-                                future.completeExceptionally(new PlcConnectionException("Error adding AMS route"));
+                            if (statusBlock.getStatus() != Status.SUCCESS) {
+                                future.completeExceptionally(new PlcException("Error adding AMS route"));
                                 return;
                             }
                         }
                     }
                 }
+
+                future.complete(null);
             } catch (Exception e) {
-                e.printStackTrace();
+                future.completeExceptionally(new PlcException("Error adding AMS route", e));
             }
-        }
+        }).start();
+
+        return future;
+    }
+
+    protected CompletableFuture<Void> readSymbolTableAndDatatypeTable(ConversationContext<AmsTCPPacket> context) {
+        final CompletableFuture<Void> future = new CompletableFuture<>();
 
-        List<AdsDataTypeTableEntry> dataTypes = new ArrayList<>();
-        List<AdsSymbolTableEntry> symbols = new ArrayList<>();
         // Initialize the request.
         AmsPacket amsPacket = new AdsReadRequest(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(),
             configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(), 0, getInvokeId(),
@@ -220,7 +258,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                                     for (int i = 0; i < adsTableSizes.getDataTypeCount(); i++) {
                                         try {
                                             AdsDataTypeTableEntry adsDataTypeTableEntry = AdsDataTypeTableEntry.staticParse(rb);
-                                            dataTypes.add(adsDataTypeTableEntry);
+                                            dataTypeTable.put(adsDataTypeTableEntry.getDataTypeName(), adsDataTypeTableEntry);
                                         } catch (ParseException e) {
                                             throw new RuntimeException(e);
                                         }
@@ -244,7 +282,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                                                 for (int i = 0; i < adsTableSizes.getSymbolCount(); i++) {
                                                     try {
                                                         AdsSymbolTableEntry adsSymbolTableEntry = AdsSymbolTableEntry.staticParse(rb2);
-                                                        symbols.add(adsSymbolTableEntry);
+                                                        symbolTable.put(adsSymbolTableEntry.getName(), adsSymbolTableEntry);
                                                     } catch (ParseException e) {
                                                         throw new RuntimeException(e);
                                                     }
@@ -262,19 +300,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                     future.completeExceptionally(new PlcException("Result is " + responseAdsData.getResult()));
                 }
             }));
-        future.whenComplete((unused, throwable) -> {
-            if(throwable != null) {
-                LOGGER.error("Error fetching symbol and datatype table sizes");
-            } else {
-                for (AdsDataTypeTableEntry dataType : dataTypes) {
-                    dataTypeTable.put(dataType.getDataTypeName(), dataType);
-                }
-                for (AdsSymbolTableEntry symbol : symbols) {
-                    symbolTable.put(symbol.getName(), symbol);
-                }
-                context.fireConnected();
-            }
-        });
+        return future;
     }
 
     @Override