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 2023/12/23 09:24:00 UTC

(plc4x) 02/02: feat: Continued working on getting the PN stuff working.

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

commit 43b5e7d2f490ec7aa7b3aa924e017d499f6e6d8c
Author: Christofer Dutz <cd...@apache.org>
AuthorDate: Sat Dec 23 10:23:49 2023 +0100

    feat: Continued working on getting the PN stuff working.
---
 .../java/profinet/packets/PnDcpPacketFactory.java  |  3 +-
 .../profinet/protocol/ProfinetProtocolLogic.java   | 81 ++++++++++------------
 ...oTest2.java => ManualProfinetIoTestAdamPN.java} |  2 +-
 ...Test.java => ManualProfinetIoTestSimocode.java} |  4 +-
 ...java => ManualProfinetIoTestWagoPNCoupler.java} |  2 +-
 ....java => ManualProfinetIoTestZylkSimocode.java} | 10 +--
 .../plc4x/java/profinet/device/ProfinetDevice.java |  3 +-
 .../plc4x/java/profinet/ManualProfinetIoTest.java  |  4 +-
 8 files changed, 52 insertions(+), 57 deletions(-)

diff --git a/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/packets/PnDcpPacketFactory.java b/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/packets/PnDcpPacketFactory.java
index 79fcffe6ac..17c26edbdd 100644
--- a/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/packets/PnDcpPacketFactory.java
+++ b/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/packets/PnDcpPacketFactory.java
@@ -206,7 +206,8 @@ public class PnDcpPacketFactory {
                 Collections.singletonList(
                     new IODReadRequestHeader((short) 1, (short) 0, 0,
                         new Uuid(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
-                        0, 0, 1, 0xF000, 16696,
+                        // * REMARK: It seems that it doesn't matter if we use subSlotNumber 0 or 1, the responses seem to be the same.
+                        0, 0, 0, 0xF000, 16696,
                         new Uuid(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}))
                 ))
         );
diff --git a/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/protocol/ProfinetProtocolLogic.java b/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/protocol/ProfinetProtocolLogic.java
index fefd5254e2..142d078e63 100644
--- a/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/protocol/ProfinetProtocolLogic.java
+++ b/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/protocol/ProfinetProtocolLogic.java
@@ -40,7 +40,6 @@ import org.apache.plc4x.java.spi.configuration.HasConfiguration;
 import org.apache.plc4x.java.spi.context.DriverContext;
 import org.apache.plc4x.java.spi.messages.DefaultPlcBrowseItem;
 import org.apache.plc4x.java.spi.messages.DefaultPlcBrowseResponse;
-import org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse;
 import org.apache.plc4x.java.utils.rawsockets.netty.RawSocketChannel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -50,13 +49,18 @@ import java.security.SecureRandom;
 import java.time.Duration;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicInteger;
 
 public class ProfinetProtocolLogic extends Plc4xProtocolBase<Ethernet_Frame> implements HasConfiguration<ProfinetConfiguration> {
 
+    // This is the minimum cycle time defined in the PN Spec (Page 205): 31,25us
+    private static final int NANOS_PER_CYCLE = 31250;
+
     private ProfinetDriverContext profinetDriverContext;
     private ProfinetConfiguration configuration;
 
+    private Integer cycleOffset = null;
+    private boolean connected = false;
+
     private final Logger logger = LoggerFactory.getLogger(ProfinetProtocolLogic.class);
 
     @Override
@@ -722,6 +726,7 @@ public class ProfinetProtocolLogic extends Plc4xProtocolBase<Ethernet_Frame> imp
                         RawSocketChannel pnChannel = (RawSocketChannel) context.getChannel();
                         PnDcpPacketFactory.sendApplicationReadyResponse(context, pnChannel, profinetDriverContext, payloadIPv4.getSourcePort(), dceRpc_packet.getActivityUuid(), arUuid, sessionKey);
 
+                        connected = true;
                         // TODO: Prepare the subscription response.
 //                        future.complete(new DefaultPlcSubscriptionResponse(subscriptionRequest, ))
                     });
