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

cdutz pushed a commit to branch feature/implement-df1-driver
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 376101d1ef939b3d1e191b4c5d467117af596b3a
Author: Christofer Dutz <[email protected]>
AuthorDate: Wed Aug 7 16:26:29 2019 +0200

    - Simplified the mspec for the DF1 protocol
    - Added a "terminated" type of arrayField
    - Made the ReadBuffer endianness aware
    - Made the testsuite endianness aware
---
 .../language/java/JavaLanguageTemplateHelper.java  |  58 ++++++++-
 .../main/resources/templates/java/io-template.ftlh |  62 +++++++---
 .../plugins/codegenerator/language/mspec/MSpec.g4  |   2 +
 .../mspec/model/fields/DefaultArrayField.java      |   5 -
 .../mspec/parser/MessageFormatListener.java        |   6 +-
 plc4j/examples/hello-world-plc4x/pom.xml           |   1 +
 .../org/apache/plc4x/java/utils/ReadBuffer.java    |  39 ++++++-
 .../org/apache/plc4x/java/utils/WriteBuffer.java   |   8 +-
 .../protocol/test/ProtocolTestsuiteRunner.java     |  14 +--
 .../protocol/test/model/ProtocolTestsuite.java     |   8 +-
 .../src/main/resources/schemas/testsuite.xsd       |   1 +
 .../main/resources/protocols/df1/protocol.mspec    |  43 +++----
 sandbox/test-java-df1-driver/pom.xml               |  31 ++++-
 .../plc4x/java/df1/protocol/Df1Protocol.java       |  16 +--
 .../org/apache/plc4x/java/df1/util/DF1Utils.java   | 129 +++++++++++++++++++++
 .../org/apache/plc4x/protocol/df1/DF1Utils.java    |  84 --------------
 .../plc4x/protocol/df1/BenchmarkGeneratedDf1.java  |   7 +-
 .../plc4x/protocol/df1/BenchmarkManualDf1.java     |   1 -
 .../org/apache/plc4x/protocol/df1/Df1Test.java     |  30 +++++
 .../apache/plc4x/protocol/df1/EndToEndTest.java    |   3 +-
 .../java/org/apache/plc4x/protocol/df1/IOTest.java |  99 ++++++++++++++++
 .../src/test/resources/testsuite/Df1Testsuite.xml  |  81 +++++++++++++
 22 files changed, 554 insertions(+), 174 deletions(-)

diff --git 
a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
 
b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index bf293a6..034a690 100644
--- 
a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ 
b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -376,6 +376,14 @@ public class JavaLanguageTemplateHelper implements 
FreemarkerLanguageTemplateHel
         return arrayField.getLengthType() == ArrayField.LengthType.COUNT;
     }
 
+    public boolean isLengthArray(ArrayField arrayField) {
+        return arrayField.getLengthType() == ArrayField.LengthType.LENGTH;
+    }
+
+    public boolean isTerminatedArray(ArrayField arrayField) {
+        return arrayField.getLengthType() == ArrayField.LengthType.TERMINATED;
+    }
+
     public String toSwitchExpression(String expression) {
         StringBuilder sb = new StringBuilder();
         Pattern pattern = Pattern.compile("([^\\.]*)\\.([a-zA-Z\\d]+)(.*)");
@@ -390,8 +398,8 @@ public class JavaLanguageTemplateHelper implements 
FreemarkerLanguageTemplateHel
         return sb.toString();
     }
 
-    public String toDeserializationExpression(Term term) {
-        return toExpression(term, this::toVariableDeserializationExpression);
+    public String toDeserializationExpression(Term term, Argument[] 
parserArguments) {
+        return toExpression(term, term1 -> 
toVariableDeserializationExpression(term1, parserArguments));
     }
 
     public String toSerializationExpression(Term term, Argument[] 
parserArguments) {
@@ -450,7 +458,7 @@ public class JavaLanguageTemplateHelper implements 
FreemarkerLanguageTemplateHel
         }
     }
 
