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 2020/09/01 07:12:45 UTC

[plc4x] branch develop updated: PLC4X-246 - S7 driver hangs on read

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 c7e6e3c  PLC4X-246 - S7 driver hangs on read
c7e6e3c is described below

commit c7e6e3c389cf91202ec93d5967c5606401f46bac
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Sep 1 09:12:34 2020 +0200

    PLC4X-246 - S7 driver hangs on read
    
    Turns out an error response is not a S7MessageResponseData but a S7MessageResponse ... adjusted the handler to handle any S7Message with the correct pdu-id.
---
 .../s7/readwrite/protocol/S7ProtocolLogic.java     | 90 ++++++++++------------
 1 file changed, 41 insertions(+), 49 deletions(-)

diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
index 073c572..e87d995 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
@@ -32,40 +32,7 @@ import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.value.PlcNull;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.api.value.PlcValues;
-import org.apache.plc4x.java.s7.readwrite.COTPPacket;
-import org.apache.plc4x.java.s7.readwrite.COTPPacketConnectionRequest;
-import org.apache.plc4x.java.s7.readwrite.COTPPacketConnectionResponse;
-import org.apache.plc4x.java.s7.readwrite.COTPPacketData;
-import org.apache.plc4x.java.s7.readwrite.COTPParameter;
-import org.apache.plc4x.java.s7.readwrite.COTPParameterCalledTsap;
-import org.apache.plc4x.java.s7.readwrite.COTPParameterCallingTsap;
-import org.apache.plc4x.java.s7.readwrite.COTPParameterTpduSize;
-import org.apache.plc4x.java.s7.readwrite.S7Address;
-import org.apache.plc4x.java.s7.readwrite.S7AddressAny;
-import org.apache.plc4x.java.s7.readwrite.S7Message;
-import org.apache.plc4x.java.s7.readwrite.S7MessageRequest;
-import org.apache.plc4x.java.s7.readwrite.S7MessageResponseData;
-import org.apache.plc4x.java.s7.readwrite.S7MessageUserData;
-import org.apache.plc4x.java.s7.readwrite.S7ParameterReadVarRequest;
-import org.apache.plc4x.java.s7.readwrite.S7ParameterSetupCommunication;
-import org.apache.plc4x.java.s7.readwrite.S7ParameterUserData;
-import org.apache.plc4x.java.s7.readwrite.S7ParameterUserDataItem;
-import org.apache.plc4x.java.s7.readwrite.S7ParameterUserDataItemCPUFunctions;
-import org.apache.plc4x.java.s7.readwrite.S7ParameterWriteVarRequest;
-import org.apache.plc4x.java.s7.readwrite.S7PayloadReadVarResponse;
-import org.apache.plc4x.java.s7.readwrite.S7PayloadUserData;
-import org.apache.plc4x.java.s7.readwrite.S7PayloadUserDataItem;
-import org.apache.plc4x.java.s7.readwrite.S7PayloadUserDataItemCpuFunctionReadSzlRequest;
-import org.apache.plc4x.java.s7.readwrite.S7PayloadUserDataItemCpuFunctionReadSzlResponse;
-import org.apache.plc4x.java.s7.readwrite.S7PayloadWriteVarRequest;
-import org.apache.plc4x.java.s7.readwrite.S7PayloadWriteVarResponse;
-import org.apache.plc4x.java.s7.readwrite.S7VarPayloadDataItem;
-import org.apache.plc4x.java.s7.readwrite.S7VarPayloadStatusItem;
-import org.apache.plc4x.java.s7.readwrite.S7VarRequestParameterItem;
-import org.apache.plc4x.java.s7.readwrite.S7VarRequestParameterItemAddress;
-import org.apache.plc4x.java.s7.readwrite.SzlDataTreeItem;
-import org.apache.plc4x.java.s7.readwrite.SzlId;
-import org.apache.plc4x.java.s7.readwrite.TPKTPacket;
+import org.apache.plc4x.java.s7.readwrite.*;
 import org.apache.plc4x.java.s7.readwrite.context.S7DriverContext;
 import org.apache.plc4x.java.s7.readwrite.field.S7StringField;
 import org.apache.plc4x.java.s7.readwrite.io.DataItemIO;
@@ -218,7 +185,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
     }
 
     /** Maps the S7ReadResponse of a PlcReadRequest to a PlcReadResponse */