@@ -732,45 +737,6 @@ public class ProfinetProtocolLogic extends Plc4xProtocolBase<Ethernet_Frame> imp
                     // We needed to put the code to expect the ApplicationReady to subscribe before sending,
                     // as the device sends it within 4 ms, and we can't guarantee that we're done setting up
                     // the listener.
-
-                    // TODO: Start sending data.
-                    Thread task = new Thread(() -> {
-                        int curCounterValue = 0;
-                        RawSocketChannel pnChannel = (RawSocketChannel) context.getChannel();
-                        MacAddress srcAddress = new MacAddress(pnChannel.getLocalMacAddress().getAddress());
-                        MacAddress dstAddress = new MacAddress(pnChannel.getRemoteMacAddress().getAddress());
-                        byte[] data = new byte[40];
-                        data[0] = (byte) 0x80;
-                        data[1] = (byte) 0x80;
-                        data[2] = (byte) 0x80;
-                        data[3] = (byte) 0x80;
-                        long nextExecutionTime = System.currentTimeMillis();
-                        System.out.println("Starting Loop");
-                        while(context.getChannel().isOpen()) {
-                            if(nextExecutionTime < System.currentTimeMillis()) {
-                                curCounterValue += 512;
-                                Ethernet_Frame frame = new Ethernet_Frame(
-                                    dstAddress,
-                                    srcAddress,
-                                    new Ethernet_FramePayload_VirtualLan(VirtualLanPriority.INTERNETWORK_CONTROL, false, (short) 0,
-                                        new Ethernet_FramePayload_PnDcp(
-                                            new PnDcp_Pdu_RealTimeCyclic(0x8003,
-                                                new PnIo_CyclicServiceDataUnit(data, (short) 40),
-                                                curCounterValue, false, true,
-                                                true, true, false, true)
-                                        )
-                                    )
-                                );
-                                System.out.println("Sending");
-                                context.sendToWire(frame);
-                                // Send a packet every 16ms
-                                nextExecutionTime += 16;
-                            }
-                        }
-                        System.out.println("Channel closed");
-                    });
-                    task.setPriority(Thread.MAX_PRIORITY);
-                    task.start();
                 });
             });
 