-    private String toVariableDeserializationExpression(Term term) {
+    private String toVariableDeserializationExpression(Term term, Argument[] 
parserArguments) {
         VariableLiteral vl = (VariableLiteral) term;
         // CAST expressions are special as we need to add a ".class" to the 
second parameter in Java.
         if("CAST".equals(vl.getName())) {
@@ -458,10 +466,47 @@ public class JavaLanguageTemplateHelper implements 
FreemarkerLanguageTemplateHel
             if((vl.getArgs() == null) || (vl.getArgs().size() != 2)) {
                 throw new RuntimeException("A CAST expression expects exactly 
two arguments.");
             }
-            
sb.append("(").append(toVariableDeserializationExpression(vl.getArgs().get(0)))
+            
sb.append("(").append(toVariableDeserializationExpression(vl.getArgs().get(0), 
parserArguments))
                 .append(", ").append(((VariableLiteral) 
vl.getArgs().get(1)).getName()).append(".class)");
             return sb.toString() + ((vl.getChild() != null) ? "." + 
toVariableExpressionRest(vl.getChild()) : "");
         }
+        else if("STATIC_CALL".equals(vl.getName())) {
+            StringBuilder sb = new StringBuilder();
+            if(!(vl.getArgs().get(0) instanceof StringLiteral)) {
+                throw new RuntimeException("Expecting the first argument of a 
'STATIC_CALL' to be a StringLiteral");
+            }
+            String methodName = ((StringLiteral) 
vl.getArgs().get(0)).getValue();
+            methodName = methodName.substring(1, methodName.length() - 1);
+            sb.append(methodName).append("(");
+            for(int i = 1; i < vl.getArgs().size(); i++) {
+                Term arg = vl.getArgs().get(i);
+                if(i > 1) {
+                    sb.append(", ");
+                }
+                if(arg instanceof VariableLiteral) {
+                    VariableLiteral va = (VariableLiteral) arg;
+                    // "io" is the default name of the reader argument which 
is always available.
+                    boolean isDeserializerArg = "io".equals(va.getName());
+                    if(parserArguments != null) {
+                        for (Argument parserArgument : parserArguments) {
+                            if (parserArgument.getName().equals(va.getName())) 
{
+                                isDeserializerArg = true;
+                                break;
+                            }
+                        }
+                    }
+                    if(isDeserializerArg) {
+                        sb.append(va.getName() + ((va.getChild() != null) ? 
"." + toVariableExpressionRest(va.getChild()) : ""));
+                    } else {
+                        sb.append(toVariableDeserializationExpression(va, 
null));
+                    }
+                } else if(arg instanceof StringLiteral) {
+                    sb.append(((StringLiteral) arg).getValue());
+                }
+            }
+            sb.append(")");
+            return sb.toString();
+        }
         // All uppercase names are not fields, but utility methods.
         else if(vl.getName().equals(vl.getName().toUpperCase())) {
             StringBuilder sb = new StringBuilder(vl.getName());
@@ -472,7 +517,7 @@ public class JavaLanguageTemplateHelper implements 
FreemarkerLanguageTemplateHel
                     if(!firstArg) {
                         sb.append(", ");
                     }
-                    sb.append(toVariableDeserializationExpression(arg));
+                    sb.append(toVariableDeserializationExpression(arg, 
parserArguments));
                     firstArg = false;
                 }
                 sb.append(")");
@@ -499,7 +544,8 @@ public class JavaLanguageTemplateHelper implements 
FreemarkerLanguageTemplateHel
                 }
                 if(arg instanceof VariableLiteral) {
                     VariableLiteral va = (VariableLiteral) arg;
-                    boolean isSerializerArg = false;
+                    // "io" and "value" are always available in every parser.
+                    boolean isSerializerArg = "io".equals(va.getName()) || 
"value".equals(va.getName());
                     if(parserArguments != null) {
                         for (Argument parserArgument : parserArguments) {
                             if (parserArgument.getName().equals(va.getName())) 
{
diff --git 
a/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh 
b/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
index 33d0696..82a8056 100644
--- 
a/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
+++ 
b/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
@@ -78,32 +78,59 @@ public class ${typeName}IO implements 
MessageIO<${typeName}<#if helper.isDiscrim
     <#case "array">
 
         // Array field
+        <#-- Only update curPos if the length expression uses it -->
         <#if field.lengthExpression.contains("curPos")>
         curPos = io.getPos() - startPos;
         </#if>
-        int ${field.name}Size = 
${helper.toDeserializationExpression(field.lengthExpression)};
+        <#-- If this is a count array, we can directly initialize an array 
with the given size -->
         <#if helper.isCountArray(field)>
-        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = new 
${helper.getLanguageTypeNameForField(field)}[${field.name}Size];
-        for(int i = 0; i < ${field.name}Size; i++) {
+        // Count array
+        int _${field.name}Count = 
${helper.toDeserializationExpression(field.lengthExpression, 
type.parserArguments)};
+        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = new 
${helper.getLanguageTypeNameForField(field)}[_${field.name}Count];
+        for(int i = 0; i < _${field.name}Count; i++) {
             ${field.name}[i] = <#if 
helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name?uncap_first}IO.parse(io<#if
 field.params?has_content>, <#list field.params as 
parserArgument>${parserArgument}<#sep>, </#sep></#list></#if>)</#if>;
         }
+        <#-- In all other cases do we have to work with a list, that is later 
converted to an array -->
         <#else>
-        List<${helper.getNonPrimitiveLanguageTypeNameForField(field)}> 
${field.name}List = <#if helper.isCountArray(field)>new 
ArrayList<>(size)<#else>new LinkedList<>()</#if>;
-        int ${field.name}EndPos = io.getPos() + ${field.name}Size;
+            <#-- For a length array, we read data till the read position of 
the buffer reaches a given position -->
+            <#if helper.isLengthArray(field)>
+        // Length array
+        int _${field.name}Length = 
${helper.toDeserializationExpression(field.lengthExpression, 
type.parserArguments)};
+        List<${helper.getNonPrimitiveLanguageTypeNameForField(field)}> 
_${field.name}List = new LinkedList<>();
+        int ${field.name}EndPos = io.getPos() + _${field.name}Length;
         while(io.getPos() < ${field.name}EndPos) {
+            _${field.name}List.add(<#if 
helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name?uncap_first}IO.parse(io<#if
 field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getArgumentType(field.type, parserArgument?index)}) 
(${helper.toDeserializationExpression(parserArgument, 
type.parserArguments)})<#sep>, </#sep></#list></#if>)</#if>);
+            <#-- After parsing, update the current position, but only if it's 
needed -->
             <#if field.lengthExpression.contains("curPos")>
             curPos = io.getPos() - startPos;
             </#if>
-            ${field.name}List.add(<#if 
helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name?uncap_first}IO.parse(io<#if
 field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getArgumentType(field.type, parserArgument?index)}) 
(${helper.toDeserializationExpression(parserArgument)})<#sep>, 
</#sep></#list></#if>)</#if>);
         }
-        <#if helper.isSimpleType(field.type)>
-        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = new 
${helper.getLanguageTypeNameForField(field)}[${field.name}List.size()];
-        for(int i = 0; i < ${field.name}List.size(); i++) {
-            ${field.name}[i] = (${helper.getLanguageTypeNameForField(field)}) 
${field.name}List.get(i);
+            <#-- A terminated array keeps on reading data as long as the 
termination expression evaluates to false -->
+            <#elseif helper.isTerminatedArray(field)>
+        // Terminated array
+        List<${helper.getNonPrimitiveLanguageTypeNameForField(field)}> 
_${field.name}List = new LinkedList<>();
+        while(!((boolean) 
(${helper.toDeserializationExpression(field.lengthExpression, 
type.parserArguments)}))) {
+            _${field.name}List.add(<#if 
helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name?uncap_first}IO.parse(io<#if
 field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getArgumentType(field.type, parserArgument?index)}) 
(${helper.toDeserializationExpression(parserArgument, 
type.parserArguments)})<#sep>, </#sep></#list></#if>)</#if>);
+
+            <#-- After parsing, update the current position, but only if it's 
needed -->
+            <#if field.lengthExpression.contains("curPos")>
+            curPos = io.getPos() - startPos;
+            </#if>
         }
-        <#else>
-        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = 
${field.name}List.toArray(new 
${helper.getNonPrimitiveLanguageTypeNameForField(field)}[0]);
-        </#if>
+            </#if>
+            <#--
+                Convert the list into an array. However if the array is of a 
primitive
+                type we have to iterate over it's elements and explicitly cast 
them.
+                Otherwise a simple toArray call is fine.
+            -->
+            <#if helper.isSimpleType(field.type)>
+        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = new 
${helper.getLanguageTypeNameForField(field)}[_${field.name}List.size()];
+        for(int i = 0; i < _${field.name}List.size(); i++) {
+            ${field.name}[i] = (${helper.getLanguageTypeNameForField(field)}) 
_${field.name}List.get(i);
+        }
+            <#else>
+        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = 
_${field.name}List.toArray(new 
${helper.getNonPrimitiveLanguageTypeNameForField(field)}[0]);
+            </#if>
         </#if>
         <#break>
     <#case "const">
@@ -128,7 +155,7 @@ public class ${typeName}IO implements 
MessageIO<${typeName}<#if helper.isDiscrim
 
         // Optional Field (Can be skipped, if a given expression evaluates to 
false)
         ${helper.getLanguageTypeNameForField(field)} ${field.name} = 
${helper.getNullValueForType(field.type)};
-        if(${helper.toDeserializationExpression(field.conditionExpression)}) {
+        if(${helper.toDeserializationExpression(field.conditionExpression, 
type.parserArguments)}) {
             ${field.name} = <#if 
helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name?uncap_first}IO.parse(io);</#if>;
         }
         <#break>
@@ -145,7 +172,7 @@ public class ${typeName}IO implements 
MessageIO<${typeName}<#if helper.isDiscrim
     <#case "simple">
 
         // Simple field
-        ${helper.getLanguageTypeNameForField(field)} ${field.name} = <#if 
helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name?uncap_first}IO.parse(io<#if
 field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getArgumentType(field.type, parserArgument?index)}) 
(${helper.toDeserializationExpression(parserArgument)})<#sep>, 
</#sep></#list></#if>)</#if>;
+        ${helper.getLanguageTypeNameForField(field)} ${field.name} = <#if 
helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name?uncap_first}IO.parse(io<#if
 field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getArgumentType(field.type, parserArgument?index)}) 
(${helper.toDeserializationExpression(parserArgument, 
type.parserArguments)})<#sep>, </#sep></#list></#if>)</#if>;
         <#break>
     <#case "switch">
 
@@ -240,7 +267,7 @@ public class ${typeName}IO implements 
MessageIO<${typeName}<#if helper.isDiscrim
         <#if helper.isSimpleType(field.type)>
         io.${helper.getWriteBufferReadMethodCall(field.type, "(" + field.name 
+ ")")};
         <#else>
-        ${field.type.name?uncap_first}IO.serialize(io, ${field.name}<#if 
field.params?has_content>, <#list field.params as 
term>(${helper.getArgumentType(field.type, term?index)}) 
(${helper.toDeserializationExpression(term)})<#sep>, </#sep></#list></#if>);
+        ${field.type.name?uncap_first}IO.serialize(io, ${field.name}<#if 
field.params?has_content>, <#list field.params as 
term>(${helper.getArgumentType(field.type, term?index)}) 
(${helper.toDeserializationExpression(term, type.parserArguments)})<#sep>, 
</#sep></#list></#if>);
         </#if>
         <#break>
     <#case "switch">
@@ -255,9 +282,6 @@ public class ${typeName}IO implements 
MessageIO<${typeName}<#if helper.isDiscrim
 </#switch>
 </#list>
     }
-    public static int CRC(Object... args) {
-        return 0;
-    }
 
     private static int COUNT(Object obj) {
         if(obj.getClass().isArray()) {
diff --git 
a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
 
b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
index 374894b..3b50253 100644
--- 
a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
+++ 
b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
@@ -148,6 +148,7 @@ fragment HexDigit
 arrayType
  : K_COUNT
  | K_LENGTH
+ | K_TERMINATED
  ;
 
 idExpression
@@ -170,6 +171,7 @@ K_TYPE_SWITCH : 'typeSwitch';
 
 K_COUNT : 'count';
 K_LENGTH : 'length';
+K_TERMINATED : 'terminated';
 
 K_BIT : 'bit';
 K_INT : 'int';
diff --git 
a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultArrayField.java
 
b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultArrayField.java
index 4a06206..83737f8 100644
--- 
a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultArrayField.java
+++ 
b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultArrayField.java
@@ -60,9 +60,4 @@ public class DefaultArrayField implements ArrayField {
         return params;
     }
 
-    public static enum LengthType {
-        COUNT,
-        LENGTH
-    }
-
 }
diff --git 
a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
 
b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 5a6441c..aeec697 100644
--- 
a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++ 
b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -96,8 +96,12 @@ public class MessageFormatListener extends MSpecBaseListener 
{
         ArrayField.LengthType lengthType;
         if(ctx.lengthType.K_COUNT() != null) {
             lengthType = ArrayField.LengthType.COUNT;
-        } else {
+        } else if(ctx.lengthType.K_LENGTH() != null){
             lengthType = ArrayField.LengthType.LENGTH;
+        } else if(ctx.lengthType.K_TERMINATED() != null) {
+            lengthType = ArrayField.LengthType.TERMINATED;
+        } else {
+            throw new RuntimeException("Unsupported lenghtType for 
arrayField");
         }
         String lengthExpressionString = ctx.lengthExpression.expr.getText();
         InputStream inputStream = 
IOUtils.toInputStream(lengthExpressionString);
diff --git a/plc4j/examples/hello-world-plc4x/pom.xml 
b/plc4j/examples/hello-world-plc4x/pom.xml
index e3295da..eaee6fe 100644
--- a/plc4j/examples/hello-world-plc4x/pom.xml
+++ b/plc4j/examples/hello-world-plc4x/pom.xml
@@ -91,6 +91,7 @@
           <usedDependencies combine.children="append">
             <usedDependency>org.apache.plc4x:plc4j-driver-s7</usedDependency>
             
<usedDependency>org.apache.plc4x:plc4j-driver-simulated</usedDependency>
+            
<usedDependency>org.apache.plc4x.sandbox:test-java-df1-driver</usedDependency>
             <usedDependency>org.slf4j:log4j-over-slf4j</usedDependency>
           </usedDependencies>
         </configuration>
diff --git 
a/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/ReadBuffer.java
 
b/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/ReadBuffer.java
index 283e1b3..43ac53c 100644
--- 
a/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/ReadBuffer.java
+++ 
b/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/ReadBuffer.java
@@ -28,17 +28,39 @@ import java.math.BigInteger;
 
 public class ReadBuffer {
 
-    private MyDefaultBitInput bi;
+    private final MyDefaultBitInput bi;
+    private final boolean littleEndian;
 
     public ReadBuffer(byte[] input) {
+        this(input, true);
+    }
+
+    public ReadBuffer(byte[] input, boolean littleEndian) {
         ArrayByteInput abi = new ArrayByteInput(input);
         bi = new MyDefaultBitInput(abi);
+        this.littleEndian = littleEndian;
     }
 
     public int getPos() {
         return (int) bi.getPos();
     }
 
+    public byte peekByte(int offset) throws ParseException {
+        // Remember the old index.
+        int oldIndex = bi.getDelegate().getIndex();
+        try {
+            // Set the delegate to the desired position.
+            bi.getDelegate().index(oldIndex + offset);
+            // Read the byte.
+            return bi.readByte(false, 8);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        } finally {
+            // Reset the delegate to the old index.
+            bi.getDelegate().index(oldIndex);
+        }
+    }
+
     public boolean readBit() throws ParseException {
         try {
             return bi.readBoolean();
@@ -83,6 +105,9 @@ public class ReadBuffer {
             throw new ParseException("unsigned int can only contain max 16 
bits");
         }
         try {
+            if(!littleEndian) {
+                return Integer.reverseBytes(bi.readInt(true, bitLength)) >> 16;
+            }
             return bi.readInt(true, bitLength);
         } catch (IOException e) {
             throw new ParseException("Error reading", e);
@@ -97,6 +122,9 @@ public class ReadBuffer {
             throw new ParseException("unsigned long can only contain max 32 
bits");
         }
         try {
+            if(!littleEndian) {
+                return Long.reverseBytes(bi.readLong(true, bitLength)) >> 32;
+            }
             return bi.readLong(true, bitLength);
         } catch (IOException e) {
             throw new ParseException("Error reading", e);
@@ -129,6 +157,9 @@ public class ReadBuffer {
             throw new ParseException("short can only contain max 16 bits");
         }
         try {
+            if(!littleEndian) {
+                return Short.reverseBytes(bi.readShort(false, bitLength));
+            }
             return bi.readShort(false, bitLength);
         } catch (IOException e) {
             throw new ParseException("Error reading", e);
@@ -143,6 +174,9 @@ public class ReadBuffer {
             throw new ParseException("int can only contain max 32 bits");
         }
         try {
+            if(!littleEndian) {
+                return Integer.reverseBytes(bi.readInt(false, bitLength));
+            }
             return bi.readInt(false, bitLength);
         } catch (IOException e) {
             throw new ParseException("Error reading", e);
@@ -157,6 +191,9 @@ public class ReadBuffer {
             throw new ParseException("long can only contain max 64 bits");
         }
         try {
+            if(!littleEndian) {
+                return Long.reverseBytes(bi.readLong(false, bitLength));
+            }
             return bi.readLong(false, bitLength);
         } catch (IOException e) {
             throw new ParseException("Error reading", e);
diff --git 
a/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
 
b/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
index bc10358..8c14102 100644
--- 
a/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
+++ 
b/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
@@ -30,10 +30,10 @@ import java.nio.ByteBuffer;
 
 public class WriteBuffer {
 
-    private ByteBuffer bb;
-    private BufferByteOutput bbo;
-    private BitOutput bo;
-    private boolean littleEndian;
+    private final ByteBuffer bb;
+    private final BufferByteOutput bbo;
+    private final BitOutput bo;
+    private final boolean littleEndian;
 
     public WriteBuffer(int size) {
         this(size, true);
diff --git 
a/plc4j/utils/protocol-test-utils/src/main/java/org/apache/plc4x/protocol/test/ProtocolTestsuiteRunner.java
 
b/plc4j/utils/protocol-test-utils/src/main/java/org/apache/plc4x/protocol/test/ProtocolTestsuiteRunner.java
index f85d3af..50dbc41 100644
--- 
a/plc4j/utils/protocol-test-utils/src/main/java/org/apache/plc4x/protocol/test/ProtocolTestsuiteRunner.java
+++ 
b/plc4j/utils/protocol-test-utils/src/main/java/org/apache/plc4x/protocol/test/ProtocolTestsuiteRunner.java
@@ -59,7 +59,7 @@ public class ProtocolTestsuiteRunner {
             String testcaseName = testcase.getName();
             String testcaseLabel = testSuite.getName() + ": " + testcaseName;
             DynamicTest test = DynamicTest.dynamicTest(testcaseLabel, () ->
-                run(testcase)
+                run(testSuite, testcase)
             );
             dynamicTests.add(test);
         }
@@ -71,6 +71,7 @@ public class ProtocolTestsuiteRunner {
             SAXReader reader = new SAXReader();
             Document document = reader.read(testsuiteDocumentXml);
             Element testsuiteXml = document.getRootElement();
+            boolean littleEndian = 
!"true".equals(testsuiteXml.attributeValue("bigEndian"));
             Element testsuiteName = testsuiteXml.element(new QName("name"));
             List<Element> testcasesXml = testsuiteXml.elements(new 
QName("testcase"));
             List<Testcase> testcases = new ArrayList<>(testcasesXml.size());
@@ -89,7 +90,7 @@ public class ProtocolTestsuiteRunner {
                 testcases.add(new Testcase(name, description, raw, rootType, 
xmlElement));
             }
             LOGGER.info(String.format("Found %d testcases.", 
testcases.size()));
-            return new ProtocolTestsuite(testsuiteName.getTextTrim(), 
testcases);
+            return new ProtocolTestsuite(testsuiteName.getTextTrim(), 
testcases, littleEndian);
         } catch (DocumentException e) {
             throw new ProtocolTestsuiteException("Error parsing testsuite 
xml", e);
         } catch (DecoderException e) {
@@ -97,9 +98,9 @@ public class ProtocolTestsuiteRunner {
         }
     }
 
-    private void run(Testcase testcase) throws ProtocolTestsuiteException {
+    private void run(ProtocolTestsuite testSuite, Testcase testcase) throws 
ProtocolTestsuiteException {
         ObjectMapper mapper = new XmlMapper().enableDefaultTyping();
-        ReadBuffer readBuffer = new ReadBuffer(testcase.getRaw());
+        ReadBuffer readBuffer = new ReadBuffer(testcase.getRaw(), 
testSuite.isLittleEndian());
         String referenceXml = testcase.getXml().elements().get(0).asXML();
 
         MessageIO messageIO = getMessageIOForTestcase(testcase);
@@ -108,10 +109,9 @@ public class ProtocolTestsuiteRunner {
             String xmlString = 
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(msg);
             Diff diff = 
DiffBuilder.compare(referenceXml).withTest(xmlString).ignoreWhitespace().build();
             if(diff.hasDifferences()) {
-                // TODO: Add some more information ...
-                throw new ProtocolTestsuiteException("Differences were found 
after parsing.");
+                throw new ProtocolTestsuiteException("Differences were found 
after parsing.\n" + diff.toString());
             }
-            WriteBuffer writeBuffer = new WriteBuffer(((SizeAware) 
msg).getLengthInBytes());
+            WriteBuffer writeBuffer = new WriteBuffer(((SizeAware) 
msg).getLengthInBytes(), testSuite.isLittleEndian());
             messageIO.serialize(writeBuffer, msg);
             byte[] data = writeBuffer.getData();
             if(!Arrays.equals(testcase.getRaw(), data)) {
diff --git 
a/plc4j/utils/protocol-test-utils/src/main/java/org/apache/plc4x/protocol/test/model/ProtocolTestsuite.java
 
b/plc4j/utils/protocol-test-utils/src/main/java/org/apache/plc4x/protocol/test/model/ProtocolTestsuite.java
index 68b0ffe..83de706 100644
--- 
a/plc4j/utils/protocol-test-utils/src/main/java/org/apache/plc4x/protocol/test/model/ProtocolTestsuite.java
+++ 
b/plc4j/utils/protocol-test-utils/src/main/java/org/apache/plc4x/protocol/test/model/ProtocolTestsuite.java
@@ -25,10 +25,12 @@ public class ProtocolTestsuite {
 
     private final String name;
     private final List<Testcase> testcases;
+    private final boolean littleEndian;
 
-    public ProtocolTestsuite(String name, List<Testcase> testcases) {
+    public ProtocolTestsuite(String name, List<Testcase> testcases, boolean 
littleEndian) {
         this.name = name;
         this.testcases = testcases;
+        this.littleEndian = littleEndian;
     }
 
     public String getName() {
@@ -39,4 +41,8 @@ public class ProtocolTestsuite {
         return testcases;
     }
 
+    public boolean isLittleEndian() {
+        return littleEndian;
+    }
+
 }
diff --git 
a/plc4j/utils/protocol-test-utils/src/main/resources/schemas/testsuite.xsd 
b/plc4j/utils/protocol-test-utils/src/main/resources/schemas/testsuite.xsd
index 5ef4977..58c099b 100644
--- a/plc4j/utils/protocol-test-utils/src/main/resources/schemas/testsuite.xsd
+++ b/plc4j/utils/protocol-test-utils/src/main/resources/schemas/testsuite.xsd
@@ -48,6 +48,7 @@
                     </xs:complexType>
                 </xs:element>
             </xs:sequence>
+            <xs:attribute name="bigEndian" type="xs:boolean"/>
         </xs:complexType>
     </xs:element>
 
diff --git a/protocols/df1/src/main/resources/protocols/df1/protocol.mspec 
b/protocols/df1/src/main/resources/protocols/df1/protocol.mspec
index d63974c..5e997fb 100644
--- a/protocols/df1/src/main/resources/protocols/df1/protocol.mspec
+++ b/protocols/df1/src/main/resources/protocols/df1/protocol.mspec
@@ -17,32 +17,17 @@
 // under the License.
 //
 
-
-[type 'ReadRequest'
-    [field    DF1Symbol    'messageFrameStart' ['0', 'null']]
-    [field    DF1Symbol    'messageFrameEnd' ['0', 'messageFrameStart']]
-]
-
-[type 'ReadResponse' [uint 8 'payloadSize']
-    [field    DF1Symbol    'messageFrameStart' ['payloadSize', 'null']]
-    [field    DF1Symbol    'messageFrameEnd' ['0', 'messageFrameStart']]
-]
-
-[type 'Result'
-    [field    DF1Symbol    'result' ['0', 'null']]
-]
-
-[discriminatedType 'DF1Symbol' [uint 8 'payloadSize', 
DF1SymbolMessageFrameStart 'messageStartSymbol']
+[discriminatedType 'DF1Symbol'
     [const            uint 8       'messageStart' '0x10']
     [discriminator    uint 8       'symbolType']
     [typeSwitch 'symbolType'
-        ['0x02' DF1SymbolMessageFrameStart
+        ['0x02' DF1SymbolMessageFrame
             [field    uint 8       'destinationAddress']
             [field    uint 8       'sourceAddress']
-            [field    DF1Command   'command' ['payloadSize']]
-        ]
-        ['0x03' DF1SymbolMessageFrameEnd
-            [implicit uint 16      'crc' 
'STATIC_CALL("org.apache.plc4x.protocol.df1.DF1Utils.CRCCheck", 
discriminatorValues[0], messageStartSymbol)']
+            [field    DF1Command   'command']
+            [const    uint 8       'messageEnd' '0x10']
+            [const    uint 8       'endTransaction' '0x03']
+            [implicit uint 16      'crc' 
'STATIC_CALL("org.apache.plc4x.java.df1.util.DF1Utils.CRCCheck", value)']
         ]
         ['0x06' DF1SymbolMessageFrameACK
         ]
@@ -51,17 +36,17 @@
     ]
 ]
 
-[discriminatedType 'DF1Command' [uint 8 'payloadSize']
-    [discriminator uint 8  'commandType']
+[discriminatedType 'DF1Command'
+    [discriminator uint 8  'commandCode']
     [field    uint 8       'status']
     [field    uint 16      'transactionCounter']
-    [typeSwitch 'commandType'
-        ['0x01' DF1ReadRequest
-         [field uint 16    'address']
-         [field uint 8     'size']
+    [typeSwitch 'commandCode'
+        ['0x01' DF1UnprotectedReadRequest
+            [field uint 16    'address']
+            [field uint 8     'size']
         ]
-        ['0x41' DF1ReadResponse
-         [arrayField uint 8 'data' length 'payloadSize']
+        ['0x41' DF1UnprotectedReadResponse
+            [arrayField uint 8 'data' terminated 
'STATIC_CALL("org.apache.plc4x.java.df1.util.DF1Utils.dataTerminate", io)']
         ]
     ]
 ]
diff --git a/sandbox/test-java-df1-driver/pom.xml 
b/sandbox/test-java-df1-driver/pom.xml
index 7159072..904ef55 100644
--- a/sandbox/test-java-df1-driver/pom.xml
+++ b/sandbox/test-java-df1-driver/pom.xml
@@ -132,10 +132,37 @@
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-utils-protocol-test-utils</artifactId>
+      <version>0.5.0-SNAPSHOT</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-xml</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
 </project>
diff --git 
a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/protocol/Df1Protocol.java
 
b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/protocol/Df1Protocol.java
index bbeece2..31a9024 100644
--- 
a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/protocol/Df1Protocol.java
+++ 
b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/protocol/Df1Protocol.java
@@ -23,9 +23,9 @@ import io.netty.buffer.ByteBufUtil;
 import io.netty.channel.ChannelHandlerContext;
 import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
 import org.apache.plc4x.java.base.PlcByteToMessageCodec;
-import org.apache.plc4x.java.df1.DF1ReadRequest;
 import org.apache.plc4x.java.df1.DF1Symbol;
-import org.apache.plc4x.java.df1.DF1SymbolMessageFrameStart;
+import org.apache.plc4x.java.df1.DF1SymbolMessageFrame;
+import org.apache.plc4x.java.df1.DF1UnprotectedReadRequest;
 import org.apache.plc4x.java.df1.io.DF1SymbolIO;
 import org.apache.plc4x.java.utils.ReadBuffer;
 import org.apache.plc4x.java.utils.WriteBuffer;
@@ -52,12 +52,12 @@ public class Df1Protocol extends 
PlcByteToMessageCodec<DF1Symbol> {
     @Override
     protected void encode(ChannelHandlerContext ctx, DF1Symbol msg, ByteBuf 
out) throws Exception {
         // Remember the size of the request as we need this to decode the 
response.
-        if(msg instanceof DF1SymbolMessageFrameStart) {
-            DF1SymbolMessageFrameStart frameStart = 
(DF1SymbolMessageFrameStart) msg;
-            if(frameStart.getCommand() instanceof DF1ReadRequest) {
-                DF1ReadRequest readRequest = (DF1ReadRequest) 
frameStart.getCommand();
-                int transactionCounter = readRequest.getTransactionCounter();
-                readRequestSizes.put(transactionCounter, 
readRequest.getSize());
+        if(msg instanceof DF1SymbolMessageFrame) {
+            DF1SymbolMessageFrame frame = (DF1SymbolMessageFrame) msg;
+            if(frame.getCommand() instanceof DF1UnprotectedReadRequest) {
+                DF1UnprotectedReadRequest unprotectedReadRequest = 
(DF1UnprotectedReadRequest) frame.getCommand();
+                int transactionCounter = 
unprotectedReadRequest.getTransactionCounter();
+                readRequestSizes.put(transactionCounter, 
unprotectedReadRequest.getSize());
             }
         }
 
diff --git 
a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/util/DF1Utils.java
 
b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/util/DF1Utils.java
new file mode 100644
index 0000000..1d36d65
--- /dev/null
+++ 
b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/util/DF1Utils.java
@@ -0,0 +1,129 @@
+/*
+ * 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
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   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
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.df1.util;
+
+import org.apache.plc4x.java.df1.DF1Symbol;
+import org.apache.plc4x.java.df1.DF1SymbolMessageFrame;
+import org.apache.plc4x.java.df1.DF1UnprotectedReadRequest;
+import org.apache.plc4x.java.df1.DF1UnprotectedReadResponse;
+import org.apache.plc4x.java.utils.ParseException;
+import org.apache.plc4x.java.utils.ReadBuffer;
+import org.apache.plc4x.java.utils.WriteBuffer;
+
+public class DF1Utils {
+
+    public static short CRCCheck(Object... args) {
+        DF1Symbol symbol = (DF1Symbol) args[0];
+        if(symbol instanceof DF1SymbolMessageFrame) {
+            DF1SymbolMessageFrame messageFrame = (DF1SymbolMessageFrame) 
symbol;
+
+            short destinationAddress = messageFrame.getDestinationAddress();
+            short sourceAddress = messageFrame.getSourceAddress();
+            short commandDiscriminatorValues = (short) 
messageFrame.getCommand().getDiscriminatorValues()[0];
+            short status = messageFrame.getCommand().getStatus();
+            int   counter = messageFrame.getCommand().getTransactionCounter();
+            if(messageFrame.getCommand() instanceof DF1UnprotectedReadRequest) 
{
+                DF1UnprotectedReadRequest unprotectedReadRequestCommand = 
(DF1UnprotectedReadRequest) messageFrame.getCommand();
+                try {
+                    WriteBuffer writeBuffer = new WriteBuffer(10, false);
+                    writeBuffer.writeUnsignedShort(8, destinationAddress);
+                    writeBuffer.writeUnsignedShort(8, sourceAddress);
+                    writeBuffer.writeUnsignedShort(8, 
commandDiscriminatorValues);
+                    writeBuffer.writeUnsignedShort(8, status);
+                    writeBuffer.writeUnsignedInt(16, (short) counter);
+                    writeBuffer.writeUnsignedInt(16, (short) 
unprotectedReadRequestCommand.getAddress());
+                    writeBuffer.writeUnsignedShort(8, (byte) 
unprotectedReadRequestCommand.getSize());
+                    writeBuffer.writeUnsignedShort(8, (byte) 0x03);
+
+                    byte[] data = writeBuffer.getData();
+
+                    int tmp = 0;
+                    int crcL, crcR;
+
+                    for (int newByte : data) {
+                        crcL = tmp >> 8;
+                        crcR = tmp & 0xFF;
+                        tmp = (crcL << 8) + (newByte ^ crcR);
+                        for (int j=0; j<8; j++)
+                            if (tmp % 2 == 1) {     // check if LSB shifted 
out is 1 or 0
+                                tmp = tmp >> 1;
+                                tmp = tmp ^ 0xA001;
+                            } else {
+                                tmp = tmp >> 1;
+                            }
+                    }
+
+                    return (short) tmp;
+                } catch (ParseException e) {
+                    throw new RuntimeException("Something wen't wrong during 
the CRC check", e);
+                }
+            } else if(messageFrame.getCommand() instanceof 
DF1UnprotectedReadResponse) {
+                DF1UnprotectedReadResponse unprotectedReadResponseCommand = 
(DF1UnprotectedReadResponse) messageFrame.getCommand();
+                try {
+                    WriteBuffer writeBuffer = new WriteBuffer(10, false);
+                    writeBuffer.writeUnsignedShort(8, destinationAddress);
+                    writeBuffer.writeUnsignedShort(8, sourceAddress);
+                    writeBuffer.writeUnsignedShort(8, 
commandDiscriminatorValues);
+                    writeBuffer.writeUnsignedShort(8, status);
+                    writeBuffer.writeUnsignedInt(16, (short) counter);
+                    for (short data : 
unprotectedReadResponseCommand.getData()) {
+                        writeBuffer.writeUnsignedShort(8,  data);
+                    }
+                    writeBuffer.writeUnsignedShort(8, (byte) 0x03);
+
+                    byte[] data = writeBuffer.getData();
+
+                    int tmp = 0;
+                    int crcL, crcR;
+
+                    for (int newByte : data) {
+                        crcL = tmp >> 8;
+                        crcR = tmp & 0xFF;
+                        tmp = (crcL << 8) + (newByte ^ crcR);
+                        for (int j=0; j<8; j++)
+                            if (tmp % 2 == 1) {     // check if LSB shifted 
out is 1 or 0
+                                tmp = tmp >> 1;
+                                tmp = tmp ^ 0xA001;
+                            } else {
+                                tmp = tmp >> 1;
+                            }
+                    }
+
+                    return (short) tmp;
+                } catch (ParseException e) {
+                    throw new RuntimeException("Something wen't wrong during 
the CRC check", e);
+                }
+            }
+        }
+
+        return 0;
+    }
+
+    public static boolean dataTerminate(ReadBuffer io) {
+        try {
+            if ((io.peekByte(0) == (byte) 0x10) && (io.peekByte(1) == (byte) 
0x03)) {
+                return true;
+            }
+        } catch (ParseException e) {
+            // Just ignore and return false.
+        }
+        return false;
+    }
+
+}
diff --git 
a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/protocol/df1/DF1Utils.java
 
b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/protocol/df1/DF1Utils.java
deleted file mode 100644
index a85ab8f..0000000
--- 
a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/protocol/df1/DF1Utils.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   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
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.protocol.df1;
-
-import org.apache.plc4x.java.df1.DF1ReadRequest;
-import org.apache.plc4x.java.df1.DF1Symbol;
-import org.apache.plc4x.java.df1.DF1SymbolMessageFrameStart;
-import org.apache.plc4x.java.utils.ParseException;
-import org.apache.plc4x.java.utils.WriteBuffer;
-
-import java.nio.ByteBuffer;
-
-public class DF1Utils {
-
-    public static short CRCCheck(Object... args) {
-        DF1Symbol symbol = (DF1Symbol) args[1];
-        short messageType = (short) args[0];
-        if(symbol instanceof DF1SymbolMessageFrameStart) {
-            DF1SymbolMessageFrameStart messageFrameStart = 
(DF1SymbolMessageFrameStart) symbol;
-
-            short destinationAddress = 
messageFrameStart.getDestinationAddress();
-            short sourceAddress = messageFrameStart.getSourceAddress();
-            short commandDiscriminatorValues = (short) 
messageFrameStart.getCommand().getDiscriminatorValues()[0];
-            short status = messageFrameStart.getCommand().getStatus();
-            int   counter = 
messageFrameStart.getCommand().getTransactionCounter();
-            if(messageFrameStart.getCommand() instanceof DF1ReadRequest) {
-                DF1ReadRequest readRequestCommand = (DF1ReadRequest) 
messageFrameStart.getCommand();
-
-                try {
-                    WriteBuffer writeBuffer = new WriteBuffer(10, false);
-                    writeBuffer.writeUnsignedShort(8, destinationAddress);
-                    writeBuffer.writeUnsignedShort(8, sourceAddress);
-                    writeBuffer.writeUnsignedShort(8, 
commandDiscriminatorValues);
-                    writeBuffer.writeUnsignedShort(8, status);
-                    writeBuffer.writeUnsignedInt(16, (short) counter);
-                    writeBuffer.writeUnsignedInt(16, (short) 
readRequestCommand.getAddress());
-                    writeBuffer.writeUnsignedShort(8, (byte) 
readRequestCommand.getSize());
-                    writeBuffer.writeUnsignedShort(8, (byte) messageType);
-
-                    byte[] data = writeBuffer.getData();
-
-                    int tmp = 0;
-                    int crcL, crcR;
-
-                    for (int newByte : data) {
-                        crcL = tmp >> 8;
-                        crcR = tmp & 0xFF;
-                        tmp = (crcL << 8) + (newByte ^ crcR);
-                        for (int j=0; j<8; j++)
-                            if (tmp % 2 == 1) {     // check if LSB shifted 
out is 1 or 0
-                                tmp = tmp >> 1;
-                                tmp = tmp ^ 0xA001;
-                            } else {
-                                tmp = tmp >> 1;
-                            }
-                    }
-
-                    return (short) tmp;
-                } catch (ParseException e) {
-                    throw new RuntimeException("Something wen't wrong during 
the CRC check", e);
-                }
-            }
-        }
-
-        return 0;
-    }
-
-}
diff --git 
a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/BenchmarkGeneratedDf1.java
 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/BenchmarkGeneratedDf1.java
index e092cb6..27c9be2 100644
--- 
a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/BenchmarkGeneratedDf1.java
+++ 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/BenchmarkGeneratedDf1.java
@@ -21,16 +21,13 @@ package org.apache.plc4x.protocol.df1;
 
 import com.fazecast.jSerialComm.SerialPort;
 import org.apache.plc4x.java.df1.*;
-import org.apache.plc4x.java.df1.io.ReadRequestIO;
-import org.apache.plc4x.java.df1.io.ReadResponseIO;
-import org.apache.plc4x.java.df1.io.ResultIO;
 import org.apache.plc4x.java.utils.ReadBuffer;
 import org.apache.plc4x.java.utils.WriteBuffer;
 
 public class BenchmarkGeneratedDf1 {
 
     public static void main(String[] args) throws Exception {
-        // Manually build a message
+        /*// Manually build a message
         ReadRequest readRequest = new ReadRequest(new 
DF1SymbolMessageFrameStart((short) 0x09, (short) 0x00, new 
DF1ReadRequest((short) 0x00, 0x01, 0x0B, (short) 0x02)), new 
DF1SymbolMessageFrameEnd());
 
         // Serialize the message
@@ -78,7 +75,7 @@ public class BenchmarkGeneratedDf1 {
             System.out.println("Didn't get an ACK");
         }
 
-        comPort.closePort();
+        comPort.closePort();*/
     }
 
 }
diff --git 
a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/BenchmarkManualDf1.java
 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/BenchmarkManualDf1.java
index c2571fe..f832798 100644
--- 
a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/BenchmarkManualDf1.java
+++ 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/BenchmarkManualDf1.java
@@ -22,7 +22,6 @@ package org.apache.plc4x.protocol.df1;
 import com.fazecast.jSerialComm.SerialPort;
 import org.apache.plc4x.java.df1.DF1Command;
 import org.apache.plc4x.java.df1.DF1Symbol;
-import org.apache.plc4x.java.df1.DF1SymbolMessageFrameStart;
 import org.apache.plc4x.java.df1.io.DF1SymbolIO;
 import org.apache.plc4x.java.utils.ReadBuffer;
 
diff --git 
a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/Df1Test.java
 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/Df1Test.java
new file mode 100644
index 0000000..bcadf1a
--- /dev/null
+++ 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/Df1Test.java
@@ -0,0 +1,30 @@
+/*
+  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
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      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
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+*/
+
+package org.apache.plc4x.protocol.df1;
+
+import org.apache.plc4x.protocol.test.ProtocolTestsuiteRunner;
+
+public class Df1Test extends ProtocolTestsuiteRunner {
+
+    public Df1Test() {
+        super("/testsuite/Df1Testsuite.xml");
+    }
+
+}
diff --git 
a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/EndToEndTest.java
 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/EndToEndTest.java
index 954d092..e35fcce 100644
--- 
a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/EndToEndTest.java
+++ 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/EndToEndTest.java
@@ -24,6 +24,7 @@ import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.junit.jupiter.api.Test;
 
 import java.util.concurrent.TimeUnit;
 
@@ -35,7 +36,7 @@ import java.util.concurrent.TimeUnit;
  */
 public class EndToEndTest {
 
-    @org.junit.Test
+    @Test
     public void helloDf1() {
         try (PlcConnection plcConnection = new 
PlcDriverManager().getConnection("df1:serial///dev/cu.usbserial-AL065SUZ")) {
             PlcReadRequest request = plcConnection.readRequestBuilder()
diff --git 
a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/IOTest.java
 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/IOTest.java
new file mode 100644
index 0000000..18543cc
--- /dev/null
+++ 
b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/IOTest.java
@@ -0,0 +1,99 @@
+/*
+ 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
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     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
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.protocol.df1;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.plc4x.java.df1.DF1Symbol;
+import org.apache.plc4x.java.df1.io.DF1SymbolIO;
+import org.apache.plc4x.java.utils.ReadBuffer;
+import org.junit.jupiter.api.Test;
+
+public class IOTest {
+
+    @Test
+    public void testXml() throws Exception {
+        byte[] rData = Hex.decodeHex("10020A0941000100FFFF1003473D");
+        ObjectMapper mapper = new XmlMapper().enableDefaultTyping();
+        ReadBuffer rBuf = new ReadBuffer(rData);
+        DF1Symbol symbol = new DF1SymbolIO().parse(rBuf);
+        String xml = 
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(symbol);
+        System.out.println(xml);
+        DF1Symbol symbol2 = mapper.readValue(xml, DF1Symbol.class);
+        System.out.println(symbol2);
+    }
+
+    @Test
+    public void testJson() throws Exception {
+        byte[] rData = Hex.decodeHex("10020900010001001100021003ABE2");
+        ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
+        ReadBuffer rBuf = new ReadBuffer(rData);
+        DF1Symbol symbol = new DF1SymbolIO().parse(rBuf);
+        String json = 
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(symbol);
+        System.out.println(json);
+        DF1Symbol symbol2 = mapper.readValue(json, DF1Symbol.class);
+        System.out.println(symbol2);
+    }
+
+    /*@Test
+    public void testParser() throws Exception {
+        byte[] rData = 
Hex.decodeHex("0610020500180801c0a82a46c4090801c0a82a46c40a0203");
+        long start = System.currentTimeMillis();
+        int numRunsParse = 20000;
+
+        KNXNetIPMessageIO knxNetIPMessageIO = new KNXNetIPMessageIO();
+
+        // Benchmark the parsing code
+        KNXNetIPMessage packet = null;
+        for(int i = 0; i < numRunsParse; i++) {
+            ReadBuffer rBuf = new ReadBuffer(rData);
+            packet = knxNetIPMessageIO.parse(rBuf);
+        }
+        long endParsing = System.currentTimeMillis();
+
+        System.out.println("Parsed " + numRunsParse + " packets in " + 
(endParsing - start) + "ms");
+        System.out.println("That's " + ((float) (endParsing - start) / 
numRunsParse) + "ms per packet");
+
+        // Benchmark the serializing code
+        int numRunsSerialize = 20000;
+        byte[] oData = null;
+        for(int i = 0; i < numRunsSerialize; i++) {
+            WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes());
+            knxNetIPMessageIO.serialize(wBuf, packet);
+            oData = wBuf.getData();
+        }
+        long endSerializing = System.currentTimeMillis();
+
+        System.out.println("Serialized " + numRunsSerialize + " packets in " + 
(endSerializing - endParsing) + "ms");
+        System.out.println("That's " + ((float) (endSerializing - endParsing) 
/ numRunsSerialize) + "ms per packet");
+        if(!Arrays.equals(rData, oData)) {
+            for(int i = 0; i < rData.length; i++) {
+                if(rData[i] != oData[i]) {
+                    System.out.println("Difference in byte " + i);
+                }
+            }
+            System.out.println("Not equals");
+        } else {
+            System.out.println("Bytes equal");
+        }
+    }*/
+
+}
diff --git 
a/sandbox/test-java-df1-driver/src/test/resources/testsuite/Df1Testsuite.xml 
b/sandbox/test-java-df1-driver/src/test/resources/testsuite/Df1Testsuite.xml
new file mode 100644
index 0000000..b0691ef
--- /dev/null
+++ b/sandbox/test-java-df1-driver/src/test/resources/testsuite/Df1Testsuite.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      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
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/testsuite.xsd";
+                bigEndian="true">
+
+  <name>Allen-Bradley DF1</name>
+
+  <testcase>
+    <name>Unprotected Read Address Request</name>
+    <raw>10020900010001001100021003546F</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrame 
className="org.apache.plc4x.java.df1.DF1SymbolMessageFrame">
+        <destinationAddress>9</destinationAddress>
+        <sourceAddress>0</sourceAddress>
+        <command 
className="org.apache.plc4x.java.df1.DF1UnprotectedReadRequest">
+          <status>0</status>
+          <transactionCounter>1</transactionCounter>
+          <address>17</address>
+          <size>2</size>
+        </command>
+      </DF1SymbolMessageFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Unprotected Read Address Response</name>
+    <raw>10020A0941000100FFFF1003DFB9</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrame 
className="org.apache.plc4x.java.df1.DF1SymbolMessageFrame">
+        <destinationAddress>10</destinationAddress>
+        <sourceAddress>9</sourceAddress>
+        <command 
className="org.apache.plc4x.java.df1.DF1UnprotectedReadResponse">
+          <status>0</status>
+          <transactionCounter>1</transactionCounter>
+          <data>
+            <data>255</data>
+            <data>255</data>
+          </data>
+        </command>
+      </DF1SymbolMessageFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>ACK Response</name>
+    <raw>1006</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrameACK 
className="org.apache.plc4x.java.df1.DF1SymbolMessageFrameACK"/>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>NACK Response</name>
+    <raw>1015</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrameNAK 
className="org.apache.plc4x.java.df1.DF1SymbolMessageFrameNAK"/>
+    </xml>
+  </testcase>
+
+</test:testsuite>
\ No newline at end of file

Reply via email to