You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2021/09/26 13:45:12 UTC

[plc4x] branch develop updated: feat: mspec extension with parameterized type refs, assert, try, const

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 22c9f00  feat: mspec extension with parameterized type refs, assert, try, const
22c9f00 is described below

commit 22c9f005abab73da1ab88e4b88d718657667fb3f
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Sep 24 23:58:06 2021 +0200

    feat: mspec extension with parameterized type refs, assert, try, const
    
    1. parameters on type refs
        with that change it is now possible to target a discriminated child in advance.
    2. assert keyword
        with that change it is possible to throw a ParserAssertException (in java, or errors in other languages). This field is similar to a const but instead of a ParseException a ParserAssertException is thrown. In contrast to a const the check expression can be dynamic (e.g. virtual fields now working on develop)
    3. try keyword to prefix fields:
        with that change it is possible to try to parse some content and in case an assert fails it resets the buffer.
    4. const is now extended to type reference
       this change allows enums to be used as const values.
---
 .../BaseFreemarkerLanguageTemplateHelper.java      |  33 +-
 .../language/go/GoLanguageTemplateHelper.java      |   2 +-
 .../templates/go/data-io-template.go.ftlh          |   1 +
 .../resources/templates/go/enum-template.go.ftlh   |   1 +
 .../resources/templates/go/model-template.go.ftlh  | 165 +++++++++-
 .../templates/go/parser-factory-template.go.ftlh   |   1 +
 .../go/xml-parser-factory-template.go.ftlh         |   1 +
 .../language/java/JavaLanguageTemplateHelper.java  |   8 +-
 .../templates/java/data-io-template.java.ftlh      |   1 +
 .../java/enum-package-info-template.java.ftlh      |   1 +
 .../templates/java/enum-template.java.ftlh         |   1 +
 .../resources/templates/java/io-template.java.ftlh | 276 +++++++++++++---
 .../templates/java/pojo-template.java.ftlh         |  12 +-
 .../plugins/codegenerator/language/mspec/MSpec.g4  |  15 +-
 .../definitions/DefaultComplexTypeDefinition.java  |  47 ++-
 .../DefaultDiscriminatedComplexTypeDefinition.java |   8 +-
 .../model/definitions/DefaultTypeDefinition.java   |   2 +-
 .../mspec/model/fields/DefaultAbstractField.java   |   6 +-
 .../mspec/model/fields/DefaultArrayField.java      |   6 +-
 ...tOptionalField.java => DefaultAssertField.java} |   8 +-
 .../mspec/model/fields/DefaultChecksumField.java   |   6 +-
 .../mspec/model/fields/DefaultConstField.java      |   6 +-
 .../model/fields/DefaultDiscriminatorField.java    |   6 +-
 .../mspec/model/fields/DefaultEnumField.java       |   6 +-
 .../language/mspec/model/fields/DefaultField.java  |  20 +-
 .../mspec/model/fields/DefaultImplicitField.java   |   6 +-
 .../model/fields/DefaultManualArrayField.java      |   6 +-
 .../mspec/model/fields/DefaultManualField.java     |   6 +-
 .../mspec/model/fields/DefaultOptionalField.java   |   6 +-
 .../mspec/model/fields/DefaultPaddingField.java    |   6 +-
 .../mspec/model/fields/DefaultReservedField.java   |   6 +-
 .../mspec/model/fields/DefaultSimpleField.java     |   6 +-
 .../mspec/model/fields/DefaultSwitchField.java     |   9 +-
 .../mspec/model/fields/DefaultUnknownField.java    |   6 +-
 .../mspec/model/fields/DefaultVirtualField.java    |   6 +-
 .../language/mspec/model/fields/TryField.java      |  25 +-
 .../mspec/parser/MessageFormatListener.java        |  99 ++++--
 .../readwrite/model/CIPEncapsulationReadRequest.go |   2 +-
 .../model/CIPEncapsulationReadResponse.go          |   2 +-
 .../readwrite/model/DF1CommandRequestMessage.go    |   2 +-
 .../plc4go/bacnetip/readwrite/ParserHelper.go      |   7 +
 .../plc4go/bacnetip/readwrite/XmlParserHelper.go   |   8 +
 .../bacnetip/readwrite/model/APDUComplexAck.go     |   2 +-
 .../readwrite/model/APDUConfirmedRequest.go        |   2 +-
 .../plc4go/bacnetip/readwrite/model/APDUError.go   |   2 +-
 .../readwrite/model/APDUUnconfirmedRequest.go      |   2 +-
 .../bacnetip/readwrite/model/BACnetComplexTag.go   | 351 +++++++++++++++++++++
 .../readwrite/model/BACnetComplexTagBitString.go   | 202 ++++++++++++
 .../readwrite/model/BACnetComplexTagBoolean.go     | 139 ++++++++
 .../model/BACnetComplexTagCharacterString.go       | 139 ++++++++
 .../readwrite/model/BACnetComplexTagDate.go        | 139 ++++++++
 .../readwrite/model/BACnetComplexTagDouble.go      | 159 ++++++++++
 .../readwrite/model/BACnetComplexTagEnumerated.go  | 183 +++++++++++
 .../readwrite/model/BACnetComplexTagNull.go        | 139 ++++++++
 .../model/BACnetComplexTagObjectIdentifier.go      | 139 ++++++++
 .../readwrite/model/BACnetComplexTagOctetString.go | 165 ++++++++++
 .../readwrite/model/BACnetComplexTagReal.go        | 159 ++++++++++
 .../model/BACnetComplexTagSignedInteger.go         | 183 +++++++++++
 .../readwrite/model/BACnetComplexTagTime.go        | 139 ++++++++
 .../model/BACnetComplexTagUnsignedInteger.go       | 183 +++++++++++
 .../BACnetConfirmedServiceRequestWriteProperty.go  |   6 +-
 .../bacnetip/readwrite/model/BACnetDataType.go     | 200 ++++++++++++
 .../model/BACnetServiceAckReadProperty.go          |   2 +-
 .../model/BACnetUnconfirmedServiceRequestWhoHas.go | 233 +++++---------
 .../bacnetip/readwrite/model/BVLCForwardedNPDU.go  |   2 +-
 .../readwrite/model/BVLCOriginalBroadcastNPDU.go   |   2 +-
 .../readwrite/model/BVLCOriginalUnicastNPDU.go     |   2 +-
 .../plc4go/bacnetip/readwrite/model/NPDU.go        |   4 +-
 .../df1/readwrite/model/DF1SymbolMessageFrame.go   |   2 +-
 .../plc4go/eip/readwrite/model/CipRRData.go        |   2 +-
 .../eip/readwrite/model/CipUnconnectedRequest.go   |   2 +-
 .../eip/readwrite/model/MultipleServiceRequest.go  |   2 +-
 .../firmata/readwrite/model/FirmataCommandSysex.go |   2 +-
 .../readwrite/model/FirmataMessageCommand.go       |   2 +-
 .../readwrite/model/ApduControlContainer.go        |   2 +-
 .../knxnetip/readwrite/model/ApduDataContainer.go  |   2 +-
 .../knxnetip/readwrite/model/ApduDataOther.go      |   2 +-
 .../CEMIAdditionalInformationRelativeTimestamp.go  |   2 +-
 .../model/ComObjectTableRealisationType6.go        |   2 +-
 .../knxnetip/readwrite/model/ConnectionRequest.go  |   6 +-
 .../knxnetip/readwrite/model/ConnectionResponse.go |   8 +-
 .../ConnectionResponseDataBlockTunnelConnection.go |   2 +-
 .../readwrite/model/ConnectionStateRequest.go      |   2 +-
 .../knxnetip/readwrite/model/DescriptionRequest.go |   2 +-
 .../readwrite/model/DescriptionResponse.go         |   4 +-
 .../readwrite/model/DeviceConfigurationAck.go      |   2 +-
 .../readwrite/model/DeviceConfigurationRequest.go  |   4 +-
 .../knxnetip/readwrite/model/DisconnectRequest.go  |   2 +-
 .../knxnetip/readwrite/model/KnxManufacturer.go    |  26 +-
 .../plc4go/knxnetip/readwrite/model/LBusmonInd.go  |   2 +-
 .../plc4go/knxnetip/readwrite/model/LDataCon.go    |   2 +-
 .../knxnetip/readwrite/model/LDataExtended.go      |   4 +-
 .../plc4go/knxnetip/readwrite/model/LDataInd.go    |   2 +-
 .../plc4go/knxnetip/readwrite/model/LDataReq.go    |   2 +-
 .../plc4go/knxnetip/readwrite/model/LPollData.go   |   2 +-
 .../knxnetip/readwrite/model/SearchRequest.go      |   2 +-
 .../knxnetip/readwrite/model/SearchResponse.go     |   6 +-
 .../knxnetip/readwrite/model/TunnelingRequest.go   |   4 +-
 .../knxnetip/readwrite/model/TunnelingResponse.go  |   2 +-
 .../plc4go/s7/readwrite/model/COTPPacket.go        |   2 +-
 .../plc4go/s7/readwrite/model/S7Message.go         |   4 +-
 .../plc4go/s7/readwrite/model/S7PayloadAlarm8.go   |   2 +-
 .../s7/readwrite/model/S7PayloadAlarmAckInd.go     |   2 +-
 .../plc4go/s7/readwrite/model/S7PayloadAlarmS.go   |   2 +-
 .../plc4go/s7/readwrite/model/S7PayloadAlarmSC.go  |   2 +-
 .../plc4go/s7/readwrite/model/S7PayloadAlarmSQ.go  |   2 +-
 .../readwrite/model/S7PayloadDiagnosticMessage.go  |   2 +-
 .../plc4go/s7/readwrite/model/S7PayloadNotify.go   |   2 +-
 .../plc4go/s7/readwrite/model/S7PayloadNotify8.go  |   2 +-
 ...PayloadUserDataItemCpuFunctionReadSzlRequest.go |   2 +-
 ...ayloadUserDataItemCpuFunctionReadSzlResponse.go |   2 +-
 .../model/S7VarRequestParameterItemAddress.go      |   2 +-
 ...aultBitInput.java => ParseAssertException.java} |  18 +-
 .../plc4x/java/spi/generation/ReadBuffer.java      |   2 +
 .../java/spi/generation/ReadBufferByteBased.java   |   5 +
 .../java/spi/generation/ReadBufferJsonBased.java   |   6 +
 .../java/spi/generation/ReadBufferXmlBased.java    |   6 +
 .../java/spi/generation/io/MyDefaultBitInput.java  |  11 +
 pom.xml                                            |   6 +-
 .../resources/protocols/bacnetip/bacnetip.mspec    |  65 +++-
 sandbox/test-java-bacnetip-driver/pom.xml          |   8 -
 .../bacnetip/PassiveBacNetIpDriver2Manual.java     |   4 +-
 122 files changed, 3543 insertions(+), 449 deletions(-)

