You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by hu...@apache.org on 2022/11/15 00:05:24 UTC

[plc4x] branch plc4py-codegen updated: feat(plc4py/codegen): more updates - included generated in source files

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

hutcheb pushed a commit to branch plc4py-codegen
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/plc4py-codegen by this push:
     new f3233d938a feat(plc4py/codegen): more updates - included generated in source files
f3233d938a is described below

commit f3233d938a52da9e248e65df92bd1a4d03f6f30b
Author: Ben Hutcheson <be...@gmail.com>
AuthorDate: Mon Nov 14 18:04:32 2022 -0600

    feat(plc4py/codegen): more updates - included generated in source files
---
 .../python/complex-type-template.python.ftlh       | 128 +++++-----
 .../plc4py/protocols/modbus/readwrite/ModbusADU.py | 146 ++++++++++++
 .../protocols/modbus/readwrite/ModbusAsciiADU.py   | 168 +++++++++++++
 .../protocols/modbus/readwrite/ModbusConstants.py  | 108 +++++++++
 .../protocols/modbus/readwrite/ModbusDataType.py   |  84 +++++++
 .../ModbusDeviceInformationConformityLevel.py      |  59 +++++
 .../readwrite/ModbusDeviceInformationLevel.py      |  59 +++++
 .../ModbusDeviceInformationMoreFollows.py          |  59 +++++
 .../readwrite/ModbusDeviceInformationObject.py     | 137 +++++++++++
 .../protocols/modbus/readwrite/ModbusErrorCode.py  |  59 +++++
 .../plc4py/protocols/modbus/readwrite/ModbusPDU.py | 188 +++++++++++++++
 .../modbus/readwrite/ModbusPDUDiagnosticRequest.py | 154 ++++++++++++
 .../readwrite/ModbusPDUDiagnosticResponse.py       | 154 ++++++++++++
 .../protocols/modbus/readwrite/ModbusPDUError.py   | 136 +++++++++++
 .../ModbusPDUGetComEventCounterRequest.py          | 116 +++++++++
 .../ModbusPDUGetComEventCounterResponse.py         | 154 ++++++++++++
 .../readwrite/ModbusPDUGetComEventLogRequest.py    | 116 +++++++++
 .../readwrite/ModbusPDUGetComEventLogResponse.py   | 203 ++++++++++++++++
 .../ModbusPDUMaskWriteHoldingRegisterRequest.py    | 173 ++++++++++++++
 .../ModbusPDUMaskWriteHoldingRegisterResponse.py   | 173 ++++++++++++++
 .../modbus/readwrite/ModbusPDUReadCoilsRequest.py  | 154 ++++++++++++
 .../modbus/readwrite/ModbusPDUReadCoilsResponse.py | 146 ++++++++++++
 .../ModbusPDUReadDeviceIdentificationRequest.py    | 167 +++++++++++++
 .../ModbusPDUReadDeviceIdentificationResponse.py   | 260 +++++++++++++++++++++
 .../ModbusPDUReadDiscreteInputsRequest.py          | 154 ++++++++++++
 .../ModbusPDUReadDiscreteInputsResponse.py         | 146 ++++++++++++
 .../ModbusPDUReadExceptionStatusRequest.py         | 116 +++++++++
 .../ModbusPDUReadExceptionStatusResponse.py        | 135 +++++++++++
 .../readwrite/ModbusPDUReadFifoQueueRequest.py     | 135 +++++++++++
 .../readwrite/ModbusPDUReadFifoQueueResponse.py    | 155 ++++++++++++
 .../readwrite/ModbusPDUReadFileRecordRequest.py    | 148 ++++++++++++
 .../ModbusPDUReadFileRecordRequestItem.py          | 156 +++++++++++++
 .../readwrite/ModbusPDUReadFileRecordResponse.py   | 148 ++++++++++++
 .../ModbusPDUReadFileRecordResponseItem.py         | 137 +++++++++++
 .../ModbusPDUReadHoldingRegistersRequest.py        | 154 ++++++++++++
 .../ModbusPDUReadHoldingRegistersResponse.py       | 146 ++++++++++++
 .../ModbusPDUReadInputRegistersRequest.py          | 154 ++++++++++++
 .../ModbusPDUReadInputRegistersResponse.py         | 146 ++++++++++++
 ...sPDUReadWriteMultipleHoldingRegistersRequest.py | 222 ++++++++++++++++++
 ...PDUReadWriteMultipleHoldingRegistersResponse.py | 146 ++++++++++++
 .../readwrite/ModbusPDUReportServerIdRequest.py    | 116 +++++++++
 .../readwrite/ModbusPDUReportServerIdResponse.py   | 146 ++++++++++++
 .../readwrite/ModbusPDUWriteFileRecordRequest.py   | 148 ++++++++++++
 .../ModbusPDUWriteFileRecordRequestItem.py         | 167 +++++++++++++
 .../readwrite/ModbusPDUWriteFileRecordResponse.py  | 148 ++++++++++++
 .../ModbusPDUWriteFileRecordResponseItem.py        | 167 +++++++++++++
 .../ModbusPDUWriteMultipleCoilsRequest.py          | 184 +++++++++++++++
 .../ModbusPDUWriteMultipleCoilsResponse.py         | 154 ++++++++++++
 ...odbusPDUWriteMultipleHoldingRegistersRequest.py | 184 +++++++++++++++
 ...dbusPDUWriteMultipleHoldingRegistersResponse.py | 154 ++++++++++++
 .../readwrite/ModbusPDUWriteSingleCoilRequest.py   | 154 ++++++++++++
 .../readwrite/ModbusPDUWriteSingleCoilResponse.py  | 154 ++++++++++++
 .../ModbusPDUWriteSingleRegisterRequest.py         | 154 ++++++++++++
 .../ModbusPDUWriteSingleRegisterResponse.py        | 154 ++++++++++++
 .../protocols/modbus/readwrite/ModbusRtuADU.py     | 168 +++++++++++++
 .../protocols/modbus/readwrite/ModbusTcpADU.py     | 200 ++++++++++++++++
 56 files changed, 8183 insertions(+), 68 deletions(-)

