You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cg...@apache.org on 2023/01/29 00:38:04 UTC

[plc4x] branch develop updated: Fix issue-701 for S7 driver. (#770)

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

cgarcia 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 fd8d1f4608 Fix issue-701 for S7 driver. (#770)
fd8d1f4608 is described below

commit fd8d1f4608fef510204f5300369fe6bded066d63
Author: César José García León <ce...@gmail.com>
AuthorDate: Sat Jan 28 20:37:53 2023 -0400

    Fix issue-701 for S7 driver. (#770)
    
    * Fix issue-701 for S7 driver.
    
    * Fix symbol for hasNext parameter.
    
    ---------
    
    Co-authored-by: César García <ce...@ceos.com.ve>
---
 .../s7/readwrite/S7PayloadReadVarResponse.java     |  2 +-
 .../java/s7/readwrite/S7VarPayloadDataItem.java    | 39 ++++++++++++++++++----
 .../s7/readwrite/protocol/S7ProtocolLogic.java     | 27 ++++++++++++---
 plc4j/drivers/s7/src/test/java/S7IoTest.java       |  3 +-
 .../plc4x/java/spi/generation/StaticHelper.java    |  4 +++
 .../server/s7/protocol/S7Step7ServerAdapter.java   |  6 ++--
 .../s7/src/main/resources/protocols/s7/s7.mspec    | 11 +++---
 7 files changed, 71 insertions(+), 21 deletions(-)

diff --git a/plc4j/drivers/s7/src/main/generated/org/apache/plc4x/java/s7/readwrite/S7PayloadReadVarResponse.java b/plc4j/drivers/s7/src/main/generated/org/apache/plc4x/java/s7/readwrite/S7PayloadReadVarResponse.java
index c4209e3341..7b4551d234 100644
--- a/plc4j/drivers/s7/src/main/generated/org/apache/plc4x/java/s7/readwrite/S7PayloadReadVarResponse.java
+++ b/plc4j/drivers/s7/src/main/generated/org/apache/plc4x/java/s7/readwrite/S7PayloadReadVarResponse.java
@@ -103,7 +103,7 @@ public class S7PayloadReadVarResponse extends S7Payload implements Message {
         readCountArrayField(
             "items",
             new DataReaderComplexDefault<>(
-                () -> S7VarPayloadDataItem.staticParse(readBuffer), readBuffer),
+                () -> S7VarPayloadDataItem.staticParse(readBuffer, (boolean) (true)), readBuffer),
             CAST(parameter, S7ParameterReadVarResponse.class).getNumItems());
 
     readBuffer.closeContext("S7PayloadReadVarResponse");
diff --git a/plc4j/drivers/s7/src/main/generated/org/apache/plc4x/java/s7/readwrite/S7VarPayloadDataItem.java b/plc4j/drivers/s7/src/main/generated/org/apache/plc4x/java/s7/readwrite/S7VarPayloadDataItem.java
index c61ffe226f..f08cb90ecd 100644
--- a/plc4j/drivers/s7/src/main/generated/org/apache/plc4x/java/s7/readwrite/S7VarPayloadDataItem.java
+++ b/plc4j/drivers/s7/src/main/generated/org/apache/plc4x/java/s7/readwrite/S7VarPayloadDataItem.java
@@ -42,12 +42,19 @@ public class S7VarPayloadDataItem implements Message {
   protected final DataTransportSize transportSize;
   protected final byte[] data;
 
+  // Arguments.
+  protected final Boolean hasNext;
+
   public S7VarPayloadDataItem(
-      DataTransportErrorCode returnCode, DataTransportSize transportSize, byte[] data) {
+      DataTransportErrorCode returnCode,
+      DataTransportSize transportSize,
+      byte[] data,
+      Boolean hasNext) {
     super();
     this.returnCode = returnCode;
     this.transportSize = transportSize;
     this.data = data;
+    this.hasNext = hasNext;
   }
 
   public DataTransportErrorCode getReturnCode() {
@@ -102,7 +109,10 @@ public class S7VarPayloadDataItem implements Message {
 
     // Padding Field (padding)
     writePaddingField(
-        "padding", (int) ((COUNT(data)) % (2)), (short) 0x00, writeUnsignedShort(writeBuffer, 8));
+        "padding",
+        (int) (((PADCOUNT(data, hasNext)) % (2))),
+        (short) 0x00,
+        writeUnsignedShort(writeBuffer, 8));
 
     writeBuffer.popContext("S7VarPayloadDataItem");
   }
@@ -132,7 +142,7 @@ public class S7VarPayloadDataItem implements Message {
     }
 
     // Padding Field (padding)
-    int _timesPadding = (int) ((COUNT(data)) % (2));
+    int _timesPadding = (int) (((PADCOUNT(data, hasNext)) % (2)));
     while (_timesPadding-- > 0) {
       lengthInBits += 8;
     }
@@ -143,10 +153,25 @@ public class S7VarPayloadDataItem implements Message {
   public static S7VarPayloadDataItem staticParse(ReadBuffer readBuffer, Object... args)
       throws ParseException {
     PositionAware positionAware = readBuffer;
-    return staticParse(readBuffer);
+    if ((args == null) || (args.length != 1)) {
+      throw new PlcRuntimeException(
+          "Wrong number of arguments, expected 1, but got " + args.length);
+    }
+    Boolean hasNext;
+    if (args[0] instanceof Boolean) {
+      hasNext = (Boolean) args[0];
+    } else if (args[0] instanceof String) {
+      hasNext = Boolean.valueOf((String) args[0]);
+    } else {
+      throw new PlcRuntimeException(
+          "Argument 0 expected to be of type Boolean or a string which is parseable but was "
+              + args[0].getClass().getName());
+    }
+    return staticParse(readBuffer, hasNext);
   }
 
-  public static S7VarPayloadDataItem staticParse(ReadBuffer readBuffer) throws ParseException {
+  public static S7VarPayloadDataItem staticParse(ReadBuffer readBuffer, Boolean hasNext)
+      throws ParseException {
     readBuffer.pullContext("S7VarPayloadDataItem");
     PositionAware positionAware = readBuffer;
     int startPos = positionAware.getPos();
@@ -174,12 +199,12 @@ public class S7VarPayloadDataItem implements Message {
             Math.toIntExact(
                 ((transportSize.getSizeInBits()) ? CEIL((dataLength) / (8.0)) : dataLength)));
 
-    readPaddingField(readUnsignedShort(readBuffer, 8), (int) ((COUNT(data)) % (2)));
+    readPaddingField(readUnsignedShort(readBuffer, 8), (int) (((PADCOUNT(data, hasNext)) % (2))));
 
     readBuffer.closeContext("S7VarPayloadDataItem");
     // Create the instance
     S7VarPayloadDataItem _s7VarPayloadDataItem;
-    _s7VarPayloadDataItem = new S7VarPayloadDataItem(returnCode, transportSize, data);
+    _s7VarPayloadDataItem = new S7VarPayloadDataItem(returnCode, transportSize, data, hasNext);
     return _s7VarPayloadDataItem;
   }
 
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 f36a06cd5f..9e7f790e49 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
@@ -324,12 +324,29 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
         DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
         List<S7VarRequestParameterItem> parameterItems = new ArrayList<>(request.getNumberOfTags());
         List<S7VarPayloadDataItem> payloadItems = new ArrayList<>(request.getNumberOfTags());
-        for (String tagName : request.getTagNames()) {
+
+        Iterator<String> iter = request.getTagNames().iterator();
+        
+        String tagName = null;
+        while(iter.hasNext()) {
+            tagName = iter.next();
             final S7Tag tag = (S7Tag) request.getTag(tagName);
             final PlcValue plcValue = request.getPlcValue(tagName);
             parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(tag)));
-            payloadItems.add(serializePlcValue(tag, plcValue));
+            payloadItems.add(serializePlcValue(tag, plcValue, iter.hasNext()));            
         }
+        
+        
+//        for (String tagName : request.getTagNames()) {
+//            final S7Tag tag = (S7Tag) request.getTag(tagName);
+//            final PlcValue plcValue = request.getPlcValue(tagName);
+//            parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(tag)));
+//            payloadItems.add(serializePlcValue(tag, plcValue));
+//
+//        }
+        
+        
+        
         final int tpduId = tpduGenerator.getAndIncrement();
         // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
         if (tpduGenerator.get() == 0xFFFF) {
@@ -347,7 +364,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
                 (short) tpduId
             )
         );
-
+        
         // Start a new request-transaction (Is ended in the response-handler)
         RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
         transaction.submit(() -> context.sendRequest(tpktPacket)
@@ -897,7 +914,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
         return new DefaultPlcWriteResponse(plcWriteRequest, responses);
     }
 
-    private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue) {
+    private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue, Boolean hasNext) {
         try {
             DataTransportSize transportSize = tag.getDataType().getDataTransportSize();
             int stringLength = (tag instanceof S7StringTag) ? ((S7StringTag) tag).getStringLength() : 254;
@@ -914,7 +931,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
             }
             if (byteBuffer != null) {
                 byte[] data = byteBuffer.array();
-                return new S7VarPayloadDataItem(DataTransportErrorCode.OK, transportSize, data);
+                return new S7VarPayloadDataItem(DataTransportErrorCode.OK, transportSize, data, hasNext);
             }
         } catch (SerializationException e) {
             logger.warn("Error serializing tag item of type: '{}'", tag.getDataType().name(), e);
diff --git a/plc4j/drivers/s7/src/test/java/S7IoTest.java b/plc4j/drivers/s7/src/test/java/S7IoTest.java
index 2c23628e3d..86d3639c76 100644
--- a/plc4j/drivers/s7/src/test/java/S7IoTest.java
+++ b/plc4j/drivers/s7/src/test/java/S7IoTest.java
@@ -340,7 +340,8 @@ public class S7IoTest {
                             new S7VarPayloadDataItem(
                                 DataTransportErrorCode.OK,
                                 DataTransportSize.BIT,
-                                new byte[]{0x1}
+                                new byte[]{0x1},
+                                    false
                             )
                         )
                     ),
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
index 60e0fccd31..93883498a9 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
@@ -121,5 +121,9 @@ public class StaticHelper {
     public static int CEIL(double value) {
         return (int) Math.ceil(value);
     }
+    
+    public static int PADCOUNT(Object obj, boolean hasNext) {
+        return hasNext ? COUNT(obj) : 0;
+    }    
 
 }
diff --git a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
index d50501e822..c10e27659c 100644
--- a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
+++ b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
@@ -254,7 +254,7 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                                     final byte bitAddress = addressAny.getBitAddress();
                                                     switch (addressAny.getTransportSize()) {
                                                         case BOOL:
-                                                            payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BIT, new byte[]{1}));
+                                                            payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BIT, new byte[]{1}, true));
                                                             break;
                                                         case INT:
                                                         case UINT: {
@@ -264,7 +264,7 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                                             byte[] data = new byte[2];
                                                             data[1] = (byte) (shortValue & 0xff);
                                                             data[0] = (byte) ((shortValue >> 8) & 0xff);
-                                                            payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, data));
+                                                            payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, data, true));
                                                             break;
                                                         }
                                                         default: {
@@ -280,7 +280,7 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                                         addressAny.getNumberOfElements() : addressAny.getTransportSize().getSizeInBytes() * 8;
                                                     final BitSet bitSet = toBitSet(context.getDigitalInputs(), ioNumber, numElements);
                                                     final byte[] data = Arrays.copyOf(bitSet.toByteArray(), (numElements + 7) / 8);
-                                                    payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, data));
+                                                    payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, data, true));
                                                     break;
                                                 }
                                             }
