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/07/03 18:47:07 UTC

[plc4x] 02/02: - Extended the case statement to be able to take arguments - Excluded ConstFields from the PropertyFields - Converted the params of complex typed fields from String[] to Term[]

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

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit c1867000a9acb5b8fb8c368608a86498d4605998
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Jul 3 20:46:16 2019 +0200

    - Extended the case statement to be able to take arguments
    - Excluded ConstFields from the PropertyFields
    - Converted the params of complex typed fields from String[] to Term[]
---
 .../language/java/JavaLanguageTemplateHelper.java  |  3 +
 .../main/resources/templates/java/io-template.ftlh |  6 +-
 .../plugins/codegenerator/language/mspec/MSpec.g4  |  2 +-
 .../definitions/DefaultComplexTypeDefinition.java  |  2 +-
 .../mspec/model/fields/DefaultArrayField.java      |  6 +-
 .../mspec/model/fields/DefaultConstField.java      |  5 +-
 .../model/fields/DefaultDiscriminatorField.java    |  5 +-
 .../mspec/model/fields/DefaultImplicitField.java   |  4 +-
 .../mspec/model/fields/DefaultOptionalField.java   |  6 +-
 .../mspec/model/fields/DefaultReservedField.java   |  5 +-
 .../mspec/model/fields/DefaultSimpleField.java     |  7 +-
 .../mspec/model/fields/DefaultSwitchField.java     |  5 +-
 .../mspec/parser/MessageFormatListener.java        | 31 +++++---
 .../resources/protocols/knxnetip/knxnetip.mspec    | 87 +++++++++++++++-------
 .../test/resources/testsuite/KNXNetIPTestsuite.xml | 87 ++++++++++++++--------
 15 files changed, 168 insertions(+), 93 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 5f43830..0f7745d 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
@@ -390,6 +390,9 @@ public class JavaLanguageTemplateHelper implements FreemarkerLanguageTemplateHel
     }
 
     private String toExpression(Term term, Function<Term, String> variableExpressionGenerator) {
+        if(term == null) {
+            return "";
+        }
         if(term instanceof Literal) {
             if(term instanceof NullLiteral) {
                 return "null";
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 085f4a2..4cb4234 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
@@ -95,7 +95,7 @@ public class ${typeName}IO implements MessageIO<${typeName}<#if helper.isDiscrim
             <#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)}) (${parserArgument})<#sep>, </#sep></#list></#if>)</#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>);
         }
         ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = ${field.name}List.toArray(new ${helper.getLanguageTypeNameForField(field)}[0]);
         </#if>
@@ -139,7 +139,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>${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)})<#sep>, </#sep></#list></#if>)</#if>;
         <#break>
     <#case "switch">
 