diff --git a/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java b/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
index e494acd..bca0e61 100644
--- a/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
+++ b/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
@@ -686,9 +686,20 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
      * @return list of symbolic names for the discriminators.
      */
     public List<String> getDiscriminatorNames() {
-        TypeDefinition baseType = thisType;
-        if (thisType.getParentType() != null) {
-            baseType = thisType.getParentType();
+        return getDiscriminatorNames(thisType);
+    }
+
+    /**
+     * Get an ordered list of generated names for the discriminators.
+     * These names can be used to access the type definitions as well as well as the values.
+     *
+     * @param baseType the type to get the discriminator Names from
+     *
+     * @return list of symbolic names for the discriminators.
+     */
+    public List<String> getDiscriminatorNames(TypeDefinition baseType) {
+        if (baseType.getParentType() != null) {
+            baseType = baseType.getParentType();
         }
         final SwitchField switchField = getSwitchField(baseType);
         List<String> discriminatorNames = new ArrayList<>();
@@ -722,9 +733,21 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
      * @return true if a field with the given name already exists in the same type.
      */
     public boolean isDiscriminatorField(String discriminatorName) {
-        List<String> names = getDiscriminatorNames();
+        return isDiscriminatorField(thisType, discriminatorName);
+    }
+
+    /**
+     * Check if there's any field with the given name.
+     * This is required to suppress the generation of a virtual field
+     * in case a discriminated field is providing the information.
+     *
+     * @param discriminatorName name of the virtual name
+     * @return true if a field with the given name already exists in the same type.
+     */
+    public boolean isDiscriminatorField(TypeDefinition typeDefinition, String discriminatorName) {
+        List<String> names = getDiscriminatorNames(typeDefinition);
         if (names != null) {
-            return getDiscriminatorNames().stream()
+            return names.stream()
                 .anyMatch(field -> field.equals(discriminatorName));
         }
         return false;
diff --git a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
index 9347768..64be124 100644
--- a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
+++ b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
@@ -527,7 +527,7 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                 return tracer + "\"" + ((StringLiteral) term).getValue() + "\"";
             } else if (term instanceof VariableLiteral) {
                 tracer = tracer.dive("variable literal instanceOf");
-                return tracer+toVariableExpression(fieldType, (VariableLiteral) term, parserArguments, serializerArguments, serialize, suppressPointerAccess);
+                return tracer + toVariableExpression(fieldType, (VariableLiteral) term, parserArguments, serializerArguments, serialize, suppressPointerAccess);
             } else {
                 throw new RuntimeException("Unsupported Literal type " + term.getClass().getName());
             }
diff --git a/code-generation/language-go/src/main/resources/templates/go/data-io-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/data-io-template.go.ftlh
index 248c793..fef9ef0 100644
--- a/code-generation/language-go/src/main/resources/templates/go/data-io-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/data-io-template.go.ftlh
@@ -23,6 +23,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.go.GoLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
 <#-- Declare the name and type of variables declared locally inside the template -->
 <#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" -->
diff --git a/code-generation/language-go/src/main/resources/templates/go/enum-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/enum-template.go.ftlh
index 4677be9..98d883f 100644
--- a/code-generation/language-go/src/main/resources/templates/go/enum-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/enum-template.go.ftlh
@@ -24,6 +24,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.go.GoLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.EnumTypeDefinition" -->
 <#-- @ftlvariable name="simpleTypeReference" type="org.apache.plc4x.plugins.codegenerator.types.references.SimpleTypeReference" -->
 ${helper.fileName(protocolName, languageName, outputFlavor)?replace(".", "/")}/model/${type.name}.go
diff --git a/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
index 7c148fc..cd5264e 100644
--- a/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
@@ -23,6 +23,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.go.GoLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
 <#-- Declare the name and type of variables declared locally inside the template -->
 <#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" -->
@@ -87,7 +88,11 @@ import (
 
 // Constant values.
 	<#list type.constFields as field>
+		<#if helper.isEnumField(field)>
+const ${type.name}_${field.name?upper_case} ${helper.getLanguageTypeNameForField(field)} = ${field.referenceValue?replace(".","_")}
+		<#else>
 const ${type.name}_${field.name?upper_case} ${helper.getLanguageTypeNameForField(field)} = ${field.referenceValue}
+		</#if>
 	</#list>
 </#if>
 
@@ -431,6 +436,8 @@ func (m *${type.name}) ParentLengthInBits() uint16 {
 	// Const Field (${constField.name})
 				<#if helper.getLanguageTypeNameForTypeReference(constField.type) = "string">
 	lengthInBits += uint16(${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)})
+				<#elseif helper.isEnumTypeReference(constField.type)>
+	lengthInBits += ${helper.getEnumBaseTypeReference(constField.type).sizeInBits};
 				<#else>
 	lengthInBits += ${simpleTypeReference.sizeInBits}
 				</#if>
@@ -550,7 +557,11 @@ func (m *${type.name}) LengthInBytes() uint16 {
 	return m.LengthInBits() / 8
 }
 
-func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${parserArgument.name} <#if helper.isComplexTypeReference(parserArgument.type) && !helper.isEnumTypeReference(parserArgument.type)>*</#if>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) (*<#if type.parentType?has_content>${type.parentType.name}<#else>${type.name}</#if>, error) {
+<#assign hasParserArguments=type.parserArguments?has_content/>
+<#assign parserArgumentList><#if hasParserArguments><#list type.parserArguments as parserArgument>${parserArgument.name}${tracer.dive("parserArgument")} <#if helper.isComplexTypeReference(parserArgument.type) && !helper.isEnumTypeReference(parserArgument.type)>*</#if>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if></#assign>
+<#assign hasParentParserArguments=(type.parentType?? && type.parentType.parserArguments?has_content && type.parentType.parserArguments?filter(arg -> hasParserArguments && !type.parserArguments?map(argument->argument.name)?seq_contains(arg.name) || !hasParserArguments)?has_content)>
+<#assign parentParserArgumentList><#if hasParentParserArguments><#list type.parentType.parserArguments?filter(arg -> (hasParserArguments && !type.parserArguments?map(argument->argument.name)?seq_contains(arg.name) || !hasParserArguments) && helper.isNonDiscriminatorField(arg.name)) as parserArgument>${tracer.dive("parentParserArgument")}${parserArgument.name} <#if helper.isComplexTypeReference(parserArgument.type) && !helper.isEnumTypeReference(parserArgument.type)>*</#if>${helper.getLan [...]
+func ${type.name}Parse(readBuffer utils.ReadBuffer<#if hasParserArguments>, ${parserArgumentList}</#if><#if hasParentParserArguments>, ${parentParserArgumentList}</#if>) (*<#if type.parentType?has_content>${type.parentType.name}<#else>${type.name}</#if>, error) {
 	if pullErr := readBuffer.PullContext("${type.name}"); pullErr != nil {
 		return nil, pullErr
 	}
@@ -672,7 +683,25 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 				<#assign simpleTypeReference = constField.type>
 
 	// Const Field (${constField.name})
+				<#if helper.isEnumTypeReference(constField.type)>
+                    <#if constField.fieldName?has_content>
+	${constField.name}${constField.fieldName?cap_first}, _${constField.name}${constField.fieldName?cap_first}Err := ${helper.getReadBufferReadMethodCall(constField.type.name, helper.getConstFieldSimpleTypeReference(constField.type, constField.fieldName))}
+	if _${constField.name}${constField.fieldName?cap_first}Err != nil {
+		return nil, errors.Wrap(_${constField.name}${constField.fieldName?cap_first}Err, "Error serializing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" />
+	}
+	${constField.name}, _${constField.name}Err := ${helper.getLanguageTypeNameForField(field)}FirstEnumForField${constField.fieldName?cap_first}(${constField.name}${constField.fieldName?cap_first})
+	if _${constField.name}Err != nil {
+		return nil, errors.Wrap(_${constField.name}Err, "Error serializing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" />
+	}
+                    <#else>
+	${constField.name}, _${constField.name}Err := ${helper.getLanguageTypeNameForField(field)}Parse(readBuffer)
+	if _${constField.name}Err != nil {
+		return nil, errors.Wrap(_${constField.name}Err, "Error parsing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" />
+	}
+                    </#if> 
+				<#else>
 	${constField.name}, _${constField.name}Err := ${helper.getReadBufferReadMethodCall(constField.name, simpleTypeReference)}
+				</#if>
 	if _${constField.name}Err != nil {
 		return nil, errors.Wrap(_${constField.name}Err, "Error parsing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" />
 	}
@@ -834,13 +863,83 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 		}
 		${optionalField.name} = &_val
 			<#else>
-		_val, _err := ${helper.getLanguageTypeNameForField(field)}Parse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument>${helper.toTypedParseExpression(helper.getArgumentType(optionalField.type, parserArgument?index), parserArgument, type.parserArguments)}<#sep>, </#sep></#list></#if>)
+				<@compress single_line=true>
+                <#assign complexTypeReference=optionalField.type>
+                <#assign typeName=complexTypeReference.name>
+                <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(complexTypeReference)>
+                <#if helper.isDiscriminatedChildTypeDefinition(typeDefinition)>
+                <#-- Usually you don't use child directly unless they are parameterized #-->
+                    <#assign typeName=typeDefinition.parentType.name>
+                    <#assign typeDefinition=typeDefinition.parentType>
+                </#if>
+				<#assign hasFieldParams=field.params?has_content>
+				<#assign fieldParams>
+					<#if hasFieldParams>
+						,
+						<#list field.params as parserArgument>
+							${helper.toTypedParseExpression(helper.getArgumentType(optionalField.type, parserArgument?index), parserArgument, type.parserArguments)}
+							<#sep>, </#sep>
+						</#list>
+					</#if>
+				</#assign>
+				<#assign hasRefParams=complexTypeReference.params?has_content && typeDefinition.parserArguments?has_content>
+				<#assign refParams>
+                    <#if hasRefParams>
+						,
+						<#list complexTypeReference.params as typeParam>
+							${helper.toTypedParseExpression(null, typeParam, null)}
+							<#sep>, </#sep>
+						</#list>
+                    </#if>
+				</#assign>
+		_val, _err := ${typeName}Parse(readBuffer${fieldParams}${refParams})
+                </...@compress>
+
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing '${optionalField.name}' field")<@emitImport import="github.com/pkg/errors" />
 		}
-		${optionalField.name} = _val
+		${optionalField.name} = Cast${helper.getLanguageTypeNameForField(field)}(_val)
 			</#if>
 	}
+			<#break>
+			<#case "assert">
+				<#assign assertField = field>
+
+	// Assert Field (${assertField.name}) (Can be skipped, if a given expression evaluates to false)
+				<#if assertField.conditionExpression.contains("curPos")>
+	curPos = readBuffer.GetPos() - startPos
+				</#if>
+			<#if helper.isSimpleTypeReference(assertField.type)>
+	${assertField.name}, _err := ${helper.getReadBufferReadMethodCall(assertField.name, assertField.type)}
+	if _err != nil {
+		return nil, errors.Wrap(_err, "Error parsing '${assertField.name}' field")<@emitImport import="github.com/pkg/errors" />
+	}
+			<#elseif helper.isEnumField(field)>
+	${assertField.name}, _err := ${helper.getLanguageTypeNameForField(field)}Parse(readBuffer)
+	if _err != nil {
+		return nil, errors.Wrap(_err, "Error parsing '${assertField.name}' field")<@emitImport import="github.com/pkg/errors" />
+	}
+			<#else>
+				<@compress single_line=true>
+                <#assign complexTypeReference=assertField.type>
+                <#assign typeName=complexTypeReference.name>
+                <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(complexTypeReference)>
+                <#if helper.isDiscriminatedChildTypeDefinition(typeDefinition)>
+                <#-- Usually you don't use child directly unless they are parameterized #-->
+                    <#assign typeName=typeDefinition.parentType.name>
+                    <#assign typeDefinition=typeDefinition.parentType>
+                </#if>
+				<#assign hasFieldParams=field.params?has_content>
+				<#assign fieldParams><#if hasFieldParams>, <#list field.params as parserArgument>${helper.toTypedParseExpression(helper.getArgumentType(assertField.type, parserArgument?index), parserArgument, type.parserArguments)}<#sep>, </#sep></#list></#if></#assign>
+				<#assign hasRefParams=complexTypeReference.params?has_content && typeDefinition.parserArguments?has_content>
+				<#assign refParams> <#if hasRefParams> <#assign filteredCompleTypeReferences=helper.removeDiscriminatorsFromReferenceParams(assertField, complexTypeReference)> , <#list filteredCompleTypeReferences as typeParam>${helper.toTypedParseExpression(null, typeParam, null)}<#sep>, </#sep></#list> </#if> </#assign>
+                </...@compress>
+	_val, _err := ${helper.getLanguageTypeNameForField(field)}Parse(readBuffer${fieldParams}${refParams})
+	if _err != nil {
+		return nil, errors.Wrap(_err, "Error parsing '${assertField.name}' field")<@emitImport import="github.com/pkg/errors" />
+	}
+	${assertField.name} = Cast${helper.getLanguageTypeNameForField(field)}(_val)
+			</#if>
 				<#break>
 			<#case "padding">
 				<#assign paddingField = field>
@@ -892,7 +991,43 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 	}
 				</#if>
     <#assign simpleFieldLogicalName><#if helper.isSimpleTypeReference(simpleField.type) && !helper.isEnumField(field)>${simpleField.name}<#else>${simpleField.typeName}</#if></#assign>
-	${simpleField.name}, _${simpleField.name}Err := <#if helper.isSimpleTypeReference(simpleField.type)>${helper.getReadBufferReadMethodCall(simpleFieldLogicalName, simpleField.type, null, field)}<#else>${simpleField.type.name}Parse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument><#if helper.isOptionalField(helper.getFieldForNameFromCurrentOrParent(parserArgument.name))>*<#elseif helper.needsReferenceForParserArgument(parserArgument.name, helper.getArgumentTy [...]
+	<@compress single_line=true>
+	${simpleField.name}, _${simpleField.name}Err :=
+	<#if helper.isSimpleTypeReference(simpleField.type)>
+		${helper.getReadBufferReadMethodCall(simpleFieldLogicalName, simpleField.type, null, field)}
+	<#else>
+        <#assign complexTypeReference=simpleField.type>
+        <#assign typeName=complexTypeReference.name>
+        <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(complexTypeReference)>
+        <#if helper.isDiscriminatedChildTypeDefinition(typeDefinition)>
+        <#-- Usually you don't use child directly unless they are parameterized #-->
+            <#assign typeName=typeDefinition.parentType.name>
+            <#assign typeDefinition=typeDefinition.parentType>
+        </#if>
+        <#assign hasFieldParams=field.params?has_content>
+        <#assign fieldParams>
+            <#if hasFieldParams>
+				,
+                <#list field.params as parserArgument>
+                    ${helper.toTypedParseExpression(helper.getArgumentType(simpleField.type, parserArgument?index), parserArgument, type.parserArguments)}
+                    <#sep>, </#sep>
+                </#list>
+            </#if>
+        </#assign>
+        <#assign hasRefParams=complexTypeReference.params?has_content && typeDefinition.parserArguments?has_content>
+        <#assign refParams>
+            <#if hasRefParams>
+				,
+                <#list complexTypeReference.params as typeParam>
+                    ${helper.toTypedParseExpression(null, typeParam, null)}
+                    <#sep>, </#sep>
+                </#list>
+            </#if>
+        </#assign>
+		${typeName}Parse(readBuffer${fieldParams}${refParams})
+	</#if>
+    </...@compress>
+
 	if _${simpleField.name}Err != nil {
 			<#if helper.isEnumField(field)>
 		return nil, errors.Wrap(_${simpleField.name}Err, "Error parsing '${simpleField.name}' field")<@emitImport import="github.com/pkg/errors" />
@@ -959,7 +1094,7 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 	// Create a partially initialized instance
 	_child := &${type.name}{
 		<#list type.propertyFields as field>
-		${field.name?cap_first}: ${field.name},
+		${field.name?cap_first}: <#if helper.isComplex(field) && !helper.isEnumField(field) && !helper.isArrayField(field)>Cast${helper.getLanguageTypeNameForField(field)}(</#if>${field.name}<#if helper.isComplex(field) && !helper.isEnumField(field) && !helper.isArrayField(field)>)</#if>,
 		</#list>
 		Parent: &${type.parentType.name}{},
 	}
@@ -1073,11 +1208,29 @@ func (m *${type.name}) Serialize(writeBuffer utils.WriteBuffer<#if helper.getSer
 					<#assign constField = field>
 					<#assign simpleTypeReference = constField.type>
 
+					<#if helper.isEnumTypeReference(constField.type)>
+                        <#if constField.fieldName?has_content>
+                            <#assign enumValueFieldAccessor=type.name+"_"+constField.name?upper_case>
+	// Const field (${constField.name})
+	_${constField.name}Err := ${helper.getWriteBufferWriteMethodCall(constField.type.name, helper.getConstFieldSimpleTypeReference(constField.type, constField.fieldName), enumValueFieldAccessor, constField, "utils.WithAdditionalStringRepresentation(${type.name}_${constField.name?upper_case}.name())")}
+	if _${constField.name}Err != nil {
+		return errors.Wrap(_${constField.name}Err, "Error serializing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" />
+	}
+                        <#else>
+	// Const field (${constField.name})
+	${constField.name} := Cast${helper.getLanguageTypeNameForField(field)}(${type.name}_${constField.name?upper_case})
+	_${constField.name}Err := ${constField.name}.Serialize(writeBuffer)
+	if _${constField.name}Err != nil {
+		return errors.Wrap(_${constField.name}Err, "Error serializing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" />
+	}
+                        </#if>
+					<#else>
 	// Const Field (${constField.name})
 	_${constField.name}Err := ${helper.getWriteBufferWriteMethodCall(constField.name, simpleTypeReference, constField.referenceValue, field)}
 	if _${constField.name}Err != nil {
 		return errors.Wrap(_${constField.name}Err, "Error serializing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" />
 	}
+					</#if>
 					<#break>
 				<#case "discriminator">
 					<#assign discriminatorField = field>
@@ -1115,7 +1268,7 @@ func (m *${type.name}) Serialize(writeBuffer utils.WriteBuffer<#if helper.getSer
 	if _${enumField.name}Err != nil {
 		return errors.Wrap(_${enumField.name}Err, "Error serializing '${enumField.name}' field")<@emitImport import="github.com/pkg/errors" />
 	}
-				</#if>
+						</#if>
 	if popErr := writeBuffer.PopContext("${enumField.name}"); popErr != nil {
 		return popErr
 	}
diff --git a/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
index 76a4df7..d6c9f8e 100644
--- a/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
@@ -23,6 +23,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.go.GoLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
 <#-- Declare the name and type of variables declared locally inside the template -->
 <#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" -->
diff --git a/code-generation/language-go/src/main/resources/templates/go/xml-parser-factory-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/xml-parser-factory-template.go.ftlh
index 480a8c5..2139408 100644
--- a/code-generation/language-go/src/main/resources/templates/go/xml-parser-factory-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/xml-parser-factory-template.go.ftlh
@@ -23,6 +23,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.go.GoLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
 <#-- Declare the name and type of variables declared locally inside the template -->
 <#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" -->
diff --git a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index b7d8d3d..43a5ea7 100644
--- a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -554,9 +554,9 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
         return tracer + toExpression(field, term, variableLiteral -> tracer.dive("variableExpressionGenerator") + toVariableParseExpression(field, variableLiteral, parserArguments));
     }
 
-    public String toSerializationExpression(TypedField field, Term term, Argument[] serializerArgments) {
+    public String toSerializationExpression(TypedField field, Term term, Argument[] serializerArguments) {
         Tracer tracer = Tracer.start("toSerializationExpression");
-        return tracer + toExpression(field, term, variableLiteral -> tracer.dive("variableExpressionGenerator") + toVariableSerializationExpression(field, variableLiteral, serializerArgments));
+        return tracer + toExpression(field, term, variableLiteral -> tracer.dive("variableExpressionGenerator") + toVariableSerializationExpression(field, variableLiteral, serializerArguments));
     }
 
     private String toExpression(TypedField field, Term term, Function<VariableLiteral, String> variableExpressionGenerator) {
@@ -640,6 +640,10 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
         }
     }
 
+    public String toVariableEnumAccessExpression(VariableLiteral variableLiteral) {
+        return variableLiteral.getName();
+    }
+
     private String toVariableParseExpression(TypedField field, VariableLiteral variableLiteral, Argument[] parserArguments) {
         Tracer tracer = Tracer.start("toVariableParseExpression");
         // CAST expressions are special as we need to add a ".class" to the second parameter in Java.
diff --git a/code-generation/language-java/src/main/resources/templates/java/data-io-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
index c1d2609..ca8926a 100644
--- a/code-generation/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
@@ -23,6 +23,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.java.JavaLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
 <#-- Declare the name and type of variables declared locally inside the template -->
 <#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" -->
diff --git a/code-generation/language-java/src/main/resources/templates/java/enum-package-info-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/enum-package-info-template.java.ftlh
index a1b0853..8c79f5b 100644
--- a/code-generation/language-java/src/main/resources/templates/java/enum-package-info-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/enum-package-info-template.java.ftlh
@@ -23,6 +23,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.java.JavaLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 ${helper.packageName(protocolName, languageName, outputFlavor)?replace(".", "/")}/types/package-info.java
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
diff --git a/code-generation/language-java/src/main/resources/templates/java/enum-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/enum-template.java.ftlh
index c0f01b6..a5ad8a1 100644
--- a/code-generation/language-java/src/main/resources/templates/java/enum-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/enum-template.java.ftlh
@@ -24,6 +24,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.java.JavaLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.EnumTypeDefinition" -->
 ${helper.packageName(protocolName, languageName, outputFlavor)?replace(".", "/")}/types/${type.name}.java
 /*
diff --git a/code-generation/language-java/src/main/resources/templates/java/io-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/io-template.java.ftlh
index c2230ac..c50b1ba 100644
--- a/code-generation/language-java/src/main/resources/templates/java/io-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/io-template.java.ftlh
@@ -23,6 +23,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.java.JavaLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
 <#-- Declare the name and type of variables declared locally inside the template -->
 <#-- @ftlvariable name="typedField" type="org.apache.plc4x.plugins.codegenerator.types.fields.TypedField" -->
@@ -35,6 +36,7 @@
 <#-- @ftlvariable name="manualArrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ManualArrayField" -->
 <#-- @ftlvariable name="manualField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ManualField" -->
 <#-- @ftlvariable name="optionalField" type="org.apache.plc4x.plugins.codegenerator.types.fields.OptionalField" -->
+<#-- @ftlvariable name="assertField" type="org.apache.plc4x.plugins.codegenerator.types.fields.AssertField" -->
 <#-- @ftlvariable name="paddingField" type="org.apache.plc4x.plugins.codegenerator.types.fields.PaddingField" -->
 <#-- @ftlvariable name="reservedField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ReservedField" -->
 <#-- @ftlvariable name="simpleField" type="org.apache.plc4x.plugins.codegenerator.types.fields.SimpleField" -->
@@ -145,7 +147,11 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
 </#if>
 </#if>
 <#-- Here come the actual parse and serialize methods that actually do the parsing and serlaizing -->
-    public static ${type.name}<#if helper.isDiscriminatedChildTypeDefinition()>Builder</#if> staticParse(ReadBuffer readBuffer<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws ParseException {
+    <#assign hasParserArguments=type.parserArguments?has_content/>
+    <#assign parserArgumentList><#if hasParserArguments><#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
+    <#assign hasParentParserArguments=(type.parentType?? && type.parentType.parserArguments?has_content && type.parentType.parserArguments?filter(arg -> hasParserArguments && !type.parserArguments?map(argument->argument.name)?seq_contains(arg.name) || !hasParserArguments)?has_content)>
+    <#assign parentParserArgumentList><#if hasParentParserArguments><#list type.parentType.parserArguments?filter(arg -> hasParserArguments && !type.parserArguments?map(argument->argument.name)?seq_contains(arg.name) || !hasParserArguments) as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
+    public static ${type.name}<#if helper.isDiscriminatedChildTypeDefinition()>Builder</#if> staticParse(ReadBuffer readBuffer<#if hasParserArguments>, ${parserArgumentList}</#if><#if hasParentParserArguments>, ${parentParserArgumentList}</#if>) throws ParseException {
         readBuffer.pullContext("${type.name}");
         int startPos = readBuffer.getPos();
         int curPos;
@@ -208,7 +214,13 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
                                 (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parserArgument, type.parserArguments)})<#sep>, </#sep>
                             </#if>
                         </#list>
-                    </#if>)
+                    </#if>
+                    <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(arrayField.type)>
+                    <#-- We expose the parentParserArguments to the child here too-->
+                    <#assign hasParentParseArguments=typeDefinition.parentType?? && typeDefinition.parentType.parserArguments?has_content>
+                    <#assign parentParseArguments><#if hasParentParseArguments><#list typeDefinition.parentType.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
+                    <#if hasParentParseArguments>, ${tracer.dive("count array parent parse arguments")} ${parentParseArguments}</#if>
+                    )
                     <#if helper.isDiscriminatedChildTypeDefinition(helper.getTypeDefinitionForTypeReference(arrayField.type))>
                         .build()
                     </#if>
@@ -225,7 +237,29 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         List<${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}> _${arrayField.name}List = new LinkedList<>();
         long ${arrayField.name}EndPos = readBuffer.getPos() + _${arrayField.name}Length;
         while(readBuffer.getPos() < ${arrayField.name}EndPos) {
-            _${arrayField.name}List.add(<#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall("", simpleTypeReference, "", arrayField)}<#else>${arrayField.type.name}IO.staticParse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayF [...]
+                    <@compress single_line=true>
+            _${arrayField.name}List.add(
+                        <#if helper.isSimpleTypeReference(arrayField.type)>
+                            <#assign simpleTypeReference = arrayField.type>
+                            ${helper.getReadBufferReadMethodCall("", simpleTypeReference, "", arrayField)}
+                        <#else>
+                            ${arrayField.type.name}IO.staticParse(readBuffer
+                            <#if field.params?has_content>
+                                ,
+                                <#list field.params as parserArgument>
+                                    (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)})
+                                    (${helper.toParseExpression(arrayField, parserArgument, type.parserArguments)})<#sep>, </#sep>
+                                </#list>
+                            </#if>
+                            <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(arrayField.type)>
+                        <#-- We expose the parentParserArguments to the child here too-->
+                            <#assign hasParentParseArguments=typeDefinition.parentType?? && typeDefinition.parentType.parserArguments?has_content>
+                            <#assign parentParseArguments><#if hasParentParseArguments><#list typeDefinition.parentType.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
+                            <#if hasParentParseArguments>, ${tracer.dive("count array parent parse arguments")} ${parentParseArguments}</#if>
+                            )
+                        </#if>
+                        );
+                    </...@compress>
             <#-- After parsing, update the current position, but only if it's needed -->
                 <#if arrayField.loopExpression.contains("curPos")>
             curPos = readBuffer.getPos() - startPos;
@@ -236,7 +270,29 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         // Terminated array
         List<${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}> _${arrayField.name}List = new LinkedList<>();
         while(!((boolean) (${helper.toParseExpression(arrayField, arrayField.loopExpression, type.parserArguments)}))) {
-            _${arrayField.name}List.add(<#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall("", simpleTypeReference, "", arrayField)}<#else>${arrayField.type.name}IO.staticParse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayF [...]
+                    <@compress single_line=true>
+            _${arrayField.name}List.add(
+                        <#if helper.isSimpleTypeReference(arrayField.type)>
+                            <#assign simpleTypeReference = arrayField.type>
+                            ${helper.getReadBufferReadMethodCall("", simpleTypeReference, "", arrayField)}
+                        <#else>
+                            ${arrayField.type.name}IO.staticParse(readBuffer
+                            <#if field.params?has_content>
+                                ,
+                                <#list field.params as parserArgument>
+                                    (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)})
+                                    (${helper.toParseExpression(arrayField, parserArgument, type.parserArguments)})<#sep>, </#sep>
+                                </#list>
+                            </#if>
+                            <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(arrayField.type)>
+                        <#-- We expose the parentParserArguments to the child here too-->
+                            <#assign hasParentParseArguments=typeDefinition.parentType?? && typeDefinition.parentType.parserArguments?has_content>
+                            <#assign parentParseArguments><#if hasParentParseArguments><#list typeDefinition.parentType.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
+                            <#if hasParentParseArguments>, ${tracer.dive("count array parent parse arguments")} ${parentParseArguments}</#if>
+                            )
+                        </#if>
+                        );
+                    </...@compress>
 
             <#-- After parsing, update the current position, but only if it's needed -->
                 <#if arrayField.loopExpression.contains("curPos")>
@@ -277,10 +333,14 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         <#break>
     <#case "const">
         <#assign constField = field>
-        <#assign simpleTypeReference = constField.type>
 
         // Const Field (${constField.name})
+        <#if helper.isSimpleTypeReference(constField.type)>
+        <#assign simpleTypeReference = constField.type>
         ${helper.getLanguageTypeNameForField(field)} ${constField.name} = ${helper.getReadBufferReadMethodCall(constField.name, simpleTypeReference, "", constField)};
+        <#else>
+        ${helper.getLanguageTypeNameForField(field)} ${constField.name} = ${helper.getLanguageTypeNameForField(field)}.enumForValue(${helper.getReadBufferReadMethodCall(constField.name, helper.getEnumBaseTypeReference(constField.type), "", constField)});
+        </#if>
         if(${constField.name} != ${type.name}.${constField.name?upper_case}) {
             throw new ParseException("Expected constant value " + ${type.name}.${constField.name?upper_case} + " but got " + ${constField.name});
         }
@@ -292,7 +352,22 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         <#if helper.isEnumField(field)>
         ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = ${helper.getLanguageTypeNameForField(discriminatorField)}.enumForValue(${helper.getReadBufferReadMethodCall(discriminatorField.name, helper.getEnumBaseTypeReference(discriminatorField.type), "", discriminatorField)});
         <#else>
-        ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = <#if helper.isSimpleTypeReference(discriminatorField.type)>${helper.getReadBufferReadMethodCall(discriminatorField.name, discriminatorField.type, "", discriminatorField)}<#else>${discriminatorField.type.name}IO.staticParse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(discriminatorField.type, parserArgumen [...]
+            <@compress single_line=true>
+        ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} =
+                <#if helper.isSimpleTypeReference(discriminatorField.type)>
+                    ${helper.getReadBufferReadMethodCall(discriminatorField.name, discriminatorField.type, "", discriminatorField)}
+                <#else>
+                    ${discriminatorField.type.name}IO.staticParse(readBuffer
+                    <#if field.params?has_content>
+                        ,
+                        <#list field.params as parserArgument>
+                            (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(discriminatorField.type, parserArgument?index), true)})
+                            (${helper.toParseExpression(discriminatorField, parserArgument, type)})<#sep>, </#sep>
+                        </#list>
+                    </#if>
+                    )
+                </#if>;
+            </...@compress>
         </#if>
 
         <#break>
@@ -391,11 +466,83 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         </#if>
         ${helper.getLanguageTypeNameForField(field)} ${optionalField.name} = null;
         if(${helper.toParseExpression(optionalField, optionalField.conditionExpression, type.parserArguments)}) {
-            <#if helper.isEnumField(field)>
-            ${optionalField.name} = ${helper.getLanguageTypeNameForField(optionalField)}.enumForValue(${helper.getReadBufferReadMethodCall(optionalField.name, helper.getEnumBaseTypeReference(optionalField.type), "", optionalField)});
+        <@compress single_line=true>
+            ${optionalField.name} =
+            <#if helper.isEnumField(optionalField)>
+             ${helper.getLanguageTypeNameForField(optionalField)}.enumForValue(
+                ${helper.getReadBufferReadMethodCall(optionalField.name, helper.getEnumBaseTypeReference(optionalField.type), "", optionalField)}
+            )
+            <#elseif helper.isComplexTypeReference(optionalField.type)>
+                <#assign complexTypeReference=optionalField.type>
+                <#assign typeName=complexTypeReference.name>
+                <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(complexTypeReference)>
+                <#if helper.isDiscriminatedChildTypeDefinition(typeDefinition)>
+                    <#-- Usually you don't use child directly unless they are parameterized #-->
+                    <#assign typeName=typeDefinition.parentType.name>
+                    <#assign typeDefinition=typeDefinition.parentType>
+                </#if>
+                <#-- We downcast to the referenced type-->
+            (${optionalField.type.name}) ${typeName}IO.staticParse(
+                readBuffer
+                <#if field.params?has_content>,
+                    <#list field.params as parserArgument>
+                        (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(optionalField.type, parserArgument?index), true)})
+                        (${helper.toParseExpression(optionalField, parserArgument, type.parserArguments)})<#sep>, </#sep>
+                    </#list>
+                </#if>
+                <#if complexTypeReference.params?has_content && typeDefinition.parserArguments?has_content>
+                    <#assign argumentOffset=0>
+                    <#if field.params?has_content><#assign argumentOffset=field.params?size></#if>
+                    ,
+                    <#list complexTypeReference.params as typeParam>
+                    <#-- We cast here explicitly as java sometimes can't infer the type. e.g. 0 is a int and not a byte#-->
+                        (${helper.getLanguageTypeNameForTypeReference(typeDefinition.parserArguments[typeParam?index + argumentOffset].type, true)})
+                        ${helper.toAccessExpression(null, typeParam, null)}<#sep>, </#sep>
+                    </#list>
+                </#if>
+                )
             <#else>
-            ${optionalField.name} = <#if helper.isSimpleTypeReference(optionalField.type)>${helper.getReadBufferReadMethodCall(optionalField.name, optionalField.type, "", optionalField)}<#else>${optionalField.type.name}IO.staticParse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(optionalField.type, parserArgument?index), true)}) (${helper.toParseExpression(optionalField, parserArgument, [...]
+             ${helper.getReadBufferReadMethodCall(optionalField.name, optionalField.type, "", optionalField)}
             </#if>
+            ;
+        </...@compress>
+
+        }
+        <#break>
+    <#case "assert">
+        <#assign assertField = field>
+
+        // Assert Field
+        <#if helper.isEnumField(assertField)>
+        ${helper.getLanguageTypeNameForField(field)} ${assertField.name} = ${helper.getLanguageTypeNameForField(assertField)}.enumForValue(${helper.getReadBufferReadMethodCall(assertField.name, helper.getEnumBaseTypeReference(assertField.type), "", assertField)});
+        <#elseif helper.isComplexTypeReference(assertField.type)>
+            <#assign complexTypeReference=assertField.type>
+            <#assign typeName=complexTypeReference.name>
+            <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(complexTypeReference)>
+            <#if helper.isDiscriminatedChildTypeDefinition(typeDefinition)>
+                <#assign typeName=typeDefinition.getParentType().name>
+            </#if>
+            <@compress single_line=true>
+        ${helper.getLanguageTypeNameForField(field)} ${assertField.name} = (${assertField.type.name}) ${typeName}IO.staticParse(readBuffer
+                <#if field.params?has_content>
+                    ,
+                    <#list field.params as parserArgument>
+                        (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(assertField.type, parserArgument?index), true)})
+                        (${helper.toParseExpression(assertField, parserArgument, type.parserArguments)})<#sep>, </#sep>
+                    </#list>
+                </#if>
+                <#if assertField.type.params?has_content>
+                    ,
+                    <#list assertField.type.params as typeParam>
+                        ${helper.toAccessExpression(null, typeParam, null)}<#sep>, </#sep>
+                    </#list>
+                </#if>);
+            </...@compress>
+        <#else>
+        ${helper.getLanguageTypeNameForField(field)} ${assertField.name} = ${helper.getReadBufferReadMethodCall(assertField.name, assertField.type, "", assertField)};
+        </#if>
+        if(${assertField.name} != ${helper.toParseExpression(assertField, assertField.conditionExpression, type.parserArguments)}) {
+            throw new ParseAssertException("assertField ${assertField.name} with value " + ${assertField.name} + " didn't match the expected value " + ${helper.toParseExpression(assertField, assertField.conditionExpression, type.parserArguments)});
         }
         <#break>
     <#case "padding">
@@ -428,40 +575,75 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
     <#case "simple">
         <#assign simpleField = field>
 
+        <#if simpleField.isTry()>
+            <#-- TODO: we need to initalize base types-->
+        ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = null;
+        curPos = readBuffer.getPos();
+        try {
+        </#if>
+
         <#if !helper.isSimpleTypeReference(simpleField.type)>
         readBuffer.pullContext("${simpleField.name}");
         </#if>
 
         // Simple Field (${simpleField.name})
-        <#if helper.isEnumField(field)>
-        // enum based simple field with type ${simpleField.type.name}
-        ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = ${helper.getLanguageTypeNameForField(simpleField)}.enumForValue(${helper.getReadBufferReadMethodCall(simpleField.type.name, helper.getEnumBaseTypeReference(simpleField.type), "", simpleField)});
-        <#else>
-        <#assign simpleFieldLogicalName><#if helper.isSimpleTypeReference(simpleField.type)>${simpleField.name}<#else>${simpleField.typeName}</#if></#assign>
         <@compress single_line=true>
-            ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} =
-            <#if helper.isSimpleTypeReference(simpleField.type)>
-                <#assign simpleTypeReference = simpleField.type>
-                ${helper.getReadBufferReadMethodCall(simpleFieldLogicalName, simpleTypeReference, "", simpleField)}
-            <#else>
-                <#assign complexTypeReference = simpleField.type>
-                ${complexTypeReference.name}IO.staticParse(readBuffer
-                <#if field.params?has_content>
-                    ,
-                    <#list field.params as parserArgument>
-                        <#if helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(simpleField.type, parserArgument?index), true) = 'String'>
-                            ${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(simpleField.type, parserArgument?index), true)}.valueOf(${helper.toParseExpression(simpleField, parserArgument, type.parserArguments)})<#sep>, </#sep>
-                        <#else>
-                            (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(simpleField.type, parserArgument?index), true)}) (${helper.toParseExpression(simpleField, parserArgument, type.parserArguments)})<#sep>, </#sep>
-                        </#if>
+        <#if !simpleField.isTry()>${helper.getLanguageTypeNameForField(simpleField)}</#if> ${simpleField.name} =
+        <#assign simpleFieldLogicalName><#if helper.isSimpleTypeReference(simpleField.type)>${simpleField.name}<#else>${simpleField.typeName}</#if></#assign>
+        <#if helper.isEnumField(simpleField)>
+        /* enum based simple field with type ${simpleField.type.name} */
+        ${helper.getLanguageTypeNameForField(simpleField)}.enumForValue(
+            ${helper.getReadBufferReadMethodCall(simpleField.type.name, helper.getEnumBaseTypeReference(simpleField.type), "", simpleField)}
+        );
+        <#elseif helper.isComplexTypeReference(simpleField.type)>
+            <#assign complexTypeReference = simpleField.type>
+            <#assign typeName=complexTypeReference.name>
+            <#assign typeDefinition = helper.getTypeDefinitionForTypeReference(complexTypeReference)>
+            <#if helper.isDiscriminatedChildTypeDefinition(typeDefinition)>
+                <#-- Usually you don't use child directly unless they are parameterized #-->
+                <#assign typeName=typeDefinition.parentType.name>
+                <#assign typeDefinition=typeDefinition.parentType>
+            </#if>
+                <#-- We downcast to the referenced type -->
+        (${simpleField.type.name}) ${typeName}IO.staticParse(readBuffer
+            <#if field.params?has_content>,
+                <#list field.params as parserArgument>
+                    <#if helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(complexTypeReference, parserArgument?index), true) = 'String'>
+            ${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(complexTypeReference, parserArgument?index), true)}
+                .valueOf(${helper.toParseExpression(simpleField, parserArgument, type.parserArguments)})<#sep>, </#sep>
+                    <#else>
+                (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(complexTypeReference, parserArgument?index), true)})
+                (${helper.toParseExpression(simpleField, parserArgument, type.parserArguments)})<#sep>, </#sep>
+                    </#if>
+                </#list>
+            </#if>
+            <#if complexTypeReference.params?has_content && typeDefinition.parserArguments?has_content>
+                <#assign argumentOffset=0>
+                <#if field.params?has_content><#assign argumentOffset=field.params?size></#if>
+            ,
+                    <#list complexTypeReference.params as typeParam>
+                            <#-- We cast here explicitly as java sometimes can't infer the type. e.g. 0 is a int and not a byte#-->
+            (${helper.getLanguageTypeNameForTypeReference(typeDefinition.parserArguments[typeParam?index + argumentOffset].type, true)})
+            ${helper.toAccessExpression(null, typeParam, null)}<#sep>, </#sep>
                     </#list>
-                </#if>)
-            </#if>;
-        </...@compress>
+            </#if>
+                )
+        <#else>
+        ${helper.getReadBufferReadMethodCall(simpleFieldLogicalName, simpleField.type, "", simpleField)}
         </#if>
+            ;
+        </...@compress>
+
         <#if !helper.isSimpleTypeReference(simpleField.type)>
         readBuffer.closeContext("${simpleField.name}");
         </#if>
+
+
+        <#if simpleField.isTry()>
+        } catch(ParseAssertException ignore){
+            readBuffer.reset(curPos);
+        }
+        </#if>
         <#break>
     <#case "switch">
         <#assign switchField = field>
@@ -469,8 +651,15 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         // Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
         ${type.name}Builder builder = null;
         <#list switchField.cases as case>
-                <#if case.discriminatorValues?has_content>if(<#list case.discriminatorValues as discriminatorValue>EvaluationHelper.equals(${helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)}, <#if helper.discriminatorValueNeedsStringEqualityCheck(switchField.discriminatorExpressions[discriminatorValue?index])>"${discriminatorValue}"<#elseif helper.isComplexTypeReference(helper.getDiscriminatorTypes()[field.discriminatorE [...]
-            builder = ${case.name}IO.staticParse(readBuffer<#if case.parserArguments?has_content>, <#list case.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>);
+            <#if case.discriminatorValues?has_content>if(<#list case.discriminatorValues as discriminatorValue>EvaluationHelper.equals(${helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)}, <#if helper.discriminatorValueNeedsStringEqualityCheck(switchField.discriminatorExpressions[discriminatorValue?index])>"${discriminatorValue}"<#elseif helper.isComplexTypeReference(helper.getDiscriminatorTypes()[field.discriminatorExpre [...]
+            <@compress single_line=true>
+            <#assign hasCaseParseArguments=case.parserArguments?has_content>
+            <#assign caseParseArguments><#if hasCaseParseArguments><#list case.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
+            <#-- We expose the parentParserArguments to the child here too-->
+            <#assign hasParentCaseParseArguments=case.parentType?? && case.parentType.parserArguments?has_content && case.parentType.parserArguments?filter(arg -> hasCaseParseArguments && !case.parserArguments?map(argument->argument.name)?seq_contains(arg.name) || !hasCaseParseArguments)?has_content>
+            <#assign parentCaseParseArguments><#if hasParentCaseParseArguments><#list case.parentType.parserArguments?filter(arg -> hasCaseParseArguments && !case.parserArguments?map(argument->argument.name)?seq_contains(arg.name) || !hasCaseParseArguments) as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
+            builder = ${case.name}IO.staticParse(readBuffer<#if hasCaseParseArguments>, ${tracer.dive("case parse arguments")} ${caseParseArguments}</#if><#if hasParentCaseParseArguments>, ${tracer.dive("case parent parse arguments")} ${parentCaseParseArguments}</#if>);
+            </...@compress>
         }<#sep> else </#sep>
         </#list>
         if (builder == null) {
@@ -560,11 +749,18 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         <#break>
     <#case "const">
         <#assign constField = field>
-        <#assign simpleTypeReference = constField.type>
 
         // Const Field (${constField.name})
-        <#if helper.getLanguageTypeNameForField(field) = 'float'>${helper.getWriteBufferWriteMethodCall(simpleTypeReference, constField.referenceValue + "f", field)};
-        <#else>${helper.getWriteBufferWriteMethodCall(constField.name, simpleTypeReference, constField.referenceValue, field)};
+        <#if helper.isSimpleTypeReference(constField.type)>
+            <#assign simpleTypeReference = constField.type>
+            <#if helper.getLanguageTypeNameForField(field) = 'float'>
+        ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, constField.referenceValue + "f", field)};
+            <#else>
+        ${helper.getWriteBufferWriteMethodCall(constField.name, simpleTypeReference, constField.referenceValue, field)};
+            </#if>
+        <#else>
+            <#assign enumTypeReference = constField.type>
+            ${helper.getWriteBufferWriteMethodCall(helper.getTypeDefinitionForTypeReference(enumTypeReference).name, helper.getEnumBaseTypeReference(enumTypeReference), "(" + type.name + "." + constField.name?upper_case + ".getValue())", field, "WithReaderWriterArgs.WithAdditionalStringRepresentation("+ type.name + "." + constField.name?upper_case + ".name())")};
         </#if>
         <#break>
     <#case "discriminator">
@@ -718,9 +914,9 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
 <#if helper.isDiscriminatedChildTypeDefinition()>
     public static class ${type.name}Builder implements ${type.parentType.name}IO.${type.parentType.name}Builder {
         <#if type.propertyFields?has_content>
-        <#list type.propertyFields as field>
+            <#list type.propertyFields as field>
         private final ${helper.getLanguageTypeNameForField(field)}<#if field.loopType??>[]</#if> ${field.name};
-        </#list>
+            </#list>
         </#if>
 
         public ${type.name}Builder(<#list type.propertyFields as field>${helper.getLanguageTypeNameForField(field)}<#if field.loopType??>[]</#if> ${field.name}<#sep>, </#sep></#list>) {
@@ -730,7 +926,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         }
 
         public ${type.name} build(<#list type.parentType.propertyFields as field>${helper.getLanguageTypeNameForField(field)}<#if field.loopType??>[]</#if> ${field.name}<#sep>, </#sep></#list>) {
-            return new ${type.name}(<#list type.getAllPropertyFields() as field>${field.name}<#sep>, </#sep></#list>);
+            return new ${type.name}(<#list type.allPropertyFields as field>${field.name}<#sep>, </#sep></#list>);
         }
     }
 
diff --git a/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
index 582c94a..ab85f9a 100644
--- a/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
@@ -23,6 +23,7 @@
 <#-- @ftlvariable name="protocolName" type="java.lang.String" -->
 <#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
 <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.java.JavaLanguageTemplateHelper" -->
+<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
 <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
 <#-- Declare the name and type of variables declared locally inside the template -->
 <#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" -->
@@ -111,7 +112,7 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
     <#assign discriminatedParentType = type>
     <#-- @ftlvariable name="discriminatedParentType" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
     // Abstract accessors for discriminator values.
-    <#list helper.getDiscriminatorTypes() as discriminatorName, discriminatorType>
+    <#list helper.discriminatorTypes as discriminatorName, discriminatorType>
         <#-- If the discriminator name matches that of another field, suppress the methods generation -->
         <#if !helper.isNonDiscriminatorField(discriminatorName)>
     public abstract ${helper.getLanguageTypeNameForTypeReference(discriminatorType)} get${discriminatorName?cap_first}();
@@ -126,7 +127,7 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
     public static final ${helper.getLanguageTypeNameForField(field)} ${field.name?upper_case} = <#if helper.getLanguageTypeNameForField(field) = 'float'>${field.referenceValue}f<#else>${field.referenceValue}</#if>;
 </#list>
 </#if>
-<#-- Prpoerty fields are fields that require a property in the pojo -->
+<#-- Property fields are fields that require a property in the pojo -->
 <#if type.propertyFields?has_content>
 
     // Properties.
@@ -214,10 +215,15 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
         <#break>
     <#case "const">
         <#assign constField = field>
-        <#assign simpleTypeReference = constField.type>
+        <#assign typeReference = constField.type>
 
         // Const Field (${constField.name})
+        <#if helper.isSimpleTypeReference(typeReference)>
+        <#assign simpleTypeReference = typeReference>
         lengthInBits += ${simpleTypeReference.sizeInBits};
+        <#else>
+        lengthInBits += ${helper.getEnumBaseTypeReference(typeReference).sizeInBits};
+        </#if>
         <#break>
     <#case "discriminator">
         <#assign discriminatorField = field>
diff --git a/code-generation/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4 b/code-generation/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
index 5a331ee..53332c7 100644
--- a/code-generation/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
+++ b/code-generation/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
@@ -34,7 +34,7 @@ complexType
  ;
 
 fieldDefinition
- : LBRACKET field (LBRACKET params=multipleExpressions RBRACKET)? RBRACKET
+ : LBRACKET tryParse? field (LBRACKET params=multipleExpressions RBRACKET)? RBRACKET
  ;
 
 dataIoDefinition
@@ -49,6 +49,7 @@ field
  | discriminatorField
  | enumField
  | implicitField
+ | assertField
  | manualArrayField
  | manualField
  | optionalField
@@ -73,7 +74,7 @@ checksumField
  ;
 
 constField
- : 'const' type=dataType name=idExpression expected=expression
+ : 'const' type=typeReference name=idExpression expected=expression
  ;
 
 discriminatorField
@@ -88,6 +89,10 @@ implicitField
  : 'implicit' type=dataType name=idExpression serializeExpression=expression
  ;
 
+assertField
+ : 'assert' type=typeReference name=idExpression condition=expression
+ ;
+
 manualArrayField
  : 'manualArray' type=typeReference name=idExpression loopType=ARRAY_LOOP_TYPE loopExpression=expression parseExpression=expression serializeExpression=expression lengthExpression=expression
  ;
@@ -129,7 +134,7 @@ enumValueDefinition
  ;
 
 typeReference
- : complexTypeReference=IDENTIFIER_LITERAL
+ : complexTypeReference=IDENTIFIER_LITERAL (LBRACKET params=multipleExpressions RBRACKET)?
  | simpleTypeReference=dataType
  ;
 
@@ -150,6 +155,10 @@ dataType
  | base='dateTime'
  ;
 
+tryParse
+ : 'try'
+ ;
+
 argument
  : type=typeReference name=idExpression
  ;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
index 670b520..3bc873e 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
@@ -48,36 +48,57 @@ public class DefaultComplexTypeDefinition extends DefaultTypeDefinition implemen
 
     @Override
     public List<SimpleField> getSimpleFields() {
-        return fields.stream().filter(field -> field instanceof SimpleField).map(
-            field -> (SimpleField) field).collect(Collectors.toList());
+        return fields.stream()
+            .filter(SimpleField.class::isInstance)
+            .map(SimpleField.class::cast)
+            .collect(Collectors.toList());
     }
 
     @Override
     public List<ConstField> getConstFields() {
-        return fields.stream().filter(field -> field instanceof ConstField).map(
-            field -> (ConstField) field).collect(Collectors.toList());
+        return fields.stream()
+            .filter(ConstField.class::isInstance)
+            .map(ConstField.class::cast)
+            .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<AssertField> getAssertFields() {
+        return fields.stream()
+            .filter(AssertField.class::isInstance)
+            .map(AssertField.class::cast)
+            .collect(Collectors.toList());
     }
 
     @Override
     public List<PropertyField> getPropertyFields() {
-        return fields.stream().filter(field -> ((field instanceof PropertyField) && !(field instanceof ConstField) && !(field instanceof VirtualField))).map(field -> (PropertyField) field)
+        return fields.stream()
+            .filter(PropertyField.class::isInstance)
+            .filter(field -> !(field instanceof ConstField) && !(field instanceof VirtualField))
+            .map(PropertyField.class::cast)
             .collect(Collectors.toList());
     }
 
     @Override
     public List<AbstractField> getAbstractFields() {
-        return fields.stream().filter(field -> field instanceof AbstractField).map(
-            field -> (AbstractField) field).collect(Collectors.toList());
+        return fields.stream()
+            .filter(AbstractField.class::isInstance)
+            .map(AbstractField.class::cast)
+            .collect(Collectors.toList());
     }
 
     public List<ImplicitField> getImplicitFields() {
-        return fields.stream().filter(field -> field instanceof ImplicitField).map(
-            field -> (ImplicitField) field).collect(Collectors.toList());
+        return fields.stream()
+            .filter(ImplicitField.class::isInstance)
+            .map(ImplicitField.class::cast)
+            .collect(Collectors.toList());
     }
 
     @Override
     public List<VirtualField> getVirtualFields() {
-        return fields.stream().filter(field -> (field instanceof VirtualField)).map(field -> (VirtualField) field)
+        return fields.stream()
+            .filter(VirtualField.class::isInstance)
+            .map(VirtualField.class::cast)
             .collect(Collectors.toList());
     }
 
@@ -93,10 +114,10 @@ public class DefaultComplexTypeDefinition extends DefaultTypeDefinition implemen
 
     @Override
     public List<PropertyField> getParentPropertyFields() {
-        if (getParentType() != null) {
-            return ((ComplexTypeDefinition) getParentType()).getAllPropertyFields();
+        if (getParentType() == null) {
+            return Collections.emptyList();
         }
-        return Collections.emptyList();
+        return ((ComplexTypeDefinition) getParentType()).getAllPropertyFields();
     }
 
 }
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDiscriminatedComplexTypeDefinition.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDiscriminatedComplexTypeDefinition.java
index a9feacf..c7d39b9 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDiscriminatedComplexTypeDefinition.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDiscriminatedComplexTypeDefinition.java
@@ -37,9 +37,11 @@ public class DefaultDiscriminatedComplexTypeDefinition extends DefaultComplexTyp
     public DiscriminatorField getDiscriminatorField() {
         // For a discriminated type, the discriminator is always defined in the parent type,
         // which is always a DefaultComplexTypeDefinition instance.
-        return ((DefaultComplexTypeDefinition) getParentType()).getFields().stream().filter(
-            field -> field instanceof DiscriminatorField).map(
-            field -> (DiscriminatorField) field).findFirst().orElse(null);
+        return ((DefaultComplexTypeDefinition) getParentType()).getFields().stream()
+            .filter(field -> field instanceof DiscriminatorField)
+            .map(field -> (DiscriminatorField) field)
+            .findFirst()
+            .orElse(null);
     }
 
     public String[] getDiscriminatorValues() {
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultTypeDefinition.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultTypeDefinition.java
index df86645..e72df8a 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultTypeDefinition.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultTypeDefinition.java
@@ -59,7 +59,7 @@ public abstract class DefaultTypeDefinition {
     }
 
     public TypeReference getTypeReference() {
-        return new DefaultComplexTypeReference(getName());
+        return new DefaultComplexTypeReference(getName(), null);
     }
 
 }
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultAbstractField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultAbstractField.java
index 8e88dd8..2bcd33b 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultAbstractField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultAbstractField.java
@@ -23,14 +23,14 @@ 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 DefaultAbstractField extends DefaultTaggedField implements AbstractField {
+public class DefaultAbstractField extends DefaultField implements AbstractField {
 
     private final TypeReference type;
     private final String name;
     private final Term[] params;
 
-    public DefaultAbstractField(String[] tags, TypeReference type, String name, Term[] params) {
-        super(tags);
+    public DefaultAbstractField(String[] tags, boolean isTry, TypeReference type, String name, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.params = params;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultArrayField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultArrayField.java
index cd0cd42..2405869 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultArrayField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultArrayField.java
@@ -22,7 +22,7 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultArrayField extends DefaultTaggedField implements ArrayField {
+public class DefaultArrayField extends DefaultField implements ArrayField {
 
     private final TypeReference type;
     private final String name;
@@ -30,8 +30,8 @@ public class DefaultArrayField extends DefaultTaggedField implements ArrayField
     private final Term loopExpression;
     private final Term[] params;
 
-    public DefaultArrayField(String[] tags, TypeReference type, String name, LoopType loopType, Term loopExpression, Term[] params) {
-        super(tags);
+    public DefaultArrayField(String[] tags, boolean isTry, TypeReference type, String name, LoopType loopType, Term loopExpression, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.loopType = loopType;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultAssertField.java
similarity index 83%
copy from code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java
copy to code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultAssertField.java
index bd6f42a..5299099 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultAssertField.java
@@ -18,19 +18,19 @@
  */
 package org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields;
 
-import org.apache.plc4x.plugins.codegenerator.types.fields.OptionalField;
+import org.apache.plc4x.plugins.codegenerator.types.fields.AssertField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultOptionalField extends DefaultTaggedField implements OptionalField {
+public class DefaultAssertField extends DefaultField implements AssertField {
 
     private final TypeReference type;
     private final String name;
     private final Term conditionExpression;
     private final Term[] params;
 
-    public DefaultOptionalField(String[] tags, TypeReference type, String name, Term conditionExpression, Term[] params) {
-        super(tags);
+    public DefaultAssertField(String[] tags, boolean isTry, TypeReference type, String name, Term conditionExpression, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.conditionExpression = conditionExpression;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultChecksumField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultChecksumField.java
index 5ed22d8..f305320 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultChecksumField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultChecksumField.java
@@ -22,14 +22,14 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.ChecksumField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultChecksumField extends DefaultTaggedField implements ChecksumField {
+public class DefaultChecksumField extends DefaultField implements ChecksumField {
 
     private final TypeReference type;
     private final String name;
     private final Term checksumExpression;
 
-    public DefaultChecksumField(String[] tags, TypeReference type, String name, Term checksumExpression) {
-        super(tags);
+    public DefaultChecksumField(String[] tags, boolean isTry, TypeReference type, String name, Term checksumExpression) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.checksumExpression = checksumExpression;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultConstField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultConstField.java
index bcf2993..ebadc92 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultConstField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultConstField.java
@@ -22,14 +22,14 @@ 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 extends DefaultTaggedField implements ConstField {
+public class DefaultConstField extends DefaultField implements ConstField {
 
     private final TypeReference type;
     private final String name;
     private final Object referenceValue;
 
-    public DefaultConstField(String[] tags, TypeReference type, String name, Object referenceValue) {
-        super(tags);
+    public DefaultConstField(String[] tags, boolean isTry, TypeReference type, String name, Object referenceValue) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.referenceValue = referenceValue;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultDiscriminatorField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultDiscriminatorField.java
index 41ab9d3..aa94673 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultDiscriminatorField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultDiscriminatorField.java
@@ -22,13 +22,13 @@ 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 extends DefaultTaggedField implements DiscriminatorField {
+public class DefaultDiscriminatorField extends DefaultField implements DiscriminatorField {
 
     private final TypeReference type;
     private final String name;
 
-    public DefaultDiscriminatorField(String[] tags, TypeReference type, String name) {
-        super(tags);
+    public DefaultDiscriminatorField(String[] tags, boolean isTry, TypeReference type, String name) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
     }
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultEnumField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultEnumField.java
index 575bef9..c59d159 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultEnumField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultEnumField.java
@@ -22,15 +22,15 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.EnumField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultEnumField extends DefaultTaggedField implements EnumField {
+public class DefaultEnumField extends DefaultField implements EnumField {
 
     private final TypeReference type;
     private final String name;
     private final String fieldName;
     private final Term[] params;
 
-    public DefaultEnumField(String[] tags, TypeReference type, String name, String fieldName, Term[] params) {
-        super(tags);
+    public DefaultEnumField(String[] tags, boolean isTry, TypeReference type, String name, String fieldName, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.fieldName = fieldName;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultField.java
similarity index 66%
copy from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
copy to code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultField.java
index 9a047c2..62fa841 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultField.java
@@ -16,22 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.spi.generation.io;
+package org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields;
 
-import com.github.jinahya.bit.io.ArrayByteInput;
-import com.github.jinahya.bit.io.DefaultBitInput;
+public abstract class DefaultField extends DefaultTaggedField implements TryField {
 
-/**
- * Modified version that exposes the position.
- */
-public class MyDefaultBitInput extends DefaultBitInput<ArrayByteInput> {
+    private final boolean isTry;
 
-    public MyDefaultBitInput(ArrayByteInput delegate) {
-        super(delegate);
+    protected DefaultField(String[] tags, boolean isTry) {
+        super(tags);
+        this.isTry = isTry;
     }
 
-    public long getPos() {
-        return delegate.getIndex();
+    public boolean isTry() {
+        return isTry;
     }
-
 }
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultImplicitField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultImplicitField.java
index d71baaa..ebae488 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultImplicitField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultImplicitField.java
@@ -22,14 +22,14 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.ImplicitField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultImplicitField extends DefaultTaggedField implements ImplicitField {
+public class DefaultImplicitField extends DefaultField implements ImplicitField {
 
     private final TypeReference type;
     private final String name;
     private final Term serializeExpression;
 
-    public DefaultImplicitField(String[] tags, TypeReference type, String name, Term serializeExpression) {
-        super(tags);
+    public DefaultImplicitField(String[] tags, boolean isTry, TypeReference type, String name, Term serializeExpression) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.serializeExpression = serializeExpression;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultManualArrayField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultManualArrayField.java
index 19e1eab..b39a4b6 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultManualArrayField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultManualArrayField.java
@@ -22,7 +22,7 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.ManualArrayField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultManualArrayField extends DefaultTaggedField implements ManualArrayField {
+public class DefaultManualArrayField extends DefaultField implements ManualArrayField {
 
     private final TypeReference type;
     private final String name;
@@ -33,8 +33,8 @@ public class DefaultManualArrayField extends DefaultTaggedField implements Manua
     private final Term lengthExpression;
     private final Term[] params;
 
-    public DefaultManualArrayField(String[] tags, TypeReference type, String name, LoopType loopType, Term loopExpression, Term parseExpression, Term serializeExpression, Term lengthExpression, Term[] params) {
-        super(tags);
+    public DefaultManualArrayField(String[] tags, boolean isTry, TypeReference type, String name, LoopType loopType, Term loopExpression, Term parseExpression, Term serializeExpression, Term lengthExpression, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.loopType = loopType;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultManualField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultManualField.java
index a3952ea..9328418 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultManualField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultManualField.java
@@ -22,7 +22,7 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.ManualField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultManualField extends DefaultTaggedField implements ManualField {
+public class DefaultManualField extends DefaultField implements ManualField {
 
     private final TypeReference type;
     private final String name;
@@ -31,8 +31,8 @@ public class DefaultManualField extends DefaultTaggedField implements ManualFiel
     private final Term lengthExpression;
     private final Term[] params;
 
-    public DefaultManualField(String[] tags, TypeReference type, String name, Term parseExpression, Term serializeExpression, Term lengthExpression, Term[] params) {
-        super(tags);
+    public DefaultManualField(String[] tags, boolean isTry, TypeReference type, String name, Term parseExpression, Term serializeExpression, Term lengthExpression, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.parseExpression = parseExpression;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java
index bd6f42a..3697e59 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultOptionalField.java
@@ -22,15 +22,15 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.OptionalField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultOptionalField extends DefaultTaggedField implements OptionalField {
+public class DefaultOptionalField extends DefaultField implements OptionalField {
 
     private final TypeReference type;
     private final String name;
     private final Term conditionExpression;
     private final Term[] params;
 
-    public DefaultOptionalField(String[] tags, TypeReference type, String name, Term conditionExpression, Term[] params) {
-        super(tags);
+    public DefaultOptionalField(String[] tags, boolean isTry, TypeReference type, String name, Term conditionExpression, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.conditionExpression = conditionExpression;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultPaddingField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultPaddingField.java
index e5d7eed..59f83da 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultPaddingField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultPaddingField.java
@@ -22,7 +22,7 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.PaddingField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultPaddingField extends DefaultTaggedField implements PaddingField {
+public class DefaultPaddingField extends DefaultField implements PaddingField {
 
     private final TypeReference type;
     private final String name;
@@ -30,8 +30,8 @@ public class DefaultPaddingField extends DefaultTaggedField implements PaddingFi
     private final Term paddingCondition;
     private final Term[] params;
 
-    public DefaultPaddingField(String[] tags, TypeReference type, String name, Term paddingValue, Term paddingCondition, Term[] params) {
-        super(tags);
+    public DefaultPaddingField(String[] tags, boolean isTry, TypeReference type, String name, Term paddingValue, Term paddingCondition, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.paddingValue = paddingValue;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultReservedField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultReservedField.java
index 28ec3dd..f535cdf 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultReservedField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultReservedField.java
@@ -22,13 +22,13 @@ 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 extends DefaultTaggedField implements ReservedField {
+public class DefaultReservedField extends DefaultField implements ReservedField {
 
     private final TypeReference type;
     private final Object referenceValue;
 
-    public DefaultReservedField(String[] tags, TypeReference type, Object referenceValue) {
-        super(tags);
+    public DefaultReservedField(String[] tags, boolean isTry, TypeReference type, Object referenceValue) {
+        super(tags, isTry);
         this.type = type;
         this.referenceValue = referenceValue;
     }
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSimpleField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSimpleField.java
index 549ccf1..4c5abe3 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSimpleField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSimpleField.java
@@ -22,14 +22,14 @@ 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 extends DefaultTaggedField implements SimpleField {
+public class DefaultSimpleField extends DefaultField implements SimpleField {
 
     private final TypeReference type;
     private final String name;
     private final Term[] params;
 
-    public DefaultSimpleField(String[] tags, TypeReference type, String name, Term[] params) {
-        super(tags);
+    public DefaultSimpleField(String[] tags, boolean isTry, TypeReference type, String name, Term[] params) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.params = params;
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSwitchField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSwitchField.java
index f177e8f..3fd3f7f 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSwitchField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultSwitchField.java
@@ -26,12 +26,14 @@ import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 import java.util.LinkedList;
 import java.util.List;
 
-public class DefaultSwitchField implements SwitchField {
+public class DefaultSwitchField implements SwitchField, TryField {
 
+    private final boolean isTry;
     private final Term[] discriminatorExpressions;
     private final List<DiscriminatedComplexTypeDefinition> cases;
 
-    public DefaultSwitchField(Term[] discriminatorExpressions) {
+    public DefaultSwitchField(boolean isTry, Term[] discriminatorExpressions) {
+        this.isTry = isTry;
         this.discriminatorExpressions = discriminatorExpressions;
         this.cases = new LinkedList<>();
     }
@@ -52,4 +54,7 @@ public class DefaultSwitchField implements SwitchField {
         return new Term[0];
     }
 
+    public boolean isTry() {
+        return isTry;
+    }
 }
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultUnknownField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultUnknownField.java
index b0f5d2c..ce15538 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultUnknownField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultUnknownField.java
@@ -22,12 +22,12 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.UnknownField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultUnknownField extends DefaultTaggedField implements UnknownField {
+public class DefaultUnknownField extends DefaultField implements UnknownField {
 
     private final TypeReference type;
 
-    public DefaultUnknownField(String[] tags, TypeReference type) {
-        super(tags);
+    public DefaultUnknownField(String[] tags, boolean isTry, TypeReference type) {
+        super(tags, isTry);
         this.type = type;
     }
 
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultVirtualField.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultVirtualField.java
index 3efe5a3..c4fee4e 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultVirtualField.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/DefaultVirtualField.java
@@ -22,14 +22,14 @@ import org.apache.plc4x.plugins.codegenerator.types.fields.VirtualField;
 import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
-public class DefaultVirtualField extends DefaultTaggedField implements VirtualField {
+public class DefaultVirtualField extends DefaultField implements VirtualField {
 
     private final TypeReference type;
     private final String name;
     private final Term valueExpression;
 
-    public DefaultVirtualField(String[] tags, TypeReference type, String name, Term valueExpression) {
-        super(tags);
+    public DefaultVirtualField(String[] tags, boolean isTry, TypeReference type, String name, Term valueExpression) {
+        super(tags, isTry);
         this.type = type;
         this.name = name;
         this.valueExpression = valueExpression;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/TryField.java
similarity index 65%
copy from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
copy to code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/TryField.java
index 9a047c2..6b51a70 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/fields/TryField.java
@@ -16,22 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.spi.generation.io;
-
-import com.github.jinahya.bit.io.ArrayByteInput;
-import com.github.jinahya.bit.io.DefaultBitInput;
-
-/**
- * Modified version that exposes the position.
- */
-public class MyDefaultBitInput extends DefaultBitInput<ArrayByteInput> {
-
-    public MyDefaultBitInput(ArrayByteInput delegate) {
-        super(delegate);
-    }
-
-    public long getPos() {
-        return delegate.getIndex();
-    }
+package org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields;
 
+public interface TryField {
+    /**
+     * Returns true if this field should be tryed to be parsed
+     *
+     * @return true if failure is an option
+     */
+    boolean isTry();
 }
diff --git a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 2038a50..3b72bf0 100644
--- a/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++ b/code-generation/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -41,7 +41,6 @@ import java.util.*;
 
 public class MessageFormatListener extends MSpecBaseListener {
 
-
     private Deque<List<Field>> parserContexts;
 
     private Deque<List<EnumValue>> enumContexts;
@@ -133,8 +132,9 @@ public class MessageFormatListener extends MSpecBaseListener {
     public void enterAbstractField(MSpecParser.AbstractFieldContext ctx) {
         TypeReference type = getTypeReference(ctx.type);
         String name = getIdString(ctx.name);
-        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
-        Field field = new DefaultAbstractField(null, type, name, params);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultAbstractField(null, fieldDefinitionContext.tryParse() != null, type, name, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -147,8 +147,9 @@ public class MessageFormatListener extends MSpecBaseListener {
         ArrayField.LoopType loopType = ArrayField.LoopType.valueOf(ctx.loopType.getText().toUpperCase());
         String loopExpressionString = getExprString(ctx.loopExpression);
         Term loopExpression = getExpressionTerm(loopExpressionString);
-        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
-        Field field = new DefaultArrayField(null, type, name, loopType, loopExpression, params);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultArrayField(null, fieldDefinitionContext.tryParse() != null, type, name, loopType, loopExpression, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -160,7 +161,8 @@ public class MessageFormatListener extends MSpecBaseListener {
         String name = getIdString(ctx.name);
         String checksumExpressionString = getExprString(ctx.checksumExpression);
         Term checksumExpression = getExpressionTerm(checksumExpressionString);
-        Field field = new DefaultChecksumField(null, type, name, checksumExpression);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Field field = new DefaultChecksumField(null, fieldDefinitionContext.tryParse() != null, type, name, checksumExpression);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -168,10 +170,11 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     @Override
     public void enterConstField(MSpecParser.ConstFieldContext ctx) {
-        SimpleTypeReference type = getSimpleTypeReference(ctx.type);
+        TypeReference type = ctx.type.dataType() != null ? getSimpleTypeReference(ctx.type.dataType()) : getTypeReference(ctx.type);
         String name = getIdString(ctx.name);
         String expected = getExprString(ctx.expected);
-        Field field = new DefaultConstField(null, type, name, expected);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Field field = new DefaultConstField(null, fieldDefinitionContext.tryParse() != null, type, name, expected);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -181,7 +184,8 @@ public class MessageFormatListener extends MSpecBaseListener {
     public void enterDiscriminatorField(MSpecParser.DiscriminatorFieldContext ctx) {
         TypeReference type = getTypeReference(ctx.type);
         String name = getIdString(ctx.name);
-        Field field = new DefaultDiscriminatorField(null, type, name);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Field field = new DefaultDiscriminatorField(null, fieldDefinitionContext.tryParse() != null, type, name);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -189,14 +193,15 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     @Override
     public void enterEnumField(MSpecParser.EnumFieldContext ctx) {
-        ComplexTypeReference type = new DefaultComplexTypeReference(ctx.type.complexTypeReference.getText());
+        ComplexTypeReference type = new DefaultComplexTypeReference(ctx.type.complexTypeReference.getText(), null);
         String name = getIdString(ctx.name);
         String fieldName = null;
         if (ctx.fieldName != null) {
             fieldName = getIdString(ctx.fieldName);
         }
-        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
-        Field field = new DefaultEnumField(null, type, name, fieldName, params);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultEnumField(null, fieldDefinitionContext.tryParse() != null, type, name, fieldName, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -208,7 +213,22 @@ public class MessageFormatListener extends MSpecBaseListener {
         String name = getIdString(ctx.name);
         String serializeExpressionString = getExprString(ctx.serializeExpression);
         Term serializeExpression = getExpressionTerm(serializeExpressionString);
-        Field field = new DefaultImplicitField(null, type, name, serializeExpression);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Field field = new DefaultImplicitField(null, fieldDefinitionContext.tryParse() != null, type, name, serializeExpression);
+        if (parserContexts.peek() != null) {
+            parserContexts.peek().add(field);
+        }
+    }
+
+    @Override
+    public void enterAssertField(MSpecParser.AssertFieldContext ctx) {
+        TypeReference type = getTypeReference(ctx.type);
+        String name = getIdString(ctx.name);
+        String conditionExpressionString = getExprString(ctx.condition);
+        Term conditionExpression = getExpressionTerm(conditionExpressionString);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultAssertField(null, fieldDefinitionContext.tryParse() != null, type, name, conditionExpression, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -228,8 +248,9 @@ public class MessageFormatListener extends MSpecBaseListener {
         Term serializeExpression = getExpressionTerm(serializeExpressionString);
         String lengthExpressionString = getExprString(ctx.lengthExpression);
         Term lengthExpression = getExpressionTerm(lengthExpressionString);
-        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
-        Field field = new DefaultManualArrayField(null, type, name, loopType, loopExpression,
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultManualArrayField(null, fieldDefinitionContext.tryParse() != null, type, name, loopType, loopExpression,
             parseExpression, serializeExpression, lengthExpression, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
@@ -246,8 +267,9 @@ public class MessageFormatListener extends MSpecBaseListener {
         Term serializeExpression = getExpressionTerm(serializeExpressionString);
         String lengthExpressionString = getExprString(ctx.lengthExpression);
         Term lengthExpression = getExpressionTerm(lengthExpressionString);
-        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
-        Field field = new DefaultManualField(null, type, name, parseExpression, serializeExpression,
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultManualField(null, fieldDefinitionContext.tryParse() != null, type, name, parseExpression, serializeExpression,
             lengthExpression, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
@@ -260,8 +282,9 @@ public class MessageFormatListener extends MSpecBaseListener {
         String name = getIdString(ctx.name);
         String conditionExpressionString = getExprString(ctx.condition);
         Term conditionExpression = getExpressionTerm(conditionExpressionString);
-        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
-        Field field = new DefaultOptionalField(null, type, name, conditionExpression, params);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultOptionalField(null, fieldDefinitionContext.tryParse() != null, type, name, conditionExpression, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -275,8 +298,9 @@ public class MessageFormatListener extends MSpecBaseListener {
         Term paddingValue = getExpressionTerm(paddingValueString);
         String paddingConditionString = getExprString(ctx.paddingCondition);
         Term paddingCondition = getExpressionTerm(paddingConditionString);
-        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
-        Field field = new DefaultPaddingField(null, type, name, paddingValue, paddingCondition, params);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultPaddingField(null, fieldDefinitionContext.tryParse() != null, type, name, paddingValue, paddingCondition, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -286,7 +310,7 @@ public class MessageFormatListener extends MSpecBaseListener {
     public void enterReservedField(MSpecParser.ReservedFieldContext ctx) {
         SimpleTypeReference type = getSimpleTypeReference(ctx.type);
         String expected = getExprString(ctx.expected);
-        Field field = new DefaultReservedField(null, type, expected);
+        Field field = new DefaultReservedField(null, false, type, expected);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -296,8 +320,9 @@ public class MessageFormatListener extends MSpecBaseListener {
     public void enterSimpleField(MSpecParser.SimpleFieldContext ctx) {
         TypeReference type = getTypeReference(ctx.type);
         String name = getIdString(ctx.name);
-        Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
-        Field field = new DefaultSimpleField(null, type, name, params);
+        MSpecParser.FieldDefinitionContext fieldDefinitionContext = (MSpecParser.FieldDefinitionContext) ctx.parent.parent;
+        Term[] params = getFieldParams(fieldDefinitionContext);
+        Field field = new DefaultSimpleField(null, fieldDefinitionContext.tryParse() != null, type, name, params);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -310,7 +335,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         for (int i = 0; i < numDiscriminators; i++) {
             discriminatorExpressions[i] = getExpressionTerm(getExprString(ctx.discriminators.expression().get(i)));
         }
-        DefaultSwitchField field = new DefaultSwitchField(discriminatorExpressions);
+        DefaultSwitchField field = new DefaultSwitchField(false, discriminatorExpressions);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -319,7 +344,7 @@ public class MessageFormatListener extends MSpecBaseListener {
     @Override
     public void enterUnknownField(MSpecParser.UnknownFieldContext ctx) {
         SimpleTypeReference type = getSimpleTypeReference(ctx.type);
-        Field field = new DefaultUnknownField(null, type);
+        Field field = new DefaultUnknownField(null, false, type);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -331,7 +356,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         String name = getIdString(ctx.name);
         String valueExpressionString = getExprString(ctx.valueExpression);
         Term valueExpression = getExpressionTerm(valueExpressionString);
-        Field field = new DefaultVirtualField(null, type, name, valueExpression);
+        Field field = new DefaultVirtualField(null, false, type, name, valueExpression);
         if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
@@ -431,7 +456,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         if (ctx.simpleTypeReference != null) {
             return getSimpleTypeReference(ctx.simpleTypeReference);
         } else {
-            return new DefaultComplexTypeReference(ctx.complexTypeReference.getText());
+            return new DefaultComplexTypeReference(ctx.complexTypeReference.getText(), getParams(ctx.params));
         }
     }
 
@@ -493,14 +518,18 @@ public class MessageFormatListener extends MSpecBaseListener {
     }
 
     private Term[] getFieldParams(MSpecParser.FieldDefinitionContext parentCtx) {
-        Term[] params = null;
-        if (parentCtx.params != null) {
-            params = new Term[parentCtx.params.expression().size()];
-            for (int i = 0; i < parentCtx.params.expression().size(); i++) {
-                params[i] = parseExpression(getExprString(parentCtx.params.expression().get(i)));
-            }
+        return getParams(parentCtx.params);
+    }
+
+    private Term[] getParams(MSpecParser.MultipleExpressionsContext params) {
+        if (params == null) {
+            return null;
+        }
+        Term[] terms = new Term[params.expression().size()];
+        for (int i = 0; i < params.expression().size(); i++) {
+            terms[i] = parseExpression(getExprString(params.expression().get(i)));
         }
-        return params;
+        return terms;
     }
 
     private Term parseExpression(String expressionString) {
diff --git a/plc4go/internal/plc4go/abeth/readwrite/model/CIPEncapsulationReadRequest.go b/plc4go/internal/plc4go/abeth/readwrite/model/CIPEncapsulationReadRequest.go
index 87b600a..afa9253 100644
--- a/plc4go/internal/plc4go/abeth/readwrite/model/CIPEncapsulationReadRequest.go
+++ b/plc4go/internal/plc4go/abeth/readwrite/model/CIPEncapsulationReadRequest.go
@@ -125,7 +125,7 @@ func CIPEncapsulationReadRequestParse(readBuffer utils.ReadBuffer) (*CIPEncapsul
 
 	// Create a partially initialized instance
 	_child := &CIPEncapsulationReadRequest{
-		Request: request,
+		Request: CastDF1RequestMessage(request),
 		Parent:  &CIPEncapsulationPacket{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/abeth/readwrite/model/CIPEncapsulationReadResponse.go b/plc4go/internal/plc4go/abeth/readwrite/model/CIPEncapsulationReadResponse.go
index 58d17fe..a95ec22 100644
--- a/plc4go/internal/plc4go/abeth/readwrite/model/CIPEncapsulationReadResponse.go
+++ b/plc4go/internal/plc4go/abeth/readwrite/model/CIPEncapsulationReadResponse.go
@@ -125,7 +125,7 @@ func CIPEncapsulationReadResponseParse(readBuffer utils.ReadBuffer, len uint16)
 
 	// Create a partially initialized instance
 	_child := &CIPEncapsulationReadResponse{
-		Response: response,
+		Response: CastDF1ResponseMessage(response),
 		Parent:   &CIPEncapsulationPacket{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/abeth/readwrite/model/DF1CommandRequestMessage.go b/plc4go/internal/plc4go/abeth/readwrite/model/DF1CommandRequestMessage.go
index 918b4e8..b00ee3c 100644
--- a/plc4go/internal/plc4go/abeth/readwrite/model/DF1CommandRequestMessage.go
+++ b/plc4go/internal/plc4go/abeth/readwrite/model/DF1CommandRequestMessage.go
@@ -125,7 +125,7 @@ func DF1CommandRequestMessageParse(readBuffer utils.ReadBuffer) (*DF1RequestMess
 
 	// Create a partially initialized instance
 	_child := &DF1CommandRequestMessage{
-		Command: command,
+		Command: CastDF1RequestCommand(command),
 		Parent:  &DF1RequestMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go b/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
index ec88584..1e51e79 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
@@ -32,6 +32,13 @@ type BacnetipParserHelper struct {
 
 func (m BacnetipParserHelper) Parse(typeName string, arguments []string, io utils.ReadBuffer) (interface{}, error) {
 	switch typeName {
+	case "BACnetComplexTag":
+		tagNumberArgument, err := utils.StrToUint8(arguments[0])
+		if err != nil {
+			return nil, errors.Wrap(err, "Error parsing")
+		}
+		var dataType model.BACnetDataType
+		return model.BACnetComplexTagParse(io, tagNumberArgument, dataType)
 	case "APDU":
 		apduLength, err := utils.StrToUint16(arguments[0])
 		if err != nil {
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/XmlParserHelper.go b/plc4go/internal/plc4go/bacnetip/readwrite/XmlParserHelper.go
index 63824d1..38aa5b1 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/XmlParserHelper.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/XmlParserHelper.go
@@ -42,6 +42,14 @@ func init() {
 
 func (m BacnetipXmlParserHelper) Parse(typeName string, xmlString string, parserArguments ...string) (interface{}, error) {
 	switch typeName {
+	case "BACnetComplexTag":
+		parsedUint0, err := strconv.ParseUint(parserArguments[0], 10, 4)
+		if err != nil {
+			return nil, err
+		}
+		tagNumberArgument := uint8(parsedUint0)
+		dataType := model.BACnetDataTypeByName(parserArguments[1])
+		return model.BACnetComplexTagParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), tagNumberArgument, dataType)
 	case "APDU":
 		parsedUint0, err := strconv.ParseUint(parserArguments[0], 10, 16)
 		if err != nil {
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUComplexAck.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUComplexAck.go
index 19f0c95..5192857 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUComplexAck.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUComplexAck.go
@@ -211,7 +211,7 @@ func APDUComplexAckParse(readBuffer utils.ReadBuffer) (*APDU, error) {
 		OriginalInvokeId:   originalInvokeId,
 		SequenceNumber:     sequenceNumber,
 		ProposedWindowSize: proposedWindowSize,
-		ServiceAck:         serviceAck,
+		ServiceAck:         CastBACnetServiceAck(serviceAck),
 		Parent:             &APDU{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUConfirmedRequest.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUConfirmedRequest.go
index 7d1cd87..7e23965 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUConfirmedRequest.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUConfirmedRequest.go
@@ -247,7 +247,7 @@ func APDUConfirmedRequestParse(readBuffer utils.ReadBuffer, apduLength uint16) (
 		InvokeId:                  invokeId,
 		SequenceNumber:            sequenceNumber,
 		ProposedWindowSize:        proposedWindowSize,
-		ServiceRequest:            serviceRequest,
+		ServiceRequest:            CastBACnetConfirmedServiceRequest(serviceRequest),
 		Parent:                    &APDU{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUError.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUError.go
index 14ff2d4..158b2ca 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUError.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUError.go
@@ -151,7 +151,7 @@ func APDUErrorParse(readBuffer utils.ReadBuffer) (*APDU, error) {
 	// Create a partially initialized instance
 	_child := &APDUError{
 		OriginalInvokeId: originalInvokeId,
-		Error:            error,
+		Error:            CastBACnetError(error),
 		Parent:           &APDU{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUUnconfirmedRequest.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUUnconfirmedRequest.go
index 1810a26..0ba9e32 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUUnconfirmedRequest.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/APDUUnconfirmedRequest.go
@@ -139,7 +139,7 @@ func APDUUnconfirmedRequestParse(readBuffer utils.ReadBuffer, apduLength uint16)
 
 	// Create a partially initialized instance
 	_child := &APDUUnconfirmedRequest{
-		ServiceRequest: serviceRequest,
+		ServiceRequest: CastBACnetUnconfirmedServiceRequest(serviceRequest),
 		Parent:         &APDU{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTag.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTag.go
new file mode 100644
index 0000000..28aec9c
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTag.go
@@ -0,0 +1,351 @@
+/*
+ * 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 model
+
+import (
+	"fmt"
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// Constant values.
+const BACnetComplexTag_TAGCLASS TagClass = TagClass_CONTEXT_SPECIFIC_TAGS
+
+// The data-structure of this message
+type BACnetComplexTag struct {
+	TagNumber                uint8
+	LengthValueType          uint8
+	ExtTagNumber             *uint8
+	ExtLength                *uint8
+	ExtExtLength             *uint16
+	ExtExtExtLength          *uint32
+	ActualTagNumber          uint8
+	IsPrimitiveAndNotBoolean bool
+	ActualLength             uint32
+	Child                    IBACnetComplexTagChild
+}
+
+// The corresponding interface
+type IBACnetComplexTag interface {
+	DataType() BACnetDataType
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+type IBACnetComplexTagParent interface {
+	SerializeParent(writeBuffer utils.WriteBuffer, child IBACnetComplexTag, serializeChildFunction func() error) error
+	GetTypeName() string
+}
+
+type IBACnetComplexTagChild interface {
+	Serialize(writeBuffer utils.WriteBuffer) error
+	InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32)
+	GetTypeName() string
+	IBACnetComplexTag
+}
+
+func NewBACnetComplexTag(tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	return &BACnetComplexTag{TagNumber: tagNumber, LengthValueType: lengthValueType, ExtTagNumber: extTagNumber, ExtLength: extLength, ExtExtLength: extExtLength, ExtExtExtLength: extExtExtLength}
+}
+
+func CastBACnetComplexTag(structType interface{}) *BACnetComplexTag {
+	castFunc := func(typ interface{}) *BACnetComplexTag {
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return casted
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTag) GetTypeName() string {
+	return "BACnetComplexTag"
+}
+
+func (m *BACnetComplexTag) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTag) LengthInBitsConditional(lastItem bool) uint16 {
+	return m.Child.LengthInBits()
+}
+
+func (m *BACnetComplexTag) ParentLengthInBits() uint16 {
+	lengthInBits := uint16(0)
+
+	// Const Field (tagClass)
+	lengthInBits += 1
+
+	// Simple field (lengthValueType)
+	lengthInBits += 3
+
+	// Optional Field (extTagNumber)
+	if m.ExtTagNumber != nil {
+		lengthInBits += 8
+	}
+
+	// A virtual field doesn't have any in- or output.
+
+	// A virtual field doesn't have any in- or output.
+
+	// Optional Field (extLength)
+	if m.ExtLength != nil {
+		lengthInBits += 8
+	}
+
+	// Optional Field (extExtLength)
+	if m.ExtExtLength != nil {
+		lengthInBits += 16
+	}
+
+	// Optional Field (extExtExtLength)
+	if m.ExtExtExtLength != nil {
+		lengthInBits += 32
+	}
+
+	// A virtual field doesn't have any in- or output.
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTag) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagParse(readBuffer utils.ReadBuffer, tagNumberArgument uint8, dataType BACnetDataType) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTag"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Assert Field (tagNumber) (Can be skipped, if a given expression evaluates to false)
+	tagNumber, _err := readBuffer.ReadUint8("tagNumber", 4)
+	if _err != nil {
+		return nil, errors.Wrap(_err, "Error parsing 'tagNumber' field")
+	}
+
+	// Const Field (tagClass)
+	tagClass, _tagClassErr := TagClassParse(readBuffer)
+	if _tagClassErr != nil {
+		return nil, errors.Wrap(_tagClassErr, "Error parsing 'tagClass' field")
+	}
+	if _tagClassErr != nil {
+		return nil, errors.Wrap(_tagClassErr, "Error parsing 'tagClass' field")
+	}
+	if tagClass != BACnetComplexTag_TAGCLASS {
+		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetComplexTag_TAGCLASS) + " but got " + fmt.Sprintf("%d", tagClass))
+	}
+
+	// Simple Field (lengthValueType)
+	lengthValueType, _lengthValueTypeErr := readBuffer.ReadUint8("lengthValueType", 3)
+	if _lengthValueTypeErr != nil {
+		return nil, errors.Wrap(_lengthValueTypeErr, "Error parsing 'lengthValueType' field")
+	}
+
+	// Optional Field (extTagNumber) (Can be skipped, if a given expression evaluates to false)
+	var extTagNumber *uint8 = nil
+	if bool((tagNumber) == (15)) {
+		_val, _err := readBuffer.ReadUint8("extTagNumber", 8)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'extTagNumber' field")
+		}
+		extTagNumber = &_val
+	}
+
+	// Virtual field
+	actualTagNumber := utils.InlineIf(bool((tagNumber) < (15)), func() interface{} { return uint8(tagNumber) }, func() interface{} { return uint8((*extTagNumber)) }).(uint8)
+
+	// Virtual field
+	isPrimitiveAndNotBoolean := bool(!(bool(bool((lengthValueType) == (6))))) && bool(bool((tagNumber) != (1)))
+
+	// Optional Field (extLength) (Can be skipped, if a given expression evaluates to false)
+	var extLength *uint8 = nil
+	if bool(isPrimitiveAndNotBoolean) && bool(bool((lengthValueType) == (5))) {
+		_val, _err := readBuffer.ReadUint8("extLength", 8)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'extLength' field")
+		}
+		extLength = &_val
+	}
+
+	// Optional Field (extExtLength) (Can be skipped, if a given expression evaluates to false)
+	var extExtLength *uint16 = nil
+	if bool(bool(isPrimitiveAndNotBoolean) && bool(bool((lengthValueType) == (5)))) && bool(bool((*extLength) == (254))) {
+		_val, _err := readBuffer.ReadUint16("extExtLength", 16)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'extExtLength' field")
+		}
+		extExtLength = &_val
+	}
+
+	// Optional Field (extExtExtLength) (Can be skipped, if a given expression evaluates to false)
+	var extExtExtLength *uint32 = nil
+	if bool(bool(isPrimitiveAndNotBoolean) && bool(bool((lengthValueType) == (5)))) && bool(bool((*extLength) == (255))) {
+		_val, _err := readBuffer.ReadUint32("extExtExtLength", 32)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'extExtExtLength' field")
+		}
+		extExtExtLength = &_val
+	}
+
+	// Virtual field
+	actualLength := utils.InlineIf(bool(bool((lengthValueType) == (5))) && bool(bool((*extLength) == (255))), func() interface{} { return uint32((*extExtExtLength)) }, func() interface{} {
+		return uint32(uint32(utils.InlineIf(bool(bool((lengthValueType) == (5))) && bool(bool((*extLength) == (254))), func() interface{} { return uint32((*extExtLength)) }, func() interface{} {
+			return uint32(uint32(utils.InlineIf(bool((lengthValueType) == (5)), func() interface{} { return uint32((*extLength)) }, func() interface{} {
+				return uint32(uint32(utils.InlineIf(isPrimitiveAndNotBoolean, func() interface{} { return uint32(lengthValueType) }, func() interface{} { return uint32(uint32(0)) }).(uint32)))
+			}).(uint32)))
+		}).(uint32)))
+	}).(uint32)
+
+	// Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
+	var _parent *BACnetComplexTag
+	var typeSwitchError error
+	switch {
+	case dataType == BACnetDataType_NULL: // BACnetComplexTagNull
+		_parent, typeSwitchError = BACnetComplexTagNullParse(readBuffer)
+	case dataType == BACnetDataType_BOOLEAN: // BACnetComplexTagBoolean
+		_parent, typeSwitchError = BACnetComplexTagBooleanParse(readBuffer)
+	case dataType == BACnetDataType_UNSIGNED_INTEGER: // BACnetComplexTagUnsignedInteger
+		_parent, typeSwitchError = BACnetComplexTagUnsignedIntegerParse(readBuffer, lengthValueType, *extLength)
+	case dataType == BACnetDataType_SIGNED_INTEGER: // BACnetComplexTagSignedInteger
+		_parent, typeSwitchError = BACnetComplexTagSignedIntegerParse(readBuffer, lengthValueType, *extLength)
+	case dataType == BACnetDataType_REAL: // BACnetComplexTagReal
+		_parent, typeSwitchError = BACnetComplexTagRealParse(readBuffer, lengthValueType, *extLength)
+	case dataType == BACnetDataType_DOUBLE: // BACnetComplexTagDouble
+		_parent, typeSwitchError = BACnetComplexTagDoubleParse(readBuffer, lengthValueType, *extLength)
+	case dataType == BACnetDataType_OCTET_STRING: // BACnetComplexTagOctetString
+		_parent, typeSwitchError = BACnetComplexTagOctetStringParse(readBuffer, actualLength)
+	case dataType == BACnetDataType_CHARACTER_STRING: // BACnetComplexTagCharacterString
+		_parent, typeSwitchError = BACnetComplexTagCharacterStringParse(readBuffer)
+	case dataType == BACnetDataType_BIT_STRING: // BACnetComplexTagBitString
+		_parent, typeSwitchError = BACnetComplexTagBitStringParse(readBuffer, lengthValueType, *extLength)
+	case dataType == BACnetDataType_ENUMERATED: // BACnetComplexTagEnumerated
+		_parent, typeSwitchError = BACnetComplexTagEnumeratedParse(readBuffer, lengthValueType, *extLength)
+	case dataType == BACnetDataType_DATE: // BACnetComplexTagDate
+		_parent, typeSwitchError = BACnetComplexTagDateParse(readBuffer)
+	case dataType == BACnetDataType_TIME: // BACnetComplexTagTime
+		_parent, typeSwitchError = BACnetComplexTagTimeParse(readBuffer)
+	case dataType == BACnetDataType_BACNET_OBJECT_IDENTIFIER: // BACnetComplexTagObjectIdentifier
+		_parent, typeSwitchError = BACnetComplexTagObjectIdentifierParse(readBuffer)
+	default:
+		// TODO: return actual type
+		typeSwitchError = errors.New("Unmapped type")
+	}
+	if typeSwitchError != nil {
+		return nil, errors.Wrap(typeSwitchError, "Error parsing sub-type for type-switch.")
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTag"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Finish initializing
+	_parent.Child.InitializeParent(_parent, tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength, actualTagNumber, isPrimitiveAndNotBoolean, actualLength)
+	return _parent, nil
+}
+
+func (m *BACnetComplexTag) Serialize(writeBuffer utils.WriteBuffer) error {
+	return m.Child.Serialize(writeBuffer)
+}
+
+func (m *BACnetComplexTag) SerializeParent(writeBuffer utils.WriteBuffer, child IBACnetComplexTag, serializeChildFunction func() error) error {
+	if pushErr := writeBuffer.PushContext("BACnetComplexTag"); pushErr != nil {
+		return pushErr
+	}
+
+	// Const field (tagClass)
+	tagClass := CastTagClass(BACnetComplexTag_TAGCLASS)
+	_tagClassErr := tagClass.Serialize(writeBuffer)
+	if _tagClassErr != nil {
+		return errors.Wrap(_tagClassErr, "Error serializing 'tagClass' field")
+	}
+
+	// Simple Field (lengthValueType)
+	lengthValueType := uint8(m.LengthValueType)
+	_lengthValueTypeErr := writeBuffer.WriteUint8("lengthValueType", 3, (lengthValueType))
+	if _lengthValueTypeErr != nil {
+		return errors.Wrap(_lengthValueTypeErr, "Error serializing 'lengthValueType' field")
+	}
+
+	// Optional Field (extTagNumber) (Can be skipped, if the value is null)
+	var extTagNumber *uint8 = nil
+	if m.ExtTagNumber != nil {
+		extTagNumber = m.ExtTagNumber
+		_extTagNumberErr := writeBuffer.WriteUint8("extTagNumber", 8, *(extTagNumber))
+		if _extTagNumberErr != nil {
+			return errors.Wrap(_extTagNumberErr, "Error serializing 'extTagNumber' field")
+		}
+	}
+
+	// Optional Field (extLength) (Can be skipped, if the value is null)
+	var extLength *uint8 = nil
+	if m.ExtLength != nil {
+		extLength = m.ExtLength
+		_extLengthErr := writeBuffer.WriteUint8("extLength", 8, *(extLength))
+		if _extLengthErr != nil {
+			return errors.Wrap(_extLengthErr, "Error serializing 'extLength' field")
+		}
+	}
+
+	// Optional Field (extExtLength) (Can be skipped, if the value is null)
+	var extExtLength *uint16 = nil
+	if m.ExtExtLength != nil {
+		extExtLength = m.ExtExtLength
+		_extExtLengthErr := writeBuffer.WriteUint16("extExtLength", 16, *(extExtLength))
+		if _extExtLengthErr != nil {
+			return errors.Wrap(_extExtLengthErr, "Error serializing 'extExtLength' field")
+		}
+	}
+
+	// Optional Field (extExtExtLength) (Can be skipped, if the value is null)
+	var extExtExtLength *uint32 = nil
+	if m.ExtExtExtLength != nil {
+		extExtExtLength = m.ExtExtExtLength
+		_extExtExtLengthErr := writeBuffer.WriteUint32("extExtExtLength", 32, *(extExtExtLength))
+		if _extExtExtLengthErr != nil {
+			return errors.Wrap(_extExtExtLengthErr, "Error serializing 'extExtExtLength' field")
+		}
+	}
+
+	// Switch field (Depending on the discriminator values, passes the serialization to a sub-type)
+	_typeSwitchErr := serializeChildFunction()
+	if _typeSwitchErr != nil {
+		return errors.Wrap(_typeSwitchErr, "Error serializing sub-type field")
+	}
+
+	if popErr := writeBuffer.PopContext("BACnetComplexTag"); popErr != nil {
+		return popErr
+	}
+	return nil
+}
+
+func (m *BACnetComplexTag) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagBitString.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagBitString.go
new file mode 100644
index 0000000..4535d38
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagBitString.go
@@ -0,0 +1,202 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagBitString struct {
+	UnusedBits uint8
+	Data       []int8
+	Parent     *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagBitString interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagBitString) DataType() BACnetDataType {
+	return BACnetDataType_BIT_STRING
+}
+
+func (m *BACnetComplexTagBitString) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagBitString(unusedBits uint8, data []int8, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagBitString{
+		UnusedBits: unusedBits,
+		Data:       data,
+		Parent:     NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagBitString(structType interface{}) *BACnetComplexTagBitString {
+	castFunc := func(typ interface{}) *BACnetComplexTagBitString {
+		if casted, ok := typ.(BACnetComplexTagBitString); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagBitString); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagBitString(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagBitString(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagBitString) GetTypeName() string {
+	return "BACnetComplexTagBitString"
+}
+
+func (m *BACnetComplexTagBitString) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagBitString) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	// Simple field (unusedBits)
+	lengthInBits += 8
+
+	// Array field
+	if len(m.Data) > 0 {
+		lengthInBits += 8 * uint16(len(m.Data))
+	}
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagBitString) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagBitStringParse(readBuffer utils.ReadBuffer, lengthValueType uint8, extLength uint8) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagBitString"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Simple Field (unusedBits)
+	unusedBits, _unusedBitsErr := readBuffer.ReadUint8("unusedBits", 8)
+	if _unusedBitsErr != nil {
+		return nil, errors.Wrap(_unusedBitsErr, "Error parsing 'unusedBits' field")
+	}
+
+	// Array field (data)
+	if pullErr := readBuffer.PullContext("data", utils.WithRenderAsList(true)); pullErr != nil {
+		return nil, pullErr
+	}
+	// Length array
+	data := make([]int8, 0)
+	_dataLength := utils.InlineIf(bool(bool((lengthValueType) == (5))), func() interface{} { return uint16(uint16(uint16(extLength) - uint16(uint16(1)))) }, func() interface{} { return uint16(uint16(uint16(lengthValueType) - uint16(uint16(1)))) }).(uint16)
+	_dataEndPos := readBuffer.GetPos() + uint16(_dataLength)
+	for readBuffer.GetPos() < _dataEndPos {
+		_item, _err := readBuffer.ReadInt8("", 8)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'data' field")
+		}
+		data = append(data, _item)
+	}
+	if closeErr := readBuffer.CloseContext("data", utils.WithRenderAsList(true)); closeErr != nil {
+		return nil, closeErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagBitString"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagBitString{
+		UnusedBits: unusedBits,
+		Data:       data,
+		Parent:     &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagBitString) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagBitString"); pushErr != nil {
+			return pushErr
+		}
+
+		// Simple Field (unusedBits)
+		unusedBits := uint8(m.UnusedBits)
+		_unusedBitsErr := writeBuffer.WriteUint8("unusedBits", 8, (unusedBits))
+		if _unusedBitsErr != nil {
+			return errors.Wrap(_unusedBitsErr, "Error serializing 'unusedBits' field")
+		}
+
+		// Array Field (data)
+		if m.Data != nil {
+			if pushErr := writeBuffer.PushContext("data", utils.WithRenderAsList(true)); pushErr != nil {
+				return pushErr
+			}
+			for _, _element := range m.Data {
+				_elementErr := writeBuffer.WriteInt8("", 8, _element)
+				if _elementErr != nil {
+					return errors.Wrap(_elementErr, "Error serializing 'data' field")
+				}
+			}
+			if popErr := writeBuffer.PopContext("data", utils.WithRenderAsList(true)); popErr != nil {
+				return popErr
+			}
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagBitString"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagBitString) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagBoolean.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagBoolean.go
new file mode 100644
index 0000000..5bd58c6
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagBoolean.go
@@ -0,0 +1,139 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagBoolean struct {
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagBoolean interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagBoolean) DataType() BACnetDataType {
+	return BACnetDataType_BOOLEAN
+}
+
+func (m *BACnetComplexTagBoolean) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagBoolean(tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagBoolean{
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagBoolean(structType interface{}) *BACnetComplexTagBoolean {
+	castFunc := func(typ interface{}) *BACnetComplexTagBoolean {
+		if casted, ok := typ.(BACnetComplexTagBoolean); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagBoolean); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagBoolean(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagBoolean(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagBoolean) GetTypeName() string {
+	return "BACnetComplexTagBoolean"
+}
+
+func (m *BACnetComplexTagBoolean) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagBoolean) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagBoolean) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagBooleanParse(readBuffer utils.ReadBuffer) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagBoolean"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagBoolean"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagBoolean{
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagBoolean) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagBoolean"); pushErr != nil {
+			return pushErr
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagBoolean"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagBoolean) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagCharacterString.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagCharacterString.go
new file mode 100644
index 0000000..43dea18
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagCharacterString.go
@@ -0,0 +1,139 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagCharacterString struct {
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagCharacterString interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagCharacterString) DataType() BACnetDataType {
+	return BACnetDataType_CHARACTER_STRING
+}
+
+func (m *BACnetComplexTagCharacterString) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagCharacterString(tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagCharacterString{
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagCharacterString(structType interface{}) *BACnetComplexTagCharacterString {
+	castFunc := func(typ interface{}) *BACnetComplexTagCharacterString {
+		if casted, ok := typ.(BACnetComplexTagCharacterString); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagCharacterString); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagCharacterString(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagCharacterString(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagCharacterString) GetTypeName() string {
+	return "BACnetComplexTagCharacterString"
+}
+
+func (m *BACnetComplexTagCharacterString) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagCharacterString) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagCharacterString) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagCharacterStringParse(readBuffer utils.ReadBuffer) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagCharacterString"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagCharacterString"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagCharacterString{
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagCharacterString) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagCharacterString"); pushErr != nil {
+			return pushErr
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagCharacterString"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagCharacterString) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagDate.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagDate.go
new file mode 100644
index 0000000..5fa8b95
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagDate.go
@@ -0,0 +1,139 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagDate struct {
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagDate interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagDate) DataType() BACnetDataType {
+	return BACnetDataType_DATE
+}
+
+func (m *BACnetComplexTagDate) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagDate(tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagDate{
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagDate(structType interface{}) *BACnetComplexTagDate {
+	castFunc := func(typ interface{}) *BACnetComplexTagDate {
+		if casted, ok := typ.(BACnetComplexTagDate); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagDate); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagDate(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagDate(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagDate) GetTypeName() string {
+	return "BACnetComplexTagDate"
+}
+
+func (m *BACnetComplexTagDate) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagDate) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagDate) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagDateParse(readBuffer utils.ReadBuffer) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagDate"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagDate"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagDate{
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagDate) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagDate"); pushErr != nil {
+			return pushErr
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagDate"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagDate) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagDouble.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagDouble.go
new file mode 100644
index 0000000..9afeed7
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagDouble.go
@@ -0,0 +1,159 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagDouble struct {
+	Value  float64
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagDouble interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagDouble) DataType() BACnetDataType {
+	return BACnetDataType_DOUBLE
+}
+
+func (m *BACnetComplexTagDouble) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagDouble(value float64, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagDouble{
+		Value:  value,
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagDouble(structType interface{}) *BACnetComplexTagDouble {
+	castFunc := func(typ interface{}) *BACnetComplexTagDouble {
+		if casted, ok := typ.(BACnetComplexTagDouble); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagDouble); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagDouble(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagDouble(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagDouble) GetTypeName() string {
+	return "BACnetComplexTagDouble"
+}
+
+func (m *BACnetComplexTagDouble) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagDouble) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	// Simple field (value)
+	lengthInBits += 64
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagDouble) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagDoubleParse(readBuffer utils.ReadBuffer, lengthValueType uint8, extLength uint8) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagDouble"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Simple Field (value)
+	value, _valueErr := readBuffer.ReadFloat64("value", true, 11, 52)
+	if _valueErr != nil {
+		return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagDouble"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagDouble{
+		Value:  value,
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagDouble) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagDouble"); pushErr != nil {
+			return pushErr
+		}
+
+		// Simple Field (value)
+		value := float64(m.Value)
+		_valueErr := writeBuffer.WriteFloat64("value", 64, (value))
+		if _valueErr != nil {
+			return errors.Wrap(_valueErr, "Error serializing 'value' field")
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagDouble"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagDouble) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagEnumerated.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagEnumerated.go
new file mode 100644
index 0000000..4e8fb2a
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagEnumerated.go
@@ -0,0 +1,183 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagEnumerated struct {
+	Data   []int8
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagEnumerated interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagEnumerated) DataType() BACnetDataType {
+	return BACnetDataType_ENUMERATED
+}
+
+func (m *BACnetComplexTagEnumerated) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagEnumerated(data []int8, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagEnumerated{
+		Data:   data,
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagEnumerated(structType interface{}) *BACnetComplexTagEnumerated {
+	castFunc := func(typ interface{}) *BACnetComplexTagEnumerated {
+		if casted, ok := typ.(BACnetComplexTagEnumerated); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagEnumerated); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagEnumerated(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagEnumerated(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagEnumerated) GetTypeName() string {
+	return "BACnetComplexTagEnumerated"
+}
+
+func (m *BACnetComplexTagEnumerated) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagEnumerated) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	// Array field
+	if len(m.Data) > 0 {
+		lengthInBits += 8 * uint16(len(m.Data))
+	}
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagEnumerated) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagEnumeratedParse(readBuffer utils.ReadBuffer, lengthValueType uint8, extLength uint8) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagEnumerated"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Array field (data)
+	if pullErr := readBuffer.PullContext("data", utils.WithRenderAsList(true)); pullErr != nil {
+		return nil, pullErr
+	}
+	// Length array
+	data := make([]int8, 0)
+	_dataLength := utils.InlineIf(bool(bool((lengthValueType) == (5))), func() interface{} { return uint16(extLength) }, func() interface{} { return uint16(lengthValueType) }).(uint16)
+	_dataEndPos := readBuffer.GetPos() + uint16(_dataLength)
+	for readBuffer.GetPos() < _dataEndPos {
+		_item, _err := readBuffer.ReadInt8("", 8)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'data' field")
+		}
+		data = append(data, _item)
+	}
+	if closeErr := readBuffer.CloseContext("data", utils.WithRenderAsList(true)); closeErr != nil {
+		return nil, closeErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagEnumerated"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagEnumerated{
+		Data:   data,
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagEnumerated) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagEnumerated"); pushErr != nil {
+			return pushErr
+		}
+
+		// Array Field (data)
+		if m.Data != nil {
+			if pushErr := writeBuffer.PushContext("data", utils.WithRenderAsList(true)); pushErr != nil {
+				return pushErr
+			}
+			for _, _element := range m.Data {
+				_elementErr := writeBuffer.WriteInt8("", 8, _element)
+				if _elementErr != nil {
+					return errors.Wrap(_elementErr, "Error serializing 'data' field")
+				}
+			}
+			if popErr := writeBuffer.PopContext("data", utils.WithRenderAsList(true)); popErr != nil {
+				return popErr
+			}
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagEnumerated"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagEnumerated) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagNull.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagNull.go
new file mode 100644
index 0000000..f6f78b4
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagNull.go
@@ -0,0 +1,139 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagNull struct {
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagNull interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagNull) DataType() BACnetDataType {
+	return BACnetDataType_NULL
+}
+
+func (m *BACnetComplexTagNull) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagNull(tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagNull{
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagNull(structType interface{}) *BACnetComplexTagNull {
+	castFunc := func(typ interface{}) *BACnetComplexTagNull {
+		if casted, ok := typ.(BACnetComplexTagNull); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagNull); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagNull(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagNull(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagNull) GetTypeName() string {
+	return "BACnetComplexTagNull"
+}
+
+func (m *BACnetComplexTagNull) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagNull) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagNull) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagNullParse(readBuffer utils.ReadBuffer) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagNull"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagNull"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagNull{
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagNull) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagNull"); pushErr != nil {
+			return pushErr
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagNull"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagNull) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagObjectIdentifier.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagObjectIdentifier.go
new file mode 100644
index 0000000..9372efe
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagObjectIdentifier.go
@@ -0,0 +1,139 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagObjectIdentifier struct {
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagObjectIdentifier interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagObjectIdentifier) DataType() BACnetDataType {
+	return BACnetDataType_BACNET_OBJECT_IDENTIFIER
+}
+
+func (m *BACnetComplexTagObjectIdentifier) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagObjectIdentifier(tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagObjectIdentifier{
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagObjectIdentifier(structType interface{}) *BACnetComplexTagObjectIdentifier {
+	castFunc := func(typ interface{}) *BACnetComplexTagObjectIdentifier {
+		if casted, ok := typ.(BACnetComplexTagObjectIdentifier); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagObjectIdentifier); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagObjectIdentifier(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagObjectIdentifier(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagObjectIdentifier) GetTypeName() string {
+	return "BACnetComplexTagObjectIdentifier"
+}
+
+func (m *BACnetComplexTagObjectIdentifier) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagObjectIdentifier) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagObjectIdentifier) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagObjectIdentifierParse(readBuffer utils.ReadBuffer) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagObjectIdentifier"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagObjectIdentifier"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagObjectIdentifier{
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagObjectIdentifier) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagObjectIdentifier"); pushErr != nil {
+			return pushErr
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagObjectIdentifier"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagObjectIdentifier) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagOctetString.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagOctetString.go
new file mode 100644
index 0000000..e52e012
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagOctetString.go
@@ -0,0 +1,165 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagOctetString struct {
+	TheString         string
+	ActualLengthInBit uint16
+	Parent            *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagOctetString interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagOctetString) DataType() BACnetDataType {
+	return BACnetDataType_OCTET_STRING
+}
+
+func (m *BACnetComplexTagOctetString) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagOctetString(theString string, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagOctetString{
+		TheString: theString,
+		Parent:    NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagOctetString(structType interface{}) *BACnetComplexTagOctetString {
+	castFunc := func(typ interface{}) *BACnetComplexTagOctetString {
+		if casted, ok := typ.(BACnetComplexTagOctetString); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagOctetString); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagOctetString(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagOctetString(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagOctetString) GetTypeName() string {
+	return "BACnetComplexTagOctetString"
+}
+
+func (m *BACnetComplexTagOctetString) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagOctetString) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	// A virtual field doesn't have any in- or output.
+
+	// Simple field (theString)
+	lengthInBits += uint16(m.ActualLengthInBit)
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagOctetString) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagOctetStringParse(readBuffer utils.ReadBuffer, actualLength uint32) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagOctetString"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Virtual field
+	actualLengthInBit := uint16(actualLength) * uint16(uint16(8))
+
+	// Simple Field (theString)
+	theString, _theStringErr := readBuffer.ReadString("theString", uint32(actualLengthInBit))
+	if _theStringErr != nil {
+		return nil, errors.Wrap(_theStringErr, "Error parsing 'theString' field")
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagOctetString"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagOctetString{
+		TheString: theString,
+		Parent:    &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagOctetString) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagOctetString"); pushErr != nil {
+			return pushErr
+		}
+
+		// Simple Field (theString)
+		theString := string(m.TheString)
+		_theStringErr := writeBuffer.WriteString("theString", uint8(m.ActualLengthInBit), "ASCII", (theString))
+		if _theStringErr != nil {
+			return errors.Wrap(_theStringErr, "Error serializing 'theString' field")
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagOctetString"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagOctetString) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagReal.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagReal.go
new file mode 100644
index 0000000..8c9dbf9
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagReal.go
@@ -0,0 +1,159 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagReal struct {
+	Value  float32
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagReal interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagReal) DataType() BACnetDataType {
+	return BACnetDataType_REAL
+}
+
+func (m *BACnetComplexTagReal) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagReal(value float32, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagReal{
+		Value:  value,
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagReal(structType interface{}) *BACnetComplexTagReal {
+	castFunc := func(typ interface{}) *BACnetComplexTagReal {
+		if casted, ok := typ.(BACnetComplexTagReal); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagReal); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagReal(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagReal(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagReal) GetTypeName() string {
+	return "BACnetComplexTagReal"
+}
+
+func (m *BACnetComplexTagReal) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagReal) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	// Simple field (value)
+	lengthInBits += 32
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagReal) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagRealParse(readBuffer utils.ReadBuffer, lengthValueType uint8, extLength uint8) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagReal"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Simple Field (value)
+	value, _valueErr := readBuffer.ReadFloat32("value", true, 8, 23)
+	if _valueErr != nil {
+		return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagReal"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagReal{
+		Value:  value,
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagReal) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagReal"); pushErr != nil {
+			return pushErr
+		}
+
+		// Simple Field (value)
+		value := float32(m.Value)
+		_valueErr := writeBuffer.WriteFloat32("value", 32, (value))
+		if _valueErr != nil {
+			return errors.Wrap(_valueErr, "Error serializing 'value' field")
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagReal"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagReal) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagSignedInteger.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagSignedInteger.go
new file mode 100644
index 0000000..7cd2cd9
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagSignedInteger.go
@@ -0,0 +1,183 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagSignedInteger struct {
+	Data   []int8
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagSignedInteger interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagSignedInteger) DataType() BACnetDataType {
+	return BACnetDataType_SIGNED_INTEGER
+}
+
+func (m *BACnetComplexTagSignedInteger) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagSignedInteger(data []int8, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagSignedInteger{
+		Data:   data,
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagSignedInteger(structType interface{}) *BACnetComplexTagSignedInteger {
+	castFunc := func(typ interface{}) *BACnetComplexTagSignedInteger {
+		if casted, ok := typ.(BACnetComplexTagSignedInteger); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagSignedInteger); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagSignedInteger(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagSignedInteger(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagSignedInteger) GetTypeName() string {
+	return "BACnetComplexTagSignedInteger"
+}
+
+func (m *BACnetComplexTagSignedInteger) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagSignedInteger) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	// Array field
+	if len(m.Data) > 0 {
+		lengthInBits += 8 * uint16(len(m.Data))
+	}
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagSignedInteger) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagSignedIntegerParse(readBuffer utils.ReadBuffer, lengthValueType uint8, extLength uint8) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagSignedInteger"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Array field (data)
+	if pullErr := readBuffer.PullContext("data", utils.WithRenderAsList(true)); pullErr != nil {
+		return nil, pullErr
+	}
+	// Length array
+	data := make([]int8, 0)
+	_dataLength := utils.InlineIf(bool(bool((lengthValueType) == (5))), func() interface{} { return uint16(extLength) }, func() interface{} { return uint16(lengthValueType) }).(uint16)
+	_dataEndPos := readBuffer.GetPos() + uint16(_dataLength)
+	for readBuffer.GetPos() < _dataEndPos {
+		_item, _err := readBuffer.ReadInt8("", 8)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'data' field")
+		}
+		data = append(data, _item)
+	}
+	if closeErr := readBuffer.CloseContext("data", utils.WithRenderAsList(true)); closeErr != nil {
+		return nil, closeErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagSignedInteger"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagSignedInteger{
+		Data:   data,
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagSignedInteger) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagSignedInteger"); pushErr != nil {
+			return pushErr
+		}
+
+		// Array Field (data)
+		if m.Data != nil {
+			if pushErr := writeBuffer.PushContext("data", utils.WithRenderAsList(true)); pushErr != nil {
+				return pushErr
+			}
+			for _, _element := range m.Data {
+				_elementErr := writeBuffer.WriteInt8("", 8, _element)
+				if _elementErr != nil {
+					return errors.Wrap(_elementErr, "Error serializing 'data' field")
+				}
+			}
+			if popErr := writeBuffer.PopContext("data", utils.WithRenderAsList(true)); popErr != nil {
+				return popErr
+			}
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagSignedInteger"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagSignedInteger) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagTime.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagTime.go
new file mode 100644
index 0000000..24e68f1
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagTime.go
@@ -0,0 +1,139 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagTime struct {
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagTime interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagTime) DataType() BACnetDataType {
+	return BACnetDataType_TIME
+}
+
+func (m *BACnetComplexTagTime) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagTime(tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagTime{
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagTime(structType interface{}) *BACnetComplexTagTime {
+	castFunc := func(typ interface{}) *BACnetComplexTagTime {
+		if casted, ok := typ.(BACnetComplexTagTime); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagTime); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagTime(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagTime(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagTime) GetTypeName() string {
+	return "BACnetComplexTagTime"
+}
+
+func (m *BACnetComplexTagTime) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagTime) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagTime) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagTimeParse(readBuffer utils.ReadBuffer) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagTime"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagTime"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagTime{
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagTime) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagTime"); pushErr != nil {
+			return pushErr
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagTime"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagTime) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagUnsignedInteger.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagUnsignedInteger.go
new file mode 100644
index 0000000..d54a05d
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTagUnsignedInteger.go
@@ -0,0 +1,183 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetComplexTagUnsignedInteger struct {
+	Data   []int8
+	Parent *BACnetComplexTag
+}
+
+// The corresponding interface
+type IBACnetComplexTagUnsignedInteger interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetComplexTagUnsignedInteger) DataType() BACnetDataType {
+	return BACnetDataType_UNSIGNED_INTEGER
+}
+
+func (m *BACnetComplexTagUnsignedInteger) InitializeParent(parent *BACnetComplexTag, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32, actualTagNumber uint8, isPrimitiveAndNotBoolean bool, actualLength uint32) {
+	m.Parent.TagNumber = tagNumber
+	m.Parent.LengthValueType = lengthValueType
+	m.Parent.ExtTagNumber = extTagNumber
+	m.Parent.ExtLength = extLength
+	m.Parent.ExtExtLength = extExtLength
+	m.Parent.ExtExtExtLength = extExtExtLength
+}
+
+func NewBACnetComplexTagUnsignedInteger(data []int8, tagNumber uint8, lengthValueType uint8, extTagNumber *uint8, extLength *uint8, extExtLength *uint16, extExtExtLength *uint32) *BACnetComplexTag {
+	child := &BACnetComplexTagUnsignedInteger{
+		Data:   data,
+		Parent: NewBACnetComplexTag(tagNumber, lengthValueType, extTagNumber, extLength, extExtLength, extExtExtLength),
+	}
+	child.Parent.Child = child
+	return child.Parent
+}
+
+func CastBACnetComplexTagUnsignedInteger(structType interface{}) *BACnetComplexTagUnsignedInteger {
+	castFunc := func(typ interface{}) *BACnetComplexTagUnsignedInteger {
+		if casted, ok := typ.(BACnetComplexTagUnsignedInteger); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetComplexTagUnsignedInteger); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetComplexTag); ok {
+			return CastBACnetComplexTagUnsignedInteger(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetComplexTag); ok {
+			return CastBACnetComplexTagUnsignedInteger(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetComplexTagUnsignedInteger) GetTypeName() string {
+	return "BACnetComplexTagUnsignedInteger"
+}
+
+func (m *BACnetComplexTagUnsignedInteger) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetComplexTagUnsignedInteger) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.Parent.ParentLengthInBits())
+
+	// Array field
+	if len(m.Data) > 0 {
+		lengthInBits += 8 * uint16(len(m.Data))
+	}
+
+	return lengthInBits
+}
+
+func (m *BACnetComplexTagUnsignedInteger) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetComplexTagUnsignedIntegerParse(readBuffer utils.ReadBuffer, lengthValueType uint8, extLength uint8) (*BACnetComplexTag, error) {
+	if pullErr := readBuffer.PullContext("BACnetComplexTagUnsignedInteger"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Array field (data)
+	if pullErr := readBuffer.PullContext("data", utils.WithRenderAsList(true)); pullErr != nil {
+		return nil, pullErr
+	}
+	// Length array
+	data := make([]int8, 0)
+	_dataLength := utils.InlineIf(bool(bool((lengthValueType) == (5))), func() interface{} { return uint16(extLength) }, func() interface{} { return uint16(lengthValueType) }).(uint16)
+	_dataEndPos := readBuffer.GetPos() + uint16(_dataLength)
+	for readBuffer.GetPos() < _dataEndPos {
+		_item, _err := readBuffer.ReadInt8("", 8)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'data' field")
+		}
+		data = append(data, _item)
+	}
+	if closeErr := readBuffer.CloseContext("data", utils.WithRenderAsList(true)); closeErr != nil {
+		return nil, closeErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetComplexTagUnsignedInteger"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetComplexTagUnsignedInteger{
+		Data:   data,
+		Parent: &BACnetComplexTag{},
+	}
+	_child.Parent.Child = _child
+	return _child.Parent, nil
+}
+
+func (m *BACnetComplexTagUnsignedInteger) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetComplexTagUnsignedInteger"); pushErr != nil {
+			return pushErr
+		}
+
+		// Array Field (data)
+		if m.Data != nil {
+			if pushErr := writeBuffer.PushContext("data", utils.WithRenderAsList(true)); pushErr != nil {
+				return pushErr
+			}
+			for _, _element := range m.Data {
+				_elementErr := writeBuffer.WriteInt8("", 8, _element)
+				if _elementErr != nil {
+					return errors.Wrap(_elementErr, "Error serializing 'data' field")
+				}
+			}
+			if popErr := writeBuffer.PopContext("data", utils.WithRenderAsList(true)); popErr != nil {
+				return popErr
+			}
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetComplexTagUnsignedInteger"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.Parent.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetComplexTagUnsignedInteger) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
index c4896e2..d0b4cfe 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
@@ -244,7 +244,7 @@ func BACnetConfirmedServiceRequestWritePropertyParse(readBuffer utils.ReadBuffer
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'priority' field")
 		}
-		priority = _val
+		priority = CastBACnetTag(_val)
 	}
 
 	if closeErr := readBuffer.CloseContext("BACnetConfirmedServiceRequestWriteProperty"); closeErr != nil {
@@ -257,8 +257,8 @@ func BACnetConfirmedServiceRequestWritePropertyParse(readBuffer utils.ReadBuffer
 		ObjectInstanceNumber:     objectInstanceNumber,
 		PropertyIdentifierLength: propertyIdentifierLength,
 		PropertyIdentifier:       propertyIdentifier,
-		Value:                    value,
-		Priority:                 priority,
+		Value:                    CastBACnetTag(value),
+		Priority:                 CastBACnetTag(priority),
 		Parent:                   &BACnetConfirmedServiceRequest{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetDataType.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetDataType.go
new file mode 100644
index 0000000..c9b4a5c
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetDataType.go
@@ -0,0 +1,200 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+type BACnetDataType int8
+
+type IBACnetDataType interface {
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+const (
+	BACnetDataType_NULL                     BACnetDataType = 0x0
+	BACnetDataType_BOOLEAN                  BACnetDataType = 0x1
+	BACnetDataType_UNSIGNED_INTEGER         BACnetDataType = 0x2
+	BACnetDataType_SIGNED_INTEGER           BACnetDataType = 0x3
+	BACnetDataType_REAL                     BACnetDataType = 0x4
+	BACnetDataType_DOUBLE                   BACnetDataType = 0x5
+	BACnetDataType_OCTET_STRING             BACnetDataType = 0x6
+	BACnetDataType_CHARACTER_STRING         BACnetDataType = 0x7
+	BACnetDataType_BIT_STRING               BACnetDataType = 0x8
+	BACnetDataType_ENUMERATED               BACnetDataType = 0x9
+	BACnetDataType_DATE                     BACnetDataType = 0xA
+	BACnetDataType_TIME                     BACnetDataType = 0xB
+	BACnetDataType_BACNET_OBJECT_IDENTIFIER BACnetDataType = 0xC
+)
+
+var BACnetDataTypeValues []BACnetDataType
+
+func init() {
+	_ = errors.New
+	BACnetDataTypeValues = []BACnetDataType{
+		BACnetDataType_NULL,
+		BACnetDataType_BOOLEAN,
+		BACnetDataType_UNSIGNED_INTEGER,
+		BACnetDataType_SIGNED_INTEGER,
+		BACnetDataType_REAL,
+		BACnetDataType_DOUBLE,
+		BACnetDataType_OCTET_STRING,
+		BACnetDataType_CHARACTER_STRING,
+		BACnetDataType_BIT_STRING,
+		BACnetDataType_ENUMERATED,
+		BACnetDataType_DATE,
+		BACnetDataType_TIME,
+		BACnetDataType_BACNET_OBJECT_IDENTIFIER,
+	}
+}
+
+func BACnetDataTypeByValue(value int8) BACnetDataType {
+	switch value {
+	case 0x0:
+		return BACnetDataType_NULL
+	case 0x1:
+		return BACnetDataType_BOOLEAN
+	case 0x2:
+		return BACnetDataType_UNSIGNED_INTEGER
+	case 0x3:
+		return BACnetDataType_SIGNED_INTEGER
+	case 0x4:
+		return BACnetDataType_REAL
+	case 0x5:
+		return BACnetDataType_DOUBLE
+	case 0x6:
+		return BACnetDataType_OCTET_STRING
+	case 0x7:
+		return BACnetDataType_CHARACTER_STRING
+	case 0x8:
+		return BACnetDataType_BIT_STRING
+	case 0x9:
+		return BACnetDataType_ENUMERATED
+	case 0xA:
+		return BACnetDataType_DATE
+	case 0xB:
+		return BACnetDataType_TIME
+	case 0xC:
+		return BACnetDataType_BACNET_OBJECT_IDENTIFIER
+	}
+	return 0
+}
+
+func BACnetDataTypeByName(value string) BACnetDataType {
+	switch value {
+	case "NULL":
+		return BACnetDataType_NULL
+	case "BOOLEAN":
+		return BACnetDataType_BOOLEAN
+	case "UNSIGNED_INTEGER":
+		return BACnetDataType_UNSIGNED_INTEGER
+	case "SIGNED_INTEGER":
+		return BACnetDataType_SIGNED_INTEGER
+	case "REAL":
+		return BACnetDataType_REAL
+	case "DOUBLE":
+		return BACnetDataType_DOUBLE
+	case "OCTET_STRING":
+		return BACnetDataType_OCTET_STRING
+	case "CHARACTER_STRING":
+		return BACnetDataType_CHARACTER_STRING
+	case "BIT_STRING":
+		return BACnetDataType_BIT_STRING
+	case "ENUMERATED":
+		return BACnetDataType_ENUMERATED
+	case "DATE":
+		return BACnetDataType_DATE
+	case "TIME":
+		return BACnetDataType_TIME
+	case "BACNET_OBJECT_IDENTIFIER":
+		return BACnetDataType_BACNET_OBJECT_IDENTIFIER
+	}
+	return 0
+}
+
+func CastBACnetDataType(structType interface{}) BACnetDataType {
+	castFunc := func(typ interface{}) BACnetDataType {
+		if sBACnetDataType, ok := typ.(BACnetDataType); ok {
+			return sBACnetDataType
+		}
+		return 0
+	}
+	return castFunc(structType)
+}
+
+func (m BACnetDataType) LengthInBits() uint16 {
+	return 4
+}
+
+func (m BACnetDataType) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetDataTypeParse(readBuffer utils.ReadBuffer) (BACnetDataType, error) {
+	val, err := readBuffer.ReadInt8("BACnetDataType", 4)
+	if err != nil {
+		return 0, nil
+	}
+	return BACnetDataTypeByValue(val), nil
+}
+
+func (e BACnetDataType) Serialize(writeBuffer utils.WriteBuffer) error {
+	return writeBuffer.WriteInt8("BACnetDataType", 4, int8(e), utils.WithAdditionalStringRepresentation(e.name()))
+}
+
+func (e BACnetDataType) name() string {
+	switch e {
+	case BACnetDataType_NULL:
+		return "NULL"
+	case BACnetDataType_BOOLEAN:
+		return "BOOLEAN"
+	case BACnetDataType_UNSIGNED_INTEGER:
+		return "UNSIGNED_INTEGER"
+	case BACnetDataType_SIGNED_INTEGER:
+		return "SIGNED_INTEGER"
+	case BACnetDataType_REAL:
+		return "REAL"
+	case BACnetDataType_DOUBLE:
+		return "DOUBLE"
+	case BACnetDataType_OCTET_STRING:
+		return "OCTET_STRING"
+	case BACnetDataType_CHARACTER_STRING:
+		return "CHARACTER_STRING"
+	case BACnetDataType_BIT_STRING:
+		return "BIT_STRING"
+	case BACnetDataType_ENUMERATED:
+		return "ENUMERATED"
+	case BACnetDataType_DATE:
+		return "DATE"
+	case BACnetDataType_TIME:
+		return "TIME"
+	case BACnetDataType_BACNET_OBJECT_IDENTIFIER:
+		return "BACNET_OBJECT_IDENTIFIER"
+	}
+	return ""
+}
+
+func (e BACnetDataType) String() string {
+	return e.name()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
index 9cdf60d..5fc4ae8 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
@@ -237,7 +237,7 @@ func BACnetServiceAckReadPropertyParse(readBuffer utils.ReadBuffer) (*BACnetServ
 		ObjectInstanceNumber:     objectInstanceNumber,
 		PropertyIdentifierLength: propertyIdentifierLength,
 		PropertyIdentifier:       propertyIdentifier,
-		Value:                    value,
+		Value:                    CastBACnetTag(value),
 		Parent:                   &BACnetServiceAck{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
index ee1c97b..fd708f9 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
@@ -20,25 +20,19 @@
 package model
 
 import (
-	"fmt"
 	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
 	"github.com/pkg/errors"
 )
 
 // Code generated by code-generation. DO NOT EDIT.
 
-// Constant values.
-const BACnetUnconfirmedServiceRequestWhoHas_DEVICEINSTANCELOWLIMITHEADER uint8 = 0x0B
-const BACnetUnconfirmedServiceRequestWhoHas_DEVICEINSTANCEHIGHLIMITHEADER uint8 = 0x1B
-const BACnetUnconfirmedServiceRequestWhoHas_OBJECTNAMEHEADER uint8 = 0x3D
-
 // The data-structure of this message
 type BACnetUnconfirmedServiceRequestWhoHas struct {
-	DeviceInstanceLowLimit  uint32
-	DeviceInstanceHighLimit uint32
-	ObjectNameCharacterSet  uint8
-	ObjectName              []int8
-	Parent                  *BACnetUnconfirmedServiceRequest
+	DeviceInstanceRangeLowLimit  *BACnetComplexTagUnsignedInteger
+	DeviceInstanceRangeHighLimit *BACnetComplexTagUnsignedInteger
+	ObjectIdentifier             *BACnetComplexTagOctetString
+	ObjectName                   *BACnetComplexTagOctetString
+	Parent                       *BACnetUnconfirmedServiceRequest
 }
 
 // The corresponding interface
@@ -58,13 +52,13 @@ func (m *BACnetUnconfirmedServiceRequestWhoHas) ServiceChoice() uint8 {
 func (m *BACnetUnconfirmedServiceRequestWhoHas) InitializeParent(parent *BACnetUnconfirmedServiceRequest) {
 }
 
-func NewBACnetUnconfirmedServiceRequestWhoHas(deviceInstanceLowLimit uint32, deviceInstanceHighLimit uint32, objectNameCharacterSet uint8, objectName []int8) *BACnetUnconfirmedServiceRequest {
+func NewBACnetUnconfirmedServiceRequestWhoHas(deviceInstanceRangeLowLimit *BACnetComplexTagUnsignedInteger, deviceInstanceRangeHighLimit *BACnetComplexTagUnsignedInteger, objectIdentifier *BACnetComplexTagOctetString, objectName *BACnetComplexTagOctetString) *BACnetUnconfirmedServiceRequest {
 	child := &BACnetUnconfirmedServiceRequestWhoHas{
-		DeviceInstanceLowLimit:  deviceInstanceLowLimit,
-		DeviceInstanceHighLimit: deviceInstanceHighLimit,
-		ObjectNameCharacterSet:  objectNameCharacterSet,
-		ObjectName:              objectName,
-		Parent:                  NewBACnetUnconfirmedServiceRequest(),
+		DeviceInstanceRangeLowLimit:  deviceInstanceRangeLowLimit,
+		DeviceInstanceRangeHighLimit: deviceInstanceRangeHighLimit,
+		ObjectIdentifier:             objectIdentifier,
+		ObjectName:                   objectName,
+		Parent:                       NewBACnetUnconfirmedServiceRequest(),
 	}
 	child.Parent.Child = child
 	return child.Parent
@@ -100,30 +94,20 @@ func (m *BACnetUnconfirmedServiceRequestWhoHas) LengthInBits() uint16 {
 func (m *BACnetUnconfirmedServiceRequestWhoHas) LengthInBitsConditional(lastItem bool) uint16 {
 	lengthInBits := uint16(m.Parent.ParentLengthInBits())
 
-	// Const Field (deviceInstanceLowLimitHeader)
-	lengthInBits += 8
-
-	// Simple field (deviceInstanceLowLimit)
-	lengthInBits += 24
-
-	// Const Field (deviceInstanceHighLimitHeader)
-	lengthInBits += 8
-
-	// Simple field (deviceInstanceHighLimit)
-	lengthInBits += 24
-
-	// Const Field (objectNameHeader)
-	lengthInBits += 8
+	// Simple field (deviceInstanceRangeLowLimit)
+	lengthInBits += m.DeviceInstanceRangeLowLimit.LengthInBits()
 
-	// Implicit Field (objectNameLength)
-	lengthInBits += 8
+	// Optional Field (deviceInstanceRangeHighLimit)
+	if m.DeviceInstanceRangeHighLimit != nil {
+		lengthInBits += (*m.DeviceInstanceRangeHighLimit).LengthInBits()
+	}
 
-	// Simple field (objectNameCharacterSet)
-	lengthInBits += 8
+	// Simple field (objectIdentifier)
+	lengthInBits += m.ObjectIdentifier.LengthInBits()
 
-	// Array field
-	if len(m.ObjectName) > 0 {
-		lengthInBits += 8 * uint16(len(m.ObjectName))
+	// Optional Field (objectName)
+	if m.ObjectName != nil {
+		lengthInBits += (*m.ObjectName).LengthInBits()
 	}
 
 	return lengthInBits
@@ -138,75 +122,48 @@ func BACnetUnconfirmedServiceRequestWhoHasParse(readBuffer utils.ReadBuffer) (*B
 		return nil, pullErr
 	}
 
-	// Const Field (deviceInstanceLowLimitHeader)
-	deviceInstanceLowLimitHeader, _deviceInstanceLowLimitHeaderErr := readBuffer.ReadUint8("deviceInstanceLowLimitHeader", 8)
-	if _deviceInstanceLowLimitHeaderErr != nil {
-		return nil, errors.Wrap(_deviceInstanceLowLimitHeaderErr, "Error parsing 'deviceInstanceLowLimitHeader' field")
-	}
-	if deviceInstanceLowLimitHeader != BACnetUnconfirmedServiceRequestWhoHas_DEVICEINSTANCELOWLIMITHEADER {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetUnconfirmedServiceRequestWhoHas_DEVICEINSTANCELOWLIMITHEADER) + " but got " + fmt.Sprintf("%d", deviceInstanceLowLimitHeader))
-	}
-
-	// Simple Field (deviceInstanceLowLimit)
-	deviceInstanceLowLimit, _deviceInstanceLowLimitErr := readBuffer.ReadUint32("deviceInstanceLowLimit", 24)
-	if _deviceInstanceLowLimitErr != nil {
-		return nil, errors.Wrap(_deviceInstanceLowLimitErr, "Error parsing 'deviceInstanceLowLimit' field")
+	// Simple Field (deviceInstanceRangeLowLimit)
+	if pullErr := readBuffer.PullContext("deviceInstanceRangeLowLimit"); pullErr != nil {
+		return nil, pullErr
 	}
-
-	// Const Field (deviceInstanceHighLimitHeader)
-	deviceInstanceHighLimitHeader, _deviceInstanceHighLimitHeaderErr := readBuffer.ReadUint8("deviceInstanceHighLimitHeader", 8)
-	if _deviceInstanceHighLimitHeaderErr != nil {
-		return nil, errors.Wrap(_deviceInstanceHighLimitHeaderErr, "Error parsing 'deviceInstanceHighLimitHeader' field")
+	deviceInstanceRangeLowLimit, _deviceInstanceRangeLowLimitErr := BACnetComplexTagParse(readBuffer, (0), BACnetDataType_UNSIGNED_INTEGER)
+	if _deviceInstanceRangeLowLimitErr != nil {
+		return nil, errors.Wrap(_deviceInstanceRangeLowLimitErr, "Error parsing 'deviceInstanceRangeLowLimit' field")
 	}
-	if deviceInstanceHighLimitHeader != BACnetUnconfirmedServiceRequestWhoHas_DEVICEINSTANCEHIGHLIMITHEADER {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetUnconfirmedServiceRequestWhoHas_DEVICEINSTANCEHIGHLIMITHEADER) + " but got " + fmt.Sprintf("%d", deviceInstanceHighLimitHeader))
+	if closeErr := readBuffer.CloseContext("deviceInstanceRangeLowLimit"); closeErr != nil {
+		return nil, closeErr
 	}
 
-	// Simple Field (deviceInstanceHighLimit)
-	deviceInstanceHighLimit, _deviceInstanceHighLimitErr := readBuffer.ReadUint32("deviceInstanceHighLimit", 24)
-	if _deviceInstanceHighLimitErr != nil {
-		return nil, errors.Wrap(_deviceInstanceHighLimitErr, "Error parsing 'deviceInstanceHighLimit' field")
+	// Optional Field (deviceInstanceRangeHighLimit) (Can be skipped, if a given expression evaluates to false)
+	var deviceInstanceRangeHighLimit *BACnetComplexTagUnsignedInteger = nil
+	if bool((deviceInstanceRangeLowLimit) != (nil)) {
+		_val, _err := BACnetComplexTagParse(readBuffer, (1), BACnetDataType_UNSIGNED_INTEGER)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'deviceInstanceRangeHighLimit' field")
+		}
+		deviceInstanceRangeHighLimit = CastBACnetComplexTagUnsignedInteger(_val)
 	}
 
-	// Const Field (objectNameHeader)
-	objectNameHeader, _objectNameHeaderErr := readBuffer.ReadUint8("objectNameHeader", 8)
-	if _objectNameHeaderErr != nil {
-		return nil, errors.Wrap(_objectNameHeaderErr, "Error parsing 'objectNameHeader' field")
-	}
-	if objectNameHeader != BACnetUnconfirmedServiceRequestWhoHas_OBJECTNAMEHEADER {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetUnconfirmedServiceRequestWhoHas_OBJECTNAMEHEADER) + " but got " + fmt.Sprintf("%d", objectNameHeader))
+	// Simple Field (objectIdentifier)
+	if pullErr := readBuffer.PullContext("objectIdentifier"); pullErr != nil {
+		return nil, pullErr
 	}
-
-	// Implicit Field (objectNameLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-	objectNameLength, _objectNameLengthErr := readBuffer.ReadUint8("objectNameLength", 8)
-	_ = objectNameLength
-	if _objectNameLengthErr != nil {
-		return nil, errors.Wrap(_objectNameLengthErr, "Error parsing 'objectNameLength' field")
+	objectIdentifier, _objectIdentifierErr := BACnetComplexTagParse(readBuffer, (2), BACnetDataType_OCTET_STRING)
+	if _objectIdentifierErr != nil {
+		return nil, errors.Wrap(_objectIdentifierErr, "Error parsing 'objectIdentifier' field")
 	}
-
-	// Simple Field (objectNameCharacterSet)
-	objectNameCharacterSet, _objectNameCharacterSetErr := readBuffer.ReadUint8("objectNameCharacterSet", 8)
-	if _objectNameCharacterSetErr != nil {
-		return nil, errors.Wrap(_objectNameCharacterSetErr, "Error parsing 'objectNameCharacterSet' field")
+	if closeErr := readBuffer.CloseContext("objectIdentifier"); closeErr != nil {
+		return nil, closeErr
 	}
 
-	// Array field (objectName)
-	if pullErr := readBuffer.PullContext("objectName", utils.WithRenderAsList(true)); pullErr != nil {
-		return nil, pullErr
-	}
-	// Length array
-	objectName := make([]int8, 0)
-	_objectNameLength := uint16(objectNameLength) - uint16(uint16(1))
-	_objectNameEndPos := readBuffer.GetPos() + uint16(_objectNameLength)
-	for readBuffer.GetPos() < _objectNameEndPos {
-		_item, _err := readBuffer.ReadInt8("", 8)
+	// Optional Field (objectName) (Can be skipped, if a given expression evaluates to false)
+	var objectName *BACnetComplexTagOctetString = nil
+	if bool((objectIdentifier) == (nil)) {
+		_val, _err := BACnetComplexTagParse(readBuffer, (3), BACnetDataType_OCTET_STRING)
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'objectName' field")
 		}
-		objectName = append(objectName, _item)
-	}
-	if closeErr := readBuffer.CloseContext("objectName", utils.WithRenderAsList(true)); closeErr != nil {
-		return nil, closeErr
+		objectName = CastBACnetComplexTagOctetString(_val)
 	}
 
 	if closeErr := readBuffer.CloseContext("BACnetUnconfirmedServiceRequestWhoHas"); closeErr != nil {
@@ -215,11 +172,11 @@ func BACnetUnconfirmedServiceRequestWhoHasParse(readBuffer utils.ReadBuffer) (*B
 
 	// Create a partially initialized instance
 	_child := &BACnetUnconfirmedServiceRequestWhoHas{
-		DeviceInstanceLowLimit:  deviceInstanceLowLimit,
-		DeviceInstanceHighLimit: deviceInstanceHighLimit,
-		ObjectNameCharacterSet:  objectNameCharacterSet,
-		ObjectName:              objectName,
-		Parent:                  &BACnetUnconfirmedServiceRequest{},
+		DeviceInstanceRangeLowLimit:  CastBACnetComplexTagUnsignedInteger(deviceInstanceRangeLowLimit),
+		DeviceInstanceRangeHighLimit: CastBACnetComplexTagUnsignedInteger(deviceInstanceRangeHighLimit),
+		ObjectIdentifier:             CastBACnetComplexTagOctetString(objectIdentifier),
+		ObjectName:                   CastBACnetComplexTagOctetString(objectName),
+		Parent:                       &BACnetUnconfirmedServiceRequest{},
 	}
 	_child.Parent.Child = _child
 	return _child.Parent, nil
@@ -231,65 +188,47 @@ func (m *BACnetUnconfirmedServiceRequestWhoHas) Serialize(writeBuffer utils.Writ
 			return pushErr
 		}
 
-		// Const Field (deviceInstanceLowLimitHeader)
-		_deviceInstanceLowLimitHeaderErr := writeBuffer.WriteUint8("deviceInstanceLowLimitHeader", 8, 0x0B)
-		if _deviceInstanceLowLimitHeaderErr != nil {
-			return errors.Wrap(_deviceInstanceLowLimitHeaderErr, "Error serializing 'deviceInstanceLowLimitHeader' field")
+		// Simple Field (deviceInstanceRangeLowLimit)
+		if pushErr := writeBuffer.PushContext("deviceInstanceRangeLowLimit"); pushErr != nil {
+			return pushErr
 		}
-
-		// Simple Field (deviceInstanceLowLimit)
-		deviceInstanceLowLimit := uint32(m.DeviceInstanceLowLimit)
-		_deviceInstanceLowLimitErr := writeBuffer.WriteUint32("deviceInstanceLowLimit", 24, (deviceInstanceLowLimit))
-		if _deviceInstanceLowLimitErr != nil {
-			return errors.Wrap(_deviceInstanceLowLimitErr, "Error serializing 'deviceInstanceLowLimit' field")
+		_deviceInstanceRangeLowLimitErr := m.DeviceInstanceRangeLowLimit.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("deviceInstanceRangeLowLimit"); popErr != nil {
+			return popErr
 		}
-
-		// Const Field (deviceInstanceHighLimitHeader)
-		_deviceInstanceHighLimitHeaderErr := writeBuffer.WriteUint8("deviceInstanceHighLimitHeader", 8, 0x1B)
-		if _deviceInstanceHighLimitHeaderErr != nil {
-			return errors.Wrap(_deviceInstanceHighLimitHeaderErr, "Error serializing 'deviceInstanceHighLimitHeader' field")
+		if _deviceInstanceRangeLowLimitErr != nil {
+			return errors.Wrap(_deviceInstanceRangeLowLimitErr, "Error serializing 'deviceInstanceRangeLowLimit' field")
 		}
 
-		// Simple Field (deviceInstanceHighLimit)
-		deviceInstanceHighLimit := uint32(m.DeviceInstanceHighLimit)
-		_deviceInstanceHighLimitErr := writeBuffer.WriteUint32("deviceInstanceHighLimit", 24, (deviceInstanceHighLimit))
-		if _deviceInstanceHighLimitErr != nil {
-			return errors.Wrap(_deviceInstanceHighLimitErr, "Error serializing 'deviceInstanceHighLimit' field")
+		// Optional Field (deviceInstanceRangeHighLimit) (Can be skipped, if the value is null)
+		var deviceInstanceRangeHighLimit *BACnetComplexTagUnsignedInteger = nil
+		if m.DeviceInstanceRangeHighLimit != nil {
+			deviceInstanceRangeHighLimit = m.DeviceInstanceRangeHighLimit
+			_deviceInstanceRangeHighLimitErr := deviceInstanceRangeHighLimit.Serialize(writeBuffer)
+			if _deviceInstanceRangeHighLimitErr != nil {
+				return errors.Wrap(_deviceInstanceRangeHighLimitErr, "Error serializing 'deviceInstanceRangeHighLimit' field")
+			}
 		}
 
-		// Const Field (objectNameHeader)
-		_objectNameHeaderErr := writeBuffer.WriteUint8("objectNameHeader", 8, 0x3D)
-		if _objectNameHeaderErr != nil {
-			return errors.Wrap(_objectNameHeaderErr, "Error serializing 'objectNameHeader' field")
+		// Simple Field (objectIdentifier)
+		if pushErr := writeBuffer.PushContext("objectIdentifier"); pushErr != nil {
+			return pushErr
 		}
-
-		// Implicit Field (objectNameLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-		objectNameLength := uint8(uint8(uint8(len(m.ObjectName))) + uint8(uint8(1)))
-		_objectNameLengthErr := writeBuffer.WriteUint8("objectNameLength", 8, (objectNameLength))
-		if _objectNameLengthErr != nil {
-			return errors.Wrap(_objectNameLengthErr, "Error serializing 'objectNameLength' field")
+		_objectIdentifierErr := m.ObjectIdentifier.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("objectIdentifier"); popErr != nil {
+			return popErr
 		}
-
-		// Simple Field (objectNameCharacterSet)
-		objectNameCharacterSet := uint8(m.ObjectNameCharacterSet)
-		_objectNameCharacterSetErr := writeBuffer.WriteUint8("objectNameCharacterSet", 8, (objectNameCharacterSet))
-		if _objectNameCharacterSetErr != nil {
-			return errors.Wrap(_objectNameCharacterSetErr, "Error serializing 'objectNameCharacterSet' field")
+		if _objectIdentifierErr != nil {
+			return errors.Wrap(_objectIdentifierErr, "Error serializing 'objectIdentifier' field")
 		}
 
-		// Array Field (objectName)
+		// Optional Field (objectName) (Can be skipped, if the value is null)
+		var objectName *BACnetComplexTagOctetString = nil
 		if m.ObjectName != nil {
-			if pushErr := writeBuffer.PushContext("objectName", utils.WithRenderAsList(true)); pushErr != nil {
-				return pushErr
-			}
-			for _, _element := range m.ObjectName {
-				_elementErr := writeBuffer.WriteInt8("", 8, _element)
-				if _elementErr != nil {
-					return errors.Wrap(_elementErr, "Error serializing 'objectName' field")
-				}
-			}
-			if popErr := writeBuffer.PopContext("objectName", utils.WithRenderAsList(true)); popErr != nil {
-				return popErr
+			objectName = m.ObjectName
+			_objectNameErr := objectName.Serialize(writeBuffer)
+			if _objectNameErr != nil {
+				return errors.Wrap(_objectNameErr, "Error serializing 'objectName' field")
 			}
 		}
 
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCForwardedNPDU.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCForwardedNPDU.go
index 6641793..380a7dd 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCForwardedNPDU.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCForwardedNPDU.go
@@ -158,7 +158,7 @@ func BVLCForwardedNPDUParse(readBuffer utils.ReadBuffer, bvlcLength uint16) (*BV
 	_child := &BVLCForwardedNPDU{
 		Ip:     ip,
 		Port:   port,
-		Npdu:   npdu,
+		Npdu:   CastNPDU(npdu),
 		Parent: &BVLC{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCOriginalBroadcastNPDU.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCOriginalBroadcastNPDU.go
index 7667c88..0ef8601 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCOriginalBroadcastNPDU.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCOriginalBroadcastNPDU.go
@@ -121,7 +121,7 @@ func BVLCOriginalBroadcastNPDUParse(readBuffer utils.ReadBuffer, bvlcLength uint
 
 	// Create a partially initialized instance
 	_child := &BVLCOriginalBroadcastNPDU{
-		Npdu:   npdu,
+		Npdu:   CastNPDU(npdu),
 		Parent: &BVLC{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCOriginalUnicastNPDU.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCOriginalUnicastNPDU.go
index d0c4cb8..6008137 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCOriginalUnicastNPDU.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCOriginalUnicastNPDU.go
@@ -121,7 +121,7 @@ func BVLCOriginalUnicastNPDUParse(readBuffer utils.ReadBuffer, bvlcLength uint16
 
 	// Create a partially initialized instance
 	_child := &BVLCOriginalUnicastNPDU{
-		Npdu:   npdu,
+		Npdu:   CastNPDU(npdu),
 		Parent: &BVLC{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/NPDU.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/NPDU.go
index 6506ea6..afcc7e4 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/NPDU.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/NPDU.go
@@ -317,7 +317,7 @@ func NPDUParse(readBuffer utils.ReadBuffer, npduLength uint16) (*NPDU, error) {
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'nlm' field")
 		}
-		nlm = _val
+		nlm = CastNLM(_val)
 	}
 
 	// Optional Field (apdu) (Can be skipped, if a given expression evaluates to false)
@@ -327,7 +327,7 @@ func NPDUParse(readBuffer utils.ReadBuffer, npduLength uint16) (*NPDU, error) {
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'apdu' field")
 		}
-		apdu = _val
+		apdu = CastAPDU(_val)
 	}
 
 	if closeErr := readBuffer.CloseContext("NPDU"); closeErr != nil {
diff --git a/plc4go/internal/plc4go/df1/readwrite/model/DF1SymbolMessageFrame.go b/plc4go/internal/plc4go/df1/readwrite/model/DF1SymbolMessageFrame.go
index 2fe4a4f..dd15810 100644
--- a/plc4go/internal/plc4go/df1/readwrite/model/DF1SymbolMessageFrame.go
+++ b/plc4go/internal/plc4go/df1/readwrite/model/DF1SymbolMessageFrame.go
@@ -192,7 +192,7 @@ func DF1SymbolMessageFrameParse(readBuffer utils.ReadBuffer) (*DF1Symbol, error)
 	_child := &DF1SymbolMessageFrame{
 		DestinationAddress: destinationAddress,
 		SourceAddress:      sourceAddress,
-		Command:            command,
+		Command:            CastDF1Command(command),
 		Parent:             &DF1Symbol{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/eip/readwrite/model/CipRRData.go b/plc4go/internal/plc4go/eip/readwrite/model/CipRRData.go
index 9b0be07..f15fc06 100644
--- a/plc4go/internal/plc4go/eip/readwrite/model/CipRRData.go
+++ b/plc4go/internal/plc4go/eip/readwrite/model/CipRRData.go
@@ -160,7 +160,7 @@ func CipRRDataParse(readBuffer utils.ReadBuffer, len uint16) (*EipPacket, error)
 
 	// Create a partially initialized instance
 	_child := &CipRRData{
-		Exchange: exchange,
+		Exchange: CastCipExchange(exchange),
 		Parent:   &EipPacket{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/eip/readwrite/model/CipUnconnectedRequest.go b/plc4go/internal/plc4go/eip/readwrite/model/CipUnconnectedRequest.go
index e25716d..c113aa8 100644
--- a/plc4go/internal/plc4go/eip/readwrite/model/CipUnconnectedRequest.go
+++ b/plc4go/internal/plc4go/eip/readwrite/model/CipUnconnectedRequest.go
@@ -272,7 +272,7 @@ func CipUnconnectedRequestParse(readBuffer utils.ReadBuffer) (*CipService, error
 
 	// Create a partially initialized instance
 	_child := &CipUnconnectedRequest{
-		UnconnectedService: unconnectedService,
+		UnconnectedService: CastCipService(unconnectedService),
 		BackPlane:          backPlane,
 		Slot:               slot,
 		Parent:             &CipService{},
diff --git a/plc4go/internal/plc4go/eip/readwrite/model/MultipleServiceRequest.go b/plc4go/internal/plc4go/eip/readwrite/model/MultipleServiceRequest.go
index 1ea2a3b..21ab65d 100644
--- a/plc4go/internal/plc4go/eip/readwrite/model/MultipleServiceRequest.go
+++ b/plc4go/internal/plc4go/eip/readwrite/model/MultipleServiceRequest.go
@@ -150,7 +150,7 @@ func MultipleServiceRequestParse(readBuffer utils.ReadBuffer, serviceLen uint16)
 
 	// Create a partially initialized instance
 	_child := &MultipleServiceRequest{
-		Data:   data,
+		Data:   CastServices(data),
 		Parent: &CipService{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/firmata/readwrite/model/FirmataCommandSysex.go b/plc4go/internal/plc4go/firmata/readwrite/model/FirmataCommandSysex.go
index 8cc210a..3bb915d 100644
--- a/plc4go/internal/plc4go/firmata/readwrite/model/FirmataCommandSysex.go
+++ b/plc4go/internal/plc4go/firmata/readwrite/model/FirmataCommandSysex.go
@@ -139,7 +139,7 @@ func FirmataCommandSysexParse(readBuffer utils.ReadBuffer, response bool) (*Firm
 
 	// Create a partially initialized instance
 	_child := &FirmataCommandSysex{
-		Command: command,
+		Command: CastSysexCommand(command),
 		Parent:  &FirmataCommand{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/firmata/readwrite/model/FirmataMessageCommand.go b/plc4go/internal/plc4go/firmata/readwrite/model/FirmataMessageCommand.go
index 2cfde82..a9806a9 100644
--- a/plc4go/internal/plc4go/firmata/readwrite/model/FirmataMessageCommand.go
+++ b/plc4go/internal/plc4go/firmata/readwrite/model/FirmataMessageCommand.go
@@ -121,7 +121,7 @@ func FirmataMessageCommandParse(readBuffer utils.ReadBuffer, response bool) (*Fi
 
 	// Create a partially initialized instance
 	_child := &FirmataMessageCommand{
-		Command: command,
+		Command: CastFirmataCommand(command),
 		Parent:  &FirmataMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduControlContainer.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduControlContainer.go
index ae096c3..152ffd5 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduControlContainer.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduControlContainer.go
@@ -123,7 +123,7 @@ func ApduControlContainerParse(readBuffer utils.ReadBuffer) (*Apdu, error) {
 
 	// Create a partially initialized instance
 	_child := &ApduControlContainer{
-		ControlApdu: controlApdu,
+		ControlApdu: CastApduControl(controlApdu),
 		Parent:      &Apdu{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataContainer.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataContainer.go
index 238e6e9..f4c122e 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataContainer.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataContainer.go
@@ -123,7 +123,7 @@ func ApduDataContainerParse(readBuffer utils.ReadBuffer, dataLength uint8) (*Apd
 
 	// Create a partially initialized instance
 	_child := &ApduDataContainer{
-		DataApdu: dataApdu,
+		DataApdu: CastApduData(dataApdu),
 		Parent:   &Apdu{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataOther.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataOther.go
index 7d24927..152acac 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataOther.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataOther.go
@@ -121,7 +121,7 @@ func ApduDataOtherParse(readBuffer utils.ReadBuffer, dataLength uint8) (*ApduDat
 
 	// Create a partially initialized instance
 	_child := &ApduDataOther{
-		ExtendedApdu: extendedApdu,
+		ExtendedApdu: CastApduDataExt(extendedApdu),
 		Parent:       &ApduData{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIAdditionalInformationRelativeTimestamp.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIAdditionalInformationRelativeTimestamp.go
index 7a6bd01..cb11982 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIAdditionalInformationRelativeTimestamp.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIAdditionalInformationRelativeTimestamp.go
@@ -137,7 +137,7 @@ func CEMIAdditionalInformationRelativeTimestampParse(readBuffer utils.ReadBuffer
 
 	// Create a partially initialized instance
 	_child := &CEMIAdditionalInformationRelativeTimestamp{
-		RelativeTimestamp: relativeTimestamp,
+		RelativeTimestamp: CastRelativeTimestamp(relativeTimestamp),
 		Parent:            &CEMIAdditionalInformation{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ComObjectTableRealisationType6.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ComObjectTableRealisationType6.go
index 1c5d705..1561e40 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ComObjectTableRealisationType6.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ComObjectTableRealisationType6.go
@@ -121,7 +121,7 @@ func ComObjectTableRealisationType6Parse(readBuffer utils.ReadBuffer) (*ComObjec
 
 	// Create a partially initialized instance
 	_child := &ComObjectTableRealisationType6{
-		ComObjectDescriptors: comObjectDescriptors,
+		ComObjectDescriptors: CastGroupObjectDescriptorRealisationType6(comObjectDescriptors),
 		Parent:               &ComObjectTable{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionRequest.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionRequest.go
index 51cf54f..476aa88 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionRequest.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionRequest.go
@@ -155,9 +155,9 @@ func ConnectionRequestParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, erro
 
 	// Create a partially initialized instance
 	_child := &ConnectionRequest{
-		HpaiDiscoveryEndpoint:        hpaiDiscoveryEndpoint,
-		HpaiDataEndpoint:             hpaiDataEndpoint,
-		ConnectionRequestInformation: connectionRequestInformation,
+		HpaiDiscoveryEndpoint:        CastHPAIDiscoveryEndpoint(hpaiDiscoveryEndpoint),
+		HpaiDataEndpoint:             CastHPAIDataEndpoint(hpaiDataEndpoint),
+		ConnectionRequestInformation: CastConnectionRequestInformation(connectionRequestInformation),
 		Parent:                       &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponse.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponse.go
index 86dc21d..d89a32d 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponse.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponse.go
@@ -147,7 +147,7 @@ func ConnectionResponseParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, err
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'hpaiDataEndpoint' field")
 		}
-		hpaiDataEndpoint = _val
+		hpaiDataEndpoint = CastHPAIDataEndpoint(_val)
 	}
 
 	// Optional Field (connectionResponseDataBlock) (Can be skipped, if a given expression evaluates to false)
@@ -157,7 +157,7 @@ func ConnectionResponseParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, err
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'connectionResponseDataBlock' field")
 		}
-		connectionResponseDataBlock = _val
+		connectionResponseDataBlock = CastConnectionResponseDataBlock(_val)
 	}
 
 	if closeErr := readBuffer.CloseContext("ConnectionResponse"); closeErr != nil {
@@ -168,8 +168,8 @@ func ConnectionResponseParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, err
 	_child := &ConnectionResponse{
 		CommunicationChannelId:      communicationChannelId,
 		Status:                      status,
-		HpaiDataEndpoint:            hpaiDataEndpoint,
-		ConnectionResponseDataBlock: connectionResponseDataBlock,
+		HpaiDataEndpoint:            CastHPAIDataEndpoint(hpaiDataEndpoint),
+		ConnectionResponseDataBlock: CastConnectionResponseDataBlock(connectionResponseDataBlock),
 		Parent:                      &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponseDataBlockTunnelConnection.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponseDataBlockTunnelConnection.go
index 4cd3994..8776c85 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponseDataBlockTunnelConnection.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponseDataBlockTunnelConnection.go
@@ -121,7 +121,7 @@ func ConnectionResponseDataBlockTunnelConnectionParse(readBuffer utils.ReadBuffe
 
 	// Create a partially initialized instance
 	_child := &ConnectionResponseDataBlockTunnelConnection{
-		KnxAddress: knxAddress,
+		KnxAddress: CastKnxAddress(knxAddress),
 		Parent:     &ConnectionResponseDataBlock{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionStateRequest.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionStateRequest.go
index 9eb2b45..bc00cd9 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionStateRequest.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionStateRequest.go
@@ -151,7 +151,7 @@ func ConnectionStateRequestParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage,
 	// Create a partially initialized instance
 	_child := &ConnectionStateRequest{
 		CommunicationChannelId: communicationChannelId,
-		HpaiControlEndpoint:    hpaiControlEndpoint,
+		HpaiControlEndpoint:    CastHPAIControlEndpoint(hpaiControlEndpoint),
 		Parent:                 &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/DescriptionRequest.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/DescriptionRequest.go
index 6a32186..4ee1788 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/DescriptionRequest.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/DescriptionRequest.go
@@ -121,7 +121,7 @@ func DescriptionRequestParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, err
 
 	// Create a partially initialized instance
 	_child := &DescriptionRequest{
-		HpaiControlEndpoint: hpaiControlEndpoint,
+		HpaiControlEndpoint: CastHPAIControlEndpoint(hpaiControlEndpoint),
 		Parent:              &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/DescriptionResponse.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/DescriptionResponse.go
index c5e3e70..94e6273 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/DescriptionResponse.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/DescriptionResponse.go
@@ -138,8 +138,8 @@ func DescriptionResponseParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, er
 
 	// Create a partially initialized instance
 	_child := &DescriptionResponse{
-		DibDeviceInfo:      dibDeviceInfo,
-		DibSuppSvcFamilies: dibSuppSvcFamilies,
+		DibDeviceInfo:      CastDIBDeviceInfo(dibDeviceInfo),
+		DibSuppSvcFamilies: CastDIBSuppSvcFamilies(dibSuppSvcFamilies),
 		Parent:             &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/DeviceConfigurationAck.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/DeviceConfigurationAck.go
index 626dfeb..d216bc3 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/DeviceConfigurationAck.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/DeviceConfigurationAck.go
@@ -121,7 +121,7 @@ func DeviceConfigurationAckParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage,
 
 	// Create a partially initialized instance
 	_child := &DeviceConfigurationAck{
-		DeviceConfigurationAckDataBlock: deviceConfigurationAckDataBlock,
+		DeviceConfigurationAckDataBlock: CastDeviceConfigurationAckDataBlock(deviceConfigurationAckDataBlock),
 		Parent:                          &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/DeviceConfigurationRequest.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/DeviceConfigurationRequest.go
index 88e25f7..9c94026 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/DeviceConfigurationRequest.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/DeviceConfigurationRequest.go
@@ -138,8 +138,8 @@ func DeviceConfigurationRequestParse(readBuffer utils.ReadBuffer, totalLength ui
 
 	// Create a partially initialized instance
 	_child := &DeviceConfigurationRequest{
-		DeviceConfigurationRequestDataBlock: deviceConfigurationRequestDataBlock,
-		Cemi:                                cemi,
+		DeviceConfigurationRequestDataBlock: CastDeviceConfigurationRequestDataBlock(deviceConfigurationRequestDataBlock),
+		Cemi:                                CastCEMI(cemi),
 		Parent:                              &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/DisconnectRequest.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/DisconnectRequest.go
index a8d3a4d..b08ec78 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/DisconnectRequest.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/DisconnectRequest.go
@@ -151,7 +151,7 @@ func DisconnectRequestParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, erro
 	// Create a partially initialized instance
 	_child := &DisconnectRequest{
 		CommunicationChannelId: communicationChannelId,
-		HpaiControlEndpoint:    hpaiControlEndpoint,
+		HpaiControlEndpoint:    CastHPAIControlEndpoint(hpaiControlEndpoint),
 		Parent:                 &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/KnxManufacturer.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/KnxManufacturer.go
index a097ec7..f0e093a 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/KnxManufacturer.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/KnxManufacturer.go
@@ -600,8 +600,9 @@ const (
 	KnxManufacturer_M_EMBEDDED_AUTOMATION_EQUIPMENT_SHANGHAI_LIMITED     KnxManufacturer = 562
 	KnxManufacturer_M_ONEWORK                                            KnxManufacturer = 563
 	KnxManufacturer_M_PL_LINK                                            KnxManufacturer = 564
-	KnxManufacturer_M_ABB___RESERVED                                     KnxManufacturer = 565
-	KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED                    KnxManufacturer = 566
+	KnxManufacturer_M_FASEL_GMBH_ELEKTRONIK                              KnxManufacturer = 565
+	KnxManufacturer_M_ABB___RESERVED                                     KnxManufacturer = 566
+	KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED                    KnxManufacturer = 567
 )
 
 var KnxManufacturerValues []KnxManufacturer
@@ -1174,6 +1175,7 @@ func init() {
 		KnxManufacturer_M_EMBEDDED_AUTOMATION_EQUIPMENT_SHANGHAI_LIMITED,
 		KnxManufacturer_M_ONEWORK,
 		KnxManufacturer_M_PL_LINK,
+		KnxManufacturer_M_FASEL_GMBH_ELEKTRONIK,
 		KnxManufacturer_M_ABB___RESERVED,
 		KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED,
 	}
@@ -3255,10 +3257,14 @@ func (e KnxManufacturer) Number() uint16 {
 		}
 	case 565:
 		{ /* '565' */
-			return 43954
+			return 622
 		}
 	case 566:
 		{ /* '566' */
+			return 43954
+		}
+	case 567:
+		{ /* '567' */
 			return 43959
 		}
 	case 57:
@@ -5541,10 +5547,14 @@ func (e KnxManufacturer) Name() string {
 		}
 	case 565:
 		{ /* '565' */
-			return "ABB - reserved"
+			return "Fasel GmbH Elektronik"
 		}
 	case 566:
 		{ /* '566' */
+			return "ABB - reserved"
+		}
+	case 567:
+		{ /* '567' */
 			return "Busch-Jaeger Elektro - reserved"
 		}
 	case 57:
@@ -6789,8 +6799,10 @@ func KnxManufacturerByValue(value uint16) KnxManufacturer {
 	case 564:
 		return KnxManufacturer_M_PL_LINK
 	case 565:
-		return KnxManufacturer_M_ABB___RESERVED
+		return KnxManufacturer_M_FASEL_GMBH_ELEKTRONIK
 	case 566:
+		return KnxManufacturer_M_ABB___RESERVED
+	case 567:
 		return KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED
 	case 57:
 		return KnxManufacturer_M_ORAS
@@ -7928,6 +7940,8 @@ func KnxManufacturerByName(value string) KnxManufacturer {
 		return KnxManufacturer_M_ONEWORK
 	case "M_PL_LINK":
 		return KnxManufacturer_M_PL_LINK
+	case "M_FASEL_GMBH_ELEKTRONIK":
+		return KnxManufacturer_M_FASEL_GMBH_ELEKTRONIK
 	case "M_ABB___RESERVED":
 		return KnxManufacturer_M_ABB___RESERVED
 	case "M_BUSCH_JAEGER_ELEKTRO___RESERVED":
@@ -9098,6 +9112,8 @@ func (e KnxManufacturer) name() string {
 		return "M_ONEWORK"
 	case KnxManufacturer_M_PL_LINK:
 		return "M_PL_LINK"
+	case KnxManufacturer_M_FASEL_GMBH_ELEKTRONIK:
+		return "M_FASEL_GMBH_ELEKTRONIK"
 	case KnxManufacturer_M_ABB___RESERVED:
 		return "M_ABB___RESERVED"
 	case KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED:
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/LBusmonInd.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/LBusmonInd.go
index 7278082..6479dea 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/LBusmonInd.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/LBusmonInd.go
@@ -179,7 +179,7 @@ func LBusmonIndParse(readBuffer utils.ReadBuffer) (*CEMI, error) {
 	_child := &LBusmonInd{
 		AdditionalInformationLength: additionalInformationLength,
 		AdditionalInformation:       additionalInformation,
-		DataFrame:                   dataFrame,
+		DataFrame:                   CastLDataFrame(dataFrame),
 		Crc:                         crc,
 		Parent:                      &CEMI{},
 	}
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataCon.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataCon.go
index 5b2136d..9323fa0 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataCon.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataCon.go
@@ -162,7 +162,7 @@ func LDataConParse(readBuffer utils.ReadBuffer) (*CEMI, error) {
 	_child := &LDataCon{
 		AdditionalInformationLength: additionalInformationLength,
 		AdditionalInformation:       additionalInformation,
-		DataFrame:                   dataFrame,
+		DataFrame:                   CastLDataFrame(dataFrame),
 		Parent:                      &CEMI{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataExtended.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataExtended.go
index c79a884..cbb5123 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataExtended.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataExtended.go
@@ -217,9 +217,9 @@ func LDataExtendedParse(readBuffer utils.ReadBuffer) (*LDataFrame, error) {
 		GroupAddress:        groupAddress,
 		HopCount:            hopCount,
 		ExtendedFrameFormat: extendedFrameFormat,
-		SourceAddress:       sourceAddress,
+		SourceAddress:       CastKnxAddress(sourceAddress),
 		DestinationAddress:  destinationAddress,
-		Apdu:                apdu,
+		Apdu:                CastApdu(apdu),
 		Parent:              &LDataFrame{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataInd.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataInd.go
index b3361ca..f85b6f1 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataInd.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataInd.go
@@ -162,7 +162,7 @@ func LDataIndParse(readBuffer utils.ReadBuffer) (*CEMI, error) {
 	_child := &LDataInd{
 		AdditionalInformationLength: additionalInformationLength,
 		AdditionalInformation:       additionalInformation,
-		DataFrame:                   dataFrame,
+		DataFrame:                   CastLDataFrame(dataFrame),
 		Parent:                      &CEMI{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataReq.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataReq.go
index 056e2d8..91b5dae 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataReq.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/LDataReq.go
@@ -162,7 +162,7 @@ func LDataReqParse(readBuffer utils.ReadBuffer) (*CEMI, error) {
 	_child := &LDataReq{
 		AdditionalInformationLength: additionalInformationLength,
 		AdditionalInformation:       additionalInformation,
-		DataFrame:                   dataFrame,
+		DataFrame:                   CastLDataFrame(dataFrame),
 		Parent:                      &CEMI{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/LPollData.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/LPollData.go
index a32f71b..8f144f6 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/LPollData.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/LPollData.go
@@ -183,7 +183,7 @@ func LPollDataParse(readBuffer utils.ReadBuffer) (*LDataFrame, error) {
 
 	// Create a partially initialized instance
 	_child := &LPollData{
-		SourceAddress:          sourceAddress,
+		SourceAddress:          CastKnxAddress(sourceAddress),
 		TargetAddress:          targetAddress,
 		NumberExpectedPollData: numberExpectedPollData,
 		Parent:                 &LDataFrame{},
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/SearchRequest.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/SearchRequest.go
index 15699aa..99a16cf 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/SearchRequest.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/SearchRequest.go
@@ -121,7 +121,7 @@ func SearchRequestParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, error) {
 
 	// Create a partially initialized instance
 	_child := &SearchRequest{
-		HpaiIDiscoveryEndpoint: hpaiIDiscoveryEndpoint,
+		HpaiIDiscoveryEndpoint: CastHPAIDiscoveryEndpoint(hpaiIDiscoveryEndpoint),
 		Parent:                 &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/SearchResponse.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/SearchResponse.go
index b666529..4234ccf 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/SearchResponse.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/SearchResponse.go
@@ -155,9 +155,9 @@ func SearchResponseParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, error)
 
 	// Create a partially initialized instance
 	_child := &SearchResponse{
-		HpaiControlEndpoint: hpaiControlEndpoint,
-		DibDeviceInfo:       dibDeviceInfo,
-		DibSuppSvcFamilies:  dibSuppSvcFamilies,
+		HpaiControlEndpoint: CastHPAIControlEndpoint(hpaiControlEndpoint),
+		DibDeviceInfo:       CastDIBDeviceInfo(dibDeviceInfo),
+		DibSuppSvcFamilies:  CastDIBSuppSvcFamilies(dibSuppSvcFamilies),
 		Parent:              &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/TunnelingRequest.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/TunnelingRequest.go
index f027b80..a5efcff 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/TunnelingRequest.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/TunnelingRequest.go
@@ -138,8 +138,8 @@ func TunnelingRequestParse(readBuffer utils.ReadBuffer, totalLength uint16) (*Kn
 
 	// Create a partially initialized instance
 	_child := &TunnelingRequest{
-		TunnelingRequestDataBlock: tunnelingRequestDataBlock,
-		Cemi:                      cemi,
+		TunnelingRequestDataBlock: CastTunnelingRequestDataBlock(tunnelingRequestDataBlock),
+		Cemi:                      CastCEMI(cemi),
 		Parent:                    &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/TunnelingResponse.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/TunnelingResponse.go
index 701adce..841ea35 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/TunnelingResponse.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/TunnelingResponse.go
@@ -121,7 +121,7 @@ func TunnelingResponseParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, erro
 
 	// Create a partially initialized instance
 	_child := &TunnelingResponse{
-		TunnelingResponseDataBlock: tunnelingResponseDataBlock,
+		TunnelingResponseDataBlock: CastTunnelingResponseDataBlock(tunnelingResponseDataBlock),
 		Parent:                     &KnxNetIpMessage{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go b/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
index 7776c6c..d713024 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
@@ -182,7 +182,7 @@ func COTPPacketParse(readBuffer utils.ReadBuffer, cotpLen uint16) (*COTPPacket,
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'payload' field")
 		}
-		payload = _val
+		payload = CastS7Message(_val)
 	}
 
 	if closeErr := readBuffer.CloseContext("COTPPacket"); closeErr != nil {
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go b/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
index 0512549..2c6d24d 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
@@ -206,7 +206,7 @@ func S7MessageParse(readBuffer utils.ReadBuffer) (*S7Message, error) {
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'parameter' field")
 		}
-		parameter = _val
+		parameter = CastS7Parameter(_val)
 	}
 
 	// Optional Field (payload) (Can be skipped, if a given expression evaluates to false)
@@ -216,7 +216,7 @@ func S7MessageParse(readBuffer utils.ReadBuffer) (*S7Message, error) {
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'payload' field")
 		}
-		payload = _val
+		payload = CastS7Payload(_val)
 	}
 
 	if closeErr := readBuffer.CloseContext("S7Message"); closeErr != nil {
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarm8.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarm8.go
index 6d34a1c..8410e36 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarm8.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarm8.go
@@ -131,7 +131,7 @@ func S7PayloadAlarm8Parse(readBuffer utils.ReadBuffer) (*S7PayloadUserDataItem,
 
 	// Create a partially initialized instance
 	_child := &S7PayloadAlarm8{
-		AlarmMessage: alarmMessage,
+		AlarmMessage: CastAlarmMessagePushType(alarmMessage),
 		Parent:       &S7PayloadUserDataItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmAckInd.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmAckInd.go
index 6ee89a7..6eb4e93 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmAckInd.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmAckInd.go
@@ -131,7 +131,7 @@ func S7PayloadAlarmAckIndParse(readBuffer utils.ReadBuffer) (*S7PayloadUserDataI
 
 	// Create a partially initialized instance
 	_child := &S7PayloadAlarmAckInd{
-		AlarmMessage: alarmMessage,
+		AlarmMessage: CastAlarmMessageAckPushType(alarmMessage),
 		Parent:       &S7PayloadUserDataItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmS.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmS.go
index b6d4717..3b9f0e9 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmS.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmS.go
@@ -131,7 +131,7 @@ func S7PayloadAlarmSParse(readBuffer utils.ReadBuffer) (*S7PayloadUserDataItem,
 
 	// Create a partially initialized instance
 	_child := &S7PayloadAlarmS{
-		AlarmMessage: alarmMessage,
+		AlarmMessage: CastAlarmMessagePushType(alarmMessage),
 		Parent:       &S7PayloadUserDataItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmSC.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmSC.go
index 1bf1caf..81b9889 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmSC.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmSC.go
@@ -131,7 +131,7 @@ func S7PayloadAlarmSCParse(readBuffer utils.ReadBuffer) (*S7PayloadUserDataItem,
 
 	// Create a partially initialized instance
 	_child := &S7PayloadAlarmSC{
-		AlarmMessage: alarmMessage,
+		AlarmMessage: CastAlarmMessagePushType(alarmMessage),
 		Parent:       &S7PayloadUserDataItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmSQ.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmSQ.go
index 80c1962..dfd8cbd 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmSQ.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadAlarmSQ.go
@@ -131,7 +131,7 @@ func S7PayloadAlarmSQParse(readBuffer utils.ReadBuffer) (*S7PayloadUserDataItem,
 
 	// Create a partially initialized instance
 	_child := &S7PayloadAlarmSQ{
-		AlarmMessage: alarmMessage,
+		AlarmMessage: CastAlarmMessagePushType(alarmMessage),
 		Parent:       &S7PayloadUserDataItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadDiagnosticMessage.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadDiagnosticMessage.go
index f55868a..500978b 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadDiagnosticMessage.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadDiagnosticMessage.go
@@ -203,7 +203,7 @@ func S7PayloadDiagnosticMessageParse(readBuffer utils.ReadBuffer) (*S7PayloadUse
 		DatId:         DatId,
 		Info1:         Info1,
 		Info2:         Info2,
-		TimeStamp:     TimeStamp,
+		TimeStamp:     CastDateAndTime(TimeStamp),
 		Parent:        &S7PayloadUserDataItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadNotify.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadNotify.go
index 86b9e88..f015874 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadNotify.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadNotify.go
@@ -131,7 +131,7 @@ func S7PayloadNotifyParse(readBuffer utils.ReadBuffer) (*S7PayloadUserDataItem,
 
 	// Create a partially initialized instance
 	_child := &S7PayloadNotify{
-		AlarmMessage: alarmMessage,
+		AlarmMessage: CastAlarmMessagePushType(alarmMessage),
 		Parent:       &S7PayloadUserDataItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadNotify8.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadNotify8.go
index e264c33..48078c9 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadNotify8.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadNotify8.go
@@ -131,7 +131,7 @@ func S7PayloadNotify8Parse(readBuffer utils.ReadBuffer) (*S7PayloadUserDataItem,
 
 	// Create a partially initialized instance
 	_child := &S7PayloadNotify8{
-		AlarmMessage: alarmMessage,
+		AlarmMessage: CastAlarmMessagePushType(alarmMessage),
 		Parent:       &S7PayloadUserDataItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadUserDataItemCpuFunctionReadSzlRequest.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadUserDataItemCpuFunctionReadSzlRequest.go
index 92ee763..846465f 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadUserDataItemCpuFunctionReadSzlRequest.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadUserDataItemCpuFunctionReadSzlRequest.go
@@ -142,7 +142,7 @@ func S7PayloadUserDataItemCpuFunctionReadSzlRequestParse(readBuffer utils.ReadBu
 
 	// Create a partially initialized instance
 	_child := &S7PayloadUserDataItemCpuFunctionReadSzlRequest{
-		SzlId:    szlId,
+		SzlId:    CastSzlId(szlId),
 		SzlIndex: szlIndex,
 		Parent:   &S7PayloadUserDataItem{},
 	}
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadUserDataItemCpuFunctionReadSzlResponse.go b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadUserDataItemCpuFunctionReadSzlResponse.go
index de40f91..de047a0 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadUserDataItemCpuFunctionReadSzlResponse.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7PayloadUserDataItemCpuFunctionReadSzlResponse.go
@@ -195,7 +195,7 @@ func S7PayloadUserDataItemCpuFunctionReadSzlResponseParse(readBuffer utils.ReadB
 
 	// Create a partially initialized instance
 	_child := &S7PayloadUserDataItemCpuFunctionReadSzlResponse{
-		SzlId:    szlId,
+		SzlId:    CastSzlId(szlId),
 		SzlIndex: szlIndex,
 		Items:    items,
 		Parent:   &S7PayloadUserDataItem{},
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7VarRequestParameterItemAddress.go b/plc4go/internal/plc4go/s7/readwrite/model/S7VarRequestParameterItemAddress.go
index 5ecb822..c7da581 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7VarRequestParameterItemAddress.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7VarRequestParameterItemAddress.go
@@ -131,7 +131,7 @@ func S7VarRequestParameterItemAddressParse(readBuffer utils.ReadBuffer) (*S7VarR
 
 	// Create a partially initialized instance
 	_child := &S7VarRequestParameterItemAddress{
-		Address: address,
+		Address: CastS7Address(address),
 		Parent:  &S7VarRequestParameterItem{},
 	}
 	_child.Parent.Child = _child
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ParseAssertException.java
similarity index 66%
copy from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
copy to plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ParseAssertException.java
index 9a047c2..6b5227b 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ParseAssertException.java
@@ -16,22 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.spi.generation.io;
 
-import com.github.jinahya.bit.io.ArrayByteInput;
-import com.github.jinahya.bit.io.DefaultBitInput;
+package org.apache.plc4x.java.spi.generation;
 
 /**
- * Modified version that exposes the position.
+ * Is thrown when an assert field in mspec says no.
  */
-public class MyDefaultBitInput extends DefaultBitInput<ArrayByteInput> {
-
-    public MyDefaultBitInput(ArrayByteInput delegate) {
-        super(delegate);
+public class ParseAssertException extends ParseException {
+    public ParseAssertException(String message) {
+        super(message);
     }
 
-    public long getPos() {
-        return delegate.getIndex();
+    public ParseAssertException(String message, Throwable cause) {
+        super(message, cause);
     }
-
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
index fcadb25..d5a3baa 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
@@ -24,6 +24,8 @@ import java.math.BigInteger;
 public interface ReadBuffer {
     int getPos();
 
+    void reset(int pos);
+
     boolean hasMore(int numBits);
 
     void pullContext(String logicalName, WithReaderArgs... readerArgs);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
index bb19b7c..83a8657 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
@@ -49,6 +49,11 @@ public class ReadBufferByteBased implements ReadBuffer {
         return (int) bi.getPos();
     }
 
+    @Override
+    public void reset(int pos) {
+        bi.reset(pos);
+    }
+
     public byte[] getBytes(int startPos, int endPos) {
         int numBytes = endPos - startPos;
         byte[] data = new byte[numBytes];
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferJsonBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferJsonBased.java
index cbe1e4a..1c8328c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferJsonBased.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferJsonBased.java
@@ -19,6 +19,7 @@
 package org.apache.plc4x.java.spi.generation;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang3.NotImplementedException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 
 import java.io.IOException;
@@ -62,6 +63,11 @@ public class ReadBufferJsonBased implements ReadBuffer, BufferCommons {
     }
 
     @Override
+    public void reset(int pos) {
+        throw new NotImplementedException();
+    }
+
+    @Override
     public boolean hasMore(int numBits) {
         return false;
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferXmlBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferXmlBased.java
index 4237934..5acbe7c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferXmlBased.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferXmlBased.java
@@ -18,6 +18,7 @@
  */
 package org.apache.plc4x.java.spi.generation;
 
+import org.apache.commons.lang3.NotImplementedException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 
 import javax.xml.XMLConstants;
@@ -53,6 +54,11 @@ public class ReadBufferXmlBased implements ReadBuffer, BufferCommons {
     }
 
     @Override
+    public void reset(int pos) {
+        throw new NotImplementedException();
+    }
+
+    @Override
     public boolean hasMore(int numBits) {
         return true;
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
index 9a047c2..352418c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/io/MyDefaultBitInput.java
@@ -21,6 +21,8 @@ package org.apache.plc4x.java.spi.generation.io;
 import com.github.jinahya.bit.io.ArrayByteInput;
 import com.github.jinahya.bit.io.DefaultBitInput;
 
+import java.io.IOException;
+
 /**
  * Modified version that exposes the position.
  */
@@ -31,7 +33,16 @@ public class MyDefaultBitInput extends DefaultBitInput<ArrayByteInput> {
     }
 
     public long getPos() {
+        // TODO: we should report bits as we would loose this information on a reset
         return delegate.getIndex();
     }
 
+    public void reset(int pos) {
+        try {
+            align(1);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        delegate.setIndex(pos);
+    }
 }
diff --git a/pom.xml b/pom.xml
index 367eb40..ae153ab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -104,7 +104,7 @@
     <sonar.cfamily.threads>1</sonar.cfamily.threads>
     <sonar.cfamily.cache.enabled>false</sonar.cfamily.cache.enabled>
 
-    <plc4x-code-generation.version>1.5.0</plc4x-code-generation.version>
+    <plc4x-code-generation.version>1.6.0-SNAPSHOT</plc4x-code-generation.version>
 
     <antlr.version>4.9.2</antlr.version>
     <apiguardian.version>1.1.1</apiguardian.version>
@@ -145,8 +145,7 @@
     <jackson.version>2.12.5</jackson.version>
     <!-- When updating this to the latest version, we're getting errors in the opcua server tests -->
     <jaxb.version>2.3.3</jaxb.version>
-    <!-- Newer versions are only compatible with Java 11. It's currently only used for obfuscating a password in the OPC-UA Server anyway -->
-    <jetty-util.version>9.4.43.v20210629</jetty-util.version>
+    <jetty-util.version>11.0.6</jetty-util.version>
     <jna.version>5.8.0</jna.version>
     <joda-time.version>2.10.10</joda-time.version>
     <jserialcom.version>2.7.0</jserialcom.version>
@@ -794,7 +793,6 @@
             <exclude>**/go.sum</exclude>
 
             <!--exclude>plc4go/**</exclude-->
-            <exclude>content/**</exclude>
           </excludes>
         </configuration>
       </plugin>
diff --git a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
index 52b6747..ddb74f5 100644
--- a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
+++ b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
@@ -302,14 +302,10 @@
         ['0x06' BACnetUnconfirmedServiceRequestTimeSynchronization
         ]
         ['0x07' BACnetUnconfirmedServiceRequestWhoHas
-            [const uint 8 'deviceInstanceLowLimitHeader' '0x0B'         ]
-            [simple uint 24 'deviceInstanceLowLimit'                    ]
-            [const uint 8 'deviceInstanceHighLimitHeader' '0x1B'        ]
-            [simple uint 24 'deviceInstanceHighLimit'                   ]
-            [const uint 8 'objectNameHeader' '0x3D'                     ]
-            [implicit uint 8 'objectNameLength' 'COUNT(objectName) + 1' ]
-            [simple uint 8 'objectNameCharacterSet'                     ]
-            [array int 8 'objectName' length 'objectNameLength - 1'     ]
+            [try simple     BACnetComplexTagUnsignedInteger ['0', 'BACnetDataType.UNSIGNED_INTEGER' ] 'deviceInstanceRangeLowLimit'  ]
+            [optional       BACnetComplexTagUnsignedInteger ['1', 'BACnetDataType.UNSIGNED_INTEGER' ] 'deviceInstanceRangeHighLimit' 'deviceInstanceRangeLowLimit != null']
+            [try simple     BACnetComplexTagOctetString     ['2', 'BACnetDataType.OCTET_STRING'     ] 'objectIdentifier' ]
+            [optional       BACnetComplexTagOctetString     ['3', 'BACnetDataType.OCTET_STRING'     ] 'objectName' 'objectIdentifier == null' ]
         ]
         ['0x08' BACnetUnconfirmedServiceRequestWhoIs
             // TODO: here we need proper bacnet tags (like a dicriminator etc... see line 494 BACnetTag)
@@ -329,6 +325,57 @@
     ]
 ]
 
+[discriminatedType 'BACnetComplexTag' [uint 4 'tagNumberArgument', BACnetDataType 'dataType']
+    [assert        uint 4           'tagNumber'                 'tagNumberArgument'                                           ]
+    [const         TagClass         'tagClass'                  'TagClass.CONTEXT_SPECIFIC_TAGS'                              ]
+    [simple        uint 3           'lengthValueType'                                                                         ]
+    [optional      uint 8           'extTagNumber'              'tagNumber == 15'                                             ]
+    [virtual       uint 8           'actualTagNumber'           'tagNumber < 15 ? tagNumber : extTagNumber'                   ]
+    [virtual       bit              'isPrimitiveAndNotBoolean'  '!(lengthValueType == 6) && tagNumber != 1'                   ]
+    [optional      uint 8           'extLength'        'isPrimitiveAndNotBoolean && lengthValueType == 5'                     ]
+    [optional      uint 16          'extExtLength'     'isPrimitiveAndNotBoolean && lengthValueType == 5 && extLength == 254' ]
+    [optional      uint 32          'extExtExtLength'  'isPrimitiveAndNotBoolean && lengthValueType == 5 && extLength == 255' ]
+    [virtual       uint 32          'actualLength'     'lengthValueType == 5 && extLength == 255 ? extExtExtLength : (lengthValueType == 5 && extLength == 254 ? extExtLength : (lengthValueType == 5 ? extLength : (isPrimitiveAndNotBoolean ? lengthValueType : 0)))']
+    [typeSwitch 'dataType'
+        ['NULL' BACnetComplexTagNull
+        ]
+        ['BOOLEAN' BACnetComplexTagBoolean
+        ]
+        ['UNSIGNED_INTEGER' BACnetComplexTagUnsignedInteger [uint 3 'lengthValueType', uint 8 'extLength']
+            [array int 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType']
+        ]
+        ['SIGNED_INTEGER' BACnetComplexTagSignedInteger [uint 3 'lengthValueType', uint 8 'extLength']
+            [array int 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType']
+        ]
+        ['REAL' BACnetComplexTagReal [uint 3 'lengthValueType', uint 8 'extLength']
+            [simple float 8.23 'value']
+        ]
+        ['DOUBLE' BACnetComplexTagDouble [uint 3 'lengthValueType', uint 8 'extLength']
+            [simple float 11.52 'value']
+        ]
+        ['OCTET_STRING' BACnetComplexTagOctetString [uint 32 'actualLength']
+            // TODO: The reader expects int but uint32 get's mapped to long so even uint32 would easily overflow...
+            [virtual    uint    16                           'actualLengthInBit' 'actualLength * 8']
+            [simple     string 'actualLengthInBit' 'ASCII'   'theString']
+        ]
+        ['CHARACTER_STRING' BACnetComplexTagCharacterString
+        ]
+        ['BIT_STRING' BACnetComplexTagBitString [uint 3 'lengthValueType', uint 8 'extLength']
+            [simple uint 8 'unusedBits']
+            [array int 8 'data' length '(lengthValueType == 5) ? (extLength - 1) : (lengthValueType - 1)']
+        ]
+        ['ENUMERATED' BACnetComplexTagEnumerated [uint 3 'lengthValueType', uint 8 'extLength']
+            [array int 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType']
+        ]
+        ['DATE' BACnetComplexTagDate
+        ]
+        ['TIME' BACnetComplexTagTime
+        ]
+        ['BACNET_OBJECT_IDENTIFIER' BACnetComplexTagObjectIdentifier
+        ]
+    ]
+]
+
 [discriminatedType 'BACnetServiceAck'
     [discriminator   uint 8 'serviceChoice']
     [typeSwitch 'serviceChoice'
@@ -547,7 +594,7 @@
     ['0x1' CONTEXT_SPECIFIC_TAGS]
 ]
 
-[enum int 4 'ApplicationTag'
+[enum int 4 'BACnetDataType'
     ['0x0' NULL]
     ['0x1' BOOLEAN]
     ['0x2' UNSIGNED_INTEGER]
diff --git a/sandbox/test-java-bacnetip-driver/pom.xml b/sandbox/test-java-bacnetip-driver/pom.xml
index c600b5b..b2e92a6 100644
--- a/sandbox/test-java-bacnetip-driver/pom.xml
+++ b/sandbox/test-java-bacnetip-driver/pom.xml
@@ -50,14 +50,6 @@
           </execution>
         </executions>
       </plugin>
-        <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-compiler-plugin</artifactId>
-            <configuration>
-                <source>11</source>
-                <target>11</target>
-            </configuration>
-        </plugin>
     </plugins>
   </build>
 
diff --git a/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriver2Manual.java b/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriver2Manual.java
index a4cbae4..f64f04b 100644
--- a/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriver2Manual.java
+++ b/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriver2Manual.java
@@ -26,13 +26,13 @@ import org.apache.plc4x.java.spi.values.PlcStruct;
 
 import java.io.File;
 import java.net.URL;
-import java.nio.file.Path;
+import java.nio.file.FileSystems;
 
 public class PassiveBacNetIpDriver2Manual {
 
     public static void main(String[] args) throws Exception {
         String tempDirectory = FileUtils.getTempDirectoryPath();
-        File pcapFile = Path.of(tempDirectory, "bacnet-stack-services.cap").toFile();
+        File pcapFile = FileSystems.getDefault().getPath(tempDirectory, "bacnet-stack-services.cap").toFile();
         if (!pcapFile.exists())
             FileUtils.copyURLToFile(new URL("https://wiki.wireshark.org/Protocols/bacnet?action=AttachFile&do=get&target=bacnet-stack-services.cap"), pcapFile);