@@ -779,11 +745,41 @@ public class ProfinetProtocolLogic extends Plc4xProtocolBase<Ethernet_Frame> imp
 
     @Override
     protected void decode(ConversationContext<Ethernet_Frame> context, Ethernet_Frame msg) throws Exception {
+        RawSocketChannel pnChannel = (RawSocketChannel) context.getChannel();
+/*        MacAddress srcAddress = new MacAddress(pnChannel.getLocalMacAddress().getAddress());
+        MacAddress dstAddress = new MacAddress(pnChannel.getRemoteMacAddress().getAddress());
+        byte[] data = new byte[40];
+        data[0] = (byte) 0x60;
+        data[1] = (byte) 0x60;
+        data[2] = (byte) 0x60;
+        data[3] = (byte) 0x60;
+        data[4] = (byte) 0x60;
+        data[6] = (byte) 0x60;*/
+
         if (msg.getPayload() instanceof Ethernet_FramePayload_PnDcp) {
             Ethernet_FramePayload_PnDcp dcpPacket = (Ethernet_FramePayload_PnDcp) msg.getPayload();
             if (dcpPacket.getPdu() instanceof PnDcp_Pdu_RealTimeCyclic) {
                 PnDcp_Pdu_RealTimeCyclic realTimeCyclic = (PnDcp_Pdu_RealTimeCyclic) dcpPacket.getPdu();
-//                System.out.println(realTimeCyclic);
+
+/*                // Save the offset of the first packet.
+                cycleOffset = realTimeCyclic.getCycleCounter();
+
+                int newCycleCounter = (int) ((((System.nanoTime() - startTime) / (NANOS_PER_CYCLE)) + cycleOffset) % 65536);
+                Ethernet_Frame frame = new Ethernet_Frame(
+                    dstAddress,
+                    srcAddress,
+                    new Ethernet_FramePayload_VirtualLan(VirtualLanPriority.INTERNETWORK_CONTROL, false, (short) 0,
+                        new Ethernet_FramePayload_PnDcp(
+                            new PnDcp_Pdu_RealTimeCyclic(0x8003,
+                                new PnIo_CyclicServiceDataUnit(data, (short) 40),
+                                newCycleCounter, false, true,
+                                true, true, false, true)
+                        )
+                    )
+                );
+                System.out.println("Sending");
+                context.sendToWire(frame);*/
+
             } else {
                 System.out.println(dcpPacket);
             }
@@ -792,7 +788,6 @@ public class ProfinetProtocolLogic extends Plc4xProtocolBase<Ethernet_Frame> imp
             if(payloadIPv4.getPayload().getPayload() instanceof PnIoCm_Packet_Ping) {
                 DceRpc_Packet pingPacket = payloadIPv4.getPayload();
                 // Send back a ping response
-                RawSocketChannel pnChannel = (RawSocketChannel) context.getChannel();
                 PnDcpPacketFactory.sendPingResponse(context, pnChannel, profinetDriverContext, payloadIPv4);
             }
             // The remote device terminated the connection.
diff --git a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest2.java b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestAdamPN.java
similarity index 97%
copy from plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest2.java
copy to plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestAdamPN.java
index 201986a321..8f5352d8eb 100644
--- a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest2.java
+++ b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestAdamPN.java
@@ -27,7 +27,7 @@ import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
 import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
-public class ManualProfinetIoTest2 {
+public class ManualProfinetIoTestAdamPN {
 
     public static void main(String[] args) throws Exception {
         // WireShark filter: "eth.addr == 74:fe:48:63:f6:c2"
diff --git a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestSimocode.java
similarity index 94%
rename from plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
rename to plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestSimocode.java
index 838bb9a257..95072070d8 100644
--- a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
+++ b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestSimocode.java
@@ -22,13 +22,11 @@ package org.apache.plc4x.java.profinet;
 import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.*;
-import org.apache.plc4x.java.profinet.tag.ProfinetTag;
 
 import java.time.Duration;
-import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-public class ManualProfinetIoTest {
+public class ManualProfinetIoTestSimocode {
 
     public static void main(String[] args) throws Exception {
         // WireShark filter: "eth.addr == 88:3f:99:00:06:ef"
diff --git a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest3.java b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestWagoPNCoupler.java
similarity index 97%
rename from plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest3.java
rename to plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestWagoPNCoupler.java
index f3f6aa61a2..aed2d41140 100644
--- a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest3.java
+++ b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestWagoPNCoupler.java
@@ -27,7 +27,7 @@ import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
 import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
-public class ManualProfinetIoTest3 {
+public class ManualProfinetIoTestWagoPNCoupler {
 
     public static void main(String[] args) throws Exception {
         // WireShark filter: "eth.addr == 00:30:de:61:37:79"
diff --git a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest2.java b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestZylkSimocode.java
similarity index 86%
rename from plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest2.java
rename to plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestZylkSimocode.java
index 201986a321..8170a6b5e8 100644
--- a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest2.java
+++ b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTestZylkSimocode.java
@@ -7,7 +7,7 @@
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *   https://www.apache.org/licenses/LICENSE-2.0
+ *   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
@@ -27,17 +27,17 @@ import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
 import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
-public class ManualProfinetIoTest2 {
+public class ManualProfinetIoTestZylkSimocode {
 
     public static void main(String[] args) throws Exception {
-        // WireShark filter: "eth.addr == 74:fe:48:63:f6:c2"
-        try(PlcConnection connection =  new DefaultPlcDriverManager().getConnection("profinet:raw://192.168.24.41")) {
+        // WireShark filter: eth.addr == 88:3f:99:03:ef:b0
+        try(PlcConnection connection =  new DefaultPlcDriverManager().getConnection("profinet:raw://192.168.54.23")) {
             // Create and execute the subscription request.
             PlcSubscriptionRequest subscriptionRequest = connection.subscriptionRequestBuilder()
                 .addCyclicTagAddress("inputs", "1.1.INPUT.0:BYTE[10]", Duration.ofMillis(400))
                 .addCyclicTagAddress("output", "1.1.OUTPUT.0:DWORD", Duration.ofMillis(400))
                 .build();
-            PlcSubscriptionResponse subscriptionResponse = subscriptionRequest.execute().get(10000, TimeUnit.MILLISECONDS);
+            PlcSubscriptionResponse subscriptionResponse = subscriptionRequest.execute().get(100000, TimeUnit.MILLISECONDS);
             System.out.println(subscriptionResponse);
         }
     }
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java
index b9eb095147..1b8e2ec5a5 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java
@@ -215,8 +215,7 @@ public class ProfinetDevice implements PlcSubscriber {
                                 recordIdAndSend(writeParameters, deviceContext.getSourcePort(), deviceContext.getDestinationPort());
                                 writeParameters.getResponseHandled().get(timeout, TimeUnit.NANOSECONDS);
                                 break;
-                            // Send a CONTROL packet
-                            // TODO: I assume this tells the PN device that we'll be the new "master"
+                            // Send a CONTROL packet telling the device we're done configuring the connection.
                             case PREMED:
                                 WriteParametersEnd writeParametersEnd = new WriteParametersEnd();
                                 recordIdAndSend(writeParametersEnd, deviceContext.getSourcePort(), deviceContext.getDestinationPort());
diff --git a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
index 0836021331..26bc1982b8 100644
--- a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
+++ b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
@@ -34,11 +34,13 @@ public class ManualProfinetIoTest {
     private static final Logger LOGGER = LoggerFactory.getLogger(ManualProfinetIoTest.class);
 
     public static void main(String[] args) throws Exception {
+        // eth.addr == 88:3f:99:03:ef:b0
+
         // In this example 192.168.54.2 is the local IP of the computer running PLC4J and 192.168.54.23 is the IP of the PN device.
         //final PlcConnection connection = new DefaultPlcDriverManager().getConnection("profinet://192.168.54.2?gsddirectory=~/.gsd&devices=[[simocodexbpn156e,DAP%201,(1,),192.168.54.23]]&reductionratio=16&sendclockfactor=32&dataholdfactor=3&watchdogfactor=3");
         // REMARK: The driver would use the local network device with the given IP address and to an auto-discovery, trying to find any devices returned with the matching name.
         // If this device is then found and an IP address is provided, it would use PN-DCP to set the IP address of that device to the given value.
-        final PlcConnection connection = new DefaultPlcDriverManager().getConnection("profinet://192.168.24.220?gsddirectory=~/.gsd&devices=[[cdxb195b3,DAP%201,(1,)]]&reductionratio=16&sendclockfactor=32&dataholdfactor=3&watchdogfactor=3");
+        final PlcConnection connection = new DefaultPlcDriverManager().getConnection("profinet://192.168.54.220?gsddirectory=~/.gsd&devices=[[simocodexbpn156e,DAP%201,(1,)]]&reductionratio=16&sendclockfactor=32&dataholdfactor=3&watchdogfactor=3");
 
         PlcBrowseRequest browseRequest = connection.browseRequestBuilder().addQuery("all", "*").build();
         PlcBrowseResponse plcBrowseResponse = browseRequest.execute().get(4000, TimeUnit.MILLISECONDS);