@@ -147,7 +147,7 @@ public class ${typeName}IO implements MessageIO<${typeName}<#if helper.isDiscrim
         ${typeName}Builder builder = null;
         <#list field.cases as case>
         if(<#list case.discriminatorValues as discriminatorValue>EvaluationHelper.equals(${helper.toSwitchExpression(field.discriminatorNames[discriminatorValue?index])}, ${discriminatorValue})<#sep> && </#sep></#list>) {
-            builder = ${case.name?uncap_first}IO.parse(io<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>);
+            builder = ${case.name?uncap_first}IO.parse(io<#if case.parserArguments?has_content>, <#list case.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>);
         }<#sep> else </#sep>
         </#list>
         if (builder == null) {
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 15d5e5f..6f2ed24 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
@@ -87,7 +87,7 @@ typeReference
  ;
 
 caseStatement
- : LBRACKET discriminatorValues=multipleExpressions name=IDENTIFIER fieldDefinition* RBRACKET
+ : LBRACKET discriminatorValues=multipleExpressions name=IDENTIFIER (LBRACKET params=argumentList RBRACKET)? fieldDefinition* RBRACKET
  ;
 
 dataType
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
index 2618fe7..7d38171 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
@@ -64,7 +64,7 @@ public class DefaultComplexTypeDefinition extends DefaultTypeDefinition implemen
 
     @Override
     public List<PropertyField> getPropertyFields() {
-        return fields.stream().filter(field -> (field instanceof PropertyField)).map(field -> (PropertyField) field)
+        return fields.stream().filter(field -> ((field instanceof PropertyField) && !(field instanceof ConstField))).map(field -> (PropertyField) field)
             .collect(Collectors.toList());
     }
 
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 d25b1ce..4a06206 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
@@ -29,9 +29,9 @@ public class DefaultArrayField implements ArrayField {
     private final String name;
     private final ArrayField.LengthType lengthType;
     private final Term lengthExpression;
-    private final String[] params;
+    private final Term[] params;
 
-    public DefaultArrayField(TypeReference type, String name, ArrayField.LengthType lengthType, Term lengthExpression, String[] params) {
+    public DefaultArrayField(TypeReference type, String name, ArrayField.LengthType lengthType, Term lengthExpression, Term[] params) {
         this.type = type;
         this.name = name;
         this.lengthType = lengthType;
@@ -56,7 +56,7 @@ public class DefaultArrayField implements ArrayField {
     }
 
     @Override
-    public String[] getParams() {
+    public Term[] getParams() {
         return params;
     }
 
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultConstField.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultConstField.java
index 79eadff..929a18d 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultConstField.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultConstField.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields;
 
 import org.apache.plc4x.plugins.codegenerator.types.fields.ConstField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
 public class DefaultConstField implements ConstField {
 
@@ -46,8 +47,8 @@ public class DefaultConstField implements ConstField {
         return referenceValue;
     }
 
-    public String[] getParams() {
-        return new String[0];
+    public Term[] getParams() {
+        return new Term[0];
     }
 
 }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultDiscriminatorField.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultDiscriminatorField.java
index 0e012ce..47c25cf 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultDiscriminatorField.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultDiscriminatorField.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields;
 
 import org.apache.plc4x.plugins.codegenerator.types.fields.DiscriminatorField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
 public class DefaultDiscriminatorField implements DiscriminatorField {
 
@@ -40,8 +41,8 @@ public class DefaultDiscriminatorField implements DiscriminatorField {
         return name;
     }
 
-    public String[] getParams() {
-        return new String[0];
+    public Term[] getParams() {
+        return new Term[0];
     }
 
 }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultImplicitField.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultImplicitField.java
index 9c2ffb4..f535b04 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultImplicitField.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultImplicitField.java
@@ -47,8 +47,8 @@ public class DefaultImplicitField implements ImplicitField {
         return serializationExpression;
     }
 
-    public String[] getParams() {
-        return new String[0];
+    public Term[] getParams() {
+        return new Term[0];
     }
 
 }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java
index 521f75f..2eabfa2 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java
@@ -28,9 +28,9 @@ public class DefaultOptionalField implements OptionalField {
     private final TypeReference type;
     private final String name;
     private final Term conditionExpression;
-    private final String[] params;
+    private final Term[] params;
 
-    public DefaultOptionalField(TypeReference type, String name, Term conditionExpression, String[] params) {
+    public DefaultOptionalField(TypeReference type, String name, Term conditionExpression, Term[] params) {
         this.type = type;
         this.name = name;
         this.conditionExpression = conditionExpression;
@@ -49,7 +49,7 @@ public class DefaultOptionalField implements OptionalField {
         return conditionExpression;
     }
 
-    public String[] getParams() {
+    public Term[] getParams() {
         return params;
     }
 
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultReservedField.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultReservedField.java
index ab9587d..5892aff 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultReservedField.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultReservedField.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields;
 
 import org.apache.plc4x.plugins.codegenerator.types.fields.ReservedField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
 public class DefaultReservedField implements ReservedField {
 
@@ -40,8 +41,8 @@ public class DefaultReservedField implements ReservedField {
         return referenceValue;
     }
 
-    public String[] getParams() {
-        return new String[0];
+    public Term[] getParams() {
+        return new Term[0];
     }
 
 }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSimpleField.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSimpleField.java
index ceb1d80..9a973f6 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSimpleField.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSimpleField.java
@@ -21,14 +21,15 @@ package org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields;
 
 import org.apache.plc4x.plugins.codegenerator.types.fields.SimpleField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
 public class DefaultSimpleField implements SimpleField {
 
     private final TypeReference type;
     private final String name;
-    private final String[] params;
+    private final Term[] params;
 
-    public DefaultSimpleField(TypeReference type, String name, String[] params) {
+    public DefaultSimpleField(TypeReference type, String name, Term[] params) {
         this.type = type;
         this.name = name;
         this.params = params;
@@ -42,7 +43,7 @@ public class DefaultSimpleField implements SimpleField {
         return name;
     }
 
-    public String[] getParams() {
+    public Term[] getParams() {
         return params;
     }
 
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSwitchField.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSwitchField.java
index c233df8..1098532 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSwitchField.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSwitchField.java
@@ -22,6 +22,7 @@ package org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields;
 
 import org.apache.plc4x.plugins.codegenerator.types.definitions.DiscriminatedComplexTypeDefinition;
 import org.apache.plc4x.plugins.codegenerator.types.fields.SwitchField;
+import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
 import java.util.LinkedList;
 import java.util.List;
@@ -48,8 +49,8 @@ public class DefaultSwitchField implements SwitchField {
         return cases;
     }
 
-    public String[] getParams() {
-        return new String[0];
+    public Term[] getParams() {
+        return new Term[0];
     }
 
 }
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 ffb82f1..5a6441c 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
@@ -103,7 +103,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         InputStream inputStream = IOUtils.toInputStream(lengthExpressionString);
         ExpressionStringParser parser = new ExpressionStringParser();
         Term lengthExpression =  parser.parse(inputStream);
-        String[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
+        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultArrayField(type, name, lengthType, lengthExpression, params);
         parserContexts.peek().add(field);
     }
@@ -129,7 +129,7 @@ public class MessageFormatListener extends MSpecBaseListener {
     public void enterSimpleField(MSpecParser.SimpleFieldContext ctx) {
         TypeReference type = getTypeReference(ctx.type);
         String name = ctx.name.id.getText();
-        String[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
+        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultSimpleField(type, name, params);
         parserContexts.peek().add(field);
     }
@@ -154,7 +154,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         InputStream inputStream = IOUtils.toInputStream(conditionExpressionString);
         ExpressionStringParser parser = new ExpressionStringParser();
         Term conditionExpression =  parser.parse(inputStream);
-        String[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
+        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultOptionalField(type, name, conditionExpression, params);
         parserContexts.peek().add(field);
     }
@@ -187,10 +187,15 @@ public class MessageFormatListener extends MSpecBaseListener {
     @Override
     public void exitCaseStatement(MSpecParser.CaseStatementContext ctx) {
         String typeName = ctx.name.getText();
-        Argument[] parserArguments = null;
+        List<Argument> parserArguments = new LinkedList<>();
+        // Add all the arguments from the parent type.
         if(((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent.parent).params != null) {
-            parserArguments = getParserArguments(
-                ((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent.parent).params.argument());
+            parserArguments.addAll(Arrays.asList(getParserArguments(
+                ((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent.parent).params.argument())));
+        }
+        // Add all eventually existing local arguments.
+        if(ctx.argumentList() != null) {
+            parserArguments.addAll(Arrays.asList(getParserArguments(ctx.argumentList().argument())));
         }
 
         List<MSpecParser.ExpressionContext> expressions = ctx.discriminatorValues.expression();
@@ -199,7 +204,7 @@ public class MessageFormatListener extends MSpecBaseListener {
             discriminatorValues[i] = expressions.get(i).expr.getText();
         }
         DefaultDiscriminatedComplexTypeDefinition type =
-            new DefaultDiscriminatedComplexTypeDefinition(typeName, parserArguments,
+            new DefaultDiscriminatedComplexTypeDefinition(typeName, parserArguments.toArray(new Argument[0]),
                 discriminatorValues, parserContexts.pop());
 
         // Add the type to the switch field definition.
@@ -264,19 +269,21 @@ public class MessageFormatListener extends MSpecBaseListener {
         return parserArguments;
     }
 
-    private String[] getFieldParams(MSpecParser.FieldDefinitionContext parentCtx) {
-        String[] params = null;
+    private Term[] getFieldParams(MSpecParser.FieldDefinitionContext parentCtx) {
+        Term[] params = null;
         if(parentCtx.params != null) {
-            params = new String[parentCtx.params.expression().size()];
+            params = new Term[parentCtx.params.expression().size()];
             for(int i = 0; i < parentCtx.params.expression().size(); i++) {
-                params[i] = parentCtx.params.expression().get(i).expr.getText();
+                params[i] = parseExpression(parentCtx.params.expression().get(i).expr.getText());
             }
         }
         return params;
     }
 
     private Term parseExpression(String expressionString) {
-        return null;
+        InputStream inputStream = IOUtils.toInputStream(expressionString);
+        ExpressionStringParser parser = new ExpressionStringParser();
+        return parser.parse(inputStream);
     }
 
 }
diff --git a/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec b/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
index eef4d3a..419840d 100644
--- a/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
+++ b/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
@@ -18,7 +18,7 @@
 //
 
 [discriminatedType 'KNXNetIPMessage'
-    [implicit      uint 8  'headerLength' 'lengthInBytes']
+    [implicit      uint 8  'headerLength'    '6']
     [const         uint 8  'protocolVersion' '0x10']
     [discriminator uint 16 'msgType']
     [implicit      uint 16 'totalLength' 'lengthInBytes']
@@ -67,31 +67,19 @@
             [field uint 8 'communicationChannelId']
             [field uint 8 'status']
         ]
-        ['0x0310' DeviceConfigurationRequest
-            [implicit uint 8 'structureLength' 'lengthInBytes']
-            [field    uint 8 'communicationChannelId']
-            [field    uint 8 'sequenceCounter']
-            [reserved uint 8 '0x00']
-            [field    CEMI 'cEMI']
+        ['0x0310' DeviceConfigurationRequest [uint 16 'totalLength']
+            [field DeviceConfigurationRequestDataBlock 'deviceConfigurationRequestDataBlock']
+            [field CEMI                                'cEMI' ['totalLength - (6 + deviceConfigurationRequestDataBlock.lengthInBytes)']]
         ]
-        ['0x0311' DeviceConfigurationResponse
-            [implicit uint 8 'structureLength' 'lengthInBytes']
-            [field    uint 8 'communicationChannelId']
-            [field    uint 8 'sequenceCounter']
-            [field    uint 8 'status']
+        ['0x0311' DeviceConfigurationAck
+            [field DeviceConfigurationAckDataBlock 'deviceConfigurationAckDataBlock']
         ]
-        ['0x0420' TunnelingRequest
-            [implicit uint 8 'structureLength' 'lengthInBytes']
-            [field    uint 8 'communicationChannelId']
-            [field    uint 8 'sequenceCounter']
-            [reserved uint 8 '0x00']
-            [field    CEMI 'cEMI']
+        ['0x0420' TunnelingRequest [uint 16 'totalLength']
+            [field TunnelingRequestDataBlock 'tunnelingRequestDataBlock']
+            [field CEMI                      'cEMI' ['totalLength - (6 + tunnelingRequestDataBlock.lengthInBytes)']]
         ]
         ['0x0421' TunnelingResponse
-            [implicit uint 8 'structureLength' 'lengthInBytes']
-            [field    uint 8 'communicationChannelId']
-            [field    uint 8 'sequenceCounter']
-            [field    uint 8 'status']
+            [field TunnelingResponseDataBlock 'tunnelingResponseDataBlock']
         ]
     ]
 ]
@@ -126,7 +114,7 @@
 [type 'DIBSuppSvcFamilies'
     [implicit   uint 8       'structureLength' 'lengthInBytes']
     [field      uint 8       'descriptionType']
-    [arrayField ServiceId    'serviceIds' length '3']
+    [arrayField ServiceId    'serviceIds' count '3']
 ]
 
 [type 'HPAIDataEndpoint'
@@ -161,6 +149,34 @@
     ]
 ]
 
+[type 'DeviceConfigurationRequestDataBlock'
+    [implicit uint 8 'structureLength' 'lengthInBytes']
+    [field    uint 8 'communicationChannelId']
+    [field    uint 8 'sequenceCounter']
+    [reserved uint 8 '0x00']
+]
+
+[type 'DeviceConfigurationAckDataBlock'
+    [implicit uint 8 'structureLength' 'lengthInBytes']
+    [field    uint 8 'communicationChannelId']
+    [field    uint 8 'sequenceCounter']
+    [field    uint 8 'status']
+]
+
+[type 'TunnelingRequestDataBlock'
+    [implicit uint 8 'structureLength' 'lengthInBytes']
+    [field    uint 8 'communicationChannelId']
+    [field    uint 8 'sequenceCounter']
+    [reserved uint 8 '0x00']
+]
+
+[type 'TunnelingResponseDataBlock'
+    [implicit uint 8 'structureLength' 'lengthInBytes']
+    [field    uint 8 'communicationChannelId']
+    [field    uint 8 'sequenceCounter']
+    [field    uint 8 'status']
+]
+
 [type 'IPAddress'
     [arrayField uint 8 'addr' count '4']
 ]
@@ -200,7 +216,28 @@
     ]
 ]
 
-[type 'CEMI'
-    [field uint 8 'test']
+[discriminatedType 'CEMI' [uint 8 'size']
+    [discriminator uint 8 'messageCode']
+    [typeSwitch 'messageCode'
+        ['0xFC' CEMIMPropReadReq
+            [field uint 16 'interfaceObjectType']
+            [field uint  8 'objectInstance']
+            [field uint  8 'propertyId']
+            [field uint  4 'numberOfElements']
+            [field uint 12 'startIndex']
+        ]
+        ['0xFB' CEMIMPropReadCon
+            [field uint 16 'interfaceObjectType']
+            [field uint  8 'objectInstance']
+            [field uint  8 'propertyId']
+            [field uint  4 'numberOfElements']
+            [field uint 12 'startIndex']
+        ]
+        ['0x2B' CEMILBusmonInd
+            [field      uint 8 'additionalInformationLength']
+            [arrayField uint 8 'additionalInformation' count 'additionalInformationLength']
+            [arrayField uint 8 'rawFrame'              count 'size - (additionalInformationLength + 2)']
+        ]
+    ]
 ]
 
diff --git a/sandbox/test-java-knxnetip-driver/src/test/resources/testsuite/KNXNetIPTestsuite.xml b/sandbox/test-java-knxnetip-driver/src/test/resources/testsuite/KNXNetIPTestsuite.xml
index 86aa5b3..759de02 100644
--- a/sandbox/test-java-knxnetip-driver/src/test/resources/testsuite/KNXNetIPTestsuite.xml
+++ b/sandbox/test-java-knxnetip-driver/src/test/resources/testsuite/KNXNetIPTestsuite.xml
@@ -27,7 +27,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <SearchRequest className="org.apache.plc4x.java.knxnetip.SearchRequest">
-        <protocolVersion>16</protocolVersion>
         <hpaiIDiscoveryEndpoint>
           <hostProtocolCode>1</hostProtocolCode>
           <ipAddress>
@@ -50,7 +49,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <SearchResponse className="org.apache.plc4x.java.knxnetip.SearchResponse">
-        <protocolVersion>16</protocolVersion>
         <hpaiControlEndpoint>
           <hostProtocolCode>1</hostProtocolCode>
           <ipAddress>
@@ -146,6 +144,9 @@
             <serviceIds className="org.apache.plc4x.java.knxnetip.KnxNetIpDeviceManagement">
               <version>1</version>
             </serviceIds>
+            <serviceIds className="org.apache.plc4x.java.knxnetip.KnxNetIpTunneling">
+              <version>1</version>
+            </serviceIds>
           </serviceIds>
         </dibSuppSvcFamilies>
       </SearchResponse>
@@ -158,7 +159,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <DescriptionRequest className="org.apache.plc4x.java.knxnetip.DescriptionRequest">
-        <protocolVersion>16</protocolVersion>
         <hpaiControlEndpoint>
           <hostProtocolCode>1</hostProtocolCode>
           <ipAddress>
@@ -181,7 +181,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <DescriptionResponse className="org.apache.plc4x.java.knxnetip.DescriptionResponse">
-        <protocolVersion>16</protocolVersion>
         <dibDeviceInfo>
           <descriptionType>1</descriptionType>
           <knxMedium>2</knxMedium>
@@ -265,6 +264,9 @@
             <serviceIds className="org.apache.plc4x.java.knxnetip.KnxNetIpDeviceManagement">
               <version>1</version>
             </serviceIds>
+            <serviceIds className="org.apache.plc4x.java.knxnetip.KnxNetIpTunneling">
+              <version>1</version>
+            </serviceIds>
           </serviceIds>
         </dibSuppSvcFamilies>
       </DescriptionResponse>
@@ -277,7 +279,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <ConnectionRequest className="org.apache.plc4x.java.knxnetip.ConnectionRequest">
-        <protocolVersion>16</protocolVersion>
         <hpaiDiscoveryEndpoint>
           <hostProtocolCode>1</hostProtocolCode>
           <ipAddress>
@@ -315,7 +316,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <ConnectionResponse className="org.apache.plc4x.java.knxnetip.ConnectionResponse">
-        <protocolVersion>16</protocolVersion>
         <communicationChannelId>102</communicationChannelId>
         <status>0</status>
         <hpaiDataEndpoint>
@@ -347,7 +347,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <ConnectionStateRequest className="org.apache.plc4x.java.knxnetip.ConnectionStateRequest">
-        <protocolVersion>16</protocolVersion>
         <communicationChannelId>102</communicationChannelId>
         <hpaiControlEndpoint>
           <hostProtocolCode>1</hostProtocolCode>
@@ -371,7 +370,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <ConnectionStateResponse className="org.apache.plc4x.java.knxnetip.ConnectionStateResponse">
-        <protocolVersion>16</protocolVersion>
         <communicationChannelId>102</communicationChannelId>
         <status>0</status>
       </ConnectionStateResponse>
@@ -384,27 +382,33 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <DeviceConfigurationRequest className="org.apache.plc4x.java.knxnetip.DeviceConfigurationRequest">
-        <protocolVersion>16</protocolVersion>
-        <communicationChannelId>103</communicationChannelId>
-        <sequenceCounter>0</sequenceCounter>
-        <cemi>
-          <test>252</test>
+        <deviceConfigurationRequestDataBlock>
+          <communicationChannelId>103</communicationChannelId>
+          <sequenceCounter>0</sequenceCounter>
+        </deviceConfigurationRequestDataBlock>
+        <cemi className="org.apache.plc4x.java.knxnetip.CEMIMPropReadReq">
+          <interfaceObjectType>0</interfaceObjectType>
+          <objectInstance>1</objectInstance>
+          <propertyId>83</propertyId>
+          <numberOfElements>1</numberOfElements>
+          <startIndex>1</startIndex>
         </cemi>
       </DeviceConfigurationRequest>
     </xml>
   </testcase>
 
   <testcase>
-    <name>Device Configuration Response</name>
+    <name>Device Configuration Ack</name>
     <raw>06100311000a04670000</raw>
     <root-type>KNXNetIPMessage</root-type>
     <xml>
-      <DeviceConfigurationResponse className="org.apache.plc4x.java.knxnetip.DeviceConfigurationResponse">
-        <protocolVersion>16</protocolVersion>
-        <communicationChannelId>103</communicationChannelId>
-        <sequenceCounter>0</sequenceCounter>
-        <status>0</status>
-      </DeviceConfigurationResponse>
+      <DeviceConfigurationAck className="org.apache.plc4x.java.knxnetip.DeviceConfigurationAck">
+        <deviceConfigurationAckDataBlock>
+          <communicationChannelId>103</communicationChannelId>
+          <sequenceCounter>0</sequenceCounter>
+          <status>0</status>
+        </deviceConfigurationAckDataBlock>
+      </DeviceConfigurationAck>
     </xml>
   </testcase>
 
@@ -414,7 +418,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <DisconnectRequest className="org.apache.plc4x.java.knxnetip.DisconnectRequest">
-        <protocolVersion>16</protocolVersion>
         <communicationChannelId>103</communicationChannelId>
         <hpaiControlEndpoint>
           <hostProtocolCode>1</hostProtocolCode>
@@ -438,7 +441,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <DisconnectResponse className="org.apache.plc4x.java.knxnetip.DisconnectResponse">
-        <protocolVersion>16</protocolVersion>
         <communicationChannelId>102</communicationChannelId>
         <status>0</status>
       </DisconnectResponse>
@@ -451,11 +453,32 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <TunnelingRequest className="org.apache.plc4x.java.knxnetip.TunnelingRequest">
-        <protocolVersion>16</protocolVersion>
-        <communicationChannelId>107</communicationChannelId>
-        <sequenceCounter>0</sequenceCounter>
-        <cemi>
-          <test>43</test>
+        <tunnelingRequestDataBlock>
+          <communicationChannelId>107</communicationChannelId>
+          <sequenceCounter>0</sequenceCounter>
+        </tunnelingRequestDataBlock>
+        <cemi className="org.apache.plc4x.java.knxnetip.CEMILBusmonInd">
+          <additionalInformationLength>7</additionalInformationLength>
+          <additionalInformation>
+            <additionalInformation>3</additionalInformation>
+            <additionalInformation>1</additionalInformation>
+            <additionalInformation>5</additionalInformation>
+            <additionalInformation>4</additionalInformation>
+            <additionalInformation>2</additionalInformation>
+            <additionalInformation>69</additionalInformation>
+            <additionalInformation>2</additionalInformation>
+          </additionalInformation>
+          <rawFrame>
+            <rawFrame>188</rawFrame>
+            <rawFrame>54</rawFrame>
+            <rawFrame>10</rawFrame>
+            <rawFrame>30</rawFrame>
+            <rawFrame>12</rawFrame>
+            <rawFrame>225</rawFrame>
+            <rawFrame>0</rawFrame>
+            <rawFrame>129</rawFrame>
+            <rawFrame>13</rawFrame>
+          </rawFrame>
         </cemi>
       </TunnelingRequest>
     </xml>
@@ -467,10 +490,11 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <TunnelingResponse className="org.apache.plc4x.java.knxnetip.TunnelingResponse">
-        <protocolVersion>16</protocolVersion>
-        <communicationChannelId>107</communicationChannelId>
-        <sequenceCounter>0</sequenceCounter>
-        <status>0</status>
+        <tunnelingResponseDataBlock>
+          <communicationChannelId>107</communicationChannelId>
+          <sequenceCounter>0</sequenceCounter>
+          <status>0</status>
+        </tunnelingResponseDataBlock>
       </TunnelingResponse>
     </xml>
   </testcase>
@@ -481,7 +505,6 @@
     <root-type>KNXNetIPMessage</root-type>
     <xml>
       <ConnectionRequest className="org.apache.plc4x.java.knxnetip.ConnectionRequest">
-        <protocolVersion>16</protocolVersion>
         <hpaiDiscoveryEndpoint>
           <hostProtocolCode>1</hostProtocolCode>
           <ipAddress>