diff --git a/protocols/s7/src/main/resources/protocols/s7/s7.mspec b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
index 33f3ccb79c..de32c36dbe 100644
--- a/protocols/s7/src/main/resources/protocols/s7/s7.mspec
+++ b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
@@ -1,4 +1,4 @@
-/*
+'/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -223,7 +223,7 @@
 [discriminatedType S7Payload (uint 8 messageType, S7Parameter parameter)
     [typeSwitch parameter.parameterType, messageType
         ['0x04','0x03' S7PayloadReadVarResponse
-            [array S7VarPayloadDataItem items count 'CAST(parameter, "S7ParameterReadVarResponse").numItems']
+            [array S7VarPayloadDataItem ('true') items count 'CAST(parameter, "S7ParameterReadVarResponse").numItems']
         ]
         ['0x05','0x01' S7PayloadWriteVarRequest
             [array S7VarPayloadDataItem items count 'COUNT(CAST(parameter, "S7ParameterWriteVarRequest").items)']
@@ -238,12 +238,15 @@
 ]
 
 // This is actually not quite correct as depending pon the transportSize the length is either defined in bits or bytes.
-[type S7VarPayloadDataItem
+//@param hasNext In the serialization process, if you have multiple write
+//               requests the last element does not require padding.
+[type S7VarPayloadDataItem(bit hasNext)
     [simple   DataTransportErrorCode returnCode]
     [simple   DataTransportSize      transportSize]
     [implicit uint 16                dataLength 'COUNT(data) * ((transportSize == DataTransportSize.BIT) ? 1 : (transportSize.sizeInBits ? 8 : 1))']
     [array    byte                   data       count 'transportSize.sizeInBits ? CEIL(dataLength / 8.0) : dataLength']
-    [padding  uint 8                 pad        '0x00' 'COUNT(data) % 2']
+    //[padding  uint 8                 pad        '0x00' '(COUNT(data) % 2)']
+    [padding  uint 8                 pad        '0x00' '(PADCOUNT(data, hasNext) % 2)']
 ]
 
 [type S7VarPayloadStatusItem