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 2019/08/07 14:58:48 UTC
[plc4x] 04/06: - Simplified the mspec for the DF1 protocol - Added
a "terminated" type of arrayField - Made the ReadBuffer endianness aware -
Made the testsuite endianness aware
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 <ch...@c-ware.de>
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