-    private CompletableFuture<PlcReadResponse> toPlcReadResponse(InternalPlcReadRequest readRequest, CompletableFuture<S7MessageResponseData> response) {
+    private CompletableFuture<PlcReadResponse> toPlcReadResponse(InternalPlcReadRequest readRequest, CompletableFuture<S7Message> response) {
         return response
             .thenApply(p -> {
                 try {
@@ -236,8 +203,8 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
      * Assumes that the {@link S7MessageRequest} and its expected {@link S7MessageResponseData}
      * and does not further check that!
      */
-    private CompletableFuture<S7MessageResponseData> readInternal(S7MessageRequest request) {
-        CompletableFuture<S7MessageResponseData> future = new CompletableFuture<>();
+    private CompletableFuture<S7Message> readInternal(S7MessageRequest request) {
+        CompletableFuture<S7Message> future = new CompletableFuture<>();
         int tpduId = tpduGenerator.getAndIncrement();
 
         // Create a new Request with correct tpuId (is not known before)
@@ -252,8 +219,8 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
             .onError((p, e) -> future.completeExceptionally(e))
             .check(p -> p.getPayload() instanceof COTPPacketData)
             .unwrap(p -> (COTPPacketData) p.getPayload())
-            .check(p -> p.getPayload() instanceof S7MessageResponseData)
-            .unwrap(p -> (S7MessageResponseData) p.getPayload())
+            .check(p -> p.getPayload()  != null)
+            .unwrap(COTPPacket::getPayload)
             .check(p -> p.getTpduReference() == tpduId)
             .handle(p -> {
                 future.complete(p);
@@ -290,8 +257,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
             .onError((p, e) -> future.completeExceptionally(e))
             .check(p -> p.getPayload() instanceof COTPPacketData)
             .unwrap(p -> ((COTPPacketData) p.getPayload()))
-            .check(p -> p.getPayload() instanceof S7MessageResponseData)
-            .unwrap(p -> ((S7MessageResponseData) p.getPayload()))
+            .unwrap(COTPPacket::getPayload)
             .check(p -> p.getTpduReference() == tpduId)
             .handle(p -> {
                 try {
@@ -378,12 +344,25 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
             }, null, (short) 0x0000, (short) 0x000F, COTPProtocolClass.CLASS_0);
     }
 
-    private PlcResponse decodeReadResponse(S7MessageResponseData responseMessage, InternalPlcReadRequest plcReadRequest) throws PlcProtocolException {
+    private PlcResponse decodeReadResponse(S7Message responseMessage, InternalPlcReadRequest plcReadRequest) throws PlcProtocolException {
         Map<String, ResponseItem<PlcValue>> values = new HashMap<>();
+        short errorClass;
+        short errorCode;
+        if(responseMessage instanceof S7MessageResponseData) {
+            S7MessageResponseData messageResponseData = (S7MessageResponseData) responseMessage;
+            errorClass = messageResponseData.getErrorClass();
+            errorCode = messageResponseData.getErrorCode();
+        } else if(responseMessage instanceof S7MessageResponse) {
+            S7MessageResponse messageResponse = (S7MessageResponse) responseMessage;
+            errorClass = messageResponse.getErrorClass();
+            errorCode = messageResponse.getErrorCode();
+        } else {
+            throw new PlcProtocolException("Unsupported message type " + responseMessage.getClass().getName());
+        }
         // If the result contains any form of non-null error code, handle this instead.
-        if((responseMessage.getErrorClass() != 0) || (responseMessage.getErrorCode() != 0)) {
+        if((errorClass != 0) || (errorCode != 0)) {
             // This is usually the case if PUT/GET wasn't enabled on the PLC
-            if((responseMessage.getErrorClass() == 129) && (responseMessage.getErrorCode() == 4)) {
+            if((errorClass == 129) && (errorCode == 4)) {
                 LOGGER.warn("Got an error response from the PLC. This particular response code usually indicates " +
                     "that PUT/GET is not enabled on the PLC.");
                 for (String fieldName : plcReadRequest.getFieldNames()) {
@@ -396,7 +375,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
                     "We probably need to implement explicit handling for this, so please file a bug-report " +
                     "on https://issues.apache.org/jira/projects/PLC4X and ideally attach a WireShark dump " +
                     "containing a capture of the communication.",
-                    responseMessage.getErrorClass(), responseMessage.getErrorCode());
+                    errorClass, errorCode);
                 for (String fieldName : plcReadRequest.getFieldNames()) {
                     ResponseItem<PlcValue> result = new ResponseItem<>(PlcResponseCode.INTERNAL_ERROR, new PlcNull());
                     values.put(fieldName, result);
@@ -436,12 +415,25 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
         return new DefaultPlcReadResponse(plcReadRequest, values);
     }
 
-    private PlcResponse decodeWriteResponse(S7MessageResponseData responseMessage, InternalPlcWriteRequest plcWriteRequest) throws PlcProtocolException {
+    private PlcResponse decodeWriteResponse(S7Message responseMessage, InternalPlcWriteRequest plcWriteRequest) throws PlcProtocolException {
         Map<String, PlcResponseCode> responses = new HashMap<>();
+        short errorClass;
+        short errorCode;
+        if(responseMessage instanceof S7MessageResponseData) {
+            S7MessageResponseData messageResponseData = (S7MessageResponseData) responseMessage;
+            errorClass = messageResponseData.getErrorClass();
+            errorCode = messageResponseData.getErrorCode();
+        } else if(responseMessage instanceof S7MessageResponse) {
+            S7MessageResponse messageResponse = (S7MessageResponse) responseMessage;
+            errorClass = messageResponse.getErrorClass();
+            errorCode = messageResponse.getErrorCode();
+        } else {
+            throw new PlcProtocolException("Unsupported message type " + responseMessage.getClass().getName());
+        }
         // If the result contains any form of non-null error code, handle this instead.
-        if((responseMessage.getErrorClass() != 0) || (responseMessage.getErrorCode() != 0)) {
+        if((errorClass != 0) || (errorCode != 0)) {
             // This is usually the case if PUT/GET wasn't enabled on the PLC
-            if((responseMessage.getErrorClass() == 129) && (responseMessage.getErrorCode() == 4)) {
+            if((errorClass == 129) && (errorCode == 4)) {
                 LOGGER.warn("Got an error response from the PLC. This particular response code usually indicates " +
                     "that PUT/GET is not enabled on the PLC.");
                 for (String fieldName : plcWriteRequest.getFieldNames()) {
@@ -453,7 +445,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
                         "We probably need to implement explicit handling for this, so please file a bug-report " +
                         "on https://issues.apache.org/jira/projects/PLC4X and ideally attach a WireShark dump " +
                         "containing a capture of the communication.",
-                    responseMessage.getErrorClass(), responseMessage.getErrorCode());
+                    errorClass, errorCode);
                 for (String fieldName : plcWriteRequest.getFieldNames()) {
                     responses.put(fieldName, PlcResponseCode.INTERNAL_ERROR);
                 }