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 2024/02/10 09:50:57 UTC

(plc4x) 03/03: fix: Fixed one of the problems when writing structs (Some times some leading padding bytes were needed) However there still seems to be an issue with writing WSTRINGs

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

cdutz pushed a commit to branch fix/enum-discriminators
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit bf3517f2f39a7bd79e77d57c372def5795c70eb6
Author: Christofer Dutz <cd...@apache.org>
AuthorDate: Sat Feb 10 10:50:34 2024 +0100

    fix: Fixed one of the problems when writing structs (Some times some leading padding bytes were needed) However there still seems to be an issue with writing WSTRINGs
---
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  |  17 +++
 .../internal/handlers/ApiRequestHandler.java       | 144 ++++++++++++++++-
 .../resources/protocols/ads/DriverTestsuite.xml    | 170 ++++++++++++++++++++-
 3 files changed, 323 insertions(+), 8 deletions(-)

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 e66dd8b68d..ec16551b48 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
@@ -883,12 +883,15 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                 int startPos = readBuffer.getPos();
                 int curPos = 0;
                 for (AdsDataTypeTableChildEntry child : adsDataTypeTableEntry.getChildren()) {
+                    // In some cases the starting position of the data is not where we are expecting it.
+                    // So we need to skip some bytes.
                     if (child.getOffset() > curPos) {
                         long skipBytes = child.getOffset() - curPos;
                         for (long i = 0; i < skipBytes; i++) {
                             readBuffer.readByte();
                         }
                     }
+
                     String propertyName = child.getPropertyName();
                     AdsDataTypeTableEntry propertyDataTypeTableEntry = dataTypeTable.get(child.getDataTypeName());
                     PlcValueType propertyPlcValueType = getPlcValueTypeForAdsDataType(propertyDataTypeTableEntry);
@@ -900,6 +903,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                     }
                     PlcValue propertyValue = parsePlcValue(propertyPlcValueType, propertyDataTypeTableEntry, strLen, readBuffer);
                     properties.put(propertyName, propertyValue);
+
                     curPos = readBuffer.getPos() - startPos;
                 }
                 return new PlcStruct(properties);
@@ -1151,13 +1155,26 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                 throw new SerializationException("Expected a PlcStruct, but got a " + contextValue.getPlcValueType().name());
             }
             PlcStruct plcStruct = (PlcStruct) contextValue;
+            int startPos = writeBuffer.getPos();
+            int curPos = 0;
             for (AdsDataTypeTableChildEntry child : dataType.getChildren()) {
                 AdsDataTypeTableEntry childDataType = dataTypeTable.get(child.getDataTypeName());
                 if (!plcStruct.hasKey(child.getPropertyName())) {
                     throw new SerializationException("PlcStruct is missing a child with the name " + child.getPropertyName());
                 }
+                // In some cases the starting position of the data is not where we are expecting it.
+                // So we need to add some fill-bytes.
+                if (child.getOffset() > curPos) {
+                    long fillBytes = child.getOffset() - curPos;
+                    for(long i = 0; i < fillBytes; i++) {
+                        writeBuffer.writeByte("fillByte", (byte) 0x00);
+                    }
+                }
+
                 PlcValue childValue = plcStruct.getValue(child.getPropertyName());
                 serializeInternal(childValue, childDataType, childDataType.getArrayInfo(), writeBuffer);
+
+                curPos = writeBuffer.getPos() - startPos;
             }
         }
 
diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/handlers/ApiRequestHandler.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/handlers/ApiRequestHandler.java
index b3616289fa..764fbb8454 100644
--- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/handlers/ApiRequestHandler.java
+++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/handlers/ApiRequestHandler.java
@@ -23,12 +23,17 @@ import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.spi.values.*;
 import org.apache.plc4x.test.driver.exceptions.DriverTestsuiteException;
 import org.apache.plc4x.test.driver.internal.utils.Synchronizer;
 import org.dom4j.Element;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.*;
 
 public class ApiRequestHandler {
 
@@ -67,12 +72,21 @@ public class ApiRequestHandler {
                 if (payload.element("tags") != null) {
                     for (Element tagElement : payload.element("tags").elements("tag")) {
                         List<Element> valueElements = tagElement.elements("value");
-                        List<String> valueStrings = new ArrayList<>(valueElements.size());
+                        List<Object> valueObjects = new ArrayList<>(valueElements.size());
                         for (Element valueElement : valueElements) {
-                            valueStrings.add(valueElement.getTextTrim());
+                            // If the element is a simple text element, use this driectly.
+                            if(valueElement.isTextOnly()) {
+                                valueObjects.add(valueElement.getTextTrim());
+                            }
+                            // If the value is a "PlcValue" element, try to parse this.
+                            else if (valueElement.elements() != null) {
+                                for (Element element : valueElement.elements()) {
+                                    valueObjects.add(parsePlcValue(element));
+                                }
+                            }
                         }
                         builder.addTagAddress(tagElement.elementText("name"),
-                            tagElement.elementText("address"), valueStrings.toArray(new Object[0]));
+                            tagElement.elementText("address"), valueObjects.toArray(new Object[0]));
                     }
                 }
                 final PlcWriteRequest plc4xRequest = builder.build();
@@ -94,4 +108,124 @@ public class ApiRequestHandler {
         }
     }
 
+    protected PlcValue parsePlcValue(Element element) {
+        switch (element.getName()) {
+            case "PlcStruct": {
+                Map<String, PlcValue> structContent = new LinkedHashMap<>();
+                for (Element field : element.elements()) {
+                    String fieldName = field.getName();
+                    if((field.elements() == null) || (field.elements().size() != 1)) {
+                        throw new RuntimeException("Expected exactly one child element");
+                    }
+                    Element valueElement = field.elements().get(0);
+                    PlcValue fieldValue = parsePlcValue(valueElement);
+                    structContent.put(fieldName, fieldValue);
+                }
+                return new PlcStruct(structContent);
+            }
+            case "PlcList": {
+                // TODO: Implement this ...
+            }
+            case "PlcNULL": {
+                return new PlcNull();
+            }
+
+            case "PlcBOOL": {
+                return new PlcBOOL(element.getTextTrim());
+            }
+            case "PlcBYTE": {
+                return new PlcBYTE(element.getTextTrim());
+            }
+            case "PlcWORD": {
+                return new PlcWORD(element.getTextTrim());
+            }
+            case "PlcDWORD": {
+                return new PlcDWORD(element.getTextTrim());
+            }
+            case "PlcLWORD": {
+                return new PlcLWORD(element.getTextTrim());
+            }
+
+            case "PlcUSINT": {
+                return new PlcUSINT(element.getTextTrim());
+            }
+            case "PlcUINT": {
+                return new PlcUINT(element.getTextTrim());
+            }
+            case "PlcUDINT": {
+                return new PlcUDINT(element.getTextTrim());
+            }
+            case "PlcULINT": {
+                return new PlcULINT(element.getTextTrim());
+            }
+
+            case "PlcSINT": {
+                return new PlcSINT(element.getTextTrim());
+            }
+            case "PlcINT": {
+                return new PlcINT(element.getTextTrim());
+            }
+            case "PlcDINT": {
+                return new PlcDINT(element.getTextTrim());
+            }
+            case "PlcLINT": {
+                return new PlcLINT(element.getTextTrim());
+            }
+
+            case "PlcREAL": {
+                return new PlcREAL(element.getTextTrim());
+            }
+            case "PlcLREAL": {
+                return new PlcLREAL(element.getTextTrim());
+            }
+
+            case "PlcCHAR": {
+                return new PlcCHAR(element.getTextTrim());
+            }
+            case "PlcWCHAR": {
+                return new PlcWCHAR(element.getTextTrim());
+            }
+            case "PlcSTRING": {
+                return new PlcSTRING(element.getTextTrim());
+            }
+            case "PlcWSTRING": {
+                return new PlcWSTRING(element.getTextTrim());
+            }
+
+            case "PlcTIME": {
+                long milliseconds = Long.parseLong(element.getTextTrim());
+                return new PlcTIME(milliseconds);
+            }
+            case "PlcLTIME": {
+                return new PlcLTIME(Duration.parse(element.getTextTrim()));
+            }
+            case "PlcDATE": {
+                return new PlcDATE(LocalDate.parse(element.getTextTrim()));
+            }
+            case "PlcLDATE": {
+                return new PlcLDATE(LocalDate.parse(element.getTextTrim()));
+            }
+            case "PlcTIME_OF_DAY": {
+                return new PlcTIME_OF_DAY(LocalTime.parse(element.getTextTrim()));
+            }
+            case "PlcLTIME_OF_DAY": {
+                return new PlcLTIME_OF_DAY(LocalTime.parse(element.getTextTrim()));
+            }
+            case "PlcDATE_AND_TIME": {
+                return new PlcDATE_AND_TIME(LocalDateTime.parse(element.getTextTrim()));
+            }
+            case "PlcDATE_AND_LTIME": {
+                return new PlcDATE_AND_LTIME(LocalDateTime.parse(element.getTextTrim()));
+            }
+            case "PlcLDATE_AND_TIME": {
+                return new PlcLDATE_AND_TIME(LocalDateTime.parse(element.getTextTrim()));
+            }
+
+            /*case "PlcRAW_BYTE_ARRAY": {
+                return new PlcRAW_BYTE_ARRAY(element.getTextTrim());
+            }*/
+            default: throw new RuntimeException("Unsupported type of PlcValue " + element.getName());
+        }
+    }
+
 }
