You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by hu...@apache.org on 2023/02/13 11:04:05 UTC
[plc4x] 02/02: fix(plc4j/profinet): Implmented pop for the dcerpc response queue. Syncronized cyclic counter for pnio packets
This is an automated email from the ASF dual-hosted git repository.
hutcheb pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 40e6a66cd868e78d4890095dc2a0dd4874c3f18d
Author: Ben Hutcheson <be...@gmail.com>
AuthorDate: Sat Feb 11 12:48:51 2023 +0100
fix(plc4j/profinet): Implmented pop for the dcerpc response queue. Syncronized cyclic counter for pnio packets
---
.../profinet/context/ProfinetDeviceContext.java | 14 +++--
.../java/profinet/device/ProfinetChannel.java | 3 +-
.../plc4x/java/profinet/device/ProfinetDevice.java | 73 +++++++++++++++++++---
.../main/resources/protocols/profinet/pndcp.mspec | 22 +++----
4 files changed, 87 insertions(+), 25 deletions(-)
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/context/ProfinetDeviceContext.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/context/ProfinetDeviceContext.java
index e0152ce053..128f89fa98 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/context/ProfinetDeviceContext.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/context/ProfinetDeviceContext.java
@@ -459,12 +459,18 @@ public class ProfinetDeviceContext implements DriverContext, HasConfiguration<Pr
this.frameId = frameId;
}
- public Map<Long, ProfinetCallable<DceRpc_Packet>> getQueue() {
- return queue;
+ public ProfinetCallable<DceRpc_Packet> popFromQueue(long sequenceNumber) {
+ ProfinetCallable<DceRpc_Packet> r = queue.get(sequenceNumber);
+ queue.remove(sequenceNumber);
+ return r;
}
- public void setQueue(Map<Long, ProfinetCallable<DceRpc_Packet>> queue) {
- this.queue = queue;
+ public boolean hasSequenecNumberInQueue(long sequenceNumber) {
+ return queue.containsKey(sequenceNumber);
+ }
+
+ public void addToQueue(long sequenceNumber, ProfinetCallable<DceRpc_Packet> obj) {
+ queue.put(sequenceNumber, obj);
}
public int getSessionKey() {
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java
index deb608c1e0..d1c1c4ffe8 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java
@@ -103,7 +103,7 @@ public class ProfinetChannel {
} else if (ethernetPacket.getHeader().getType() == EtherType.IPV4 && ethernetPacket.getPayload().getPayload() instanceof UdpPacket) {
UdpPacket payload = (UdpPacket) ethernetPacket.getPayload().getPayload();
// Check if it's a PROFINET packet
- if (payload.getHeader().getDstPort().value() == -30572 || payload.getHeader().getDstPort().value() == -15536) {
+ if (payload.getHeader().getDstPort().value() == -30572 || payload.getHeader().getDstPort().value() == -15536 || payload.getHeader().getDstPort().value() == -15535) {
isPnPacket = true;
}
}
@@ -139,7 +139,6 @@ public class ProfinetChannel {
}
}
}
-
} else if (payload instanceof Ethernet_FramePayload_LLDP) {
Lldp_Pdu pdu = ((Ethernet_FramePayload_LLDP) payload).getPdu();
if (discoverer != null) {
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 e10de6e0b4..3e281301f5 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
@@ -70,6 +70,8 @@ public class ProfinetDevice implements PlcSubscriber{
private String deviceId;
private Thread eventLoop = null;
Map<String, List<Consumer<PlcSubscriptionEvent>>> registrations = new HashMap<>();
+ private int offset = 0;
+ private boolean firstMessage = true;
public ProfinetDevice(String deviceName, String deviceAccess, String subModules, BiFunction<String, String, ProfinetISO15745Profile> gsdHandler) {
this.gsdHandler = gsdHandler;
@@ -123,7 +125,7 @@ public class ProfinetDevice implements PlcSubscriber{
}
private void recordIdAndSend(ProfinetCallable<DceRpc_Packet> callable) {
- deviceContext.getQueue().put(callable.getId(), callable);
+ deviceContext.addToQueue(callable.getId(), callable);
ProfinetMessageWrapper.sendUdpMessage(
callable,
deviceContext
@@ -270,8 +272,8 @@ public class ProfinetDevice implements PlcSubscriber{
public void handleResponse(Ethernet_FramePayload_IPv4 packet) {
logger.debug("Received packet for {}", packet.getPayload().getObjectUuid());
long objectId = packet.getPayload().getSequenceNumber();
- if (deviceContext.getQueue().containsKey(objectId)) {
- deviceContext.getQueue().get(objectId).handle(packet.getPayload());
+ if (deviceContext.hasSequenecNumberInQueue(objectId)) {
+ deviceContext.popFromQueue(objectId).handle(packet.getPayload());
} else {
PnIoCm_Packet payloadPacket = packet.getPayload().getPayload();
deviceContext.setActivityUuid(packet.getPayload().getActivityUuid());
@@ -283,6 +285,12 @@ public class ProfinetDevice implements PlcSubscriber{
deviceContext.setState(ProfinetDeviceState.APPLRDY);
}
}
+ } else if (payloadPacket instanceof PnIoCm_Packet_Fault) {
+ DceRpcAck ack = new DceRpcAck(deviceContext.getActivityUuid(), deviceContext.getSequenceNumber());
+ recordIdAndSend(ack);
+ } else if (payloadPacket instanceof PnIoCm_Packet_Ping) {
+ DceRpcAck ack = new DceRpcAck(deviceContext.getActivityUuid(), deviceContext.getSequenceNumber());
+ recordIdAndSend(ack);
} else {
deviceContext.setState(ProfinetDeviceState.ABORT);
logger.error("Unable to match Response with Requested Profinet packet");
@@ -348,10 +356,12 @@ public class ProfinetDevice implements PlcSubscriber{
Map<String, ResponseItem<PlcValue>> tags = new HashMap<>();
ReadBuffer buffer = new ReadBufferByteBased(cyclicPdu.getDataUnit().getData());
+ if (firstMessage) {
+ offset = cyclicPdu.getCycleCounter();
+ firstMessage = false;
+ }
+
try {
- if (deviceContext.getModules() == null) {
- logger.error("HH");
- }
for (ProfinetModule module : deviceContext.getModules()) {
module.parseTags(tags, deviceContext.getDeviceName(), buffer);
}
@@ -865,6 +875,53 @@ public class ProfinetDevice implements PlcSubscriber{
}
}
+ public class DceRpcAck implements ProfinetCallable<DceRpc_Packet> {
+
+ private final DceRpc_ActivityUuid activityUuid;
+ private long id;
+
+ public DceRpcAck(DceRpc_ActivityUuid activityUuid, long seqNumber) {
+ this.activityUuid = activityUuid;
+ this.id = seqNumber;
+ }
+
+ public CompletableFuture<Boolean> getResponseHandled() {
+ return null;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public DceRpc_Packet create() {
+ return new DceRpc_Packet(
+ DceRpc_PacketType.NO_CALL,
+ false,
+ true,
+ true,
+ IntegerEncoding.BIG_ENDIAN,
+ CharacterEncoding.ASCII,
+ FloatingPointEncoding.IEEE,
+ new DceRpc_ObjectUuid((byte) 0x00, 0x0001, Integer.decode("0x" + deviceId), Integer.decode("0x" + vendorId)),
+ new DceRpc_InterfaceUuid_ControllerInterface(),
+ activityUuid,
+ 0,
+ id,
+ DceRpc_Operation.CONTROL,
+ new PnIoCm_Packet_NoCall()
+ );
+ }
+
+ @Override
+ public void handle(DceRpc_Packet packet) {
+ logger.debug("Received an unintented packet");
+ }
+ }
+
public class CyclicData implements ProfinetCallable<Ethernet_Frame> {
private final long startTime;
@@ -906,7 +963,7 @@ public class ProfinetDevice implements PlcSubscriber{
buffer.writeByte((byte) 0x00);
}
- int elapsedTime = (int) ((((System.nanoTime() - startTime)/(MIN_CYCLE_NANO_SEC))) % 65536);
+ int elapsedTime = (int) ((((System.nanoTime() - startTime)/(MIN_CYCLE_NANO_SEC)) + offset) % 65536);
Ethernet_Frame frame = new Ethernet_Frame(
deviceContext.getMacAddress(),
@@ -932,7 +989,7 @@ public class ProfinetDevice implements PlcSubscriber{
deviceContext.setState(ProfinetDeviceState.ABORT);
logger.error("Error serializing cyclic data for device {}", deviceContext.getDeviceName());
- int elapsedTime = (int) ((((System.nanoTime() - startTime)/(MIN_CYCLE_NANO_SEC))) % 65536);
+ int elapsedTime = (int) ((((System.nanoTime() - startTime)/(MIN_CYCLE_NANO_SEC)) + offset) % 65536);
Ethernet_Frame frame = new Ethernet_Frame(
deviceContext.getMacAddress(),
diff --git a/protocols/profinet/src/main/resources/protocols/profinet/pndcp.mspec b/protocols/profinet/src/main/resources/protocols/profinet/pndcp.mspec
index 42a1deb7e6..dbc515c62c 100644
--- a/protocols/profinet/src/main/resources/protocols/profinet/pndcp.mspec
+++ b/protocols/profinet/src/main/resources/protocols/profinet/pndcp.mspec
@@ -70,17 +70,17 @@
// Delay Parameter End
]
['Alarm_Low' PnDcp_Pdu_AlarmLow
- [simple uint 16 alarmDstEndpoint]
- [simple uint 16 alarmSrcEndpoint]
- [simple uint 4 version]
- [simple uint 4 errorType]
- [simple uint 4 tAck]
- [simple uint 4 windowSize]
- [simple uint 16 senSeqNum]
- [simple uint 16 ackSeqNum]
- [implicit uint 16 varPartLen 'COUNT(varPart)']
- [array byte varPart length 'varPartLen']
- ]
+ [simple uint 16 alarmDstEndpoint]
+ [simple uint 16 alarmSrcEndpoint]
+ [simple uint 4 version]
+ [simple uint 4 errorType]
+ [simple uint 4 tAck]
+ [simple uint 4 windowSize]
+ [simple uint 16 senSeqNum]
+ [simple uint 16 ackSeqNum]
+ [implicit uint 16 varPartLen 'COUNT(varPart)']
+ [array byte varPart length 'varPartLen']
+ ]
['DCP_Identify_ReqPDU' PnDcp_Pdu_IdentifyReq
[const uint 8 serviceId 0x05 ]
// ServiceType Start