diff --git a/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh b/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
index d56a8d5ed3..b068480b34 100644
--- a/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
+++ b/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
@@ -47,14 +47,15 @@ ${helper.packageName(protocolName, languageName, outputFlavor)?replace(".", "/")
 #
 
 # Code generated by code-generation. DO NOT EDIT.
-
+from abc import ABC, abstractmethod
 from dataclasses import dataclass
 
+
 <#-- TODO: the code below implies that parserArguments will be null if not present... not pretty  -->
 <#if type.parserArguments.isPresent()><#assign parserArguments=type.allParserArguments.orElseThrow()></#if>
-<#if type.isDiscriminatedParentTypeDefinition()>@abc.abstractmethod</#if>
+
 @dataclass
-class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMessage<#if type.parentType.isPresent()>,${type.parentType.orElseThrow().name}</#if>):
+class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if type.isDiscriminatedParentTypeDefinition()>ABC, </#if>PlcMessage<#if type.parentType.isPresent()>,${type.parentType.orElseThrow().name}</#if>):
     <#if parserArguments?has_content>
         <#assign filteredParserArguments=parserArguments?filter(arg -> !type.isDiscriminatorField(arg.name) && !type.getPropertyFieldFromThisOrParentByName(arg.name).isPresent())>
     </#if>
@@ -112,9 +113,9 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
 
 
     <#-- getAllPropertyFields() returns not only the property fields of this type but also of it's parents -->
-    def __post_init__():
+    def __post_init__(self):
         <@compress single_line=true>
-            super.__init__(
+            super().__init__(
             <#if type.parentPropertyFields?has_content>
                 <#list type.parentPropertyFields as field>
                     self.${field.name}
@@ -147,7 +148,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
         <#-- If the discriminator name matches that of another field, suppress the methods generation -->
             <#if !type.isNonDiscriminatorField(discriminatorName)><#-- && !type.isParserArgument(discriminatorName)-->
     @abstractmethod
-    def get${discriminatorName?cap_first}() -> ${helper.getLanguageTypeNameForTypeReference(discriminatorType)}:
+    def get${discriminatorName?cap_first}(self) -> ${helper.getLanguageTypeNameForTypeReference(discriminatorType)}:
             </#if>
         </#list>
     </#if>
@@ -155,16 +156,16 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
 
 <#list type.abstractFields as field>
     @abstractmethod
-    def get${field.asNamedField().orElseThrow().name?cap_first}() -> ${helper.getLanguageTypeNameForField(field)}:
+    def get${field.asNamedField().orElseThrow().name?cap_first}(self) -> ${helper.getLanguageTypeNameForField(field)}:
 
 </#list>
 <#list type.propertyFields as field>
-    def get${field.name?cap_first}() -> ${helper.getLanguageTypeNameForField(field)}:
+    def get${field.name?cap_first}(self) -> ${helper.getLanguageTypeNameForField(field)}:
         return ${field.name}
 
 </#list>
 <#list type.virtualFields as field>
-    def get${field.name?cap_first}() -> ${helper.getLanguageTypeNameForField(field)}:
+    def get${field.name?cap_first}(self) -> ${helper.getLanguageTypeNameForField(field)}:
         <#if helper.getLanguageTypeNameForField(field) = 'String'>
         return ${helper.getLanguageTypeNameForField(field)}.valueOf(${helper.toSerializationExpression(field, field.type, field.valueExpression, parserArguments)})
         <#--elseif helper.getLanguageTypeNameForField(field) = 'BigInteger' && !helper.isBigIntegerSource(field.valueExpression)-->
@@ -180,22 +181,22 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
 
 </#list>
 <#list type.constFields as field>
-    def get${field.name?cap_first}() -> ${helper.getLanguageTypeNameForField(field)}:
+    def get${field.name?cap_first}(self) -> ${helper.getLanguageTypeNameForField(field)}:
         return ${field.name?upper_case}
 
 </#list>
 
     <#if outputFlavor != "passive">
 <#if type.isDiscriminatedChildTypeDefinition()>
-    def serialize${type.parentType.orElseThrow().name}Child(writeBuffer: WriteBuffer):
+    def serialize${type.parentType.orElseThrow().name}Child(self, writeBuffer: WriteBuffer):
 <#else>
     <#if type.isDiscriminatedParentTypeDefinition()>
     @abstractmethod
-    abstract protected void serialize${type.name?cap_first}Child(writeBuffer: WriteBuffer):
+    def serialize${type.name?cap_first}Child(writeBuffer: WriteBuffer) -> None:
         pass
 
     </#if>
-    def serialize(writeBuffer: WriteBuffer):
+    def serialize(self, writeBuffer: WriteBuffer):
 </#if>
         positionAware: PositionAware = writeBuffer
         <#if helper.hasFieldOfType("unknown")>
@@ -342,12 +343,12 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
 
     </#if>
 
-    def getLengthInBytes() -> int:
-        return (int) Math.ceil((float) getLengthInBits() / 8.0)
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
 
-    def getLengthInBits() -> int:
-        lengthInBits: int = <#if type.parentType.isPresent()>super.getLengthInBits()<#else>0</#if>
-        _value: ${type.name}  = this
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = <#if type.parentType.isPresent()>super().getLengthInBits()<#else>0</#if>
+        _value: ${type.name} = self
 <#list type.fields as field>
 <#switch field.typeName>
     <#case "array">
@@ -355,7 +356,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
         <#assign arrayElementTypeReference = arrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>
 
         # Array field
-        if(${arrayField.name} != null) {
+        if ${arrayField.name} is not None):
         <#if arrayElementTypeReference.isSimpleTypeReference()>
             <#assign simpleTypeReference = arrayElementTypeReference.asSimpleTypeReference().orElseThrow()>
             lengthInBits += ${simpleTypeReference.sizeInBits} * ${arrayField.name}.<#if arrayElementTypeReference.isByteBased()>length<#else>size()</#if>
@@ -525,17 +526,17 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
     def staticParse(readBuffer: ReadBuffer , args) -> ${type.name}:
         positionAware: PositionAware = readBuffer
         <#if parserArguments?has_content>
-        if (args == null) or (args.length != ${parserArguments?size}):
+        if (args is None) or (args.length is not ${parserArguments?size}):
             raise PlcRuntimeException("Wrong number of arguments, expected ${parserArguments?size}, but got " + args.length)
 
             <#list parserArguments as parserArgument>
                 <#assign languageName=helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)>
-        ${languageName} ${parserArgument.name}
+        ${parserArgument.name}: ${languageName} = None
         if isinstance(args[${parserArgument?index}], ${languageName}):
-            ${parserArgument.name} = (${languageName}) args[${parserArgument?index}]
+            ${parserArgument.name} = ${languageName}(args[${parserArgument?index}])
                 <#if parserArgument.type.isSimpleTypeReference() || parserArgument.type.isEnumTypeReference()>
         elif isinstance(args[${parserArgument?index}], String):
-            ${parserArgument.name} = ${languageName}.valueOf((String) args[${parserArgument?index}])
+            ${parserArgument.name} = ${languageName}.valueOf(str(args[${parserArgument?index}]))
                 </#if>
         else:
             raise PlcRuntimeException("Argument ${parserArgument?index} expected to be of type ${languageName} or a string which is parseable but was " + args[${parserArgument?index}].getClass().getName())
@@ -549,7 +550,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
 <#-- Here come the actual parse and serialize methods that actually do the parsing and serlaizing -->
     <#assign hasParserArguments=parserArguments?has_content/>
     <#assign parserArgumentList><#if hasParserArguments><#list parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
-    def <#if type.isDiscriminatedChildTypeDefinition()>Builder staticParseBuilder<#else> staticParse</#if>(readBuffer: ReadBuffer<#if hasParserArguments>, ${parserArgumentList}</#if>) -> ${type.name}:
+    def <#if type.isDiscriminatedChildTypeDefinition()> staticParseBuilder<#else> staticParse</#if>(readBuffer: ReadBuffer<#if hasParserArguments>, ${parserArgumentList}</#if>) -> ${type.name}<#if type.isDiscriminatedChildTypeDefinition()>Builder</#if>:
         readBuffer.pullContext("${type.name}")
         positionAware: PositionAware = readBuffer
         startPos: int = positionAware.getPos()
@@ -795,8 +796,8 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
     </#if>
 
     <#if type.isDiscriminatedParentTypeDefinition()>
-        def interface ${type.name}Builder {
-            ${type.name} build(
+        class ${type.name}Builder:
+            def build(
         <#list type.propertyFields as field>
             ${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep>
             </#list>
@@ -806,27 +807,26 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
                 ${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>, </#sep>
             </#list>
         </#if>
-        )
-        }
+        ) -> ${type.name}:
 
     </#if>
     <#if type.isDiscriminatedChildTypeDefinition()>
-        public static class ${type.name}Builder implements ${type.parentType.orElseThrow().name}.${type.parentType.orElseThrow().name}Builder {
+        class ${type.name}Builder(${type.parentType.orElseThrow().name}${type.parentType.orElseThrow().name}Builder {
         <#if type.propertyFields?has_content>
             <#list type.propertyFields as field>
-        private final ${helper.getLanguageTypeNameForField(field)} ${field.name}
+        ${field.name}: ${helper.getLanguageTypeNameForField(field)}
             </#list>
         </#if>
         <#if filteredParserArguments?has_content>
             <#list filteredParserArguments as arg>
-        private final ${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}
+        ${arg.name}: ${helper.getLanguageTypeNameForTypeReference(arg.type)}
             </#list>
         </#if>
         <#list reservedFields as reservedField>
-        private final ${helper.getLanguageTypeNameForTypeReference(reservedField.type, false)} reservedField${reservedField?index}
+        reservedField${reservedField?index}: ${helper.getLanguageTypeNameForTypeReference(reservedField.type, false)}
         </#list>
 
-        public ${type.name}Builder(
+        def ${type.name}Builder(
         <#list type.propertyFields as field>
             ${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep>
         </#list>
@@ -840,21 +840,21 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
         <#list reservedFields as reservedField>
             ${helper.getLanguageTypeNameForTypeReference(reservedField.type, false)} reservedField${reservedField?index}<#sep>, </#sep>
         </#list>
-        ) {
+        ):
         <#list type.propertyFields as field>
-            this.${field.name} = ${field.name}
+            self.${field.name} = ${field.name}
         </#list>
         <#if filteredParserArguments?has_content>
             <#list filteredParserArguments as arg>
-            this.${arg.name} = ${arg.name}
+            self.${arg.name} = ${arg.name}
             </#list>
         </#if>
         <#list reservedFields as reservedField>
-            this.reservedField${reservedField?index} = reservedField${reservedField?index}
+            self.reservedField${reservedField?index} = reservedField${reservedField?index}
         </#list>
-        }
 
-        public ${type.name} build(
+
+        def build(
         <#list type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields as field>
             ${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep>
         </#list>
@@ -864,8 +864,8 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
                 ${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>, </#sep>
                 </#list>
             </#if>
-        ) {
-            ${type.name} ${type.name?uncap_first} = new ${type.name}(
+        ) -> ${type.name}:
+            ${type.name?uncap_first}: ${type.name} = ${type.name}(
             <#list type.allPropertyFields as field>
                 ${field.name}<#sep>, </#sep>
             </#list>
@@ -879,20 +879,17 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
             ${type.name?uncap_first}.reservedField${reservedField?index} = reservedField${reservedField?index}
         </#list>
             return ${type.name?uncap_first}
-        }
-    }
 
     </#if>
 
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true
-        }
-        if (!(o instanceof ${type.name})) {
-            return false
-        }
-        ${type.name} that = (${type.name}) o
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ${type.name}):
+            return False
+
+        that: ${type.name} = ${type.name}(o)
         return
             <#if type.propertyFields?has_content>
             <#list type.propertyFields as field>
@@ -900,16 +897,14 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
             </#list>
             </#if>
             <#if type.parentType.isPresent()>
-            super.equals(that) &&
+            super().equals(that) &&
             </#if>
-            true
-    }
+            True
 
-    @Override
-    public int hashCode() {
+    def hashCode(self) -> int:
         return Objects.hash(
             <#if type.parentType.isPresent()>
-            super.hashCode()<#if type.propertyFields?has_content>,</#if>
+            super().hashCode()<#if type.propertyFields?has_content>,</#if>
             </#if>
             <#if type.propertyFields?has_content>
             <#list type.propertyFields as field>
@@ -917,17 +912,14 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(PlcMess
             </#list>
             </#if>
         )
-    }
 
-    @Override
-    public String toString() {
-        WriteBufferBoxBased writeBufferBoxBased = new WriteBufferBoxBased(true, true)
-        try {
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
             writeBufferBoxBased.writeSerializable(this)
-        } catch (SerializationException e) {
-            throw new RuntimeException(e)
-        }
+        except SerializationException:
+            raise RuntimeException(e)
+
         return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
-    }
-}
+
 </#outputformat>
\ No newline at end of file
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusADU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusADU.py
new file mode 100644
index 0000000000..532de2001e
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusADU.py
@@ -0,0 +1,146 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusADU(ABC, PlcMessage):
+        # Arguments.
+            response: Boolean
+
+
+
+    def __post_init__(self):
+super().__init__( )
+
+    # Abstract accessors for discriminator values.
+    @abstractmethod
+    def getDriverType(self) -> DriverType:
+
+
+
+    @abstractmethod
+    def serializeModbusADUChild(writeBuffer: WriteBuffer) -> None:
+        pass
+
+    def serialize(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusADU")
+
+                        # Switch field (Serialize the sub-type)
+                        serializeModbusADUChild(writeBuffer)
+
+            writeBuffer.popContext("ModbusADU")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = 0
+        _value: ModbusADU = self
+
+        # Length of sub-type elements will be added by sub-type...
+
+        return lengthInBits
+
+
+    def staticParse(readBuffer: ReadBuffer , args) -> ModbusADU:
+        positionAware: PositionAware = readBuffer
+        if (args is None) or (args.length is not 2):
+            raise PlcRuntimeException("Wrong number of arguments, expected 2, but got " + args.length)
+
+        driverType: DriverType = None
+        if isinstance(args[0], DriverType):
+            driverType = DriverType(args[0])
+        elif isinstance(args[0], String):
+            driverType = DriverType.valueOf(str(args[0]))
+        else:
+            raise PlcRuntimeException("Argument 0 expected to be of type DriverType or a string which is parseable but was " + args[0].getClass().getName())
+
+        response: Boolean = None
+        if isinstance(args[1], Boolean):
+            response = Boolean(args[1])
+        elif isinstance(args[1], String):
+            response = Boolean.valueOf(str(args[1]))
+        else:
+            raise PlcRuntimeException("Argument 1 expected to be of type Boolean or a string which is parseable but was " + args[1].getClass().getName())
+
+        return staticParse(readBuffer, driverType, response)
+    }
+
+    def  staticParse(readBuffer: ReadBuffer, DriverType driverType, Boolean response) -> ModbusADU:
+        readBuffer.pullContext("ModbusADU")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                # Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
+                builder: ModbusADUBuilder = None
+if EvaluationHelper.equals( driverType, DriverType.MODBUS_TCP ) ) :builder = ModbusTcpADU.staticParseBuilder(readBuffer, driverType, response)                     else:
+if EvaluationHelper.equals( driverType, DriverType.MODBUS_RTU ) ) :builder = ModbusRtuADU.staticParseBuilder(readBuffer, driverType, response)                     else:
+if:builder = ModbusAsciiADU.staticParseBuilder(readBuffer, driverType, response)                    
+                if builder is None:
+                    raise ParseException("Unsupported case for discriminated type"+" parameters ["+"driverType="+driverType+"]")
+
+
+    readBuffer.closeContext("ModbusADU")
+    # Create the instance
+        _modbusADU: ModbusADU = builder.build(
+            
+                response
+        )
+        return _modbusADU
+
+        class ModbusADUBuilder:
+            def build(
+            
+                Boolean response
+        ) -> ModbusADU:
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusADU):
+            return False
+
+        that: ModbusADU = ModbusADU(o)
+        return
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusAsciiADU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusAsciiADU.py
new file mode 100644
index 0000000000..38a0a33d09
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusAsciiADU.py
@@ -0,0 +1,168 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusAsciiADU(PlcMessage,ModbusADU):
+            address: short
+            pdu: ModbusPDU
+        # Arguments.
+            response: Boolean
+
+    # Accessors for discriminator values.
+    def DriverType getDriverType() {
+        return DriverType.MODBUS_ASCII
+    }
+
+
+    def __post_init__(self):
+super().__init__( self.response )
+
+
+
+    def getAddress(self) -> short:
+        return address
+
+    def getPdu(self) -> ModbusPDU:
+        return pdu
+
+
+    def serializeModbusADUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusAsciiADU")
+
+                        # Simple Field (address)
+                            writeSimpleField("address", address, writeUnsignedShort(writeBuffer, 8), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                        # Simple Field (pdu)
+                            writeSimpleField("pdu", pdu, new DataWriterComplexDefault<>(writeBuffer), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                        # Checksum Field (checksum) (Calculated)
+                        writeChecksumField("crc", (short) (modbus.readwrite.utils.StaticHelper.asciiLrcCheck(address, pdu)), writeUnsignedShort(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusAsciiADU")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusAsciiADU = self
+
+        # Simple field (address)
+        lengthInBits += 8
+
+        # Simple field (pdu)
+        lengthInBits += pdu.getLengthInBits()
+
+        # Checksum Field (checksum)
+        lengthInBits += 8
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, DriverType driverType, Boolean response) -> ModbusAsciiADUBuilder:
+        readBuffer.pullContext("ModbusAsciiADU")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                address: short = readSimpleField("address", readUnsignedShort(readBuffer, 8), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                pdu: ModbusPDU = readSimpleField("pdu", new DataReaderComplexDefault<>(() -> ModbusPDU.staticParse(readBuffer, (boolean) (response)), readBuffer), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                crc: short = readChecksumField("crc", readUnsignedShort(readBuffer, 8), (short) (modbus.readwrite.utils.StaticHelper.asciiLrcCheck(address, pdu)), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+    readBuffer.closeContext("ModbusAsciiADU")
+    # Create the instance
+        return ModbusAsciiADUBuilder(
+            address, 
+            pdu
+            , 
+            response
+        
+        )
+
+        class ModbusAsciiADUBuilder(ModbusADUModbusADUBuilder {
+        address: short
+        pdu: ModbusPDU
+        response: Boolean
+
+        def ModbusAsciiADUBuilder(
+            short address, 
+            ModbusPDU pdu
+            , 
+                Boolean response
+        
+        ):
+            self.address = address
+            self.pdu = pdu
+            self.response = response
+
+
+        def build(
+            
+                Boolean response
+        ) -> ModbusAsciiADU:
+            modbusAsciiADU: ModbusAsciiADU = ModbusAsciiADU(
+                address, 
+                pdu
+            , 
+                response
+        )
+            return modbusAsciiADU
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusAsciiADU):
+            return False
+
+        that: ModbusAsciiADU = ModbusAsciiADU(o)
+        return
+            (getAddress() == that.getAddress()) &&
+            (getPdu() == that.getPdu()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getAddress(),
+            getPdu()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py
new file mode 100644
index 0000000000..be20cc264f
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py
@@ -0,0 +1,108 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusConstants(PlcMessage):
+            MODBUSTCPDEFAULTPORT: Integer = 502
+
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getModbusTcpDefaultPort(self) -> int:
+        return MODBUSTCPDEFAULTPORT
+
+
+    def serialize(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusConstants")
+
+                        # Const Field (modbusTcpDefaultPort)
+                        writeConstField("modbusTcpDefaultPort", MODBUSTCPDEFAULTPORT, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusConstants")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = 0
+        _value: ModbusConstants = self
+
+        # Const Field (modbusTcpDefaultPort)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def staticParse(readBuffer: ReadBuffer , args) -> ModbusConstants:
+        positionAware: PositionAware = readBuffer
+        return staticParse(readBuffer)
+    }
+
+    def  staticParse(readBuffer: ReadBuffer) -> ModbusConstants:
+        readBuffer.pullContext("ModbusConstants")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                modbusTcpDefaultPort: int = readConstField("modbusTcpDefaultPort", readUnsignedInt(readBuffer, 16), ModbusConstants.MODBUSTCPDEFAULTPORT)
+
+    readBuffer.closeContext("ModbusConstants")
+    # Create the instance
+        _modbusConstants: ModbusConstants = ModbusConstants(
+        )
+        return _modbusConstants
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusConstants):
+            return False
+
+        that: ModbusConstants = ModbusConstants(o)
+        return
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDataType.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDataType.py
new file mode 100644
index 0000000000..f365d4a2d5
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDataType.py
@@ -0,0 +1,84 @@
+#
+# 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
+#
+#   https://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 modbus.readwrite;
+
+import org.apache.plc4x.java.spi.generation.Message;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+// Code generated by code-generation. DO NOT EDIT.
+
+public enum ModbusDataType {
+
+BOOL( (short) 1 , (short) 2 ) , BYTE( (short) 2 , (short) 2 ) , WORD( (short) 3 , (short) 2 ) , DWORD( (short) 4 , (short) 4 ) , LWORD( (short) 5 , (short) 8 ) , SINT( (short) 6 , (short) 2 ) , INT( (short) 7 , (short) 2 ) , DINT( (short) 8 , (short) 4 ) , LINT( (short) 9 , (short) 8 ) , USINT( (short) 10 , (short) 2 ) , UINT( (short) 11 , (short) 2 ) , UDINT( (short) 12 , (short) 4 ) , ULINT( (short) 13 , (short) 8 ) , REAL( (short) 14 , (short) 4 ) , LREAL( (short) 15 , (short) 8 ) , T [...]
+    private static final Map<Short, ModbusDataType> map;
+    static {
+        map = new HashMap<>();
+        for (ModbusDataType value : ModbusDataType.values()) {
+            map.put((short) value.getValue(), value);
+        }
+    }
+
+    private short value;
+        private short dataTypeSize;
+
+    ModbusDataType(short value, short dataTypeSize) {
+        this.value = value;
+        this.dataTypeSize = dataTypeSize;
+    }
+
+    public short getValue() {
+        return value;
+    }
+
+    public short getDataTypeSize() {
+        return dataTypeSize;
+    }
+
+    public static ModbusDataType firstEnumForFieldDataTypeSize(short fieldValue) {
+        for (ModbusDataType _val : ModbusDataType.values()) {
+            if(_val.getDataTypeSize() == fieldValue) {
+                return _val;
+            }
+        }
+        return null;
+    }
+
+    public static List<ModbusDataType> enumsForFieldDataTypeSize(short fieldValue) {
+        List<ModbusDataType> _values = new ArrayList();
+        for (ModbusDataType _val : ModbusDataType.values()) {
+            if(_val.getDataTypeSize() == fieldValue) {
+                _values.add(_val);
+            }
+        }
+        return _values;
+    }
+
+    public static ModbusDataType enumForValue(short value) {
+        return map.get(value);
+    }
+
+    public static Boolean isDefined(short value) {
+        return map.containsKey(value);
+    }
+
+}
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationConformityLevel.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationConformityLevel.py
new file mode 100644
index 0000000000..a5ae88d334
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationConformityLevel.py
@@ -0,0 +1,59 @@
+#
+# 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
+#
+#   https://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 modbus.readwrite;
+
+import org.apache.plc4x.java.spi.generation.Message;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+// Code generated by code-generation. DO NOT EDIT.
+
+public enum ModbusDeviceInformationConformityLevel {
+
+BASIC_STREAM_ONLY( (short) 0x01 ) , REGULAR_STREAM_ONLY( (short) 0x02 ) , EXTENDED_STREAM_ONLY( (short) 0x03 ) ;
+    private static final Map<Short, ModbusDeviceInformationConformityLevel> map;
+    static {
+        map = new HashMap<>();
+        for (ModbusDeviceInformationConformityLevel value : ModbusDeviceInformationConformityLevel.values()) {
+            map.put((short) value.getValue(), value);
+        }
+    }
+
+    private short value;
+
+    ModbusDeviceInformationConformityLevel(short value) {
+        this.value = value;
+    }
+
+    public short getValue() {
+        return value;
+    }
+
+    public static ModbusDeviceInformationConformityLevel enumForValue(short value) {
+        return map.get(value);
+    }
+
+    public static Boolean isDefined(short value) {
+        return map.containsKey(value);
+    }
+
+}
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationLevel.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationLevel.py
new file mode 100644
index 0000000000..a21956bba1
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationLevel.py
@@ -0,0 +1,59 @@
+#
+# 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
+#
+#   https://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 modbus.readwrite;
+
+import org.apache.plc4x.java.spi.generation.Message;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+// Code generated by code-generation. DO NOT EDIT.
+
+public enum ModbusDeviceInformationLevel {
+
+BASIC( (short) 0x01 ) , REGULAR( (short) 0x02 ) , EXTENDED( (short) 0x03 ) , INDIVIDUAL( (short) 0x04 ) ;
+    private static final Map<Short, ModbusDeviceInformationLevel> map;
+    static {
+        map = new HashMap<>();
+        for (ModbusDeviceInformationLevel value : ModbusDeviceInformationLevel.values()) {
+            map.put((short) value.getValue(), value);
+        }
+    }
+
+    private short value;
+
+    ModbusDeviceInformationLevel(short value) {
+        this.value = value;
+    }
+
+    public short getValue() {
+        return value;
+    }
+
+    public static ModbusDeviceInformationLevel enumForValue(short value) {
+        return map.get(value);
+    }
+
+    public static Boolean isDefined(short value) {
+        return map.containsKey(value);
+    }
+
+}
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationMoreFollows.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationMoreFollows.py
new file mode 100644
index 0000000000..53c76ad75c
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationMoreFollows.py
@@ -0,0 +1,59 @@
+#
+# 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
+#
+#   https://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 modbus.readwrite;
+
+import org.apache.plc4x.java.spi.generation.Message;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+// Code generated by code-generation. DO NOT EDIT.
+
+public enum ModbusDeviceInformationMoreFollows {
+
+NO_MORE_OBJECTS_AVAILABLE( (short) 0x00 ) , MORE_OBJECTS_AVAILABLE( (short) 0xFF ) ;
+    private static final Map<Short, ModbusDeviceInformationMoreFollows> map;
+    static {
+        map = new HashMap<>();
+        for (ModbusDeviceInformationMoreFollows value : ModbusDeviceInformationMoreFollows.values()) {
+            map.put((short) value.getValue(), value);
+        }
+    }
+
+    private short value;
+
+    ModbusDeviceInformationMoreFollows(short value) {
+        this.value = value;
+    }
+
+    public short getValue() {
+        return value;
+    }
+
+    public static ModbusDeviceInformationMoreFollows enumForValue(short value) {
+        return map.get(value);
+    }
+
+    public static Boolean isDefined(short value) {
+        return map.containsKey(value);
+    }
+
+}
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py
new file mode 100644
index 0000000000..19fd2d318a
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py
@@ -0,0 +1,137 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusDeviceInformationObject(PlcMessage):
+            objectId: short
+            data: byte[]
+
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getObjectId(self) -> short:
+        return objectId
+
+    def getData(self) -> byte[]:
+        return data
+
+
+    def serialize(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusDeviceInformationObject")
+
+                        # Simple Field (objectId)
+                            writeSimpleField("objectId", objectId, writeUnsignedShort(writeBuffer, 8))
+
+                        # Implicit Field (objectLength) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short objectLength = (short) (COUNT(getData()))
+                        writeImplicitField("objectLength", objectLength, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (data)
+                        writeByteArrayField("data", data, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusDeviceInformationObject")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = 0
+        _value: ModbusDeviceInformationObject = self
+
+        # Simple field (objectId)
+        lengthInBits += 8
+
+        # Implicit Field (objectLength)
+        lengthInBits += 8
+
+        # Array field
+        if data is not None):
+            lengthInBits += 8 * data.length
+
+
+        return lengthInBits
+
+
+    def staticParse(readBuffer: ReadBuffer , args) -> ModbusDeviceInformationObject:
+        positionAware: PositionAware = readBuffer
+        return staticParse(readBuffer)
+    }
+
+    def  staticParse(readBuffer: ReadBuffer) -> ModbusDeviceInformationObject:
+        readBuffer.pullContext("ModbusDeviceInformationObject")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                objectId: short = readSimpleField("objectId", readUnsignedShort(readBuffer, 8))
+
+                objectLength: short = readImplicitField("objectLength", readUnsignedShort(readBuffer, 8))
+
+                    data: byte[] = readBuffer.readByteArray("data", Math.toIntExact(objectLength))
+
+    readBuffer.closeContext("ModbusDeviceInformationObject")
+    # Create the instance
+        _modbusDeviceInformationObject: ModbusDeviceInformationObject = ModbusDeviceInformationObject(
+            objectId, 
+            data
+        )
+        return _modbusDeviceInformationObject
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusDeviceInformationObject):
+            return False
+
+        that: ModbusDeviceInformationObject = ModbusDeviceInformationObject(o)
+        return
+            (getObjectId() == that.getObjectId()) &&
+            (getData() == that.getData()) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            getObjectId(),
+            getData()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusErrorCode.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusErrorCode.py
new file mode 100644
index 0000000000..83f953baed
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusErrorCode.py
@@ -0,0 +1,59 @@
+#
+# 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
+#
+#   https://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 modbus.readwrite;
+
+import org.apache.plc4x.java.spi.generation.Message;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+// Code generated by code-generation. DO NOT EDIT.
+
+public enum ModbusErrorCode {
+
+ILLEGAL_FUNCTION( (short) 1 ) , ILLEGAL_DATA_ADDRESS( (short) 2 ) , ILLEGAL_DATA_VALUE( (short) 3 ) , SLAVE_DEVICE_FAILURE( (short) 4 ) , ACKNOWLEDGE( (short) 5 ) , SLAVE_DEVICE_BUSY( (short) 6 ) , NEGATIVE_ACKNOWLEDGE( (short) 7 ) , MEMORY_PARITY_ERROR( (short) 8 ) , GATEWAY_PATH_UNAVAILABLE( (short) 10 ) , GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND( (short) 11 ) ;
+    private static final Map<Short, ModbusErrorCode> map;
+    static {
+        map = new HashMap<>();
+        for (ModbusErrorCode value : ModbusErrorCode.values()) {
+            map.put((short) value.getValue(), value);
+        }
+    }
+
+    private short value;
+
+    ModbusErrorCode(short value) {
+        this.value = value;
+    }
+
+    public short getValue() {
+        return value;
+    }
+
+    public static ModbusErrorCode enumForValue(short value) {
+        return map.get(value);
+    }
+
+    public static Boolean isDefined(short value) {
+        return map.containsKey(value);
+    }
+
+}
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
new file mode 100644
index 0000000000..451f4503eb
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
@@ -0,0 +1,188 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDU(ABC, PlcMessage):
+
+
+
+    def __post_init__(self):
+super().__init__( )
+
+    # Abstract accessors for discriminator values.
+    @abstractmethod
+    def getErrorFlag(self) -> Boolean:
+    @abstractmethod
+    def getFunctionFlag(self) -> Short:
+    @abstractmethod
+    def getResponse(self) -> Boolean:
+
+
+
+    @abstractmethod
+    def serializeModbusPDUChild(writeBuffer: WriteBuffer) -> None:
+        pass
+
+    def serialize(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDU")
+
+                        # Discriminator Field (errorFlag) (Used as input to a switch field)
+                        writeDiscriminatorField("errorFlag", getErrorFlag(), writeBoolean(writeBuffer))
+
+                        # Discriminator Field (functionFlag) (Used as input to a switch field)
+                        writeDiscriminatorField("functionFlag", getFunctionFlag(), writeUnsignedShort(writeBuffer, 7))
+
+                        # Switch field (Serialize the sub-type)
+                        serializeModbusPDUChild(writeBuffer)
+
+            writeBuffer.popContext("ModbusPDU")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = 0
+        _value: ModbusPDU = self
+
+        # Discriminator Field (errorFlag)
+        lengthInBits += 1
+
+        # Discriminator Field (functionFlag)
+        lengthInBits += 7
+
+        # Length of sub-type elements will be added by sub-type...
+
+        return lengthInBits
+
+
+    def staticParse(readBuffer: ReadBuffer , args) -> ModbusPDU:
+        positionAware: PositionAware = readBuffer
+        if (args is None) or (args.length is not 1):
+            raise PlcRuntimeException("Wrong number of arguments, expected 1, but got " + args.length)
+
+        response: Boolean = None
+        if isinstance(args[0], Boolean):
+            response = Boolean(args[0])
+        elif isinstance(args[0], String):
+            response = Boolean.valueOf(str(args[0]))
+        else:
+            raise PlcRuntimeException("Argument 0 expected to be of type Boolean or a string which is parseable but was " + args[0].getClass().getName())
+
+        return staticParse(readBuffer, response)
+    }
+
+    def  staticParse(readBuffer: ReadBuffer, Boolean response) -> ModbusPDU:
+        readBuffer.pullContext("ModbusPDU")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                errorFlag: boolean = readDiscriminatorField("errorFlag", readBoolean(readBuffer))
+
+                functionFlag: short = readDiscriminatorField("functionFlag", readUnsignedShort(readBuffer, 7))
+
+                # Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
+                builder: ModbusPDUBuilder = None
+if EvaluationHelper.equals( errorFlag, (boolean) true ) ) :builder = ModbusPDUError.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x02 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadDiscreteInputsRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x02 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReadDiscreteInputsResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x01 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadCoilsRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x01 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReadCoilsResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x05 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUWriteSingleCoilRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x05 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUWriteSingleCoilResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x0F ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUWriteMultipleCoilsRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x0F ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUWriteMultipleCoilsResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x04 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadInputRegistersRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x04 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReadInputRegistersResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x03 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadHoldingRegistersRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x03 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReadHoldingRegistersResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x06 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUWriteSingleRegisterRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x06 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUWriteSingleRegisterResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x10 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUWriteMultipleHoldingRegistersRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x10 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUWriteMultipleHoldingRegistersResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x17 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadWriteMultipleHoldingRegistersRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x17 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReadWriteMultipleHoldingRegistersResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x16 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUMaskWriteHoldingRegisterRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x16 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUMaskWriteHoldingRegisterResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x18 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadFifoQueueRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x18 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReadFifoQueueResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x14 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadFileRecordRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x14 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReadFileRecordResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x15 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUWriteFileRecordRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x15 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUWriteFileRecordResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x07 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadExceptionStatusRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x07 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReadExceptionStatusResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x08 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUDiagnosticRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x08 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUDiagnosticResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x0B ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUGetComEventCounterRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x0B ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUGetComEventCounterResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x0C ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUGetComEventLogRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x0C ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUGetComEventLogResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x11 ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReportServerIdRequest.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x11 ) and EvaluationHelper.equals( response, (boolean) true ) ) :builder = ModbusPDUReportServerIdResponse.staticParseBuilder(readBuffer, response)                     else:
+if EvaluationHelper.equals( errorFlag, (boolean) false ) and EvaluationHelper.equals( functionFlag, (short) 0x2B ) and EvaluationHelper.equals( response, (boolean) false ) ) :builder = ModbusPDUReadDeviceIdentificationRequest.staticParseBuilder(readBuffer, response)                     else:
+if:builder = ModbusPDUReadDeviceIdentificationResponse.staticParseBuilder(readBuffer, response)                    
+                if builder is None:
+                    raise ParseException("Unsupported case for discriminated type"+" parameters ["+"errorFlag="+errorFlag+" "+"functionFlag="+functionFlag+" "+"response="+response+"]")
+
+
+    readBuffer.closeContext("ModbusPDU")
+    # Create the instance
+        _modbusPDU: ModbusPDU = builder.build(
+        )
+        return _modbusPDU
+
+        class ModbusPDUBuilder:
+            def build(
+        ) -> ModbusPDU:
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDU):
+            return False
+
+        that: ModbusPDU = ModbusPDU(o)
+        return
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py
new file mode 100644
index 0000000000..cbc9cad72f
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUDiagnosticRequest(PlcMessage,ModbusPDU):
+            subFunction: int
+            data: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x08
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getSubFunction(self) -> int:
+        return subFunction
+
+    def getData(self) -> int:
+        return data
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUDiagnosticRequest")
+
+                        # Simple Field (subFunction)
+                            writeSimpleField("subFunction", subFunction, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (data)
+                            writeSimpleField("data", data, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUDiagnosticRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUDiagnosticRequest = self
+
+        # Simple field (subFunction)
+        lengthInBits += 16
+
+        # Simple field (data)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUDiagnosticRequestBuilder:
+        readBuffer.pullContext("ModbusPDUDiagnosticRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                subFunction: int = readSimpleField("subFunction", readUnsignedInt(readBuffer, 16))
+
+                data: int = readSimpleField("data", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUDiagnosticRequest")
+    # Create the instance
+        return ModbusPDUDiagnosticRequestBuilder(
+            subFunction, 
+            data
+        
+        )
+
+        class ModbusPDUDiagnosticRequestBuilder(ModbusPDUModbusPDUBuilder {
+        subFunction: int
+        data: int
+
+        def ModbusPDUDiagnosticRequestBuilder(
+            int subFunction, 
+            int data
+        
+        ):
+            self.subFunction = subFunction
+            self.data = data
+
+
+        def build(
+        ) -> ModbusPDUDiagnosticRequest:
+            modbusPDUDiagnosticRequest: ModbusPDUDiagnosticRequest = ModbusPDUDiagnosticRequest(
+                subFunction, 
+                data
+)
+            return modbusPDUDiagnosticRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUDiagnosticRequest):
+            return False
+
+        that: ModbusPDUDiagnosticRequest = ModbusPDUDiagnosticRequest(o)
+        return
+            (getSubFunction() == that.getSubFunction()) &&
+            (getData() == that.getData()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getSubFunction(),
+            getData()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py
new file mode 100644
index 0000000000..02556ed834
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUDiagnosticResponse(PlcMessage,ModbusPDU):
+            subFunction: int
+            data: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x08
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getSubFunction(self) -> int:
+        return subFunction
+
+    def getData(self) -> int:
+        return data
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUDiagnosticResponse")
+
+                        # Simple Field (subFunction)
+                            writeSimpleField("subFunction", subFunction, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (data)
+                            writeSimpleField("data", data, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUDiagnosticResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUDiagnosticResponse = self
+
+        # Simple field (subFunction)
+        lengthInBits += 16
+
+        # Simple field (data)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUDiagnosticResponseBuilder:
+        readBuffer.pullContext("ModbusPDUDiagnosticResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                subFunction: int = readSimpleField("subFunction", readUnsignedInt(readBuffer, 16))
+
+                data: int = readSimpleField("data", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUDiagnosticResponse")
+    # Create the instance
+        return ModbusPDUDiagnosticResponseBuilder(
+            subFunction, 
+            data
+        
+        )
+
+        class ModbusPDUDiagnosticResponseBuilder(ModbusPDUModbusPDUBuilder {
+        subFunction: int
+        data: int
+
+        def ModbusPDUDiagnosticResponseBuilder(
+            int subFunction, 
+            int data
+        
+        ):
+            self.subFunction = subFunction
+            self.data = data
+
+
+        def build(
+        ) -> ModbusPDUDiagnosticResponse:
+            modbusPDUDiagnosticResponse: ModbusPDUDiagnosticResponse = ModbusPDUDiagnosticResponse(
+                subFunction, 
+                data
+)
+            return modbusPDUDiagnosticResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUDiagnosticResponse):
+            return False
+
+        that: ModbusPDUDiagnosticResponse = ModbusPDUDiagnosticResponse(o)
+        return
+            (getSubFunction() == that.getSubFunction()) &&
+            (getData() == that.getData()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getSubFunction(),
+            getData()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py
new file mode 100644
index 0000000000..f7ecbe974f
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py
@@ -0,0 +1,136 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUError(PlcMessage,ModbusPDU):
+            exceptionCode: ModbusErrorCode
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) true
+    }
+    def Short getFunctionFlag() {
+        return 0
+    }
+    def Boolean getResponse() {
+        return false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getExceptionCode(self) -> ModbusErrorCode:
+        return exceptionCode
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUError")
+
+                        # Simple Field (exceptionCode)
+                            writeSimpleEnumField("exceptionCode", "ModbusErrorCode", exceptionCode, new DataWriterEnumDefault<>(ModbusErrorCode::getValue, ModbusErrorCode::name, writeUnsignedShort(writeBuffer, 8)))
+
+
+            writeBuffer.popContext("ModbusPDUError")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUError = self
+
+        # Simple field (exceptionCode)
+        lengthInBits += 8
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUErrorBuilder:
+        readBuffer.pullContext("ModbusPDUError")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                exceptionCode: ModbusErrorCode = readEnumField("exceptionCode", "ModbusErrorCode", new DataReaderEnumDefault<>(ModbusErrorCode::enumForValue, readUnsignedShort(readBuffer, 8)))
+
+    readBuffer.closeContext("ModbusPDUError")
+    # Create the instance
+        return ModbusPDUErrorBuilder(
+            exceptionCode
+        
+        )
+
+        class ModbusPDUErrorBuilder(ModbusPDUModbusPDUBuilder {
+        exceptionCode: ModbusErrorCode
+
+        def ModbusPDUErrorBuilder(
+            ModbusErrorCode exceptionCode
+        
+        ):
+            self.exceptionCode = exceptionCode
+
+
+        def build(
+        ) -> ModbusPDUError:
+            modbusPDUError: ModbusPDUError = ModbusPDUError(
+                exceptionCode
+)
+            return modbusPDUError
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUError):
+            return False
+
+        that: ModbusPDUError = ModbusPDUError(o)
+        return
+            (getExceptionCode() == that.getExceptionCode()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getExceptionCode()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py
new file mode 100644
index 0000000000..ea097bc7ef
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py
@@ -0,0 +1,116 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUGetComEventCounterRequest(PlcMessage,ModbusPDU):
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x0B
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUGetComEventCounterRequest")
+
+            writeBuffer.popContext("ModbusPDUGetComEventCounterRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUGetComEventCounterRequest = self
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUGetComEventCounterRequestBuilder:
+        readBuffer.pullContext("ModbusPDUGetComEventCounterRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+    readBuffer.closeContext("ModbusPDUGetComEventCounterRequest")
+    # Create the instance
+        return ModbusPDUGetComEventCounterRequestBuilder(
+        
+        )
+
+        class ModbusPDUGetComEventCounterRequestBuilder(ModbusPDUModbusPDUBuilder {
+
+        def ModbusPDUGetComEventCounterRequestBuilder(
+        
+        ):
+
+
+        def build(
+        ) -> ModbusPDUGetComEventCounterRequest:
+            modbusPDUGetComEventCounterRequest: ModbusPDUGetComEventCounterRequest = ModbusPDUGetComEventCounterRequest(
+)
+            return modbusPDUGetComEventCounterRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUGetComEventCounterRequest):
+            return False
+
+        that: ModbusPDUGetComEventCounterRequest = ModbusPDUGetComEventCounterRequest(o)
+        return
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py
new file mode 100644
index 0000000000..6f911c9ead
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUGetComEventCounterResponse(PlcMessage,ModbusPDU):
+            status: int
+            eventCount: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x0B
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStatus(self) -> int:
+        return status
+
+    def getEventCount(self) -> int:
+        return eventCount
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUGetComEventCounterResponse")
+
+                        # Simple Field (status)
+                            writeSimpleField("status", status, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (eventCount)
+                            writeSimpleField("eventCount", eventCount, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUGetComEventCounterResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUGetComEventCounterResponse = self
+
+        # Simple field (status)
+        lengthInBits += 16
+
+        # Simple field (eventCount)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUGetComEventCounterResponseBuilder:
+        readBuffer.pullContext("ModbusPDUGetComEventCounterResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                status: int = readSimpleField("status", readUnsignedInt(readBuffer, 16))
+
+                eventCount: int = readSimpleField("eventCount", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUGetComEventCounterResponse")
+    # Create the instance
+        return ModbusPDUGetComEventCounterResponseBuilder(
+            status, 
+            eventCount
+        
+        )
+
+        class ModbusPDUGetComEventCounterResponseBuilder(ModbusPDUModbusPDUBuilder {
+        status: int
+        eventCount: int
+
+        def ModbusPDUGetComEventCounterResponseBuilder(
+            int status, 
+            int eventCount
+        
+        ):
+            self.status = status
+            self.eventCount = eventCount
+
+
+        def build(
+        ) -> ModbusPDUGetComEventCounterResponse:
+            modbusPDUGetComEventCounterResponse: ModbusPDUGetComEventCounterResponse = ModbusPDUGetComEventCounterResponse(
+                status, 
+                eventCount
+)
+            return modbusPDUGetComEventCounterResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUGetComEventCounterResponse):
+            return False
+
+        that: ModbusPDUGetComEventCounterResponse = ModbusPDUGetComEventCounterResponse(o)
+        return
+            (getStatus() == that.getStatus()) &&
+            (getEventCount() == that.getEventCount()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStatus(),
+            getEventCount()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py
new file mode 100644
index 0000000000..4a8bdfc22e
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py
@@ -0,0 +1,116 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUGetComEventLogRequest(PlcMessage,ModbusPDU):
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x0C
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUGetComEventLogRequest")
+
+            writeBuffer.popContext("ModbusPDUGetComEventLogRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUGetComEventLogRequest = self
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUGetComEventLogRequestBuilder:
+        readBuffer.pullContext("ModbusPDUGetComEventLogRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+    readBuffer.closeContext("ModbusPDUGetComEventLogRequest")
+    # Create the instance
+        return ModbusPDUGetComEventLogRequestBuilder(
+        
+        )
+
+        class ModbusPDUGetComEventLogRequestBuilder(ModbusPDUModbusPDUBuilder {
+
+        def ModbusPDUGetComEventLogRequestBuilder(
+        
+        ):
+
+
+        def build(
+        ) -> ModbusPDUGetComEventLogRequest:
+            modbusPDUGetComEventLogRequest: ModbusPDUGetComEventLogRequest = ModbusPDUGetComEventLogRequest(
+)
+            return modbusPDUGetComEventLogRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUGetComEventLogRequest):
+            return False
+
+        that: ModbusPDUGetComEventLogRequest = ModbusPDUGetComEventLogRequest(o)
+        return
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py
new file mode 100644
index 0000000000..cfb246a453
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py
@@ -0,0 +1,203 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUGetComEventLogResponse(PlcMessage,ModbusPDU):
+            status: int
+            eventCount: int
+            messageCount: int
+            events: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x0C
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStatus(self) -> int:
+        return status
+
+    def getEventCount(self) -> int:
+        return eventCount
+
+    def getMessageCount(self) -> int:
+        return messageCount
+
+    def getEvents(self) -> byte[]:
+        return events
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUGetComEventLogResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) ((COUNT(getEvents())) + (6))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Simple Field (status)
+                            writeSimpleField("status", status, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (eventCount)
+                            writeSimpleField("eventCount", eventCount, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (messageCount)
+                            writeSimpleField("messageCount", messageCount, writeUnsignedInt(writeBuffer, 16))
+
+                        # Array Field (events)
+                        writeByteArrayField("events", events, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUGetComEventLogResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUGetComEventLogResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Simple field (status)
+        lengthInBits += 16
+
+        # Simple field (eventCount)
+        lengthInBits += 16
+
+        # Simple field (messageCount)
+        lengthInBits += 16
+
+        # Array field
+        if events is not None):
+            lengthInBits += 8 * events.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUGetComEventLogResponseBuilder:
+        readBuffer.pullContext("ModbusPDUGetComEventLogResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                status: int = readSimpleField("status", readUnsignedInt(readBuffer, 16))
+
+                eventCount: int = readSimpleField("eventCount", readUnsignedInt(readBuffer, 16))
+
+                messageCount: int = readSimpleField("messageCount", readUnsignedInt(readBuffer, 16))
+
+                    events: byte[] = readBuffer.readByteArray("events", Math.toIntExact((byteCount) - (6)))
+
+    readBuffer.closeContext("ModbusPDUGetComEventLogResponse")
+    # Create the instance
+        return ModbusPDUGetComEventLogResponseBuilder(
+            status, 
+            eventCount, 
+            messageCount, 
+            events
+        
+        )
+
+        class ModbusPDUGetComEventLogResponseBuilder(ModbusPDUModbusPDUBuilder {
+        status: int
+        eventCount: int
+        messageCount: int
+        events: byte[]
+
+        def ModbusPDUGetComEventLogResponseBuilder(
+            int status, 
+            int eventCount, 
+            int messageCount, 
+            byte[] events
+        
+        ):
+            self.status = status
+            self.eventCount = eventCount
+            self.messageCount = messageCount
+            self.events = events
+
+
+        def build(
+        ) -> ModbusPDUGetComEventLogResponse:
+            modbusPDUGetComEventLogResponse: ModbusPDUGetComEventLogResponse = ModbusPDUGetComEventLogResponse(
+                status, 
+                eventCount, 
+                messageCount, 
+                events
+)
+            return modbusPDUGetComEventLogResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUGetComEventLogResponse):
+            return False
+
+        that: ModbusPDUGetComEventLogResponse = ModbusPDUGetComEventLogResponse(o)
+        return
+            (getStatus() == that.getStatus()) &&
+            (getEventCount() == that.getEventCount()) &&
+            (getMessageCount() == that.getMessageCount()) &&
+            (getEvents() == that.getEvents()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStatus(),
+            getEventCount(),
+            getMessageCount(),
+            getEvents()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py
new file mode 100644
index 0000000000..53a1e1c2f4
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py
@@ -0,0 +1,173 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUMaskWriteHoldingRegisterRequest(PlcMessage,ModbusPDU):
+            referenceAddress: int
+            andMask: int
+            orMask: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x16
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getReferenceAddress(self) -> int:
+        return referenceAddress
+
+    def getAndMask(self) -> int:
+        return andMask
+
+    def getOrMask(self) -> int:
+        return orMask
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUMaskWriteHoldingRegisterRequest")
+
+                        # Simple Field (referenceAddress)
+                            writeSimpleField("referenceAddress", referenceAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (andMask)
+                            writeSimpleField("andMask", andMask, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (orMask)
+                            writeSimpleField("orMask", orMask, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUMaskWriteHoldingRegisterRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUMaskWriteHoldingRegisterRequest = self
+
+        # Simple field (referenceAddress)
+        lengthInBits += 16
+
+        # Simple field (andMask)
+        lengthInBits += 16
+
+        # Simple field (orMask)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUMaskWriteHoldingRegisterRequestBuilder:
+        readBuffer.pullContext("ModbusPDUMaskWriteHoldingRegisterRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                referenceAddress: int = readSimpleField("referenceAddress", readUnsignedInt(readBuffer, 16))
+
+                andMask: int = readSimpleField("andMask", readUnsignedInt(readBuffer, 16))
+
+                orMask: int = readSimpleField("orMask", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUMaskWriteHoldingRegisterRequest")
+    # Create the instance
+        return ModbusPDUMaskWriteHoldingRegisterRequestBuilder(
+            referenceAddress, 
+            andMask, 
+            orMask
+        
+        )
+
+        class ModbusPDUMaskWriteHoldingRegisterRequestBuilder(ModbusPDUModbusPDUBuilder {
+        referenceAddress: int
+        andMask: int
+        orMask: int
+
+        def ModbusPDUMaskWriteHoldingRegisterRequestBuilder(
+            int referenceAddress, 
+            int andMask, 
+            int orMask
+        
+        ):
+            self.referenceAddress = referenceAddress
+            self.andMask = andMask
+            self.orMask = orMask
+
+
+        def build(
+        ) -> ModbusPDUMaskWriteHoldingRegisterRequest:
+            modbusPDUMaskWriteHoldingRegisterRequest: ModbusPDUMaskWriteHoldingRegisterRequest = ModbusPDUMaskWriteHoldingRegisterRequest(
+                referenceAddress, 
+                andMask, 
+                orMask
+)
+            return modbusPDUMaskWriteHoldingRegisterRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUMaskWriteHoldingRegisterRequest):
+            return False
+
+        that: ModbusPDUMaskWriteHoldingRegisterRequest = ModbusPDUMaskWriteHoldingRegisterRequest(o)
+        return
+            (getReferenceAddress() == that.getReferenceAddress()) &&
+            (getAndMask() == that.getAndMask()) &&
+            (getOrMask() == that.getOrMask()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getReferenceAddress(),
+            getAndMask(),
+            getOrMask()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py
new file mode 100644
index 0000000000..287e51656a
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py
@@ -0,0 +1,173 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUMaskWriteHoldingRegisterResponse(PlcMessage,ModbusPDU):
+            referenceAddress: int
+            andMask: int
+            orMask: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x16
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getReferenceAddress(self) -> int:
+        return referenceAddress
+
+    def getAndMask(self) -> int:
+        return andMask
+
+    def getOrMask(self) -> int:
+        return orMask
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUMaskWriteHoldingRegisterResponse")
+
+                        # Simple Field (referenceAddress)
+                            writeSimpleField("referenceAddress", referenceAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (andMask)
+                            writeSimpleField("andMask", andMask, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (orMask)
+                            writeSimpleField("orMask", orMask, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUMaskWriteHoldingRegisterResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUMaskWriteHoldingRegisterResponse = self
+
+        # Simple field (referenceAddress)
+        lengthInBits += 16
+
+        # Simple field (andMask)
+        lengthInBits += 16
+
+        # Simple field (orMask)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUMaskWriteHoldingRegisterResponseBuilder:
+        readBuffer.pullContext("ModbusPDUMaskWriteHoldingRegisterResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                referenceAddress: int = readSimpleField("referenceAddress", readUnsignedInt(readBuffer, 16))
+
+                andMask: int = readSimpleField("andMask", readUnsignedInt(readBuffer, 16))
+
+                orMask: int = readSimpleField("orMask", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUMaskWriteHoldingRegisterResponse")
+    # Create the instance
+        return ModbusPDUMaskWriteHoldingRegisterResponseBuilder(
+            referenceAddress, 
+            andMask, 
+            orMask
+        
+        )
+
+        class ModbusPDUMaskWriteHoldingRegisterResponseBuilder(ModbusPDUModbusPDUBuilder {
+        referenceAddress: int
+        andMask: int
+        orMask: int
+
+        def ModbusPDUMaskWriteHoldingRegisterResponseBuilder(
+            int referenceAddress, 
+            int andMask, 
+            int orMask
+        
+        ):
+            self.referenceAddress = referenceAddress
+            self.andMask = andMask
+            self.orMask = orMask
+
+
+        def build(
+        ) -> ModbusPDUMaskWriteHoldingRegisterResponse:
+            modbusPDUMaskWriteHoldingRegisterResponse: ModbusPDUMaskWriteHoldingRegisterResponse = ModbusPDUMaskWriteHoldingRegisterResponse(
+                referenceAddress, 
+                andMask, 
+                orMask
+)
+            return modbusPDUMaskWriteHoldingRegisterResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUMaskWriteHoldingRegisterResponse):
+            return False
+
+        that: ModbusPDUMaskWriteHoldingRegisterResponse = ModbusPDUMaskWriteHoldingRegisterResponse(o)
+        return
+            (getReferenceAddress() == that.getReferenceAddress()) &&
+            (getAndMask() == that.getAndMask()) &&
+            (getOrMask() == that.getOrMask()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getReferenceAddress(),
+            getAndMask(),
+            getOrMask()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py
new file mode 100644
index 0000000000..f57d794c05
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadCoilsRequest(PlcMessage,ModbusPDU):
+            startingAddress: int
+            quantity: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x01
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStartingAddress(self) -> int:
+        return startingAddress
+
+    def getQuantity(self) -> int:
+        return quantity
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadCoilsRequest")
+
+                        # Simple Field (startingAddress)
+                            writeSimpleField("startingAddress", startingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (quantity)
+                            writeSimpleField("quantity", quantity, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUReadCoilsRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadCoilsRequest = self
+
+        # Simple field (startingAddress)
+        lengthInBits += 16
+
+        # Simple field (quantity)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadCoilsRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadCoilsRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                startingAddress: int = readSimpleField("startingAddress", readUnsignedInt(readBuffer, 16))
+
+                quantity: int = readSimpleField("quantity", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUReadCoilsRequest")
+    # Create the instance
+        return ModbusPDUReadCoilsRequestBuilder(
+            startingAddress, 
+            quantity
+        
+        )
+
+        class ModbusPDUReadCoilsRequestBuilder(ModbusPDUModbusPDUBuilder {
+        startingAddress: int
+        quantity: int
+
+        def ModbusPDUReadCoilsRequestBuilder(
+            int startingAddress, 
+            int quantity
+        
+        ):
+            self.startingAddress = startingAddress
+            self.quantity = quantity
+
+
+        def build(
+        ) -> ModbusPDUReadCoilsRequest:
+            modbusPDUReadCoilsRequest: ModbusPDUReadCoilsRequest = ModbusPDUReadCoilsRequest(
+                startingAddress, 
+                quantity
+)
+            return modbusPDUReadCoilsRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadCoilsRequest):
+            return False
+
+        that: ModbusPDUReadCoilsRequest = ModbusPDUReadCoilsRequest(o)
+        return
+            (getStartingAddress() == that.getStartingAddress()) &&
+            (getQuantity() == that.getQuantity()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStartingAddress(),
+            getQuantity()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py
new file mode 100644
index 0000000000..f12d2bcdf3
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py
@@ -0,0 +1,146 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadCoilsResponse(PlcMessage,ModbusPDU):
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x01
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadCoilsResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadCoilsResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadCoilsResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadCoilsResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadCoilsResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUReadCoilsResponse")
+    # Create the instance
+        return ModbusPDUReadCoilsResponseBuilder(
+            value
+        
+        )
+
+        class ModbusPDUReadCoilsResponseBuilder(ModbusPDUModbusPDUBuilder {
+        value: byte[]
+
+        def ModbusPDUReadCoilsResponseBuilder(
+            byte[] value
+        
+        ):
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUReadCoilsResponse:
+            modbusPDUReadCoilsResponse: ModbusPDUReadCoilsResponse = ModbusPDUReadCoilsResponse(
+                value
+)
+            return modbusPDUReadCoilsResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadCoilsResponse):
+            return False
+
+        that: ModbusPDUReadCoilsResponse = ModbusPDUReadCoilsResponse(o)
+        return
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py
new file mode 100644
index 0000000000..8ce9eb87dd
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py
@@ -0,0 +1,167 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadDeviceIdentificationRequest(PlcMessage,ModbusPDU):
+            level: ModbusDeviceInformationLevel
+            objectId: short
+            MEITYPE: Short = 0x0E
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x2B
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getLevel(self) -> ModbusDeviceInformationLevel:
+        return level
+
+    def getObjectId(self) -> short:
+        return objectId
+
+    def getMeiType(self) -> short:
+        return MEITYPE
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadDeviceIdentificationRequest")
+
+                        # Const Field (meiType)
+                        writeConstField("meiType", MEITYPE, writeUnsignedShort(writeBuffer, 8))
+
+                        # Simple Field (level)
+                            writeSimpleEnumField("level", "ModbusDeviceInformationLevel", level, new DataWriterEnumDefault<>(ModbusDeviceInformationLevel::getValue, ModbusDeviceInformationLevel::name, writeUnsignedShort(writeBuffer, 8)))
+
+
+                        # Simple Field (objectId)
+                            writeSimpleField("objectId", objectId, writeUnsignedShort(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadDeviceIdentificationRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadDeviceIdentificationRequest = self
+
+        # Const Field (meiType)
+        lengthInBits += 8
+
+        # Simple field (level)
+        lengthInBits += 8
+
+        # Simple field (objectId)
+        lengthInBits += 8
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadDeviceIdentificationRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadDeviceIdentificationRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                meiType: short = readConstField("meiType", readUnsignedShort(readBuffer, 8), ModbusPDUReadDeviceIdentificationRequest.MEITYPE)
+
+                level: ModbusDeviceInformationLevel = readEnumField("level", "ModbusDeviceInformationLevel", new DataReaderEnumDefault<>(ModbusDeviceInformationLevel::enumForValue, readUnsignedShort(readBuffer, 8)))
+
+                objectId: short = readSimpleField("objectId", readUnsignedShort(readBuffer, 8))
+
+    readBuffer.closeContext("ModbusPDUReadDeviceIdentificationRequest")
+    # Create the instance
+        return ModbusPDUReadDeviceIdentificationRequestBuilder(
+            level, 
+            objectId
+        
+        )
+
+        class ModbusPDUReadDeviceIdentificationRequestBuilder(ModbusPDUModbusPDUBuilder {
+        level: ModbusDeviceInformationLevel
+        objectId: short
+
+        def ModbusPDUReadDeviceIdentificationRequestBuilder(
+            ModbusDeviceInformationLevel level, 
+            short objectId
+        
+        ):
+            self.level = level
+            self.objectId = objectId
+
+
+        def build(
+        ) -> ModbusPDUReadDeviceIdentificationRequest:
+            modbusPDUReadDeviceIdentificationRequest: ModbusPDUReadDeviceIdentificationRequest = ModbusPDUReadDeviceIdentificationRequest(
+                level, 
+                objectId
+)
+            return modbusPDUReadDeviceIdentificationRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadDeviceIdentificationRequest):
+            return False
+
+        that: ModbusPDUReadDeviceIdentificationRequest = ModbusPDUReadDeviceIdentificationRequest(o)
+        return
+            (getLevel() == that.getLevel()) &&
+            (getObjectId() == that.getObjectId()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getLevel(),
+            getObjectId()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py
new file mode 100644
index 0000000000..edb69b3a8c
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py
@@ -0,0 +1,260 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadDeviceIdentificationResponse(PlcMessage,ModbusPDU):
+            level: ModbusDeviceInformationLevel
+            individualAccess: boolean
+            conformityLevel: ModbusDeviceInformationConformityLevel
+            moreFollows: ModbusDeviceInformationMoreFollows
+            nextObjectId: short
+            objects: List<ModbusDeviceInformationObject>
+            MEITYPE: Short = 0x0E
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x2B
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getLevel(self) -> ModbusDeviceInformationLevel:
+        return level
+
+    def getIndividualAccess(self) -> boolean:
+        return individualAccess
+
+    def getConformityLevel(self) -> ModbusDeviceInformationConformityLevel:
+        return conformityLevel
+
+    def getMoreFollows(self) -> ModbusDeviceInformationMoreFollows:
+        return moreFollows
+
+    def getNextObjectId(self) -> short:
+        return nextObjectId
+
+    def getObjects(self) -> List<ModbusDeviceInformationObject>:
+        return objects
+
+    def getMeiType(self) -> short:
+        return MEITYPE
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadDeviceIdentificationResponse")
+
+                        # Const Field (meiType)
+                        writeConstField("meiType", MEITYPE, writeUnsignedShort(writeBuffer, 8))
+
+                        # Simple Field (level)
+                            writeSimpleEnumField("level", "ModbusDeviceInformationLevel", level, new DataWriterEnumDefault<>(ModbusDeviceInformationLevel::getValue, ModbusDeviceInformationLevel::name, writeUnsignedShort(writeBuffer, 8)))
+
+
+                        # Simple Field (individualAccess)
+                            writeSimpleField("individualAccess", individualAccess, writeBoolean(writeBuffer))
+
+                        # Simple Field (conformityLevel)
+                            writeSimpleEnumField("conformityLevel", "ModbusDeviceInformationConformityLevel", conformityLevel, new DataWriterEnumDefault<>(ModbusDeviceInformationConformityLevel::getValue, ModbusDeviceInformationConformityLevel::name, writeUnsignedShort(writeBuffer, 7)))
+
+
+                        # Simple Field (moreFollows)
+                            writeSimpleEnumField("moreFollows", "ModbusDeviceInformationMoreFollows", moreFollows, new DataWriterEnumDefault<>(ModbusDeviceInformationMoreFollows::getValue, ModbusDeviceInformationMoreFollows::name, writeUnsignedShort(writeBuffer, 8)))
+
+
+                        # Simple Field (nextObjectId)
+                            writeSimpleField("nextObjectId", nextObjectId, writeUnsignedShort(writeBuffer, 8))
+
+                        # Implicit Field (numberOfObjects) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short numberOfObjects = (short) (COUNT(getObjects()))
+                        writeImplicitField("numberOfObjects", numberOfObjects, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (objects)
+                        writeComplexTypeArrayField("objects", objects, writeBuffer)
+
+            writeBuffer.popContext("ModbusPDUReadDeviceIdentificationResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadDeviceIdentificationResponse = self
+
+        # Const Field (meiType)
+        lengthInBits += 8
+
+        # Simple field (level)
+        lengthInBits += 8
+
+        # Simple field (individualAccess)
+        lengthInBits += 1
+
+        # Simple field (conformityLevel)
+        lengthInBits += 7
+
+        # Simple field (moreFollows)
+        lengthInBits += 8
+
+        # Simple field (nextObjectId)
+        lengthInBits += 8
+
+        # Implicit Field (numberOfObjects)
+        lengthInBits += 8
+
+        # Array field
+        if objects is not None):
+            i: int = 0
+            for element in objects:
+                last: boolean = ++i >= objects.size()
+                lengthInBits += element.getLengthInBits()
+
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadDeviceIdentificationResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadDeviceIdentificationResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                meiType: short = readConstField("meiType", readUnsignedShort(readBuffer, 8), ModbusPDUReadDeviceIdentificationResponse.MEITYPE)
+
+                level: ModbusDeviceInformationLevel = readEnumField("level", "ModbusDeviceInformationLevel", new DataReaderEnumDefault<>(ModbusDeviceInformationLevel::enumForValue, readUnsignedShort(readBuffer, 8)))
+
+                individualAccess: boolean = readSimpleField("individualAccess", readBoolean(readBuffer))
+
+                conformityLevel: ModbusDeviceInformationConformityLevel = readEnumField("conformityLevel", "ModbusDeviceInformationConformityLevel", new DataReaderEnumDefault<>(ModbusDeviceInformationConformityLevel::enumForValue, readUnsignedShort(readBuffer, 7)))
+
+                moreFollows: ModbusDeviceInformationMoreFollows = readEnumField("moreFollows", "ModbusDeviceInformationMoreFollows", new DataReaderEnumDefault<>(ModbusDeviceInformationMoreFollows::enumForValue, readUnsignedShort(readBuffer, 8)))
+
+                nextObjectId: short = readSimpleField("nextObjectId", readUnsignedShort(readBuffer, 8))
+
+                numberOfObjects: short = readImplicitField("numberOfObjects", readUnsignedShort(readBuffer, 8))
+
+                        objects: List<ModbusDeviceInformationObject> = readCountArrayField("objects", new DataReaderComplexDefault<>(() -> ModbusDeviceInformationObject.staticParse(readBuffer), readBuffer), numberOfObjects)
+
+    readBuffer.closeContext("ModbusPDUReadDeviceIdentificationResponse")
+    # Create the instance
+        return ModbusPDUReadDeviceIdentificationResponseBuilder(
+            level, 
+            individualAccess, 
+            conformityLevel, 
+            moreFollows, 
+            nextObjectId, 
+            objects
+        
+        )
+
+        class ModbusPDUReadDeviceIdentificationResponseBuilder(ModbusPDUModbusPDUBuilder {
+        level: ModbusDeviceInformationLevel
+        individualAccess: boolean
+        conformityLevel: ModbusDeviceInformationConformityLevel
+        moreFollows: ModbusDeviceInformationMoreFollows
+        nextObjectId: short
+        objects: List<ModbusDeviceInformationObject>
+
+        def ModbusPDUReadDeviceIdentificationResponseBuilder(
+            ModbusDeviceInformationLevel level, 
+            boolean individualAccess, 
+            ModbusDeviceInformationConformityLevel conformityLevel, 
+            ModbusDeviceInformationMoreFollows moreFollows, 
+            short nextObjectId, 
+            List<ModbusDeviceInformationObject> objects
+        
+        ):
+            self.level = level
+            self.individualAccess = individualAccess
+            self.conformityLevel = conformityLevel
+            self.moreFollows = moreFollows
+            self.nextObjectId = nextObjectId
+            self.objects = objects
+
+
+        def build(
+        ) -> ModbusPDUReadDeviceIdentificationResponse:
+            modbusPDUReadDeviceIdentificationResponse: ModbusPDUReadDeviceIdentificationResponse = ModbusPDUReadDeviceIdentificationResponse(
+                level, 
+                individualAccess, 
+                conformityLevel, 
+                moreFollows, 
+                nextObjectId, 
+                objects
+)
+            return modbusPDUReadDeviceIdentificationResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadDeviceIdentificationResponse):
+            return False
+
+        that: ModbusPDUReadDeviceIdentificationResponse = ModbusPDUReadDeviceIdentificationResponse(o)
+        return
+            (getLevel() == that.getLevel()) &&
+            (getIndividualAccess() == that.getIndividualAccess()) &&
+            (getConformityLevel() == that.getConformityLevel()) &&
+            (getMoreFollows() == that.getMoreFollows()) &&
+            (getNextObjectId() == that.getNextObjectId()) &&
+            (getObjects() == that.getObjects()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getLevel(),
+            getIndividualAccess(),
+            getConformityLevel(),
+            getMoreFollows(),
+            getNextObjectId(),
+            getObjects()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py
new file mode 100644
index 0000000000..02f20e92ac
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadDiscreteInputsRequest(PlcMessage,ModbusPDU):
+            startingAddress: int
+            quantity: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x02
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStartingAddress(self) -> int:
+        return startingAddress
+
+    def getQuantity(self) -> int:
+        return quantity
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadDiscreteInputsRequest")
+
+                        # Simple Field (startingAddress)
+                            writeSimpleField("startingAddress", startingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (quantity)
+                            writeSimpleField("quantity", quantity, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUReadDiscreteInputsRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadDiscreteInputsRequest = self
+
+        # Simple field (startingAddress)
+        lengthInBits += 16
+
+        # Simple field (quantity)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadDiscreteInputsRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadDiscreteInputsRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                startingAddress: int = readSimpleField("startingAddress", readUnsignedInt(readBuffer, 16))
+
+                quantity: int = readSimpleField("quantity", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUReadDiscreteInputsRequest")
+    # Create the instance
+        return ModbusPDUReadDiscreteInputsRequestBuilder(
+            startingAddress, 
+            quantity
+        
+        )
+
+        class ModbusPDUReadDiscreteInputsRequestBuilder(ModbusPDUModbusPDUBuilder {
+        startingAddress: int
+        quantity: int
+
+        def ModbusPDUReadDiscreteInputsRequestBuilder(
+            int startingAddress, 
+            int quantity
+        
+        ):
+            self.startingAddress = startingAddress
+            self.quantity = quantity
+
+
+        def build(
+        ) -> ModbusPDUReadDiscreteInputsRequest:
+            modbusPDUReadDiscreteInputsRequest: ModbusPDUReadDiscreteInputsRequest = ModbusPDUReadDiscreteInputsRequest(
+                startingAddress, 
+                quantity
+)
+            return modbusPDUReadDiscreteInputsRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadDiscreteInputsRequest):
+            return False
+
+        that: ModbusPDUReadDiscreteInputsRequest = ModbusPDUReadDiscreteInputsRequest(o)
+        return
+            (getStartingAddress() == that.getStartingAddress()) &&
+            (getQuantity() == that.getQuantity()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStartingAddress(),
+            getQuantity()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py
new file mode 100644
index 0000000000..1fa4d3677b
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py
@@ -0,0 +1,146 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadDiscreteInputsResponse(PlcMessage,ModbusPDU):
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x02
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadDiscreteInputsResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadDiscreteInputsResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadDiscreteInputsResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadDiscreteInputsResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadDiscreteInputsResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUReadDiscreteInputsResponse")
+    # Create the instance
+        return ModbusPDUReadDiscreteInputsResponseBuilder(
+            value
+        
+        )
+
+        class ModbusPDUReadDiscreteInputsResponseBuilder(ModbusPDUModbusPDUBuilder {
+        value: byte[]
+
+        def ModbusPDUReadDiscreteInputsResponseBuilder(
+            byte[] value
+        
+        ):
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUReadDiscreteInputsResponse:
+            modbusPDUReadDiscreteInputsResponse: ModbusPDUReadDiscreteInputsResponse = ModbusPDUReadDiscreteInputsResponse(
+                value
+)
+            return modbusPDUReadDiscreteInputsResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadDiscreteInputsResponse):
+            return False
+
+        that: ModbusPDUReadDiscreteInputsResponse = ModbusPDUReadDiscreteInputsResponse(o)
+        return
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py
new file mode 100644
index 0000000000..f2b7b8f512
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py
@@ -0,0 +1,116 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadExceptionStatusRequest(PlcMessage,ModbusPDU):
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x07
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadExceptionStatusRequest")
+
+            writeBuffer.popContext("ModbusPDUReadExceptionStatusRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadExceptionStatusRequest = self
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadExceptionStatusRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadExceptionStatusRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+    readBuffer.closeContext("ModbusPDUReadExceptionStatusRequest")
+    # Create the instance
+        return ModbusPDUReadExceptionStatusRequestBuilder(
+        
+        )
+
+        class ModbusPDUReadExceptionStatusRequestBuilder(ModbusPDUModbusPDUBuilder {
+
+        def ModbusPDUReadExceptionStatusRequestBuilder(
+        
+        ):
+
+
+        def build(
+        ) -> ModbusPDUReadExceptionStatusRequest:
+            modbusPDUReadExceptionStatusRequest: ModbusPDUReadExceptionStatusRequest = ModbusPDUReadExceptionStatusRequest(
+)
+            return modbusPDUReadExceptionStatusRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadExceptionStatusRequest):
+            return False
+
+        that: ModbusPDUReadExceptionStatusRequest = ModbusPDUReadExceptionStatusRequest(o)
+        return
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py
new file mode 100644
index 0000000000..d111e3e43b
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py
@@ -0,0 +1,135 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadExceptionStatusResponse(PlcMessage,ModbusPDU):
+            value: short
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x07
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getValue(self) -> short:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadExceptionStatusResponse")
+
+                        # Simple Field (value)
+                            writeSimpleField("value", value, writeUnsignedShort(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadExceptionStatusResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadExceptionStatusResponse = self
+
+        # Simple field (value)
+        lengthInBits += 8
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadExceptionStatusResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadExceptionStatusResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                value: short = readSimpleField("value", readUnsignedShort(readBuffer, 8))
+
+    readBuffer.closeContext("ModbusPDUReadExceptionStatusResponse")
+    # Create the instance
+        return ModbusPDUReadExceptionStatusResponseBuilder(
+            value
+        
+        )
+
+        class ModbusPDUReadExceptionStatusResponseBuilder(ModbusPDUModbusPDUBuilder {
+        value: short
+
+        def ModbusPDUReadExceptionStatusResponseBuilder(
+            short value
+        
+        ):
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUReadExceptionStatusResponse:
+            modbusPDUReadExceptionStatusResponse: ModbusPDUReadExceptionStatusResponse = ModbusPDUReadExceptionStatusResponse(
+                value
+)
+            return modbusPDUReadExceptionStatusResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadExceptionStatusResponse):
+            return False
+
+        that: ModbusPDUReadExceptionStatusResponse = ModbusPDUReadExceptionStatusResponse(o)
+        return
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py
new file mode 100644
index 0000000000..c5957665e7
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py
@@ -0,0 +1,135 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadFifoQueueRequest(PlcMessage,ModbusPDU):
+            fifoPointerAddress: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x18
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getFifoPointerAddress(self) -> int:
+        return fifoPointerAddress
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadFifoQueueRequest")
+
+                        # Simple Field (fifoPointerAddress)
+                            writeSimpleField("fifoPointerAddress", fifoPointerAddress, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUReadFifoQueueRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadFifoQueueRequest = self
+
+        # Simple field (fifoPointerAddress)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadFifoQueueRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadFifoQueueRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                fifoPointerAddress: int = readSimpleField("fifoPointerAddress", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUReadFifoQueueRequest")
+    # Create the instance
+        return ModbusPDUReadFifoQueueRequestBuilder(
+            fifoPointerAddress
+        
+        )
+
+        class ModbusPDUReadFifoQueueRequestBuilder(ModbusPDUModbusPDUBuilder {
+        fifoPointerAddress: int
+
+        def ModbusPDUReadFifoQueueRequestBuilder(
+            int fifoPointerAddress
+        
+        ):
+            self.fifoPointerAddress = fifoPointerAddress
+
+
+        def build(
+        ) -> ModbusPDUReadFifoQueueRequest:
+            modbusPDUReadFifoQueueRequest: ModbusPDUReadFifoQueueRequest = ModbusPDUReadFifoQueueRequest(
+                fifoPointerAddress
+)
+            return modbusPDUReadFifoQueueRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadFifoQueueRequest):
+            return False
+
+        that: ModbusPDUReadFifoQueueRequest = ModbusPDUReadFifoQueueRequest(o)
+        return
+            (getFifoPointerAddress() == that.getFifoPointerAddress()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getFifoPointerAddress()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py
new file mode 100644
index 0000000000..85c96b36da
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py
@@ -0,0 +1,155 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadFifoQueueResponse(PlcMessage,ModbusPDU):
+            fifoValue: List<Integer>
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x18
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getFifoValue(self) -> List<Integer>:
+        return fifoValue
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadFifoQueueResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        int byteCount = (int) ((((COUNT(getFifoValue())) * (2))) + (2))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedInt(writeBuffer, 16))
+
+                        # Implicit Field (fifoCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        int fifoCount = (int) ((((COUNT(getFifoValue())) * (2))) / (2))
+                        writeImplicitField("fifoCount", fifoCount, writeUnsignedInt(writeBuffer, 16))
+
+                        # Array Field (fifoValue)
+                        writeSimpleTypeArrayField("fifoValue", fifoValue, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUReadFifoQueueResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadFifoQueueResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 16
+
+        # Implicit Field (fifoCount)
+        lengthInBits += 16
+
+        # Array field
+        if fifoValue is not None):
+            lengthInBits += 16 * fifoValue.size()
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadFifoQueueResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadFifoQueueResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: int = readImplicitField("byteCount", readUnsignedInt(readBuffer, 16))
+
+                fifoCount: int = readImplicitField("fifoCount", readUnsignedInt(readBuffer, 16))
+
+                        fifoValue: List<Integer> = readCountArrayField("fifoValue", readUnsignedInt(readBuffer, 16), fifoCount)
+
+    readBuffer.closeContext("ModbusPDUReadFifoQueueResponse")
+    # Create the instance
+        return ModbusPDUReadFifoQueueResponseBuilder(
+            fifoValue
+        
+        )
+
+        class ModbusPDUReadFifoQueueResponseBuilder(ModbusPDUModbusPDUBuilder {
+        fifoValue: List<Integer>
+
+        def ModbusPDUReadFifoQueueResponseBuilder(
+            List<Integer> fifoValue
+        
+        ):
+            self.fifoValue = fifoValue
+
+
+        def build(
+        ) -> ModbusPDUReadFifoQueueResponse:
+            modbusPDUReadFifoQueueResponse: ModbusPDUReadFifoQueueResponse = ModbusPDUReadFifoQueueResponse(
+                fifoValue
+)
+            return modbusPDUReadFifoQueueResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadFifoQueueResponse):
+            return False
+
+        that: ModbusPDUReadFifoQueueResponse = ModbusPDUReadFifoQueueResponse(o)
+        return
+            (getFifoValue() == that.getFifoValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getFifoValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py
new file mode 100644
index 0000000000..aef470570f
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py
@@ -0,0 +1,148 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadFileRecordRequest(PlcMessage,ModbusPDU):
+            items: List<ModbusPDUReadFileRecordRequestItem>
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x14
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getItems(self) -> List<ModbusPDUReadFileRecordRequestItem>:
+        return items
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadFileRecordRequest")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (ARRAY_SIZE_IN_BYTES(getItems()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (items)
+                        writeComplexTypeArrayField("items", items, writeBuffer)
+
+            writeBuffer.popContext("ModbusPDUReadFileRecordRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadFileRecordRequest = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if items is not None):
+            for element in items:
+                lengthInBits += element.getLengthInBits()
+
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadFileRecordRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadFileRecordRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                            items: List<ModbusPDUReadFileRecordRequestItem> = readLengthArrayField("items", new DataReaderComplexDefault<>(() -> ModbusPDUReadFileRecordRequestItem.staticParse(readBuffer), readBuffer), byteCount)
+
+    readBuffer.closeContext("ModbusPDUReadFileRecordRequest")
+    # Create the instance
+        return ModbusPDUReadFileRecordRequestBuilder(
+            items
+        
+        )
+
+        class ModbusPDUReadFileRecordRequestBuilder(ModbusPDUModbusPDUBuilder {
+        items: List<ModbusPDUReadFileRecordRequestItem>
+
+        def ModbusPDUReadFileRecordRequestBuilder(
+            List<ModbusPDUReadFileRecordRequestItem> items
+        
+        ):
+            self.items = items
+
+
+        def build(
+        ) -> ModbusPDUReadFileRecordRequest:
+            modbusPDUReadFileRecordRequest: ModbusPDUReadFileRecordRequest = ModbusPDUReadFileRecordRequest(
+                items
+)
+            return modbusPDUReadFileRecordRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadFileRecordRequest):
+            return False
+
+        that: ModbusPDUReadFileRecordRequest = ModbusPDUReadFileRecordRequest(o)
+        return
+            (getItems() == that.getItems()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getItems()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py
new file mode 100644
index 0000000000..9291e86a3d
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py
@@ -0,0 +1,156 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadFileRecordRequestItem(PlcMessage):
+            referenceType: short
+            fileNumber: int
+            recordNumber: int
+            recordLength: int
+
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getReferenceType(self) -> short:
+        return referenceType
+
+    def getFileNumber(self) -> int:
+        return fileNumber
+
+    def getRecordNumber(self) -> int:
+        return recordNumber
+
+    def getRecordLength(self) -> int:
+        return recordLength
+
+
+    def serialize(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadFileRecordRequestItem")
+
+                        # Simple Field (referenceType)
+                            writeSimpleField("referenceType", referenceType, writeUnsignedShort(writeBuffer, 8))
+
+                        # Simple Field (fileNumber)
+                            writeSimpleField("fileNumber", fileNumber, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (recordNumber)
+                            writeSimpleField("recordNumber", recordNumber, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (recordLength)
+                            writeSimpleField("recordLength", recordLength, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUReadFileRecordRequestItem")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = 0
+        _value: ModbusPDUReadFileRecordRequestItem = self
+
+        # Simple field (referenceType)
+        lengthInBits += 8
+
+        # Simple field (fileNumber)
+        lengthInBits += 16
+
+        # Simple field (recordNumber)
+        lengthInBits += 16
+
+        # Simple field (recordLength)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def staticParse(readBuffer: ReadBuffer , args) -> ModbusPDUReadFileRecordRequestItem:
+        positionAware: PositionAware = readBuffer
+        return staticParse(readBuffer)
+    }
+
+    def  staticParse(readBuffer: ReadBuffer) -> ModbusPDUReadFileRecordRequestItem:
+        readBuffer.pullContext("ModbusPDUReadFileRecordRequestItem")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                referenceType: short = readSimpleField("referenceType", readUnsignedShort(readBuffer, 8))
+
+                fileNumber: int = readSimpleField("fileNumber", readUnsignedInt(readBuffer, 16))
+
+                recordNumber: int = readSimpleField("recordNumber", readUnsignedInt(readBuffer, 16))
+
+                recordLength: int = readSimpleField("recordLength", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUReadFileRecordRequestItem")
+    # Create the instance
+        _modbusPDUReadFileRecordRequestItem: ModbusPDUReadFileRecordRequestItem = ModbusPDUReadFileRecordRequestItem(
+            referenceType, 
+            fileNumber, 
+            recordNumber, 
+            recordLength
+        )
+        return _modbusPDUReadFileRecordRequestItem
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadFileRecordRequestItem):
+            return False
+
+        that: ModbusPDUReadFileRecordRequestItem = ModbusPDUReadFileRecordRequestItem(o)
+        return
+            (getReferenceType() == that.getReferenceType()) &&
+            (getFileNumber() == that.getFileNumber()) &&
+            (getRecordNumber() == that.getRecordNumber()) &&
+            (getRecordLength() == that.getRecordLength()) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            getReferenceType(),
+            getFileNumber(),
+            getRecordNumber(),
+            getRecordLength()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py
new file mode 100644
index 0000000000..e9d33e9ddf
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py
@@ -0,0 +1,148 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadFileRecordResponse(PlcMessage,ModbusPDU):
+            items: List<ModbusPDUReadFileRecordResponseItem>
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x14
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getItems(self) -> List<ModbusPDUReadFileRecordResponseItem>:
+        return items
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadFileRecordResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (ARRAY_SIZE_IN_BYTES(getItems()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (items)
+                        writeComplexTypeArrayField("items", items, writeBuffer)
+
+            writeBuffer.popContext("ModbusPDUReadFileRecordResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadFileRecordResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if items is not None):
+            for element in items:
+                lengthInBits += element.getLengthInBits()
+
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadFileRecordResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadFileRecordResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                            items: List<ModbusPDUReadFileRecordResponseItem> = readLengthArrayField("items", new DataReaderComplexDefault<>(() -> ModbusPDUReadFileRecordResponseItem.staticParse(readBuffer), readBuffer), byteCount)
+
+    readBuffer.closeContext("ModbusPDUReadFileRecordResponse")
+    # Create the instance
+        return ModbusPDUReadFileRecordResponseBuilder(
+            items
+        
+        )
+
+        class ModbusPDUReadFileRecordResponseBuilder(ModbusPDUModbusPDUBuilder {
+        items: List<ModbusPDUReadFileRecordResponseItem>
+
+        def ModbusPDUReadFileRecordResponseBuilder(
+            List<ModbusPDUReadFileRecordResponseItem> items
+        
+        ):
+            self.items = items
+
+
+        def build(
+        ) -> ModbusPDUReadFileRecordResponse:
+            modbusPDUReadFileRecordResponse: ModbusPDUReadFileRecordResponse = ModbusPDUReadFileRecordResponse(
+                items
+)
+            return modbusPDUReadFileRecordResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadFileRecordResponse):
+            return False
+
+        that: ModbusPDUReadFileRecordResponse = ModbusPDUReadFileRecordResponse(o)
+        return
+            (getItems() == that.getItems()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getItems()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py
new file mode 100644
index 0000000000..9ec3b9287d
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py
@@ -0,0 +1,137 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadFileRecordResponseItem(PlcMessage):
+            referenceType: short
+            data: byte[]
+
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getReferenceType(self) -> short:
+        return referenceType
+
+    def getData(self) -> byte[]:
+        return data
+
+
+    def serialize(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadFileRecordResponseItem")
+
+                        # Implicit Field (dataLength) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short dataLength = (short) ((COUNT(getData())) + (1))
+                        writeImplicitField("dataLength", dataLength, writeUnsignedShort(writeBuffer, 8))
+
+                        # Simple Field (referenceType)
+                            writeSimpleField("referenceType", referenceType, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (data)
+                        writeByteArrayField("data", data, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadFileRecordResponseItem")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = 0
+        _value: ModbusPDUReadFileRecordResponseItem = self
+
+        # Implicit Field (dataLength)
+        lengthInBits += 8
+
+        # Simple field (referenceType)
+        lengthInBits += 8
+
+        # Array field
+        if data is not None):
+            lengthInBits += 8 * data.length
+
+
+        return lengthInBits
+
+
+    def staticParse(readBuffer: ReadBuffer , args) -> ModbusPDUReadFileRecordResponseItem:
+        positionAware: PositionAware = readBuffer
+        return staticParse(readBuffer)
+    }
+
+    def  staticParse(readBuffer: ReadBuffer) -> ModbusPDUReadFileRecordResponseItem:
+        readBuffer.pullContext("ModbusPDUReadFileRecordResponseItem")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                dataLength: short = readImplicitField("dataLength", readUnsignedShort(readBuffer, 8))
+
+                referenceType: short = readSimpleField("referenceType", readUnsignedShort(readBuffer, 8))
+
+                    data: byte[] = readBuffer.readByteArray("data", Math.toIntExact((dataLength) - (1)))
+
+    readBuffer.closeContext("ModbusPDUReadFileRecordResponseItem")
+    # Create the instance
+        _modbusPDUReadFileRecordResponseItem: ModbusPDUReadFileRecordResponseItem = ModbusPDUReadFileRecordResponseItem(
+            referenceType, 
+            data
+        )
+        return _modbusPDUReadFileRecordResponseItem
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadFileRecordResponseItem):
+            return False
+
+        that: ModbusPDUReadFileRecordResponseItem = ModbusPDUReadFileRecordResponseItem(o)
+        return
+            (getReferenceType() == that.getReferenceType()) &&
+            (getData() == that.getData()) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            getReferenceType(),
+            getData()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py
new file mode 100644
index 0000000000..ffb48029a5
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadHoldingRegistersRequest(PlcMessage,ModbusPDU):
+            startingAddress: int
+            quantity: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x03
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStartingAddress(self) -> int:
+        return startingAddress
+
+    def getQuantity(self) -> int:
+        return quantity
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadHoldingRegistersRequest")
+
+                        # Simple Field (startingAddress)
+                            writeSimpleField("startingAddress", startingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (quantity)
+                            writeSimpleField("quantity", quantity, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUReadHoldingRegistersRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadHoldingRegistersRequest = self
+
+        # Simple field (startingAddress)
+        lengthInBits += 16
+
+        # Simple field (quantity)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadHoldingRegistersRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadHoldingRegistersRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                startingAddress: int = readSimpleField("startingAddress", readUnsignedInt(readBuffer, 16))
+
+                quantity: int = readSimpleField("quantity", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUReadHoldingRegistersRequest")
+    # Create the instance
+        return ModbusPDUReadHoldingRegistersRequestBuilder(
+            startingAddress, 
+            quantity
+        
+        )
+
+        class ModbusPDUReadHoldingRegistersRequestBuilder(ModbusPDUModbusPDUBuilder {
+        startingAddress: int
+        quantity: int
+
+        def ModbusPDUReadHoldingRegistersRequestBuilder(
+            int startingAddress, 
+            int quantity
+        
+        ):
+            self.startingAddress = startingAddress
+            self.quantity = quantity
+
+
+        def build(
+        ) -> ModbusPDUReadHoldingRegistersRequest:
+            modbusPDUReadHoldingRegistersRequest: ModbusPDUReadHoldingRegistersRequest = ModbusPDUReadHoldingRegistersRequest(
+                startingAddress, 
+                quantity
+)
+            return modbusPDUReadHoldingRegistersRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadHoldingRegistersRequest):
+            return False
+
+        that: ModbusPDUReadHoldingRegistersRequest = ModbusPDUReadHoldingRegistersRequest(o)
+        return
+            (getStartingAddress() == that.getStartingAddress()) &&
+            (getQuantity() == that.getQuantity()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStartingAddress(),
+            getQuantity()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py
new file mode 100644
index 0000000000..4465769f54
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py
@@ -0,0 +1,146 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadHoldingRegistersResponse(PlcMessage,ModbusPDU):
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x03
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadHoldingRegistersResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadHoldingRegistersResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadHoldingRegistersResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadHoldingRegistersResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadHoldingRegistersResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUReadHoldingRegistersResponse")
+    # Create the instance
+        return ModbusPDUReadHoldingRegistersResponseBuilder(
+            value
+        
+        )
+
+        class ModbusPDUReadHoldingRegistersResponseBuilder(ModbusPDUModbusPDUBuilder {
+        value: byte[]
+
+        def ModbusPDUReadHoldingRegistersResponseBuilder(
+            byte[] value
+        
+        ):
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUReadHoldingRegistersResponse:
+            modbusPDUReadHoldingRegistersResponse: ModbusPDUReadHoldingRegistersResponse = ModbusPDUReadHoldingRegistersResponse(
+                value
+)
+            return modbusPDUReadHoldingRegistersResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadHoldingRegistersResponse):
+            return False
+
+        that: ModbusPDUReadHoldingRegistersResponse = ModbusPDUReadHoldingRegistersResponse(o)
+        return
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py
new file mode 100644
index 0000000000..0176f8cc77
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadInputRegistersRequest(PlcMessage,ModbusPDU):
+            startingAddress: int
+            quantity: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x04
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStartingAddress(self) -> int:
+        return startingAddress
+
+    def getQuantity(self) -> int:
+        return quantity
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadInputRegistersRequest")
+
+                        # Simple Field (startingAddress)
+                            writeSimpleField("startingAddress", startingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (quantity)
+                            writeSimpleField("quantity", quantity, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUReadInputRegistersRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadInputRegistersRequest = self
+
+        # Simple field (startingAddress)
+        lengthInBits += 16
+
+        # Simple field (quantity)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadInputRegistersRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadInputRegistersRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                startingAddress: int = readSimpleField("startingAddress", readUnsignedInt(readBuffer, 16))
+
+                quantity: int = readSimpleField("quantity", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUReadInputRegistersRequest")
+    # Create the instance
+        return ModbusPDUReadInputRegistersRequestBuilder(
+            startingAddress, 
+            quantity
+        
+        )
+
+        class ModbusPDUReadInputRegistersRequestBuilder(ModbusPDUModbusPDUBuilder {
+        startingAddress: int
+        quantity: int
+
+        def ModbusPDUReadInputRegistersRequestBuilder(
+            int startingAddress, 
+            int quantity
+        
+        ):
+            self.startingAddress = startingAddress
+            self.quantity = quantity
+
+
+        def build(
+        ) -> ModbusPDUReadInputRegistersRequest:
+            modbusPDUReadInputRegistersRequest: ModbusPDUReadInputRegistersRequest = ModbusPDUReadInputRegistersRequest(
+                startingAddress, 
+                quantity
+)
+            return modbusPDUReadInputRegistersRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadInputRegistersRequest):
+            return False
+
+        that: ModbusPDUReadInputRegistersRequest = ModbusPDUReadInputRegistersRequest(o)
+        return
+            (getStartingAddress() == that.getStartingAddress()) &&
+            (getQuantity() == that.getQuantity()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStartingAddress(),
+            getQuantity()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py
new file mode 100644
index 0000000000..eaac7ed2d7
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py
@@ -0,0 +1,146 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadInputRegistersResponse(PlcMessage,ModbusPDU):
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x04
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadInputRegistersResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadInputRegistersResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadInputRegistersResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadInputRegistersResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadInputRegistersResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUReadInputRegistersResponse")
+    # Create the instance
+        return ModbusPDUReadInputRegistersResponseBuilder(
+            value
+        
+        )
+
+        class ModbusPDUReadInputRegistersResponseBuilder(ModbusPDUModbusPDUBuilder {
+        value: byte[]
+
+        def ModbusPDUReadInputRegistersResponseBuilder(
+            byte[] value
+        
+        ):
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUReadInputRegistersResponse:
+            modbusPDUReadInputRegistersResponse: ModbusPDUReadInputRegistersResponse = ModbusPDUReadInputRegistersResponse(
+                value
+)
+            return modbusPDUReadInputRegistersResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadInputRegistersResponse):
+            return False
+
+        that: ModbusPDUReadInputRegistersResponse = ModbusPDUReadInputRegistersResponse(o)
+        return
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py
new file mode 100644
index 0000000000..4c7e95eb11
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py
@@ -0,0 +1,222 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadWriteMultipleHoldingRegistersRequest(PlcMessage,ModbusPDU):
+            readStartingAddress: int
+            readQuantity: int
+            writeStartingAddress: int
+            writeQuantity: int
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x17
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getReadStartingAddress(self) -> int:
+        return readStartingAddress
+
+    def getReadQuantity(self) -> int:
+        return readQuantity
+
+    def getWriteStartingAddress(self) -> int:
+        return writeStartingAddress
+
+    def getWriteQuantity(self) -> int:
+        return writeQuantity
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadWriteMultipleHoldingRegistersRequest")
+
+                        # Simple Field (readStartingAddress)
+                            writeSimpleField("readStartingAddress", readStartingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (readQuantity)
+                            writeSimpleField("readQuantity", readQuantity, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (writeStartingAddress)
+                            writeSimpleField("writeStartingAddress", writeStartingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (writeQuantity)
+                            writeSimpleField("writeQuantity", writeQuantity, writeUnsignedInt(writeBuffer, 16))
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadWriteMultipleHoldingRegistersRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadWriteMultipleHoldingRegistersRequest = self
+
+        # Simple field (readStartingAddress)
+        lengthInBits += 16
+
+        # Simple field (readQuantity)
+        lengthInBits += 16
+
+        # Simple field (writeStartingAddress)
+        lengthInBits += 16
+
+        # Simple field (writeQuantity)
+        lengthInBits += 16
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadWriteMultipleHoldingRegistersRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReadWriteMultipleHoldingRegistersRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                readStartingAddress: int = readSimpleField("readStartingAddress", readUnsignedInt(readBuffer, 16))
+
+                readQuantity: int = readSimpleField("readQuantity", readUnsignedInt(readBuffer, 16))
+
+                writeStartingAddress: int = readSimpleField("writeStartingAddress", readUnsignedInt(readBuffer, 16))
+
+                writeQuantity: int = readSimpleField("writeQuantity", readUnsignedInt(readBuffer, 16))
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUReadWriteMultipleHoldingRegistersRequest")
+    # Create the instance
+        return ModbusPDUReadWriteMultipleHoldingRegistersRequestBuilder(
+            readStartingAddress, 
+            readQuantity, 
+            writeStartingAddress, 
+            writeQuantity, 
+            value
+        
+        )
+
+        class ModbusPDUReadWriteMultipleHoldingRegistersRequestBuilder(ModbusPDUModbusPDUBuilder {
+        readStartingAddress: int
+        readQuantity: int
+        writeStartingAddress: int
+        writeQuantity: int
+        value: byte[]
+
+        def ModbusPDUReadWriteMultipleHoldingRegistersRequestBuilder(
+            int readStartingAddress, 
+            int readQuantity, 
+            int writeStartingAddress, 
+            int writeQuantity, 
+            byte[] value
+        
+        ):
+            self.readStartingAddress = readStartingAddress
+            self.readQuantity = readQuantity
+            self.writeStartingAddress = writeStartingAddress
+            self.writeQuantity = writeQuantity
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUReadWriteMultipleHoldingRegistersRequest:
+            modbusPDUReadWriteMultipleHoldingRegistersRequest: ModbusPDUReadWriteMultipleHoldingRegistersRequest = ModbusPDUReadWriteMultipleHoldingRegistersRequest(
+                readStartingAddress, 
+                readQuantity, 
+                writeStartingAddress, 
+                writeQuantity, 
+                value
+)
+            return modbusPDUReadWriteMultipleHoldingRegistersRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadWriteMultipleHoldingRegistersRequest):
+            return False
+
+        that: ModbusPDUReadWriteMultipleHoldingRegistersRequest = ModbusPDUReadWriteMultipleHoldingRegistersRequest(o)
+        return
+            (getReadStartingAddress() == that.getReadStartingAddress()) &&
+            (getReadQuantity() == that.getReadQuantity()) &&
+            (getWriteStartingAddress() == that.getWriteStartingAddress()) &&
+            (getWriteQuantity() == that.getWriteQuantity()) &&
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getReadStartingAddress(),
+            getReadQuantity(),
+            getWriteStartingAddress(),
+            getWriteQuantity(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py
new file mode 100644
index 0000000000..2023093204
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py
@@ -0,0 +1,146 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReadWriteMultipleHoldingRegistersResponse(PlcMessage,ModbusPDU):
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x17
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReadWriteMultipleHoldingRegistersResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReadWriteMultipleHoldingRegistersResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReadWriteMultipleHoldingRegistersResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReadWriteMultipleHoldingRegistersResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReadWriteMultipleHoldingRegistersResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUReadWriteMultipleHoldingRegistersResponse")
+    # Create the instance
+        return ModbusPDUReadWriteMultipleHoldingRegistersResponseBuilder(
+            value
+        
+        )
+
+        class ModbusPDUReadWriteMultipleHoldingRegistersResponseBuilder(ModbusPDUModbusPDUBuilder {
+        value: byte[]
+
+        def ModbusPDUReadWriteMultipleHoldingRegistersResponseBuilder(
+            byte[] value
+        
+        ):
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUReadWriteMultipleHoldingRegistersResponse:
+            modbusPDUReadWriteMultipleHoldingRegistersResponse: ModbusPDUReadWriteMultipleHoldingRegistersResponse = ModbusPDUReadWriteMultipleHoldingRegistersResponse(
+                value
+)
+            return modbusPDUReadWriteMultipleHoldingRegistersResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReadWriteMultipleHoldingRegistersResponse):
+            return False
+
+        that: ModbusPDUReadWriteMultipleHoldingRegistersResponse = ModbusPDUReadWriteMultipleHoldingRegistersResponse(o)
+        return
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py
new file mode 100644
index 0000000000..1581d6a059
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py
@@ -0,0 +1,116 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReportServerIdRequest(PlcMessage,ModbusPDU):
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x11
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReportServerIdRequest")
+
+            writeBuffer.popContext("ModbusPDUReportServerIdRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReportServerIdRequest = self
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReportServerIdRequestBuilder:
+        readBuffer.pullContext("ModbusPDUReportServerIdRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+    readBuffer.closeContext("ModbusPDUReportServerIdRequest")
+    # Create the instance
+        return ModbusPDUReportServerIdRequestBuilder(
+        
+        )
+
+        class ModbusPDUReportServerIdRequestBuilder(ModbusPDUModbusPDUBuilder {
+
+        def ModbusPDUReportServerIdRequestBuilder(
+        
+        ):
+
+
+        def build(
+        ) -> ModbusPDUReportServerIdRequest:
+            modbusPDUReportServerIdRequest: ModbusPDUReportServerIdRequest = ModbusPDUReportServerIdRequest(
+)
+            return modbusPDUReportServerIdRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReportServerIdRequest):
+            return False
+
+        that: ModbusPDUReportServerIdRequest = ModbusPDUReportServerIdRequest(o)
+        return
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py
new file mode 100644
index 0000000000..6db466aeb2
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py
@@ -0,0 +1,146 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUReportServerIdResponse(PlcMessage,ModbusPDU):
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x11
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUReportServerIdResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUReportServerIdResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUReportServerIdResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUReportServerIdResponseBuilder:
+        readBuffer.pullContext("ModbusPDUReportServerIdResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUReportServerIdResponse")
+    # Create the instance
+        return ModbusPDUReportServerIdResponseBuilder(
+            value
+        
+        )
+
+        class ModbusPDUReportServerIdResponseBuilder(ModbusPDUModbusPDUBuilder {
+        value: byte[]
+
+        def ModbusPDUReportServerIdResponseBuilder(
+            byte[] value
+        
+        ):
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUReportServerIdResponse:
+            modbusPDUReportServerIdResponse: ModbusPDUReportServerIdResponse = ModbusPDUReportServerIdResponse(
+                value
+)
+            return modbusPDUReportServerIdResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUReportServerIdResponse):
+            return False
+
+        that: ModbusPDUReportServerIdResponse = ModbusPDUReportServerIdResponse(o)
+        return
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py
new file mode 100644
index 0000000000..90a303d45e
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py
@@ -0,0 +1,148 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteFileRecordRequest(PlcMessage,ModbusPDU):
+            items: List<ModbusPDUWriteFileRecordRequestItem>
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x15
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getItems(self) -> List<ModbusPDUWriteFileRecordRequestItem>:
+        return items
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteFileRecordRequest")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (ARRAY_SIZE_IN_BYTES(getItems()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (items)
+                        writeComplexTypeArrayField("items", items, writeBuffer)
+
+            writeBuffer.popContext("ModbusPDUWriteFileRecordRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteFileRecordRequest = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if items is not None):
+            for element in items:
+                lengthInBits += element.getLengthInBits()
+
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteFileRecordRequestBuilder:
+        readBuffer.pullContext("ModbusPDUWriteFileRecordRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                            items: List<ModbusPDUWriteFileRecordRequestItem> = readLengthArrayField("items", new DataReaderComplexDefault<>(() -> ModbusPDUWriteFileRecordRequestItem.staticParse(readBuffer), readBuffer), byteCount)
+
+    readBuffer.closeContext("ModbusPDUWriteFileRecordRequest")
+    # Create the instance
+        return ModbusPDUWriteFileRecordRequestBuilder(
+            items
+        
+        )
+
+        class ModbusPDUWriteFileRecordRequestBuilder(ModbusPDUModbusPDUBuilder {
+        items: List<ModbusPDUWriteFileRecordRequestItem>
+
+        def ModbusPDUWriteFileRecordRequestBuilder(
+            List<ModbusPDUWriteFileRecordRequestItem> items
+        
+        ):
+            self.items = items
+
+
+        def build(
+        ) -> ModbusPDUWriteFileRecordRequest:
+            modbusPDUWriteFileRecordRequest: ModbusPDUWriteFileRecordRequest = ModbusPDUWriteFileRecordRequest(
+                items
+)
+            return modbusPDUWriteFileRecordRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteFileRecordRequest):
+            return False
+
+        that: ModbusPDUWriteFileRecordRequest = ModbusPDUWriteFileRecordRequest(o)
+        return
+            (getItems() == that.getItems()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getItems()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py
new file mode 100644
index 0000000000..13426eaeee
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py
@@ -0,0 +1,167 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteFileRecordRequestItem(PlcMessage):
+            referenceType: short
+            fileNumber: int
+            recordNumber: int
+            recordData: byte[]
+
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getReferenceType(self) -> short:
+        return referenceType
+
+    def getFileNumber(self) -> int:
+        return fileNumber
+
+    def getRecordNumber(self) -> int:
+        return recordNumber
+
+    def getRecordData(self) -> byte[]:
+        return recordData
+
+
+    def serialize(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteFileRecordRequestItem")
+
+                        # Simple Field (referenceType)
+                            writeSimpleField("referenceType", referenceType, writeUnsignedShort(writeBuffer, 8))
+
+                        # Simple Field (fileNumber)
+                            writeSimpleField("fileNumber", fileNumber, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (recordNumber)
+                            writeSimpleField("recordNumber", recordNumber, writeUnsignedInt(writeBuffer, 16))
+
+                        # Implicit Field (recordLength) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        int recordLength = (int) ((COUNT(getRecordData())) / (2))
+                        writeImplicitField("recordLength", recordLength, writeUnsignedInt(writeBuffer, 16))
+
+                        # Array Field (recordData)
+                        writeByteArrayField("recordData", recordData, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUWriteFileRecordRequestItem")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = 0
+        _value: ModbusPDUWriteFileRecordRequestItem = self
+
+        # Simple field (referenceType)
+        lengthInBits += 8
+
+        # Simple field (fileNumber)
+        lengthInBits += 16
+
+        # Simple field (recordNumber)
+        lengthInBits += 16
+
+        # Implicit Field (recordLength)
+        lengthInBits += 16
+
+        # Array field
+        if recordData is not None):
+            lengthInBits += 8 * recordData.length
+
+
+        return lengthInBits
+
+
+    def staticParse(readBuffer: ReadBuffer , args) -> ModbusPDUWriteFileRecordRequestItem:
+        positionAware: PositionAware = readBuffer
+        return staticParse(readBuffer)
+    }
+
+    def  staticParse(readBuffer: ReadBuffer) -> ModbusPDUWriteFileRecordRequestItem:
+        readBuffer.pullContext("ModbusPDUWriteFileRecordRequestItem")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                referenceType: short = readSimpleField("referenceType", readUnsignedShort(readBuffer, 8))
+
+                fileNumber: int = readSimpleField("fileNumber", readUnsignedInt(readBuffer, 16))
+
+                recordNumber: int = readSimpleField("recordNumber", readUnsignedInt(readBuffer, 16))
+
+                recordLength: int = readImplicitField("recordLength", readUnsignedInt(readBuffer, 16))
+
+                    recordData: byte[] = readBuffer.readByteArray("recordData", Math.toIntExact((recordLength) * (2)))
+
+    readBuffer.closeContext("ModbusPDUWriteFileRecordRequestItem")
+    # Create the instance
+        _modbusPDUWriteFileRecordRequestItem: ModbusPDUWriteFileRecordRequestItem = ModbusPDUWriteFileRecordRequestItem(
+            referenceType, 
+            fileNumber, 
+            recordNumber, 
+            recordData
+        )
+        return _modbusPDUWriteFileRecordRequestItem
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteFileRecordRequestItem):
+            return False
+
+        that: ModbusPDUWriteFileRecordRequestItem = ModbusPDUWriteFileRecordRequestItem(o)
+        return
+            (getReferenceType() == that.getReferenceType()) &&
+            (getFileNumber() == that.getFileNumber()) &&
+            (getRecordNumber() == that.getRecordNumber()) &&
+            (getRecordData() == that.getRecordData()) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            getReferenceType(),
+            getFileNumber(),
+            getRecordNumber(),
+            getRecordData()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py
new file mode 100644
index 0000000000..6f808a6167
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py
@@ -0,0 +1,148 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteFileRecordResponse(PlcMessage,ModbusPDU):
+            items: List<ModbusPDUWriteFileRecordResponseItem>
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x15
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getItems(self) -> List<ModbusPDUWriteFileRecordResponseItem>:
+        return items
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteFileRecordResponse")
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (ARRAY_SIZE_IN_BYTES(getItems()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (items)
+                        writeComplexTypeArrayField("items", items, writeBuffer)
+
+            writeBuffer.popContext("ModbusPDUWriteFileRecordResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteFileRecordResponse = self
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if items is not None):
+            for element in items:
+                lengthInBits += element.getLengthInBits()
+
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteFileRecordResponseBuilder:
+        readBuffer.pullContext("ModbusPDUWriteFileRecordResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                            items: List<ModbusPDUWriteFileRecordResponseItem> = readLengthArrayField("items", new DataReaderComplexDefault<>(() -> ModbusPDUWriteFileRecordResponseItem.staticParse(readBuffer), readBuffer), byteCount)
+
+    readBuffer.closeContext("ModbusPDUWriteFileRecordResponse")
+    # Create the instance
+        return ModbusPDUWriteFileRecordResponseBuilder(
+            items
+        
+        )
+
+        class ModbusPDUWriteFileRecordResponseBuilder(ModbusPDUModbusPDUBuilder {
+        items: List<ModbusPDUWriteFileRecordResponseItem>
+
+        def ModbusPDUWriteFileRecordResponseBuilder(
+            List<ModbusPDUWriteFileRecordResponseItem> items
+        
+        ):
+            self.items = items
+
+
+        def build(
+        ) -> ModbusPDUWriteFileRecordResponse:
+            modbusPDUWriteFileRecordResponse: ModbusPDUWriteFileRecordResponse = ModbusPDUWriteFileRecordResponse(
+                items
+)
+            return modbusPDUWriteFileRecordResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteFileRecordResponse):
+            return False
+
+        that: ModbusPDUWriteFileRecordResponse = ModbusPDUWriteFileRecordResponse(o)
+        return
+            (getItems() == that.getItems()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getItems()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py
new file mode 100644
index 0000000000..79661bc68c
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py
@@ -0,0 +1,167 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteFileRecordResponseItem(PlcMessage):
+            referenceType: short
+            fileNumber: int
+            recordNumber: int
+            recordData: byte[]
+
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getReferenceType(self) -> short:
+        return referenceType
+
+    def getFileNumber(self) -> int:
+        return fileNumber
+
+    def getRecordNumber(self) -> int:
+        return recordNumber
+
+    def getRecordData(self) -> byte[]:
+        return recordData
+
+
+    def serialize(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteFileRecordResponseItem")
+
+                        # Simple Field (referenceType)
+                            writeSimpleField("referenceType", referenceType, writeUnsignedShort(writeBuffer, 8))
+
+                        # Simple Field (fileNumber)
+                            writeSimpleField("fileNumber", fileNumber, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (recordNumber)
+                            writeSimpleField("recordNumber", recordNumber, writeUnsignedInt(writeBuffer, 16))
+
+                        # Implicit Field (recordLength) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        int recordLength = (int) ((COUNT(getRecordData())) / (2))
+                        writeImplicitField("recordLength", recordLength, writeUnsignedInt(writeBuffer, 16))
+
+                        # Array Field (recordData)
+                        writeByteArrayField("recordData", recordData, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUWriteFileRecordResponseItem")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = 0
+        _value: ModbusPDUWriteFileRecordResponseItem = self
+
+        # Simple field (referenceType)
+        lengthInBits += 8
+
+        # Simple field (fileNumber)
+        lengthInBits += 16
+
+        # Simple field (recordNumber)
+        lengthInBits += 16
+
+        # Implicit Field (recordLength)
+        lengthInBits += 16
+
+        # Array field
+        if recordData is not None):
+            lengthInBits += 8 * recordData.length
+
+
+        return lengthInBits
+
+
+    def staticParse(readBuffer: ReadBuffer , args) -> ModbusPDUWriteFileRecordResponseItem:
+        positionAware: PositionAware = readBuffer
+        return staticParse(readBuffer)
+    }
+
+    def  staticParse(readBuffer: ReadBuffer) -> ModbusPDUWriteFileRecordResponseItem:
+        readBuffer.pullContext("ModbusPDUWriteFileRecordResponseItem")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                referenceType: short = readSimpleField("referenceType", readUnsignedShort(readBuffer, 8))
+
+                fileNumber: int = readSimpleField("fileNumber", readUnsignedInt(readBuffer, 16))
+
+                recordNumber: int = readSimpleField("recordNumber", readUnsignedInt(readBuffer, 16))
+
+                recordLength: int = readImplicitField("recordLength", readUnsignedInt(readBuffer, 16))
+
+                    recordData: byte[] = readBuffer.readByteArray("recordData", Math.toIntExact(recordLength))
+
+    readBuffer.closeContext("ModbusPDUWriteFileRecordResponseItem")
+    # Create the instance
+        _modbusPDUWriteFileRecordResponseItem: ModbusPDUWriteFileRecordResponseItem = ModbusPDUWriteFileRecordResponseItem(
+            referenceType, 
+            fileNumber, 
+            recordNumber, 
+            recordData
+        )
+        return _modbusPDUWriteFileRecordResponseItem
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteFileRecordResponseItem):
+            return False
+
+        that: ModbusPDUWriteFileRecordResponseItem = ModbusPDUWriteFileRecordResponseItem(o)
+        return
+            (getReferenceType() == that.getReferenceType()) &&
+            (getFileNumber() == that.getFileNumber()) &&
+            (getRecordNumber() == that.getRecordNumber()) &&
+            (getRecordData() == that.getRecordData()) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            getReferenceType(),
+            getFileNumber(),
+            getRecordNumber(),
+            getRecordData()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py
new file mode 100644
index 0000000000..9343968682
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py
@@ -0,0 +1,184 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteMultipleCoilsRequest(PlcMessage,ModbusPDU):
+            startingAddress: int
+            quantity: int
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x0F
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStartingAddress(self) -> int:
+        return startingAddress
+
+    def getQuantity(self) -> int:
+        return quantity
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteMultipleCoilsRequest")
+
+                        # Simple Field (startingAddress)
+                            writeSimpleField("startingAddress", startingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (quantity)
+                            writeSimpleField("quantity", quantity, writeUnsignedInt(writeBuffer, 16))
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUWriteMultipleCoilsRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteMultipleCoilsRequest = self
+
+        # Simple field (startingAddress)
+        lengthInBits += 16
+
+        # Simple field (quantity)
+        lengthInBits += 16
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteMultipleCoilsRequestBuilder:
+        readBuffer.pullContext("ModbusPDUWriteMultipleCoilsRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                startingAddress: int = readSimpleField("startingAddress", readUnsignedInt(readBuffer, 16))
+
+                quantity: int = readSimpleField("quantity", readUnsignedInt(readBuffer, 16))
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUWriteMultipleCoilsRequest")
+    # Create the instance
+        return ModbusPDUWriteMultipleCoilsRequestBuilder(
+            startingAddress, 
+            quantity, 
+            value
+        
+        )
+
+        class ModbusPDUWriteMultipleCoilsRequestBuilder(ModbusPDUModbusPDUBuilder {
+        startingAddress: int
+        quantity: int
+        value: byte[]
+
+        def ModbusPDUWriteMultipleCoilsRequestBuilder(
+            int startingAddress, 
+            int quantity, 
+            byte[] value
+        
+        ):
+            self.startingAddress = startingAddress
+            self.quantity = quantity
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUWriteMultipleCoilsRequest:
+            modbusPDUWriteMultipleCoilsRequest: ModbusPDUWriteMultipleCoilsRequest = ModbusPDUWriteMultipleCoilsRequest(
+                startingAddress, 
+                quantity, 
+                value
+)
+            return modbusPDUWriteMultipleCoilsRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteMultipleCoilsRequest):
+            return False
+
+        that: ModbusPDUWriteMultipleCoilsRequest = ModbusPDUWriteMultipleCoilsRequest(o)
+        return
+            (getStartingAddress() == that.getStartingAddress()) &&
+            (getQuantity() == that.getQuantity()) &&
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStartingAddress(),
+            getQuantity(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py
new file mode 100644
index 0000000000..d6b894c717
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteMultipleCoilsResponse(PlcMessage,ModbusPDU):
+            startingAddress: int
+            quantity: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x0F
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStartingAddress(self) -> int:
+        return startingAddress
+
+    def getQuantity(self) -> int:
+        return quantity
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteMultipleCoilsResponse")
+
+                        # Simple Field (startingAddress)
+                            writeSimpleField("startingAddress", startingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (quantity)
+                            writeSimpleField("quantity", quantity, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUWriteMultipleCoilsResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteMultipleCoilsResponse = self
+
+        # Simple field (startingAddress)
+        lengthInBits += 16
+
+        # Simple field (quantity)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteMultipleCoilsResponseBuilder:
+        readBuffer.pullContext("ModbusPDUWriteMultipleCoilsResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                startingAddress: int = readSimpleField("startingAddress", readUnsignedInt(readBuffer, 16))
+
+                quantity: int = readSimpleField("quantity", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUWriteMultipleCoilsResponse")
+    # Create the instance
+        return ModbusPDUWriteMultipleCoilsResponseBuilder(
+            startingAddress, 
+            quantity
+        
+        )
+
+        class ModbusPDUWriteMultipleCoilsResponseBuilder(ModbusPDUModbusPDUBuilder {
+        startingAddress: int
+        quantity: int
+
+        def ModbusPDUWriteMultipleCoilsResponseBuilder(
+            int startingAddress, 
+            int quantity
+        
+        ):
+            self.startingAddress = startingAddress
+            self.quantity = quantity
+
+
+        def build(
+        ) -> ModbusPDUWriteMultipleCoilsResponse:
+            modbusPDUWriteMultipleCoilsResponse: ModbusPDUWriteMultipleCoilsResponse = ModbusPDUWriteMultipleCoilsResponse(
+                startingAddress, 
+                quantity
+)
+            return modbusPDUWriteMultipleCoilsResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteMultipleCoilsResponse):
+            return False
+
+        that: ModbusPDUWriteMultipleCoilsResponse = ModbusPDUWriteMultipleCoilsResponse(o)
+        return
+            (getStartingAddress() == that.getStartingAddress()) &&
+            (getQuantity() == that.getQuantity()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStartingAddress(),
+            getQuantity()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py
new file mode 100644
index 0000000000..4bba3f5f26
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py
@@ -0,0 +1,184 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteMultipleHoldingRegistersRequest(PlcMessage,ModbusPDU):
+            startingAddress: int
+            quantity: int
+            value: byte[]
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x10
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStartingAddress(self) -> int:
+        return startingAddress
+
+    def getQuantity(self) -> int:
+        return quantity
+
+    def getValue(self) -> byte[]:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteMultipleHoldingRegistersRequest")
+
+                        # Simple Field (startingAddress)
+                            writeSimpleField("startingAddress", startingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (quantity)
+                            writeSimpleField("quantity", quantity, writeUnsignedInt(writeBuffer, 16))
+
+                        # Implicit Field (byteCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        short byteCount = (short) (COUNT(getValue()))
+                        writeImplicitField("byteCount", byteCount, writeUnsignedShort(writeBuffer, 8))
+
+                        # Array Field (value)
+                        writeByteArrayField("value", value, writeByteArray(writeBuffer, 8))
+
+            writeBuffer.popContext("ModbusPDUWriteMultipleHoldingRegistersRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteMultipleHoldingRegistersRequest = self
+
+        # Simple field (startingAddress)
+        lengthInBits += 16
+
+        # Simple field (quantity)
+        lengthInBits += 16
+
+        # Implicit Field (byteCount)
+        lengthInBits += 8
+
+        # Array field
+        if value is not None):
+            lengthInBits += 8 * value.length
+
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteMultipleHoldingRegistersRequestBuilder:
+        readBuffer.pullContext("ModbusPDUWriteMultipleHoldingRegistersRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                startingAddress: int = readSimpleField("startingAddress", readUnsignedInt(readBuffer, 16))
+
+                quantity: int = readSimpleField("quantity", readUnsignedInt(readBuffer, 16))
+
+                byteCount: short = readImplicitField("byteCount", readUnsignedShort(readBuffer, 8))
+
+                    value: byte[] = readBuffer.readByteArray("value", Math.toIntExact(byteCount))
+
+    readBuffer.closeContext("ModbusPDUWriteMultipleHoldingRegistersRequest")
+    # Create the instance
+        return ModbusPDUWriteMultipleHoldingRegistersRequestBuilder(
+            startingAddress, 
+            quantity, 
+            value
+        
+        )
+
+        class ModbusPDUWriteMultipleHoldingRegistersRequestBuilder(ModbusPDUModbusPDUBuilder {
+        startingAddress: int
+        quantity: int
+        value: byte[]
+
+        def ModbusPDUWriteMultipleHoldingRegistersRequestBuilder(
+            int startingAddress, 
+            int quantity, 
+            byte[] value
+        
+        ):
+            self.startingAddress = startingAddress
+            self.quantity = quantity
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUWriteMultipleHoldingRegistersRequest:
+            modbusPDUWriteMultipleHoldingRegistersRequest: ModbusPDUWriteMultipleHoldingRegistersRequest = ModbusPDUWriteMultipleHoldingRegistersRequest(
+                startingAddress, 
+                quantity, 
+                value
+)
+            return modbusPDUWriteMultipleHoldingRegistersRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteMultipleHoldingRegistersRequest):
+            return False
+
+        that: ModbusPDUWriteMultipleHoldingRegistersRequest = ModbusPDUWriteMultipleHoldingRegistersRequest(o)
+        return
+            (getStartingAddress() == that.getStartingAddress()) &&
+            (getQuantity() == that.getQuantity()) &&
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStartingAddress(),
+            getQuantity(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py
new file mode 100644
index 0000000000..f951075bad
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteMultipleHoldingRegistersResponse(PlcMessage,ModbusPDU):
+            startingAddress: int
+            quantity: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x10
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getStartingAddress(self) -> int:
+        return startingAddress
+
+    def getQuantity(self) -> int:
+        return quantity
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteMultipleHoldingRegistersResponse")
+
+                        # Simple Field (startingAddress)
+                            writeSimpleField("startingAddress", startingAddress, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (quantity)
+                            writeSimpleField("quantity", quantity, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUWriteMultipleHoldingRegistersResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteMultipleHoldingRegistersResponse = self
+
+        # Simple field (startingAddress)
+        lengthInBits += 16
+
+        # Simple field (quantity)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteMultipleHoldingRegistersResponseBuilder:
+        readBuffer.pullContext("ModbusPDUWriteMultipleHoldingRegistersResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                startingAddress: int = readSimpleField("startingAddress", readUnsignedInt(readBuffer, 16))
+
+                quantity: int = readSimpleField("quantity", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUWriteMultipleHoldingRegistersResponse")
+    # Create the instance
+        return ModbusPDUWriteMultipleHoldingRegistersResponseBuilder(
+            startingAddress, 
+            quantity
+        
+        )
+
+        class ModbusPDUWriteMultipleHoldingRegistersResponseBuilder(ModbusPDUModbusPDUBuilder {
+        startingAddress: int
+        quantity: int
+
+        def ModbusPDUWriteMultipleHoldingRegistersResponseBuilder(
+            int startingAddress, 
+            int quantity
+        
+        ):
+            self.startingAddress = startingAddress
+            self.quantity = quantity
+
+
+        def build(
+        ) -> ModbusPDUWriteMultipleHoldingRegistersResponse:
+            modbusPDUWriteMultipleHoldingRegistersResponse: ModbusPDUWriteMultipleHoldingRegistersResponse = ModbusPDUWriteMultipleHoldingRegistersResponse(
+                startingAddress, 
+                quantity
+)
+            return modbusPDUWriteMultipleHoldingRegistersResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteMultipleHoldingRegistersResponse):
+            return False
+
+        that: ModbusPDUWriteMultipleHoldingRegistersResponse = ModbusPDUWriteMultipleHoldingRegistersResponse(o)
+        return
+            (getStartingAddress() == that.getStartingAddress()) &&
+            (getQuantity() == that.getQuantity()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getStartingAddress(),
+            getQuantity()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py
new file mode 100644
index 0000000000..4e6c8317ed
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteSingleCoilRequest(PlcMessage,ModbusPDU):
+            address: int
+            value: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x05
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getAddress(self) -> int:
+        return address
+
+    def getValue(self) -> int:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteSingleCoilRequest")
+
+                        # Simple Field (address)
+                            writeSimpleField("address", address, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (value)
+                            writeSimpleField("value", value, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUWriteSingleCoilRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteSingleCoilRequest = self
+
+        # Simple field (address)
+        lengthInBits += 16
+
+        # Simple field (value)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteSingleCoilRequestBuilder:
+        readBuffer.pullContext("ModbusPDUWriteSingleCoilRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                address: int = readSimpleField("address", readUnsignedInt(readBuffer, 16))
+
+                value: int = readSimpleField("value", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUWriteSingleCoilRequest")
+    # Create the instance
+        return ModbusPDUWriteSingleCoilRequestBuilder(
+            address, 
+            value
+        
+        )
+
+        class ModbusPDUWriteSingleCoilRequestBuilder(ModbusPDUModbusPDUBuilder {
+        address: int
+        value: int
+
+        def ModbusPDUWriteSingleCoilRequestBuilder(
+            int address, 
+            int value
+        
+        ):
+            self.address = address
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUWriteSingleCoilRequest:
+            modbusPDUWriteSingleCoilRequest: ModbusPDUWriteSingleCoilRequest = ModbusPDUWriteSingleCoilRequest(
+                address, 
+                value
+)
+            return modbusPDUWriteSingleCoilRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteSingleCoilRequest):
+            return False
+
+        that: ModbusPDUWriteSingleCoilRequest = ModbusPDUWriteSingleCoilRequest(o)
+        return
+            (getAddress() == that.getAddress()) &&
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getAddress(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py
new file mode 100644
index 0000000000..792aa00811
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteSingleCoilResponse(PlcMessage,ModbusPDU):
+            address: int
+            value: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x05
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getAddress(self) -> int:
+        return address
+
+    def getValue(self) -> int:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteSingleCoilResponse")
+
+                        # Simple Field (address)
+                            writeSimpleField("address", address, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (value)
+                            writeSimpleField("value", value, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUWriteSingleCoilResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteSingleCoilResponse = self
+
+        # Simple field (address)
+        lengthInBits += 16
+
+        # Simple field (value)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteSingleCoilResponseBuilder:
+        readBuffer.pullContext("ModbusPDUWriteSingleCoilResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                address: int = readSimpleField("address", readUnsignedInt(readBuffer, 16))
+
+                value: int = readSimpleField("value", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUWriteSingleCoilResponse")
+    # Create the instance
+        return ModbusPDUWriteSingleCoilResponseBuilder(
+            address, 
+            value
+        
+        )
+
+        class ModbusPDUWriteSingleCoilResponseBuilder(ModbusPDUModbusPDUBuilder {
+        address: int
+        value: int
+
+        def ModbusPDUWriteSingleCoilResponseBuilder(
+            int address, 
+            int value
+        
+        ):
+            self.address = address
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUWriteSingleCoilResponse:
+            modbusPDUWriteSingleCoilResponse: ModbusPDUWriteSingleCoilResponse = ModbusPDUWriteSingleCoilResponse(
+                address, 
+                value
+)
+            return modbusPDUWriteSingleCoilResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteSingleCoilResponse):
+            return False
+
+        that: ModbusPDUWriteSingleCoilResponse = ModbusPDUWriteSingleCoilResponse(o)
+        return
+            (getAddress() == that.getAddress()) &&
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getAddress(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py
new file mode 100644
index 0000000000..401e64f450
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteSingleRegisterRequest(PlcMessage,ModbusPDU):
+            address: int
+            value: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x06
+    }
+    def Boolean getResponse() {
+        return (boolean) false
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getAddress(self) -> int:
+        return address
+
+    def getValue(self) -> int:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteSingleRegisterRequest")
+
+                        # Simple Field (address)
+                            writeSimpleField("address", address, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (value)
+                            writeSimpleField("value", value, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUWriteSingleRegisterRequest")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteSingleRegisterRequest = self
+
+        # Simple field (address)
+        lengthInBits += 16
+
+        # Simple field (value)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteSingleRegisterRequestBuilder:
+        readBuffer.pullContext("ModbusPDUWriteSingleRegisterRequest")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                address: int = readSimpleField("address", readUnsignedInt(readBuffer, 16))
+
+                value: int = readSimpleField("value", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUWriteSingleRegisterRequest")
+    # Create the instance
+        return ModbusPDUWriteSingleRegisterRequestBuilder(
+            address, 
+            value
+        
+        )
+
+        class ModbusPDUWriteSingleRegisterRequestBuilder(ModbusPDUModbusPDUBuilder {
+        address: int
+        value: int
+
+        def ModbusPDUWriteSingleRegisterRequestBuilder(
+            int address, 
+            int value
+        
+        ):
+            self.address = address
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUWriteSingleRegisterRequest:
+            modbusPDUWriteSingleRegisterRequest: ModbusPDUWriteSingleRegisterRequest = ModbusPDUWriteSingleRegisterRequest(
+                address, 
+                value
+)
+            return modbusPDUWriteSingleRegisterRequest
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteSingleRegisterRequest):
+            return False
+
+        that: ModbusPDUWriteSingleRegisterRequest = ModbusPDUWriteSingleRegisterRequest(o)
+        return
+            (getAddress() == that.getAddress()) &&
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getAddress(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py
new file mode 100644
index 0000000000..ddd9502775
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py
@@ -0,0 +1,154 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusPDUWriteSingleRegisterResponse(PlcMessage,ModbusPDU):
+            address: int
+            value: int
+
+    # Accessors for discriminator values.
+    def Boolean getErrorFlag() {
+        return (boolean) false
+    }
+    def Short getFunctionFlag() {
+        return (short) 0x06
+    }
+    def Boolean getResponse() {
+        return (boolean) true
+    }
+
+
+    def __post_init__(self):
+super().__init__( )
+
+
+
+    def getAddress(self) -> int:
+        return address
+
+    def getValue(self) -> int:
+        return value
+
+
+    def serializeModbusPDUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusPDUWriteSingleRegisterResponse")
+
+                        # Simple Field (address)
+                            writeSimpleField("address", address, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (value)
+                            writeSimpleField("value", value, writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusPDUWriteSingleRegisterResponse")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusPDUWriteSingleRegisterResponse = self
+
+        # Simple field (address)
+        lengthInBits += 16
+
+        # Simple field (value)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, Boolean response) -> ModbusPDUWriteSingleRegisterResponseBuilder:
+        readBuffer.pullContext("ModbusPDUWriteSingleRegisterResponse")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                address: int = readSimpleField("address", readUnsignedInt(readBuffer, 16))
+
+                value: int = readSimpleField("value", readUnsignedInt(readBuffer, 16))
+
+    readBuffer.closeContext("ModbusPDUWriteSingleRegisterResponse")
+    # Create the instance
+        return ModbusPDUWriteSingleRegisterResponseBuilder(
+            address, 
+            value
+        
+        )
+
+        class ModbusPDUWriteSingleRegisterResponseBuilder(ModbusPDUModbusPDUBuilder {
+        address: int
+        value: int
+
+        def ModbusPDUWriteSingleRegisterResponseBuilder(
+            int address, 
+            int value
+        
+        ):
+            self.address = address
+            self.value = value
+
+
+        def build(
+        ) -> ModbusPDUWriteSingleRegisterResponse:
+            modbusPDUWriteSingleRegisterResponse: ModbusPDUWriteSingleRegisterResponse = ModbusPDUWriteSingleRegisterResponse(
+                address, 
+                value
+)
+            return modbusPDUWriteSingleRegisterResponse
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusPDUWriteSingleRegisterResponse):
+            return False
+
+        that: ModbusPDUWriteSingleRegisterResponse = ModbusPDUWriteSingleRegisterResponse(o)
+        return
+            (getAddress() == that.getAddress()) &&
+            (getValue() == that.getValue()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getAddress(),
+            getValue()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusRtuADU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusRtuADU.py
new file mode 100644
index 0000000000..34b5a3c438
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusRtuADU.py
@@ -0,0 +1,168 @@
+#
+# 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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusRtuADU(PlcMessage,ModbusADU):
+            address: short
+            pdu: ModbusPDU
+        # Arguments.
+            response: Boolean
+
+    # Accessors for discriminator values.
+    def DriverType getDriverType() {
+        return DriverType.MODBUS_RTU
+    }
+
+
+    def __post_init__(self):
+super().__init__( self.response )
+
+
+
+    def getAddress(self) -> short:
+        return address
+
+    def getPdu(self) -> ModbusPDU:
+        return pdu
+
+
+    def serializeModbusADUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusRtuADU")
+
+                        # Simple Field (address)
+                            writeSimpleField("address", address, writeUnsignedShort(writeBuffer, 8), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                        # Simple Field (pdu)
+                            writeSimpleField("pdu", pdu, new DataWriterComplexDefault<>(writeBuffer), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                        # Checksum Field (checksum) (Calculated)
+                        writeChecksumField("crc", (int) (modbus.readwrite.utils.StaticHelper.rtuCrcCheck(address, pdu)), writeUnsignedInt(writeBuffer, 16))
+
+            writeBuffer.popContext("ModbusRtuADU")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusRtuADU = self
+
+        # Simple field (address)
+        lengthInBits += 8
+
+        # Simple field (pdu)
+        lengthInBits += pdu.getLengthInBits()
+
+        # Checksum Field (checksum)
+        lengthInBits += 16
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, DriverType driverType, Boolean response) -> ModbusRtuADUBuilder:
+        readBuffer.pullContext("ModbusRtuADU")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                address: short = readSimpleField("address", readUnsignedShort(readBuffer, 8), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                pdu: ModbusPDU = readSimpleField("pdu", new DataReaderComplexDefault<>(() -> ModbusPDU.staticParse(readBuffer, (boolean) (response)), readBuffer), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                crc: int = readChecksumField("crc", readUnsignedInt(readBuffer, 16), (int) (modbus.readwrite.utils.StaticHelper.rtuCrcCheck(address, pdu)), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+    readBuffer.closeContext("ModbusRtuADU")
+    # Create the instance
+        return ModbusRtuADUBuilder(
+            address, 
+            pdu
+            , 
+            response
+        
+        )
+
+        class ModbusRtuADUBuilder(ModbusADUModbusADUBuilder {
+        address: short
+        pdu: ModbusPDU
+        response: Boolean
+
+        def ModbusRtuADUBuilder(
+            short address, 
+            ModbusPDU pdu
+            , 
+                Boolean response
+        
+        ):
+            self.address = address
+            self.pdu = pdu
+            self.response = response
+
+
+        def build(
+            
+                Boolean response
+        ) -> ModbusRtuADU:
+            modbusRtuADU: ModbusRtuADU = ModbusRtuADU(
+                address, 
+                pdu
+            , 
+                response
+        )
+            return modbusRtuADU
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusRtuADU):
+            return False
+
+        that: ModbusRtuADU = ModbusRtuADU(o)
+        return
+            (getAddress() == that.getAddress()) &&
+            (getPdu() == that.getPdu()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getAddress(),
+            getPdu()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py
new file mode 100644
index 0000000000..ef7ec0b1ab
--- /dev/null
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py
@@ -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
+#
+#   https:#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.
+#
+
+# Code generated by code-generation. DO NOT EDIT.
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+@dataclass
+class ModbusTcpADU(PlcMessage,ModbusADU):
+            transactionIdentifier: int
+            unitIdentifier: short
+            pdu: ModbusPDU
+        # Arguments.
+            response: Boolean
+            PROTOCOLIDENTIFIER: Integer = 0x0000
+
+    # Accessors for discriminator values.
+    def DriverType getDriverType() {
+        return DriverType.MODBUS_TCP
+    }
+
+
+    def __post_init__(self):
+super().__init__( self.response )
+
+
+
+    def getTransactionIdentifier(self) -> int:
+        return transactionIdentifier
+
+    def getUnitIdentifier(self) -> short:
+        return unitIdentifier
+
+    def getPdu(self) -> ModbusPDU:
+        return pdu
+
+    def getProtocolIdentifier(self) -> int:
+        return PROTOCOLIDENTIFIER
+
+
+    def serializeModbusADUChild(self, writeBuffer: WriteBuffer):
+        positionAware: PositionAware = writeBuffer
+            startPos: int = positionAware.getPos()
+            writeBuffer.pushContext("ModbusTcpADU")
+
+                        # Simple Field (transactionIdentifier)
+                            writeSimpleField("transactionIdentifier", transactionIdentifier, writeUnsignedInt(writeBuffer, 16), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                        # Const Field (protocolIdentifier)
+                        writeConstField("protocolIdentifier", PROTOCOLIDENTIFIER, writeUnsignedInt(writeBuffer, 16))
+
+                        # Implicit Field (length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+                        int length = (int) ((getPdu().getLengthInBytes()) + (1))
+                        writeImplicitField("length", length, writeUnsignedInt(writeBuffer, 16))
+
+                        # Simple Field (unitIdentifier)
+                            writeSimpleField("unitIdentifier", unitIdentifier, writeUnsignedShort(writeBuffer, 8), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                        # Simple Field (pdu)
+                            writeSimpleField("pdu", pdu, new DataWriterComplexDefault<>(writeBuffer), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+            writeBuffer.popContext("ModbusTcpADU")
+
+
+    def getLengthInBytes(self) -> int:
+        return int(math.ceil(float(getLengthInBits() / 8.0)))
+
+    def getLengthInBits(self) -> int:
+        lengthInBits: int = super().getLengthInBits()
+        _value: ModbusTcpADU = self
+
+        # Simple field (transactionIdentifier)
+        lengthInBits += 16
+
+        # Const Field (protocolIdentifier)
+        lengthInBits += 16
+
+        # Implicit Field (length)
+        lengthInBits += 16
+
+        # Simple field (unitIdentifier)
+        lengthInBits += 8
+
+        # Simple field (pdu)
+        lengthInBits += pdu.getLengthInBits()
+
+        return lengthInBits
+
+
+    def  staticParseBuilder(readBuffer: ReadBuffer, DriverType driverType, Boolean response) -> ModbusTcpADUBuilder:
+        readBuffer.pullContext("ModbusTcpADU")
+        positionAware: PositionAware = readBuffer
+        startPos: int = positionAware.getPos()
+        curPos: int = 0
+
+                transactionIdentifier: int = readSimpleField("transactionIdentifier", readUnsignedInt(readBuffer, 16), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                protocolIdentifier: int = readConstField("protocolIdentifier", readUnsignedInt(readBuffer, 16), ModbusTcpADU.PROTOCOLIDENTIFIER, WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                length: int = readImplicitField("length", readUnsignedInt(readBuffer, 16), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                unitIdentifier: short = readSimpleField("unitIdentifier", readUnsignedShort(readBuffer, 8), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+                pdu: ModbusPDU = readSimpleField("pdu", new DataReaderComplexDefault<>(() -> ModbusPDU.staticParse(readBuffer, (boolean) (response)), readBuffer), WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN))
+
+    readBuffer.closeContext("ModbusTcpADU")
+    # Create the instance
+        return ModbusTcpADUBuilder(
+            transactionIdentifier, 
+            unitIdentifier, 
+            pdu
+            , 
+            response
+        
+        )
+
+        class ModbusTcpADUBuilder(ModbusADUModbusADUBuilder {
+        transactionIdentifier: int
+        unitIdentifier: short
+        pdu: ModbusPDU
+        response: Boolean
+
+        def ModbusTcpADUBuilder(
+            int transactionIdentifier, 
+            short unitIdentifier, 
+            ModbusPDU pdu
+            , 
+                Boolean response
+        
+        ):
+            self.transactionIdentifier = transactionIdentifier
+            self.unitIdentifier = unitIdentifier
+            self.pdu = pdu
+            self.response = response
+
+
+        def build(
+            
+                Boolean response
+        ) -> ModbusTcpADU:
+            modbusTcpADU: ModbusTcpADU = ModbusTcpADU(
+                transactionIdentifier, 
+                unitIdentifier, 
+                pdu
+            , 
+                response
+        )
+            return modbusTcpADU
+
+
+    def equals(self, o: object) -> bool:
+        if this == o:
+            return True
+
+        if not (instanceof(o, ModbusTcpADU):
+            return False
+
+        that: ModbusTcpADU = ModbusTcpADU(o)
+        return
+            (getTransactionIdentifier() == that.getTransactionIdentifier()) &&
+            (getUnitIdentifier() == that.getUnitIdentifier()) &&
+            (getPdu() == that.getPdu()) &&
+            super().equals(that) &&
+            True
+
+    def hashCode(self) -> int:
+        return Objects.hash(
+            super().hashCode(),
+            getTransactionIdentifier(),
+            getUnitIdentifier(),
+            getPdu()
+        )
+
+    def toString(self) -> str:
+        writeBufferBoxBased: WriteBufferBoxBased = WriteBufferBoxBased(true, true)
+        try:
+            writeBufferBoxBased.writeSerializable(this)
+        except SerializationException:
+            raise RuntimeException(e)
+
+        return "\n" + writeBufferBoxBased.getBox().toString()+ "\n"
+