diff --git a/protocols/ads/src/test/resources/protocols/ads/DriverTestsuite.xml b/protocols/ads/src/test/resources/protocols/ads/DriverTestsuite.xml
index 011ba553f2..cc73c96910 100644
--- a/protocols/ads/src/test/resources/protocols/ads/DriverTestsuite.xml
+++ b/protocols/ads/src/test/resources/protocols/ads/DriverTestsuite.xml
@@ -1143,6 +1143,100 @@
           </userdata>
         </AmsTCPPacket>
       </incoming-plc-message>
+      <api-response name="Report Read Response to application">
+        <PlcReadResponse>
+          <request>
+            <PlcReadRequest>
+              <PlcTagRequest>
+                <tags isList="true">
+                  <hurz>
+                    <SymbolicAdsTag>
+                      <symbolicAddress dataType="string" bitLength="128" encoding="UTF-8">MAIN.hurz_Struct</symbolicAddress>
+                    </SymbolicAdsTag>
+                  </hurz>
+                </tags>
+              </PlcTagRequest>
+            </PlcReadRequest>
+          </request>
+          <values isList="true">
+            <hurz>
+              <ResponseItem>
+                <code dataType="string" bitLength="16" encoding="UTF-8">OK</code>
+                <value>
+                  <PlcStruct>
+                    <hurz_STRING>
+                      <PlcSTRING dataType="string" bitLength="32" encoding="UTF-8">hurz</PlcSTRING>
+                    </hurz_STRING>
+                    <hurz_LTIME>
+                      <PlcLTIME dataType="string" bitLength="192" encoding="UTF-8">PT24015H23M12.034002044S</PlcLTIME>
+                    </hurz_LTIME>
+                    <hurz_LWORD>
+                      <PlcLWORD dataType="int" bitLength="64">4</PlcLWORD>
+                    </hurz_LWORD>
+                    <hurz_REAL>
+                      <PlcREAL dataType="float" bitLength="32">13.0</PlcREAL>
+                    </hurz_REAL>
+                    <hurz_ULINT>
+                      <PlcULINT dataType="int" bitLength="64">12</PlcULINT>
+                    </hurz_ULINT>
+                    <hurz_WSTRING>
+                      <PlcWSTRING dataType="string" bitLength="80" encoding="UTF-8">wolf</PlcWSTRING>
+                    </hurz_WSTRING>
+                    <hurz_LINT>
+                      <PlcLINT dataType="int" bitLength="64">11</PlcLINT>
+                    </hurz_LINT>
+                    <hurz_DATE_AND_TIME>
+                      <PlcDATE_AND_TIME dataType="string" bitLength="152" encoding="UTF-8">1996-05-06T15:36:30</PlcDATE_AND_TIME>
+                    </hurz_DATE_AND_TIME>
+                    <hurz_UINT>
+                      <PlcUINT dataType="int" bitLength="16">8</PlcUINT>
+                    </hurz_UINT>
+                    <hurz_SINT>
+                      <PlcSINT dataType="int" bitLength="8">5</PlcSINT>
+                    </hurz_SINT>
+                    <hurz_USINT>
+                      <PlcUSINT dataType="int" bitLength="8">6</PlcUSINT>
+                    </hurz_USINT>
+                    <hurz_LREAL>
+                      <PlcLREAL dataType="float" bitLength="64">14.0</PlcLREAL>
+                    </hurz_LREAL>
+                    <hurz_TIME_OF_DAY>
+                      <PlcTIME_OF_DAY dataType="string" bitLength="96" encoding="UTF-8">15:36:30.123</PlcTIME_OF_DAY>
+                    </hurz_TIME_OF_DAY>
+                    <hurz_BOOL>
+                      <PlcBOOL dataType="bit" bitLength="1">true</PlcBOOL>
+                    </hurz_BOOL>
+                    <hurz_DINT>
+                      <PlcDINT dataType="int" bitLength="32">9</PlcDINT>
+                    </hurz_DINT>
+                    <hurz_UDINT>
+                      <PlcUDINT dataType="int" bitLength="32">10</PlcUDINT>
+                    </hurz_UDINT>
+                    <hurz_BYTE>
+                      <PlcBYTE dataType="int" bitLength="8">1</PlcBYTE>
+                    </hurz_BYTE>
+                    <hurz_TIME>
+                      <PlcTIME dataType="int" bitLength="32">1234</PlcTIME>
+                    </hurz_TIME>
+                    <hurz_DWORD>
+                      <PlcDWORD dataType="int" bitLength="32">3</PlcDWORD>
+                    </hurz_DWORD>
+                    <hurz_INT>
+                      <PlcINT dataType="int" bitLength="16">7</PlcINT>
+                    </hurz_INT>
+                    <hurz_WORD>
+                      <PlcWORD dataType="int" bitLength="16">2</PlcWORD>
+                    </hurz_WORD>
+                    <hurz_DATE>
+                      <PlcDATE dataType="string" bitLength="80" encoding="UTF-8">1978-03-28</PlcDATE>
+                    </hurz_DATE>
+                  </PlcStruct>
+                </value>
+              </ResponseItem>
+            </hurz>
+          </values>
+        </PlcReadResponse>
+      </api-response>
     </steps>
   </testcase>
 
@@ -1150,14 +1244,84 @@
     <name>Single element write request for "Struct" type field</name>
     <steps>
       <api-request name="Receive Write Request from application">
-        <TestReadRequest>
+        <TestWriteRequest>
           <tags isList="true">
-            <tag className="org.apache.plc4x.test.driver.internal.api.TestTag">
+            <tag className="org.apache.plc4x.test.driver.internal.api.TestValueTag">
               <name>hurz</name>
               <address>MAIN.hurz_Struct</address>
+              <value>
+                <PlcStruct>
+                  <hurz_STRING>
+                    <PlcSTRING dataType="string" bitLength="32" encoding="UTF-8">hurz</PlcSTRING>
+                  </hurz_STRING>
+                  <hurz_LTIME>
+                    <PlcLTIME dataType="string" bitLength="192" encoding="UTF-8">PT24015H23M12.034002044S</PlcLTIME>
+                  </hurz_LTIME>
+                  <hurz_LWORD>
+                    <PlcLWORD dataType="int" bitLength="64">4</PlcLWORD>
+                  </hurz_LWORD>
+                  <hurz_REAL>
+                    <PlcREAL dataType="float" bitLength="32">13.0</PlcREAL>
+                  </hurz_REAL>
+                  <hurz_ULINT>
+                    <PlcULINT dataType="int" bitLength="64">12</PlcULINT>
+                  </hurz_ULINT>
+                  <hurz_WSTRING>
+                    <PlcWSTRING dataType="string" bitLength="80" encoding="UTF-8">wolf</PlcWSTRING>
+                  </hurz_WSTRING>
+                  <hurz_LINT>
+                    <PlcLINT dataType="int" bitLength="64">11</PlcLINT>
+                  </hurz_LINT>
+                  <hurz_DATE_AND_TIME>
+                    <PlcDATE_AND_TIME dataType="string" bitLength="152" encoding="UTF-8">1996-05-06T15:36:30</PlcDATE_AND_TIME>
+                  </hurz_DATE_AND_TIME>
+                  <hurz_UINT>
+                    <PlcUINT dataType="int" bitLength="16">8</PlcUINT>
+                  </hurz_UINT>
+                  <hurz_SINT>
+                    <PlcSINT dataType="int" bitLength="8">5</PlcSINT>
+                  </hurz_SINT>
+                  <hurz_USINT>
+                    <PlcUSINT dataType="int" bitLength="8">6</PlcUSINT>
+                  </hurz_USINT>
+                  <hurz_LREAL>
+                    <PlcLREAL dataType="float" bitLength="64">14.0</PlcLREAL>
+                  </hurz_LREAL>
+                  <hurz_TIME_OF_DAY>
+                    <PlcTIME_OF_DAY dataType="string" bitLength="96" encoding="UTF-8">15:36:30.123</PlcTIME_OF_DAY>
+                  </hurz_TIME_OF_DAY>
+                  <hurz_BOOL>
+                    <PlcBOOL dataType="bit" bitLength="1">true</PlcBOOL>
+                  </hurz_BOOL>
+                  <hurz_DINT>
+                    <PlcDINT dataType="int" bitLength="32">9</PlcDINT>
+                  </hurz_DINT>
+                  <hurz_UDINT>
+                    <PlcUDINT dataType="int" bitLength="32">10</PlcUDINT>
+                  </hurz_UDINT>
+                  <hurz_BYTE>
+                    <PlcBYTE dataType="int" bitLength="8">1</PlcBYTE>
+                  </hurz_BYTE>
+                  <hurz_TIME>
+                    <PlcTIME dataType="int" bitLength="32">1234</PlcTIME>
+                  </hurz_TIME>
+                  <hurz_DWORD>
+                    <PlcDWORD dataType="int" bitLength="32">3</PlcDWORD>
+                  </hurz_DWORD>
+                  <hurz_INT>
+                    <PlcINT dataType="int" bitLength="16">7</PlcINT>
+                  </hurz_INT>
+                  <hurz_WORD>
+                    <PlcWORD dataType="int" bitLength="16">2</PlcWORD>
+                  </hurz_WORD>
+                  <hurz_DATE>
+                    <PlcDATE dataType="string" bitLength="80" encoding="UTF-8">1978-03-28</PlcDATE>
+                  </hurz_DATE>
+                </PlcStruct>
+              </value>
             </tag>
           </tags>
-        </TestReadRequest>
+        </TestWriteRequest>
       </api-request>
       <outgoing-plc-message name="Send Ads Write Request">
         <AmsTCPPacket>