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

[plc4x] branch develop updated: feat(modbus): Split up "modbus" into "modbus-tcp", "modbus-rtu" and "modbus-ascii". Renamed "modbus" into "modbus-tcp".

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new e3e46f3  feat(modbus): Split up "modbus" into "modbus-tcp", "modbus-rtu" and "modbus-ascii". Renamed "modbus" into "modbus-tcp".
e3e46f3 is described below

commit e3e46f3ec47b93187e3d21ad68b22e0870790c57
Author: cdutz <ch...@c-ware.de>
AuthorDate: Tue Mar 15 16:01:18 2022 +0100

    feat(modbus): Split up "modbus" into "modbus-tcp", "modbus-rtu" and "modbus-ascii". Renamed "modbus" into "modbus-tcp".
---
 RELEASE_NOTES                                      |   8 +
 .../templates/c/complex-type-template.c.ftlh       |   5 +-
 .../templates/c/complex-type-template.h.ftlh       |   2 +-
 .../apache/plc4x/language/go/GoLanguageOutput.java |   2 +-
 ...plate.go.ftlh => complex-type-template.go.ftlh} |  14 +-
 .../templates/go/parser-factory-template.go.ftlh   |   2 +
 .../plc4x/language/java/JavaLanguageOutput.java    |   2 +-
 ...e.java.ftlh => complex-type-template.java.ftlh} |   4 +-
 plc4c/drivers/modbus/CMakeLists.txt                |   3 +-
 ...code_decode.h => driver_modbus_encode_decode.h} |   0
 .../modbus/include/plc4c/driver_modbus_packets.h   |  10 +-
 .../include/plc4c/driver_modbus_static_helper.h    |  14 +-
 plc4c/drivers/modbus/src/driver_modbus.c           |   6 +-
 .../modbus/src/driver_modbus_encode_decode.c       |   2 +-
 plc4c/drivers/modbus/src/driver_modbus_packets.c   |  37 +-
 plc4c/drivers/modbus/src/driver_modbus_sm_read.c   |  22 +-
 plc4c/drivers/modbus/src/driver_modbus_sm_write.c  |   8 +-
 .../modbus/src/driver_modbus_static_helper.c       |  13 +-
 plc4c/drivers/s7/CMakeLists.txt                    |   2 +-
 .../s7/include/plc4c/driver_s7_static_helper.h     |  10 +-
 ...code_decode.c => driver_modbus_encode_decode.c} |   0
 .../simulated/include/plc4c/static_helper.h        |  10 +-
 .../hello-world-modbus/src/hello_world_modbus.c    |   4 +-
 .../generated-sources/modbus/include/driver_type.h |  64 +++
 .../generated-sources/modbus/include/modbus_adu.h  |  95 +++++
 .../modbus/include/modbus_ascii_adu.h              |  67 ----
 .../generated-sources/modbus/include/modbus_pdu.h  |   2 +-
 .../modbus/include/modbus_rtu_adu.h                |  69 ----
 .../modbus/include/modbus_serial_adu.h             |  59 ---
 .../modbus/include/modbus_tcp_adu.h                |  64 ---
 plc4c/generated-sources/modbus/src/driver_type.c   |  96 +++++
 plc4c/generated-sources/modbus/src/modbus_adu.c    | 349 +++++++++++++++++
 .../modbus/src/modbus_ascii_adu.c                  | 155 --------
 .../modbus/src/modbus_constants.c                  |   1 +
 .../modbus/src/modbus_device_information_object.c  |   1 +
 plc4c/generated-sources/modbus/src/modbus_pdu.c    |   5 +-
 .../src/modbus_pdu_read_file_record_request_item.c |   1 +
 .../modbus_pdu_read_file_record_response_item.c    |   1 +
 .../modbus_pdu_write_file_record_request_item.c    |   1 +
 .../modbus_pdu_write_file_record_response_item.c   |   1 +
 .../generated-sources/modbus/src/modbus_rtu_adu.c  | 176 ---------
 .../modbus/src/modbus_serial_adu.c                 | 115 ------
 .../generated-sources/modbus/src/modbus_tcp_adu.c  | 146 -------
 plc4c/generated-sources/s7/include/cotp_packet.h   |   2 +-
 .../generated-sources/s7/include/cotp_parameter.h  |   2 +-
 plc4c/generated-sources/s7/include/s7_address.h    |   2 +-
 .../s7/include/s7_data_alarm_message.h             |   2 +-
 plc4c/generated-sources/s7/include/s7_message.h    |   2 +-
 plc4c/generated-sources/s7/include/s7_parameter.h  |   2 +-
 .../s7/include/s7_parameter_user_data_item.h       |   2 +-
 plc4c/generated-sources/s7/include/s7_payload.h    |   2 +-
 .../s7/include/s7_payload_user_data_item.h         |   2 +-
 .../s7/include/s7_var_request_parameter_item.h     |   2 +-
 .../s7/src/alarm_message_ack_object_push_type.c    |   1 +
 .../s7/src/alarm_message_ack_push_type.c           |   1 +
 .../s7/src/alarm_message_ack_response_type.c       |   1 +
 .../s7/src/alarm_message_ack_type.c                |   1 +
 .../s7/src/alarm_message_object_ack_type.c         |   1 +
 .../s7/src/alarm_message_object_push_type.c        |   1 +
 .../s7/src/alarm_message_object_query_type.c       |   1 +
 .../s7/src/alarm_message_push_type.c               |   1 +
 .../s7/src/alarm_message_query_type.c              |   1 +
 .../s7/src/associated_value_type.c                 |   1 +
 plc4c/generated-sources/s7/src/cotp_packet.c       |   5 +-
 plc4c/generated-sources/s7/src/cotp_parameter.c    |   5 +-
 plc4c/generated-sources/s7/src/date_and_time.c     |   1 +
 plc4c/generated-sources/s7/src/s7_address.c        |   5 +-
 .../s7/src/s7_data_alarm_message.c                 |   5 +-
 plc4c/generated-sources/s7/src/s7_message.c        |   5 +-
 plc4c/generated-sources/s7/src/s7_parameter.c      |   5 +-
 .../s7/src/s7_parameter_user_data_item.c           |   5 +-
 plc4c/generated-sources/s7/src/s7_payload.c        |   5 +-
 .../s7/src/s7_payload_user_data_item.c             |   5 +-
 .../s7/src/s7_var_payload_data_item.c              |   1 +
 .../s7/src/s7_var_payload_status_item.c            |   1 +
 .../s7/src/s7_var_request_parameter_item.c         |   5 +-
 plc4c/generated-sources/s7/src/state.c             |   1 +
 .../generated-sources/s7/src/szl_data_tree_item.c  |   1 +
 plc4c/generated-sources/s7/src/szl_id.c            |   1 +
 plc4c/generated-sources/s7/src/tpkt_packet.c       |   1 +
 .../testing/protocols/modbus/DriverTestsuite.xml   | 430 +++++++++++----------
 .../protocols/modbus/ParserSerializerTestsuite.xml | 316 ++++++++-------
 .../cmd/main/drivers/tests/modbus_driver_test.go   |   4 +-
 plc4go/examples/read/hello_world_plc4go_read.go    |   4 +-
 plc4go/examples/write/hello_world_plc4go_write.go  |   4 +-
 .../internal/plc4go/ads/readwrite/ParserHelper.go  |   2 +-
 .../plc4go/bacnetip/readwrite/ParserHelper.go      |  12 +-
 .../internal/plc4go/cbus/readwrite/ParserHelper.go |   2 +-
 .../df1/readwrite/model/DF1SymbolMessageFrame.go   |  14 +-
 .../plc4go/df1/readwrite/model/StaticHelper.go     |   8 +-
 .../df1/readwrite/model/StaticHelper_test.go       |   5 +-
 .../plc4go/knxnetip/readwrite/ParserHelper.go      |   6 +-
 plc4go/internal/plc4go/modbus/MessageCodec.go      |   2 +-
 .../modbus/{Driver.go => ModbusAsciiDriver.go}     |  10 +-
 .../modbus/{Driver.go => ModbusRtuDriver.go}       |  10 +-
 .../modbus/{Driver.go => ModbusTcpDriver.go}       |  10 +-
 .../plc4go/modbus/readwrite/ParserHelper.go        |  15 +-
 .../plc4go/modbus/readwrite/XmlParserHelper.go     |  10 +-
 .../plc4go/modbus/readwrite/model/DriverType.go    | 129 +++++++
 .../plc4go/modbus/readwrite/model/ModbusADU.go     | 170 ++++++++
 .../modbus/readwrite/model/ModbusAsciiADU.go       | 207 +++++-----
 .../plc4go/modbus/readwrite/model/ModbusRtuADU.go  | 234 ++++++-----
 .../modbus/readwrite/model/ModbusSerialADU.go      | 206 ----------
 .../plc4go/modbus/readwrite/model/ModbusTcpADU.go  | 146 ++++---
 .../plc4go/modbus/readwrite/model/StaticHelper.go  |   9 +-
 plc4go/pkg/plc4go/drivers/drivers.go               |  16 +-
 plc4go/pkg/plc4go/transports/transports.go         |   5 +
 plc4j/drivers/modbus/pom.xml                       |   2 +-
 .../ModbusAsciiDriver.java}                        |  56 +--
 .../config/ModbusAsciiConfiguration.java}          |   4 +-
 .../ascii/protocol/ModbusAsciiProtocolLogic.java   | 182 +++++++++
 .../{ => base}/field/ModbusExtendedRegister.java   |   2 +-
 .../java/modbus/{ => base}/field/ModbusField.java  |   3 +-
 .../modbus/{ => base}/field/ModbusFieldCoil.java   |   2 +-
 .../{ => base}/field/ModbusFieldDiscreteInput.java |   2 +-
 .../{ => base}/field/ModbusFieldHandler.java       |   2 +-
 .../field/ModbusFieldHoldingRegister.java          |   2 +-
 .../{ => base}/field/ModbusFieldInputRegister.java |   2 +-
 .../{ => base}/protocol/ModbusProtocolLogic.java   | 190 ++-------
 .../java/modbus/readwrite/utils/StaticHelper.java  |  99 ++++-
 .../ModbusRtuDriver.java}                          |  56 +--
 .../config/ModbusRtuConfiguration.java}            |   4 +-
 .../rtu/protocol/ModbusRtuProtocolLogic.java       | 182 +++++++++
 .../ModbusTcpDriver.java}                          |  27 +-
 .../config/ModbusTcpConfiguration.java}            |   4 +-
 .../{ => tcp}/discovery/ModbusPlcDiscoverer.java   |   4 +-
 .../tcp/protocol/ModbusTcpProtocolLogic.java       | 195 ++++++++++
 .../services/org.apache.plc4x.java.api.PlcDriver   |   2 +-
 .../plc4x/java/modbus/ManualModbusDriverTest.java  |   2 +-
 .../apache/plc4x/java/modbus/ModbusEncodeTest.java |   4 +-
 .../plc4x/java/modbus/ModbusFieldDataTypeTest.java |  10 +-
 .../apache/plc4x/java/modbus/ModbusFieldTest.java  |  10 +-
 .../drivers/modbus/src/test/resources/logback.xml  |   2 +-
 .../src/main/kotlin/ReadModbusPal.kt               |   2 +-
 .../plc4x/kafka/config/SourceConfigTest.java       |   4 +-
 .../java/utils/connectionpool/PoolKeyFactory.java  |   2 +-
 .../utils/connectionpool/PoolKeyFactoryTest.java   |  12 +-
 .../resources/example_triggered_scraper_modbus.yml |   2 +-
 pom.xml                                            |   2 +-
 .../main/resources/protocols/modbus/modbus.mspec   |  68 ++--
 .../resources/protocols/modbus/DriverTestsuite.xml | 430 +++++++++++----------
 .../protocols/modbus/ParserSerializerTestsuite.xml | 316 ++++++++-------
 src/site/asciidoc/plc4go/index.adoc                |   2 +-
 .../asciidoc/users/getting-started/plc4go.adoc     |   2 +-
 .../users/getting-started/virtual-modbus.adoc      |   6 +-
 .../asciidoc/users/integrations/eclipse-milo.adoc  |   2 +-
 src/site/asciidoc/users/protocols/modbus.adoc      |   4 +-
 147 files changed, 3098 insertions(+), 2527 deletions(-)

diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 4b95569..1becc6d 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -5,9 +5,17 @@
 New Features
 ------------
 
+- The Modbus driver is now also available in the variants:
+  "modbus-rtu" and "modbus-ascii" (Both using Serial
+  communication, which however can be tunneled through a
+  "tcp" transport.
+
 Incompatible changes
 --------------------
 
+- The name of the Modbus TCP driver was changed from "modbus"
+  to "modbus-tcp".
+
 Bug Fixes
 ---------
 
diff --git a/code-generation/language-c/src/main/resources/templates/c/complex-type-template.c.ftlh b/code-generation/language-c/src/main/resources/templates/c/complex-type-template.c.ftlh
index 48462ff..f0c009a 100644
--- a/code-generation/language-c/src/main/resources/templates/c/complex-type-template.c.ftlh
+++ b/code-generation/language-c/src/main/resources/templates/c/complex-type-template.c.ftlh
@@ -47,6 +47,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_${helper.camelCaseToSnakeCase(protocolName)}_static_helper.h>
 #include "${helper.camelCaseToSnakeCase(type.name)}.h"
 
 // Code generated by code-generation. DO NOT EDIT.
@@ -56,8 +57,8 @@
 <#-- Helper function to get the discriminator for a given enum type constant -->
 <#if type.isDiscriminatedParentTypeDefinition()>
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const ${helper.getCTypeName(type.name)}_discriminator ${helper.getCTypeName(type.name)}_discriminators[] = {
     <#if type.getDiscriminatorCaseToKeyValueMap()?has_content>
         <#list type.getDiscriminatorCaseToKeyValueMap() as name, typeTerms>
diff --git a/code-generation/language-c/src/main/resources/templates/c/complex-type-template.h.ftlh b/code-generation/language-c/src/main/resources/templates/c/complex-type-template.h.ftlh
index eb80a73..bd1951e 100644
--- a/code-generation/language-c/src/main/resources/templates/c/complex-type-template.h.ftlh
+++ b/code-generation/language-c/src/main/resources/templates/c/complex-type-template.h.ftlh
@@ -102,7 +102,7 @@ struct ${helper.getCTypeName(type.name)}_discriminator {
 };
 typedef struct ${helper.getCTypeName(type.name)}_discriminator ${helper.getCTypeName(type.name)}_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum ${helper.getCTypeName(type.name)}_type {
     <#list type.getSubTypeDefinitions() as subtype>
   ${helper.getCTypeName(type.name)}_type_${helper.getCTypeName(subtype.name)} = ${subtype?index}<#sep>,
diff --git a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageOutput.java b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageOutput.java
index 8d5b5d9..11c817e 100644
--- a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageOutput.java
+++ b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageOutput.java
@@ -53,7 +53,7 @@ public class GoLanguageOutput extends FreemarkerLanguageOutput {
     @Override
     protected List<Template> getComplexTypeTemplates(Configuration freemarkerConfiguration) throws IOException {
         return Collections.singletonList(
-            freemarkerConfiguration.getTemplate("templates/go/model-template.go.ftlh"));
+            freemarkerConfiguration.getTemplate("templates/go/complex-type-template.go.ftlh"));
     }
 
     @Override
diff --git a/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/complex-type-template.go.ftlh
similarity index 99%
rename from code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
rename to code-generation/language-go/src/main/resources/templates/go/complex-type-template.go.ftlh
index 256bf73..967a633 100644
--- a/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/complex-type-template.go.ftlh
@@ -900,7 +900,10 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if hasParserArguments>, ${pa
 		if _checksumRefErr != nil {
 			return nil, errors.Wrap(_checksumRefErr, "Error parsing 'checksum' field")<@emitImport import="github.com/pkg/errors" />
 		}
-		checksum := ${helper.toParseExpression(checksumField, checksumField.type, checksumField.checksumExpression, parserArguments)}
+		checksum, _checksumErr:= ${helper.toParseExpression(checksumField, checksumField.type, checksumField.checksumExpression, parserArguments)}
+		if _checksumErr != nil {
+			return nil, errors.Wrap(_checksumErr, "Checksum verification failed")
+		}
 		if checksum != checksumRef {
 			return nil, errors.Errorf("Checksum verification failed. Expected %x but got %x", checksumRef, checksum)<@emitImport import="github.com/pkg/errors" />
 		}
@@ -1528,10 +1531,13 @@ func (m *${type.name}) Serialize(writeBuffer utils.WriteBuffer) error {
 
 	// Checksum Field (checksum) (Calculated)
 	{
-		_checksum := ${helper.toSerializationExpression(checksumField, checksumField.type, checksumField.checksumExpression, parserArguments)}
-		_checksumErr := ${helper.getWriteBufferWriteMethodCall("checksum", simpleTypeReference, "(_checksum)", checksumField)}
+		_checksum, _checksumErr := ${helper.toSerializationExpression(checksumField, checksumField.type, checksumField.checksumExpression, parserArguments)}
 		if _checksumErr != nil {
-			return errors.Wrap(_checksumErr, "Error serializing 'checksum' field")<@emitImport import="github.com/pkg/errors" />
+			return errors.Wrap(_checksumErr, "Checksum calculation failed")<@emitImport import="github.com/pkg/errors" />
+ 		}
+		_checksumWriteErr := ${helper.getWriteBufferWriteMethodCall("checksum", simpleTypeReference, "(_checksum)", checksumField)}
+		if _checksumWriteErr != nil {
+			return errors.Wrap(_checksumWriteErr, "Error serializing 'checksum' field")
 		}
 	}
 					<#break>
diff --git a/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
index 573deb0..b278fff 100644
--- a/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
@@ -69,6 +69,8 @@ func (m ${helper.getSanitizedProtocolName()?cap_first}ParserHelper) Parse(typeNa
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
 		}
+			<#elseif parserArgument.type.isEnumTypeReference()>
+        ${parserArgument.name} := model.${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}ByName(arguments[${parserArgument?index}])
 			<#else>
 		var ${parserArgument.name} model.${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}
 			</#if>
diff --git a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
index 1b86a1e..691c6ac 100644
--- a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
+++ b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
@@ -62,7 +62,7 @@ public class JavaLanguageOutput extends FreemarkerLanguageOutput {
 
     @Override
     protected List<Template> getComplexTypeTemplates(Configuration freemarkerConfiguration) throws IOException {
-        return List.of(freemarkerConfiguration.getTemplate("templates/java/model-template.java.ftlh"));
+        return List.of(freemarkerConfiguration.getTemplate("templates/java/complex-type-template.java.ftlh"));
     }
 
     @Override
diff --git a/code-generation/language-java/src/main/resources/templates/java/model-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
similarity index 99%
rename from code-generation/language-java/src/main/resources/templates/java/model-template.java.ftlh
rename to code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
index 8333edd..237aee2 100644
--- a/code-generation/language-java/src/main/resources/templates/java/model-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
@@ -561,10 +561,10 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
         }
             <#list parserArguments as parserArgument>
                 <#assign languageName=helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)>
-                ${languageName} ${parserArgument.name};
+        ${languageName} ${parserArgument.name};
         if(args[${parserArgument?index}] instanceof ${languageName}) {
             ${parserArgument.name} = (${languageName}) args[${parserArgument?index}];
-                <#if parserArgument.type.isSimpleTypeReference()>
+                <#if parserArgument.type.isSimpleTypeReference() || parserArgument.type.isEnumTypeReference()>
         } else if (args[${parserArgument?index}] instanceof String) {
             ${parserArgument.name} = ${languageName}.valueOf((String) args[${parserArgument?index}]);
                 </#if>
diff --git a/plc4c/drivers/modbus/CMakeLists.txt b/plc4c/drivers/modbus/CMakeLists.txt
index 925035b..6137e91 100644
--- a/plc4c/drivers/modbus/CMakeLists.txt
+++ b/plc4c/drivers/modbus/CMakeLists.txt
@@ -31,6 +31,7 @@ add_library(plc4c-driver-modbus
         src/driver_modbus_sm_disconnect.c
         src/driver_modbus_sm_read.c
         src/driver_modbus_sm_write.c
-        ${generatedSources} include/plc4c/driver_modbus_static.h)
+        src/driver_modbus_static_helper.c
+        ${generatedSources} include/plc4c/driver_modbus_static.h include/plc4c/driver_modbus_static_helper.h src/driver_modbus_static_helper.c)
 
 target_link_libraries(plc4c-driver-modbus plc4c-spi ${CMAKE_DL_LIBS})
\ No newline at end of file
diff --git a/plc4c/drivers/modbus/include/plc4c/driver_s7_encode_decode.h b/plc4c/drivers/modbus/include/plc4c/driver_modbus_encode_decode.h
similarity index 100%
rename from plc4c/drivers/modbus/include/plc4c/driver_s7_encode_decode.h
rename to plc4c/drivers/modbus/include/plc4c/driver_modbus_encode_decode.h
diff --git a/plc4c/drivers/modbus/include/plc4c/driver_modbus_packets.h b/plc4c/drivers/modbus/include/plc4c/driver_modbus_packets.h
index b4bfa0b..7f95ccf 100644
--- a/plc4c/drivers/modbus/include/plc4c/driver_modbus_packets.h
+++ b/plc4c/drivers/modbus/include/plc4c/driver_modbus_packets.h
@@ -25,22 +25,22 @@ extern "C" {
 #include <plc4c/types.h>
 
 #include "driver_modbus.h"
-#include "modbus_tcp_adu.h"
+#include "modbus_adu.h"
 
 plc4c_return_code plc4c_driver_modbus_send_packet(
     plc4c_connection* connection,
-    plc4c_modbus_read_write_modbus_tcp_adu* packet);
+    plc4c_modbus_read_write_modbus_adu* packet);
 plc4c_return_code plc4c_driver_modbus_receive_packet(
     plc4c_connection* connection,
-    plc4c_modbus_read_write_modbus_tcp_adu** packet);
+    plc4c_modbus_read_write_modbus_adu** packet);
 
 plc4c_return_code plc4c_driver_modbus_create_modbus_read_request(
     plc4c_driver_modbus_config* modbus_config,
     plc4c_item* read_request_item,
-    plc4c_modbus_read_write_modbus_tcp_adu** modbus_read_request_packet);
+    plc4c_modbus_read_write_modbus_adu** modbus_read_request_packet);
 plc4c_return_code plc4c_driver_modbus_create_modbus_write_request(
     plc4c_driver_modbus_item* write_request_item,
-    plc4c_modbus_read_write_modbus_tcp_adu** modbus_read_request_packet);
+    plc4c_modbus_read_write_modbus_adu** modbus_read_request_packet);
 
 #ifdef __cplusplus
 }
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java b/plc4c/drivers/modbus/include/plc4c/driver_modbus_static_helper.h
similarity index 68%
copy from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
copy to plc4c/drivers/modbus/include/plc4c/driver_modbus_static_helper.h
index a4e11e0..baaafae 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
+++ b/plc4c/drivers/modbus/include/plc4c/driver_modbus_static_helper.h
@@ -16,14 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.readwrite.utils;
 
-import org.apache.plc4x.java.modbus.readwrite.ModbusPDU;
+#ifndef PLC4C_DRIVER_MODBUS_STATIC_HELPER_H
+#define PLC4C_DRIVER_MODBUS_STATIC_HELPER_H
 
-public class StaticHelper {
+#include "modbus_adu.h"
 
-    public static int crcCheck(short address, ModbusPDU pdu) {
-        return 0;
-    }
+uint16_t plc4c_modbus_read_write_rtu_crc_check(uint8_t address, plc4c_modbus_read_write_modbus_pdu* pdu);
 
-}
+uint8_t plc4c_modbus_read_write_ascii_lrc_check(uint8_t address, plc4c_modbus_read_write_modbus_pdu* pdu);
+
+#endif  // PLC4C_DRIVER_MODBUS_STATIC_HELPER_H
diff --git a/plc4c/drivers/modbus/src/driver_modbus.c b/plc4c/drivers/modbus/src/driver_modbus.c
index a5eec4d..e0989bc 100644
--- a/plc4c/drivers/modbus/src/driver_modbus.c
+++ b/plc4c/drivers/modbus/src/driver_modbus.c
@@ -19,7 +19,7 @@
 
 #include "plc4c/driver_modbus.h"
 #include "plc4c/driver_modbus_sm.h"
-#include "plc4c/driver_s7_encode_decode.h"
+#include "plc4c/driver_modbus_encode_decode.h"
 
 plc4c_return_code plc4c_driver_modbus_configure_function(plc4c_list* parameters,
                                                      void** configuration) {
@@ -41,8 +41,8 @@ plc4c_return_code plc4c_driver_modbus_configure_function(plc4c_list* parameters,
 
 plc4c_driver *plc4c_driver_modbus_create() {
   plc4c_driver *driver = (plc4c_driver *)malloc(sizeof(plc4c_driver));
-  driver->protocol_code = "modbus";
-  driver->protocol_name = "Modbus";
+  driver->protocol_code = "modbus-tcp";
+  driver->protocol_name = "Modbus TCP";
   driver->default_transport_code = "tcp";
   driver->parse_address_function = &plc4c_driver_modbus_encode_address;
   driver->configure_function = &plc4c_driver_modbus_configure_function;
diff --git a/plc4c/drivers/modbus/src/driver_modbus_encode_decode.c b/plc4c/drivers/modbus/src/driver_modbus_encode_decode.c
index 4376951..6055165 100644
--- a/plc4c/drivers/modbus/src/driver_modbus_encode_decode.c
+++ b/plc4c/drivers/modbus/src/driver_modbus_encode_decode.c
@@ -21,7 +21,7 @@
 #include <plc4c/driver_modbus.h>
 #include <string.h>
 
-#include "plc4c/driver_s7_encode_decode.h"
+#include "plc4c/driver_modbus_encode_decode.h"
 
 plc4c_return_code plc4c_driver_modbus_encode_address(char* address,
                                                      void** item) {
diff --git a/plc4c/drivers/modbus/src/driver_modbus_packets.c b/plc4c/drivers/modbus/src/driver_modbus_packets.c
index 0cfffde..aa4c1ee 100644
--- a/plc4c/drivers/modbus/src/driver_modbus_packets.c
+++ b/plc4c/drivers/modbus/src/driver_modbus_packets.c
@@ -17,11 +17,10 @@
  * under the License.
  */
 
-#include <ctype.h>
 #include <plc4c/spi/types_private.h>
 #include <stdlib.h>
 
-#include "modbus_tcp_adu.h"
+#include "modbus_adu.h"
 #include "plc4c/driver_modbus.h"
 
 #define MIN(a,b) (((a)<(b))?(a):(b))
@@ -52,10 +51,10 @@ int16_t plc4c_driver_modbus_select_message_function(uint8_t* buffer_data,
 
 plc4c_return_code plc4c_driver_modbus_send_packet(
     plc4c_connection* connection,
-    plc4c_modbus_read_write_modbus_tcp_adu* packet) {
+    plc4c_modbus_read_write_modbus_adu* packet) {
   // Get the size required to contain the serialized form of this packet.
   uint16_t packet_size =
-      plc4c_modbus_read_write_modbus_tcp_adu_length_in_bytes(packet);
+      plc4c_modbus_read_write_modbus_adu_length_in_bytes(packet);
 
   // Serialize this message to a byte-array.
   plc4c_spi_write_buffer* write_buffer;
@@ -64,7 +63,8 @@ plc4c_return_code plc4c_driver_modbus_send_packet(
   if (return_code != OK) {
     return return_code;
   }
-  return_code = plc4c_modbus_read_write_modbus_tcp_adu_serialize(write_buffer, packet);
+  return_code = plc4c_modbus_read_write_modbus_adu_serialize(
+      write_buffer, packet);
   if (return_code != OK) {
     return return_code;
   }
@@ -81,7 +81,7 @@ plc4c_return_code plc4c_driver_modbus_send_packet(
 
 plc4c_return_code plc4c_driver_modbus_receive_packet(
     plc4c_connection* connection,
-    plc4c_modbus_read_write_modbus_tcp_adu** packet) {
+    plc4c_modbus_read_write_modbus_adu** packet) {
   // Check with the transport if there is a packet available.
   // If it is, get a read_buffer for reading it.
   plc4c_spi_read_buffer* read_buffer;
@@ -95,8 +95,12 @@ plc4c_return_code plc4c_driver_modbus_receive_packet(
 
   // Parse the packet by consuming the read_buffer data.
   *packet = NULL;
+  plc4c_modbus_read_write_driver_type driver_type =
+      plc4c_modbus_read_write_driver_type_MODBUS_TCP;
+
   return_code =
-      plc4c_modbus_read_write_modbus_tcp_adu_parse(read_buffer, true, packet);
+      plc4c_modbus_read_write_modbus_adu_parse(
+          read_buffer,&driver_type, true, packet);
   if (return_code != OK) {
     return return_code;
   }
@@ -108,7 +112,7 @@ plc4c_return_code plc4c_driver_modbus_receive_packet(
 plc4c_return_code plc4c_driver_modbus_create_modbus_read_request(
     plc4c_driver_modbus_config* modbus_config,
     plc4c_item* read_request_item,
-    plc4c_modbus_read_write_modbus_tcp_adu** modbus_read_request_packet) {
+    plc4c_modbus_read_write_modbus_adu** modbus_read_request_packet) {
 
   plc4c_modbus_read_write_modbus_pdu* pdu =
       malloc(sizeof(plc4c_modbus_read_write_modbus_pdu));
@@ -154,22 +158,23 @@ plc4c_return_code plc4c_driver_modbus_create_modbus_read_request(
     }
   }
 
-  plc4c_modbus_read_write_modbus_tcp_adu* tcp_adu =
-      malloc(sizeof(plc4c_modbus_read_write_modbus_tcp_adu));
-  if (tcp_adu == NULL) {
+  plc4c_modbus_read_write_modbus_adu* adu =
+      malloc(sizeof(plc4c_modbus_read_write_modbus_adu));
+  if (adu == NULL) {
     return NO_MEMORY;
   }
-  tcp_adu->transaction_identifier = modbus_config->communication_id_counter++;
-  tcp_adu->unit_identifier = modbus_config->unit_identifier;
-  tcp_adu->pdu = pdu;
-  *modbus_read_request_packet = tcp_adu;
+  adu->_type = plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_tcp_adu;
+  adu->modbus_tcp_adu_transaction_identifier = modbus_config->communication_id_counter++;
+  adu->modbus_tcp_adu_unit_identifier = modbus_config->unit_identifier;
+  adu->modbus_tcp_adu_pdu = pdu;
+  *modbus_read_request_packet = adu;
 
   return OK;
 }
 
 plc4c_return_code plc4c_driver_modbus_create_modbus_write_request(
     plc4c_write_request* write_request,
-    plc4c_modbus_read_write_modbus_tcp_adu** modbus_read_request_packet) {
+    plc4c_modbus_read_write_modbus_adu** modbus_read_request_packet) {
   // TODO: Implement this ...
 
   return OK;
diff --git a/plc4c/drivers/modbus/src/driver_modbus_sm_read.c b/plc4c/drivers/modbus/src/driver_modbus_sm_read.c
index a52e2ae..a2e59de 100644
--- a/plc4c/drivers/modbus/src/driver_modbus_sm_read.c
+++ b/plc4c/drivers/modbus/src/driver_modbus_sm_read.c
@@ -20,7 +20,7 @@
 #include <plc4c/spi/types_private.h>
 #include <stdlib.h>
 #include "plc4c/driver_modbus_packets.h"
-#include "modbus_tcp_adu.h"
+#include "modbus_adu.h"
 #include "data_item.h"
 
 enum plc4c_driver_modbus_read_states {
@@ -66,7 +66,7 @@ plc4c_return_code plc4c_driver_modbus_read_machine_function(
     }
 
     case PLC4C_DRIVER_MODBUS_READ_SEND_ITEM_REQUEST: {
-      plc4c_modbus_read_write_modbus_tcp_adu* modbus_read_request_packet;
+      plc4c_modbus_read_write_modbus_adu* modbus_read_request_packet;
       plc4c_return_code return_code =
           plc4c_driver_modbus_create_modbus_read_request(
               modbus_config,
@@ -88,7 +88,7 @@ plc4c_return_code plc4c_driver_modbus_read_machine_function(
     }
     case PLC4C_DRIVER_MODBUS_READ_HANDLE_ITEM_RESPONSE: {
       // Read a response packet.
-      plc4c_modbus_read_write_modbus_tcp_adu* modbus_read_response_packet;
+      plc4c_modbus_read_write_modbus_adu* modbus_read_response_packet;
       plc4c_return_code return_code = plc4c_driver_modbus_receive_packet(
           connection, &modbus_read_response_packet);
       // If we haven't read enough to process a full message, just try again
@@ -105,35 +105,35 @@ plc4c_return_code plc4c_driver_modbus_read_machine_function(
       plc4c_list* response_value;
       switch (modbus_item->type) {
         case PLC4C_DRIVER_MODBUS_ADDRESS_TYPE_COIL: {
-          if(modbus_read_response_packet->pdu->_type !=
+          if(modbus_read_response_packet->modbus_tcp_adu_pdu->_type !=
               plc4c_modbus_read_write_modbus_pdu_type_plc4c_modbus_read_write_modbus_pdu_read_coils_response) {
             return INTERNAL_ERROR;
           }
-          response_value = modbus_read_response_packet->pdu->modbus_pdu_read_coils_response_value;
+          response_value = modbus_read_response_packet->modbus_tcp_adu_pdu->modbus_pdu_read_coils_response_value;
           break;
         }
         case PLC4C_DRIVER_MODBUS_ADDRESS_TYPE_DISCRETE_INPUT: {
-          if(modbus_read_response_packet->pdu->_type !=
+          if(modbus_read_response_packet->modbus_tcp_adu_pdu->_type !=
               plc4c_modbus_read_write_modbus_pdu_type_plc4c_modbus_read_write_modbus_pdu_read_discrete_inputs_response) {
             return INTERNAL_ERROR;
           }
-          response_value = modbus_read_response_packet->pdu->modbus_pdu_read_discrete_inputs_response_value;
+          response_value = modbus_read_response_packet->modbus_tcp_adu_pdu->modbus_pdu_read_discrete_inputs_response_value;
           break;
         }
         case PLC4C_DRIVER_MODBUS_ADDRESS_TYPE_INPUT_REGISTER: {
-          if(modbus_read_response_packet->pdu->_type !=
+          if(modbus_read_response_packet->modbus_tcp_adu_pdu->_type !=
               plc4c_modbus_read_write_modbus_pdu_type_plc4c_modbus_read_write_modbus_pdu_read_input_registers_response) {
             return INTERNAL_ERROR;
           }
-          response_value = modbus_read_response_packet->pdu->modbus_pdu_read_input_registers_response_value;
+          response_value = modbus_read_response_packet->modbus_tcp_adu_pdu->modbus_pdu_read_input_registers_response_value;
           break;
         }
         case PLC4C_DRIVER_MODBUS_ADDRESS_TYPE_HOLDING_REGISTER: {
-          if(modbus_read_response_packet->pdu->_type !=
+          if(modbus_read_response_packet->modbus_tcp_adu_pdu->_type !=
               plc4c_modbus_read_write_modbus_pdu_type_plc4c_modbus_read_write_modbus_pdu_read_holding_registers_response) {
             return INTERNAL_ERROR;
           }
-          response_value = modbus_read_response_packet->pdu->modbus_pdu_read_holding_registers_response_value;
+          response_value = modbus_read_response_packet->modbus_tcp_adu_pdu->modbus_pdu_read_holding_registers_response_value;
           break;
         }
         case PLC4C_DRIVER_MODBUS_ADDRESS_TYPE_EXTENDED_REGISTER: {
diff --git a/plc4c/drivers/modbus/src/driver_modbus_sm_write.c b/plc4c/drivers/modbus/src/driver_modbus_sm_write.c
index c3b0b09..4c9698b 100644
--- a/plc4c/drivers/modbus/src/driver_modbus_sm_write.c
+++ b/plc4c/drivers/modbus/src/driver_modbus_sm_write.c
@@ -17,12 +17,10 @@
  * under the License.
  */
 
-#include <plc4c/plc4c.h>
 #include <plc4c/spi/types_private.h>
 #include <stdlib.h>
-#include <string.h>
 #include "plc4c/driver_modbus_packets.h"
-#include "modbus_tcp_adu.h"
+#include "modbus_adu.h"
 
 enum plc4c_driver_modbus_write_states {
   PLC4C_DRIVER_MODBUS_WRITE_INIT,
@@ -46,7 +44,7 @@ plc4c_return_code plc4c_driver_modbus_write_machine_function(
 
   switch (task->state_id) {
     case PLC4C_DRIVER_MODBUS_WRITE_INIT: {
-      plc4c_modbus_read_write_modbus_tcp_adu* modbus_write_request_packet;
+      plc4c_modbus_read_write_modbus_adu* modbus_write_request_packet;
       plc4c_return_code return_code =
           plc4c_driver_modbus_create_modbus_write_request(
               write_request, &modbus_write_request_packet);
@@ -66,7 +64,7 @@ plc4c_return_code plc4c_driver_modbus_write_machine_function(
     }
     case PLC4C_DRIVER_MODBUS_WRITE_FINISHED: {
       // Read a response packet.
-      plc4c_modbus_read_write_modbus_tcp_adu* modbus_write_response_packet;
+      plc4c_modbus_read_write_modbus_adu* modbus_write_response_packet;
       plc4c_return_code return_code =
           plc4c_driver_modbus_receive_packet(
               connection, &modbus_write_response_packet);
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java b/plc4c/drivers/modbus/src/driver_modbus_static_helper.c
similarity index 73%
copy from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
copy to plc4c/drivers/modbus/src/driver_modbus_static_helper.c
index a4e11e0..63ee8ea 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
+++ b/plc4c/drivers/modbus/src/driver_modbus_static_helper.c
@@ -16,14 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.readwrite.utils;
 
-import org.apache.plc4x.java.modbus.readwrite.ModbusPDU;
+#import "plc4c/driver_modbus_static_helper.h"
 
-public class StaticHelper {
-
-    public static int crcCheck(short address, ModbusPDU pdu) {
-        return 0;
-    }
+uint16_t plc4c_modbus_read_write_rtu_crc_check(uint8_t address, plc4c_modbus_read_write_modbus_pdu* pdu) {
+  return 0;
+}
 
+uint8_t plc4c_modbus_read_write_ascii_lrc_check(uint8_t address, plc4c_modbus_read_write_modbus_pdu* pdu) {
+  return 0;
 }
diff --git a/plc4c/drivers/s7/CMakeLists.txt b/plc4c/drivers/s7/CMakeLists.txt
index 3f76524..bb6e95b 100644
--- a/plc4c/drivers/s7/CMakeLists.txt
+++ b/plc4c/drivers/s7/CMakeLists.txt
@@ -25,7 +25,7 @@ file(GLOB generatedSources "../../generated-sources/s7/src/*.c")
 
 add_library(plc4c-driver-s7
         src/driver_s7.c
-        src/driver_s7_encode_decode.c
+        src/driver_modbus_encode_decode.c
         src/driver_s7_packets.c
         src/driver_s7_sm_connect.c
         src/driver_s7_sm_disconnect.c
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go b/plc4c/drivers/s7/include/plc4c/driver_s7_static_helper.h
similarity index 86%
copy from plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go
copy to plc4c/drivers/s7/include/plc4c/driver_s7_static_helper.h
index 07ff539..86bd094 100644
--- a/plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go
+++ b/plc4c/drivers/s7/include/plc4c/driver_s7_static_helper.h
@@ -17,9 +17,9 @@
  * under the License.
  */
 
-package model
+#ifndef PLC4C_DRIVER_S7_STATIC_HELPER_H
+#define PLC4C_DRIVER_S7_STATIC_HELPER_H
 
-func CrcCheck(address uint8, modbusPDU *ModbusPDU) uint16 {
-	// TODO: implement me
-	return 0
-}
+
+
+#endif  // PLC4C_DRIVER_S7_STATIC_HELPER_H
diff --git a/plc4c/drivers/s7/src/driver_s7_encode_decode.c b/plc4c/drivers/s7/src/driver_modbus_encode_decode.c
similarity index 100%
rename from plc4c/drivers/s7/src/driver_s7_encode_decode.c
rename to plc4c/drivers/s7/src/driver_modbus_encode_decode.c
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go b/plc4c/drivers/simulated/include/plc4c/static_helper.h
similarity index 88%
copy from plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go
copy to plc4c/drivers/simulated/include/plc4c/static_helper.h
index 07ff539..7001531 100644
--- a/plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go
+++ b/plc4c/drivers/simulated/include/plc4c/static_helper.h
@@ -17,9 +17,9 @@
  * under the License.
  */
 
-package model
+#ifndef PLC4C_STATIC_HELPER_H
+#define PLC4C_STATIC_HELPER_H
 
-func CrcCheck(address uint8, modbusPDU *ModbusPDU) uint16 {
-	// TODO: implement me
-	return 0
-}
+
+
+#endif  // PLC4C_STATIC_HELPER_H
diff --git a/plc4c/examples/hello-world-modbus/src/hello_world_modbus.c b/plc4c/examples/hello-world-modbus/src/hello_world_modbus.c
index 75c63fa..ed4b174 100644
--- a/plc4c/examples/hello-world-modbus/src/hello_world_modbus.c
+++ b/plc4c/examples/hello-world-modbus/src/hello_world_modbus.c
@@ -109,8 +109,8 @@ int main() {
 
   // Establish connections to remote devices
   // you may or may not care about the connection handle
-  printf("Connecting to 'modbus:tcp://192.168.23.30' ... ");
-  result = plc4c_system_connect(system, "modbus:tcp://192.168.23.30:502", &connection);
+  printf("Connecting to 'modbus-tcp://192.168.23.30' ... ");
+  result = plc4c_system_connect(system, "modbus-tcp://192.168.23.30:502", &connection);
   if (result != OK) {
     printf("FAILED\n");
     return -1;
diff --git a/plc4c/generated-sources/modbus/include/driver_type.h b/plc4c/generated-sources/modbus/include/driver_type.h
new file mode 100644
index 0000000..6f11fc7
--- /dev/null
+++ b/plc4c/generated-sources/modbus/include/driver_type.h
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef PLC4C_MODBUS_READ_WRITE_DRIVER_TYPE_H_
+#define PLC4C_MODBUS_READ_WRITE_DRIVER_TYPE_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <plc4c/driver_modbus_static.h>
+#include <plc4c/spi/read_buffer.h>
+#include <plc4c/spi/write_buffer.h>
+
+// Code generated by code-generation. DO NOT EDIT.
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum plc4c_modbus_read_write_driver_type {
+  plc4c_modbus_read_write_driver_type_MODBUS_TCP = 0x01,
+  plc4c_modbus_read_write_driver_type_MODBUS_RTU = 0x02,
+  plc4c_modbus_read_write_driver_type_MODBUS_ASCII = 0x03
+};
+typedef enum plc4c_modbus_read_write_driver_type plc4c_modbus_read_write_driver_type;
+
+// Get an empty NULL-struct
+plc4c_modbus_read_write_driver_type plc4c_modbus_read_write_driver_type_null();
+
+plc4c_return_code plc4c_modbus_read_write_driver_type_parse(plc4c_spi_read_buffer* readBuffer, plc4c_modbus_read_write_driver_type** message);
+
+plc4c_return_code plc4c_modbus_read_write_driver_type_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_driver_type* message);
+
+plc4c_modbus_read_write_driver_type plc4c_modbus_read_write_driver_type_value_of(char* value_string);
+
+int plc4c_modbus_read_write_driver_type_num_values();
+
+plc4c_modbus_read_write_driver_type plc4c_modbus_read_write_driver_type_value_for_index(int index);
+
+uint16_t plc4c_modbus_read_write_driver_type_length_in_bytes(plc4c_modbus_read_write_driver_type* message);
+
+uint16_t plc4c_modbus_read_write_driver_type_length_in_bits(plc4c_modbus_read_write_driver_type* message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // PLC4C_MODBUS_READ_WRITE_DRIVER_TYPE_H_
diff --git a/plc4c/generated-sources/modbus/include/modbus_adu.h b/plc4c/generated-sources/modbus/include/modbus_adu.h
new file mode 100644
index 0000000..f82006e
--- /dev/null
+++ b/plc4c/generated-sources/modbus/include/modbus_adu.h
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef PLC4C_MODBUS_READ_WRITE_MODBUS_ADU_H_
+#define PLC4C_MODBUS_READ_WRITE_MODBUS_ADU_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <plc4c/driver_modbus_static.h>
+#include <plc4c/spi/read_buffer.h>
+#include <plc4c/spi/write_buffer.h>
+#include <plc4c/utils/list.h>
+#include "modbus_pdu.h"
+#include "driver_type.h"
+#include "driver_type.h"
+
+// Code generated by code-generation. DO NOT EDIT.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Structure used to contain the discriminator values for discriminated types using this as a parent
+struct plc4c_modbus_read_write_modbus_adu_discriminator {
+  enum plc4c_modbus_read_write_driver_type driverType;
+};
+typedef struct plc4c_modbus_read_write_modbus_adu_discriminator plc4c_modbus_read_write_modbus_adu_discriminator;
+
+// Enum assigning each subtype an individual id.
+enum plc4c_modbus_read_write_modbus_adu_type {
+  plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_tcp_adu = 0,
+  plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_rtu_adu = 1,
+  plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_ascii_adu = 2};
+typedef enum plc4c_modbus_read_write_modbus_adu_type plc4c_modbus_read_write_modbus_adu_type;
+
+// Function to get the discriminator values for a given type.
+plc4c_modbus_read_write_modbus_adu_discriminator plc4c_modbus_read_write_modbus_adu_get_discriminator(plc4c_modbus_read_write_modbus_adu_type type);
+
+// Constant values.
+uint16_t PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER();
+
+struct plc4c_modbus_read_write_modbus_adu {
+  /* This is an abstract type so this property saves the type of this typed union */
+  plc4c_modbus_read_write_modbus_adu_type _type;
+  /* Properties */
+  union {
+    struct { /* ModbusTcpADU */
+      uint16_t modbus_tcp_adu_transaction_identifier;
+      uint8_t modbus_tcp_adu_unit_identifier;
+      plc4c_modbus_read_write_modbus_pdu* modbus_tcp_adu_pdu;
+    };
+    struct { /* ModbusRtuADU */
+      uint8_t modbus_rtu_adu_address;
+      plc4c_modbus_read_write_modbus_pdu* modbus_rtu_adu_pdu;
+    };
+    struct { /* ModbusAsciiADU */
+      uint8_t modbus_ascii_adu_address;
+      plc4c_modbus_read_write_modbus_pdu* modbus_ascii_adu_pdu;
+    };
+  };
+};
+typedef struct plc4c_modbus_read_write_modbus_adu plc4c_modbus_read_write_modbus_adu;
+
+// Create an empty NULL-struct
+plc4c_modbus_read_write_modbus_adu plc4c_modbus_read_write_modbus_adu_null();
+
+plc4c_return_code plc4c_modbus_read_write_modbus_adu_parse(plc4c_spi_read_buffer* readBuffer, plc4c_modbus_read_write_driver_type* driverType, bool response, plc4c_modbus_read_write_modbus_adu** message);
+
+plc4c_return_code plc4c_modbus_read_write_modbus_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_adu* message);
+
+uint16_t plc4c_modbus_read_write_modbus_adu_length_in_bytes(plc4c_modbus_read_write_modbus_adu* message);
+
+uint16_t plc4c_modbus_read_write_modbus_adu_length_in_bits(plc4c_modbus_read_write_modbus_adu* message);
+
+#ifdef __cplusplus
+}
+#endif
+#endif  // PLC4C_MODBUS_READ_WRITE_MODBUS_ADU_H_
diff --git a/plc4c/generated-sources/modbus/include/modbus_ascii_adu.h b/plc4c/generated-sources/modbus/include/modbus_ascii_adu.h
deleted file mode 100644
index ae827ef..0000000
--- a/plc4c/generated-sources/modbus/include/modbus_ascii_adu.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_H_
-#define PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <plc4c/driver_modbus_static.h>
-#include <plc4c/spi/read_buffer.h>
-#include <plc4c/spi/write_buffer.h>
-#include <plc4c/utils/list.h>
-#include "modbus_pdu.h"
-
-// Code generated by code-generation. DO NOT EDIT.
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-// Constant values.
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_START();
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_CR();
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_LF();
-
-struct plc4c_modbus_read_write_modbus_ascii_adu {
-  /* Properties */
-  uint8_t start;
-  uint8_t address;
-  plc4c_modbus_read_write_modbus_pdu* pdu;
-  uint8_t cr;
-  uint8_t lf;
-};
-typedef struct plc4c_modbus_read_write_modbus_ascii_adu plc4c_modbus_read_write_modbus_ascii_adu;
-
-// Create an empty NULL-struct
-plc4c_modbus_read_write_modbus_ascii_adu plc4c_modbus_read_write_modbus_ascii_adu_null();
-
-plc4c_return_code plc4c_modbus_read_write_modbus_ascii_adu_parse(plc4c_spi_read_buffer* readBuffer, bool response, plc4c_modbus_read_write_modbus_ascii_adu** message);
-
-plc4c_return_code plc4c_modbus_read_write_modbus_ascii_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_ascii_adu* message);
-
-uint16_t plc4c_modbus_read_write_modbus_ascii_adu_length_in_bytes(plc4c_modbus_read_write_modbus_ascii_adu* message);
-
-uint16_t plc4c_modbus_read_write_modbus_ascii_adu_length_in_bits(plc4c_modbus_read_write_modbus_ascii_adu* message);
-
-#ifdef __cplusplus
-}
-#endif
-#endif  // PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_H_
diff --git a/plc4c/generated-sources/modbus/include/modbus_pdu.h b/plc4c/generated-sources/modbus/include/modbus_pdu.h
index ec0b7df..ef048fd 100644
--- a/plc4c/generated-sources/modbus/include/modbus_pdu.h
+++ b/plc4c/generated-sources/modbus/include/modbus_pdu.h
@@ -51,7 +51,7 @@ struct plc4c_modbus_read_write_modbus_pdu_discriminator {
 };
 typedef struct plc4c_modbus_read_write_modbus_pdu_discriminator plc4c_modbus_read_write_modbus_pdu_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_modbus_read_write_modbus_pdu_type {
   plc4c_modbus_read_write_modbus_pdu_type_plc4c_modbus_read_write_modbus_pdu_error = 0,
   plc4c_modbus_read_write_modbus_pdu_type_plc4c_modbus_read_write_modbus_pdu_read_discrete_inputs_request = 1,
diff --git a/plc4c/generated-sources/modbus/include/modbus_rtu_adu.h b/plc4c/generated-sources/modbus/include/modbus_rtu_adu.h
deleted file mode 100644
index 08d1b84..0000000
--- a/plc4c/generated-sources/modbus/include/modbus_rtu_adu.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_H_
-#define PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <plc4c/driver_modbus_static.h>
-#include <plc4c/spi/read_buffer.h>
-#include <plc4c/spi/write_buffer.h>
-#include <plc4c/utils/list.h>
-#include "modbus_pdu.h"
-
-// Code generated by code-generation. DO NOT EDIT.
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-// Constant values.
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE1();
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE2();
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE3();
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE4();
-
-struct plc4c_modbus_read_write_modbus_rtu_adu {
-  /* Properties */
-  uint8_t space1;
-  uint8_t space2;
-  uint8_t space3;
-  uint8_t space4;
-  uint8_t address;
-  plc4c_modbus_read_write_modbus_pdu* pdu;
-};
-typedef struct plc4c_modbus_read_write_modbus_rtu_adu plc4c_modbus_read_write_modbus_rtu_adu;
-
-// Create an empty NULL-struct
-plc4c_modbus_read_write_modbus_rtu_adu plc4c_modbus_read_write_modbus_rtu_adu_null();
-
-plc4c_return_code plc4c_modbus_read_write_modbus_rtu_adu_parse(plc4c_spi_read_buffer* readBuffer, bool response, plc4c_modbus_read_write_modbus_rtu_adu** message);
-
-plc4c_return_code plc4c_modbus_read_write_modbus_rtu_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_rtu_adu* message);
-
-uint16_t plc4c_modbus_read_write_modbus_rtu_adu_length_in_bytes(plc4c_modbus_read_write_modbus_rtu_adu* message);
-
-uint16_t plc4c_modbus_read_write_modbus_rtu_adu_length_in_bits(plc4c_modbus_read_write_modbus_rtu_adu* message);
-
-#ifdef __cplusplus
-}
-#endif
-#endif  // PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_H_
diff --git a/plc4c/generated-sources/modbus/include/modbus_serial_adu.h b/plc4c/generated-sources/modbus/include/modbus_serial_adu.h
deleted file mode 100644
index 0f1dfac..0000000
--- a/plc4c/generated-sources/modbus/include/modbus_serial_adu.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef PLC4C_MODBUS_READ_WRITE_MODBUS_SERIAL_ADU_H_
-#define PLC4C_MODBUS_READ_WRITE_MODBUS_SERIAL_ADU_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <plc4c/driver_modbus_static.h>
-#include <plc4c/spi/read_buffer.h>
-#include <plc4c/spi/write_buffer.h>
-#include <plc4c/utils/list.h>
-#include "modbus_pdu.h"
-
-// Code generated by code-generation. DO NOT EDIT.
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-struct plc4c_modbus_read_write_modbus_serial_adu {
-  /* Properties */
-  uint8_t address;
-  plc4c_modbus_read_write_modbus_pdu* pdu;
-};
-typedef struct plc4c_modbus_read_write_modbus_serial_adu plc4c_modbus_read_write_modbus_serial_adu;
-
-// Create an empty NULL-struct
-plc4c_modbus_read_write_modbus_serial_adu plc4c_modbus_read_write_modbus_serial_adu_null();
-
-plc4c_return_code plc4c_modbus_read_write_modbus_serial_adu_parse(plc4c_spi_read_buffer* readBuffer, bool response, plc4c_modbus_read_write_modbus_serial_adu** message);
-
-plc4c_return_code plc4c_modbus_read_write_modbus_serial_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_serial_adu* message);
-
-uint16_t plc4c_modbus_read_write_modbus_serial_adu_length_in_bytes(plc4c_modbus_read_write_modbus_serial_adu* message);
-
-uint16_t plc4c_modbus_read_write_modbus_serial_adu_length_in_bits(plc4c_modbus_read_write_modbus_serial_adu* message);
-
-#ifdef __cplusplus
-}
-#endif
-#endif  // PLC4C_MODBUS_READ_WRITE_MODBUS_SERIAL_ADU_H_
diff --git a/plc4c/generated-sources/modbus/include/modbus_tcp_adu.h b/plc4c/generated-sources/modbus/include/modbus_tcp_adu.h
deleted file mode 100644
index 63da893..0000000
--- a/plc4c/generated-sources/modbus/include/modbus_tcp_adu.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_H_
-#define PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <plc4c/driver_modbus_static.h>
-#include <plc4c/spi/read_buffer.h>
-#include <plc4c/spi/write_buffer.h>
-#include <plc4c/utils/list.h>
-#include "modbus_pdu.h"
-
-// Code generated by code-generation. DO NOT EDIT.
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-// Constant values.
-uint16_t PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER();
-
-struct plc4c_modbus_read_write_modbus_tcp_adu {
-  /* Properties */
-  uint16_t transaction_identifier;
-  uint16_t protocol_identifier;
-  uint8_t unit_identifier;
-  plc4c_modbus_read_write_modbus_pdu* pdu;
-};
-typedef struct plc4c_modbus_read_write_modbus_tcp_adu plc4c_modbus_read_write_modbus_tcp_adu;
-
-// Create an empty NULL-struct
-plc4c_modbus_read_write_modbus_tcp_adu plc4c_modbus_read_write_modbus_tcp_adu_null();
-
-plc4c_return_code plc4c_modbus_read_write_modbus_tcp_adu_parse(plc4c_spi_read_buffer* readBuffer, bool response, plc4c_modbus_read_write_modbus_tcp_adu** message);
-
-plc4c_return_code plc4c_modbus_read_write_modbus_tcp_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_tcp_adu* message);
-
-uint16_t plc4c_modbus_read_write_modbus_tcp_adu_length_in_bytes(plc4c_modbus_read_write_modbus_tcp_adu* message);
-
-uint16_t plc4c_modbus_read_write_modbus_tcp_adu_length_in_bits(plc4c_modbus_read_write_modbus_tcp_adu* message);
-
-#ifdef __cplusplus
-}
-#endif
-#endif  // PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_H_
diff --git a/plc4c/generated-sources/modbus/src/driver_type.c b/plc4c/generated-sources/modbus/src/driver_type.c
new file mode 100644
index 0000000..90f6616
--- /dev/null
+++ b/plc4c/generated-sources/modbus/src/driver_type.c
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "driver_type.h"
+#include <string.h>
+
+// Code generated by code-generation. DO NOT EDIT.
+
+
+// Create an empty NULL-struct
+static const plc4c_modbus_read_write_driver_type plc4c_modbus_read_write_driver_type_null_const;
+
+plc4c_modbus_read_write_driver_type plc4c_modbus_read_write_driver_type_null() {
+  return plc4c_modbus_read_write_driver_type_null_const;
+}
+
+// Parse function.
+plc4c_return_code plc4c_modbus_read_write_driver_type_parse(plc4c_spi_read_buffer* readBuffer, plc4c_modbus_read_write_driver_type** _message) {
+    plc4c_return_code _res = OK;
+
+    // Allocate enough memory to contain this data structure.
+    (*_message) = malloc(sizeof(plc4c_modbus_read_write_driver_type));
+    if(*_message == NULL) {
+        return NO_MEMORY;
+    }
+
+    _res = plc4c_spi_read_unsigned_int(readBuffer, 32, (uint32_t*) *_message);
+
+    return _res;
+}
+
+plc4c_return_code plc4c_modbus_read_write_driver_type_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_driver_type* _message) {
+    plc4c_return_code _res = OK;
+
+    _res = plc4c_spi_write_unsigned_int(writeBuffer, 32, *_message);
+
+    return _res;
+}
+
+plc4c_modbus_read_write_driver_type plc4c_modbus_read_write_driver_type_value_of(char* value_string) {
+    if(strcmp(value_string, "MODBUS_TCP") == 0) {
+        return plc4c_modbus_read_write_driver_type_MODBUS_TCP;
+    }
+    if(strcmp(value_string, "MODBUS_RTU") == 0) {
+        return plc4c_modbus_read_write_driver_type_MODBUS_RTU;
+    }
+    if(strcmp(value_string, "MODBUS_ASCII") == 0) {
+        return plc4c_modbus_read_write_driver_type_MODBUS_ASCII;
+    }
+    return -1;
+}
+
+int plc4c_modbus_read_write_driver_type_num_values() {
+  return 3;
+}
+
+plc4c_modbus_read_write_driver_type plc4c_modbus_read_write_driver_type_value_for_index(int index) {
+    switch(index) {
+      case 0: {
+        return plc4c_modbus_read_write_driver_type_MODBUS_TCP;
+      }
+      case 1: {
+        return plc4c_modbus_read_write_driver_type_MODBUS_RTU;
+      }
+      case 2: {
+        return plc4c_modbus_read_write_driver_type_MODBUS_ASCII;
+      }
+      default: {
+        return -1;
+      }
+    }
+}
+
+uint16_t plc4c_modbus_read_write_driver_type_length_in_bytes(plc4c_modbus_read_write_driver_type* _message) {
+    return plc4c_modbus_read_write_driver_type_length_in_bits(_message) / 8;
+}
+
+uint16_t plc4c_modbus_read_write_driver_type_length_in_bits(plc4c_modbus_read_write_driver_type* _message) {
+    return 32;
+}
diff --git a/plc4c/generated-sources/modbus/src/modbus_adu.c b/plc4c/generated-sources/modbus/src/modbus_adu.c
new file mode 100644
index 0000000..0dc4592
--- /dev/null
+++ b/plc4c/generated-sources/modbus/src/modbus_adu.c
@@ -0,0 +1,349 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdio.h>
+#include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_modbus_static_helper.h>
+#include "modbus_adu.h"
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// Array of discriminator values that match the enum type constants.
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
+const plc4c_modbus_read_write_modbus_adu_discriminator plc4c_modbus_read_write_modbus_adu_discriminators[] = {
+  {/* plc4c_modbus_read_write_modbus_tcp_adu */
+   .driverType = plc4c_modbus_read_write_driver_type_MODBUS_TCP },
+  {/* plc4c_modbus_read_write_modbus_rtu_adu */
+   .driverType = plc4c_modbus_read_write_driver_type_MODBUS_RTU },
+  {/* plc4c_modbus_read_write_modbus_ascii_adu */
+   .driverType = plc4c_modbus_read_write_driver_type_MODBUS_ASCII }
+
+};
+
+// Function returning the discriminator values for a given type constant.
+plc4c_modbus_read_write_modbus_adu_discriminator plc4c_modbus_read_write_modbus_adu_get_discriminator(plc4c_modbus_read_write_modbus_adu_type type) {
+  return plc4c_modbus_read_write_modbus_adu_discriminators[type];
+}
+
+// Create an empty NULL-struct
+static const plc4c_modbus_read_write_modbus_adu plc4c_modbus_read_write_modbus_adu_null_const;
+
+plc4c_modbus_read_write_modbus_adu plc4c_modbus_read_write_modbus_adu_null() {
+  return plc4c_modbus_read_write_modbus_adu_null_const;
+}
+
+
+// Constant values.
+static const uint16_t PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER_const = 0x0000;
+uint16_t PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER() {
+  return PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER_const;
+}
+
+// Parse function.
+plc4c_return_code plc4c_modbus_read_write_modbus_adu_parse(plc4c_spi_read_buffer* readBuffer, plc4c_modbus_read_write_driver_type* driverType, bool response, plc4c_modbus_read_write_modbus_adu** _message) {
+  uint16_t startPos = plc4c_spi_read_get_pos(readBuffer);
+  plc4c_return_code _res = OK;
+
+  // Allocate enough memory to contain this data structure.
+  (*_message) = malloc(sizeof(plc4c_modbus_read_write_modbus_adu));
+  if(*_message == NULL) {
+    return NO_MEMORY;
+  }
+
+    // Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
+if( driverType == plc4c_modbus_read_write_driver_type_MODBUS_TCP ) { /* ModbusTcpADU */
+    (*_message)->_type = plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_tcp_adu;
+
+  // Simple Field (transactionIdentifier)
+  uint16_t transactionIdentifier = 0;
+  _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &transactionIdentifier);
+  if(_res != OK) {
+    return _res;
+  }
+  (*_message)->modbus_tcp_adu_transaction_identifier = transactionIdentifier;
+
+
+  // Const Field (protocolIdentifier)
+  uint16_t protocolIdentifier = 0;
+  _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &protocolIdentifier);
+  if(_res != OK) {
+    return _res;
+  }
+  if(protocolIdentifier != PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER()) {
+    return PARSE_ERROR;
+    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER + " but got " + protocolIdentifier);
+  }
+
+
+  // Implicit Field (length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+  uint16_t length = 0;
+  _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &length);
+  if(_res != OK) {
+    return _res;
+  }
+
+
+  // Simple Field (unitIdentifier)
+  uint8_t unitIdentifier = 0;
+  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &unitIdentifier);
+  if(_res != OK) {
+    return _res;
+  }
+  (*_message)->modbus_tcp_adu_unit_identifier = unitIdentifier;
+
+
+  // Simple Field (pdu)
+  plc4c_modbus_read_write_modbus_pdu* pdu;
+  _res = plc4c_modbus_read_write_modbus_pdu_parse(readBuffer, response, (void*) &pdu);
+  if(_res != OK) {
+    return _res;
+  }
+  (*_message)->modbus_tcp_adu_pdu = pdu;
+  } else 
+if( driverType == plc4c_modbus_read_write_driver_type_MODBUS_RTU ) { /* ModbusRtuADU */
+    (*_message)->_type = plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_rtu_adu;
+
+  // Simple Field (address)
+  uint8_t address = 0;
+  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &address);
+  if(_res != OK) {
+    return _res;
+  }
+  (*_message)->modbus_rtu_adu_address = address;
+
+
+  // Simple Field (pdu)
+  plc4c_modbus_read_write_modbus_pdu* pdu;
+  _res = plc4c_modbus_read_write_modbus_pdu_parse(readBuffer, response, (void*) &pdu);
+  if(_res != OK) {
+    return _res;
+  }
+  (*_message)->modbus_rtu_adu_pdu = pdu;
+
+
+  // Checksum Field (crc)
+  {
+    // Create an array of all the bytes read in this message element so far.
+    uint16_t _checksumRef = 0;
+    _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &_checksumRef);
+    if(_res != OK) {
+      return _res;
+    }
+    uint16_t _checksum = (uint16_t) (plc4c_modbus_read_write_rtu_crc_check(address, pdu));
+    if(_checksum != _checksumRef) {
+      return PARSE_ERROR;
+      // throw new ParseException(String.format("Checksum verification failed. Expected %04X but got %04X",_checksumRef & 0xFFFF, _checksum & 0xFFFF));
+    }
+  }
+  } else 
+if( driverType == plc4c_modbus_read_write_driver_type_MODBUS_ASCII ) { /* ModbusAsciiADU */
+    (*_message)->_type = plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_ascii_adu;
+
+  // Simple Field (address)
+  uint8_t address = 0;
+  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &address);
+  if(_res != OK) {
+    return _res;
+  }
+  (*_message)->modbus_ascii_adu_address = address;
+
+
+  // Simple Field (pdu)
+  plc4c_modbus_read_write_modbus_pdu* pdu;
+  _res = plc4c_modbus_read_write_modbus_pdu_parse(readBuffer, response, (void*) &pdu);
+  if(_res != OK) {
+    return _res;
+  }
+  (*_message)->modbus_ascii_adu_pdu = pdu;
+
+
+  // Checksum Field (crc)
+  {
+    // Create an array of all the bytes read in this message element so far.
+    uint8_t _checksumRef = 0;
+    _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &_checksumRef);
+    if(_res != OK) {
+      return _res;
+    }
+    uint8_t _checksum = (uint8_t) (plc4c_modbus_read_write_ascii_lrc_check(address, pdu));
+    if(_checksum != _checksumRef) {
+      return PARSE_ERROR;
+      // throw new ParseException(String.format("Checksum verification failed. Expected %04X but got %04X",_checksumRef & 0xFFFF, _checksum & 0xFFFF));
+    }
+  }
+  }
+
+  return OK;
+}
+
+plc4c_return_code plc4c_modbus_read_write_modbus_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_adu* _message) {
+  plc4c_return_code _res = OK;
+
+  // Switch Field (Depending on the current type, serialize the subtype elements)
+  switch(_message->_type) {
+    case plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_tcp_adu: {
+
+  // Simple Field (transactionIdentifier)
+  _res = plc4c_spi_write_unsigned_short(writeBuffer, 16, _message->modbus_tcp_adu_transaction_identifier);
+  if(_res != OK) {
+    return _res;
+  }
+
+  // Const Field (protocolIdentifier)
+  plc4c_spi_write_unsigned_short(writeBuffer, 16, PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER());
+
+  // Implicit Field (length) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
+  _res = plc4c_spi_write_unsigned_short(writeBuffer, 16, (plc4c_modbus_read_write_modbus_pdu_length_in_bytes(_message->modbus_tcp_adu_pdu)) + (1));
+  if(_res != OK) {
+    return _res;
+  }
+
+  // Simple Field (unitIdentifier)
+  _res = plc4c_spi_write_unsigned_byte(writeBuffer, 8, _message->modbus_tcp_adu_unit_identifier);
+  if(_res != OK) {
+    return _res;
+  }
+
+  // Simple Field (pdu)
+  _res = plc4c_modbus_read_write_modbus_pdu_serialize(writeBuffer, _message->modbus_tcp_adu_pdu);
+  if(_res != OK) {
+    return _res;
+  }
+
+      break;
+    }
+    case plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_rtu_adu: {
+
+  // Simple Field (address)
+  _res = plc4c_spi_write_unsigned_byte(writeBuffer, 8, _message->modbus_rtu_adu_address);
+  if(_res != OK) {
+    return _res;
+  }
+
+  // Simple Field (pdu)
+  _res = plc4c_modbus_read_write_modbus_pdu_serialize(writeBuffer, _message->modbus_rtu_adu_pdu);
+  if(_res != OK) {
+    return _res;
+  }
+
+  // Checksum Field (crc)
+  {
+    // Create an array of all the bytes read in this message element so far.
+    uint16_t _checksum = (uint16_t) (plc4c_modbus_read_write_rtu_crc_check(_message->modbus_rtu_adu_address, _message->modbus_rtu_adu_pdu));
+    plc4c_spi_write_unsigned_short(writeBuffer, 16, _checksum);
+  }
+
+      break;
+    }
+    case plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_ascii_adu: {
+
+  // Simple Field (address)
+  _res = plc4c_spi_write_unsigned_byte(writeBuffer, 8, _message->modbus_ascii_adu_address);
+  if(_res != OK) {
+    return _res;
+  }
+
+  // Simple Field (pdu)
+  _res = plc4c_modbus_read_write_modbus_pdu_serialize(writeBuffer, _message->modbus_ascii_adu_pdu);
+  if(_res != OK) {
+    return _res;
+  }
+
+  // Checksum Field (crc)
+  {
+    // Create an array of all the bytes read in this message element so far.
+    uint8_t _checksum = (uint8_t) (plc4c_modbus_read_write_ascii_lrc_check(_message->modbus_ascii_adu_address, _message->modbus_ascii_adu_pdu));
+    plc4c_spi_write_unsigned_byte(writeBuffer, 8, _checksum);
+  }
+
+      break;
+    }
+  }
+
+  return OK;
+}
+
+uint16_t plc4c_modbus_read_write_modbus_adu_length_in_bytes(plc4c_modbus_read_write_modbus_adu* _message) {
+  return plc4c_modbus_read_write_modbus_adu_length_in_bits(_message) / 8;
+}
+
+uint16_t plc4c_modbus_read_write_modbus_adu_length_in_bits(plc4c_modbus_read_write_modbus_adu* _message) {
+  uint16_t lengthInBits = 0;
+
+  // Depending of the current type, add the length of sub-type elements ...
+  switch(_message->_type) {
+    case plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_tcp_adu: {
+
+  // Simple field (transactionIdentifier)
+  lengthInBits += 16;
+
+
+  // Const Field (protocolIdentifier)
+  lengthInBits += 16;
+
+
+  // Implicit Field (length)
+  lengthInBits += 16;
+
+
+  // Simple field (unitIdentifier)
+  lengthInBits += 8;
+
+
+  // Simple field (pdu)
+  lengthInBits += plc4c_modbus_read_write_modbus_pdu_length_in_bits(_message->modbus_tcp_adu_pdu);
+
+      break;
+    }
+    case plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_rtu_adu: {
+
+  // Simple field (address)
+  lengthInBits += 8;
+
+
+  // Simple field (pdu)
+  lengthInBits += plc4c_modbus_read_write_modbus_pdu_length_in_bits(_message->modbus_rtu_adu_pdu);
+
+
+  // Checksum Field (checksum)
+  lengthInBits += 16;
+
+      break;
+    }
+    case plc4c_modbus_read_write_modbus_adu_type_plc4c_modbus_read_write_modbus_ascii_adu: {
+
+  // Simple field (address)
+  lengthInBits += 8;
+
+
+  // Simple field (pdu)
+  lengthInBits += plc4c_modbus_read_write_modbus_pdu_length_in_bits(_message->modbus_ascii_adu_pdu);
+
+
+  // Checksum Field (checksum)
+  lengthInBits += 8;
+
+      break;
+    }
+  }
+
+  return lengthInBits;
+}
+
diff --git a/plc4c/generated-sources/modbus/src/modbus_ascii_adu.c b/plc4c/generated-sources/modbus/src/modbus_ascii_adu.c
deleted file mode 100644
index 50d0b1b..0000000
--- a/plc4c/generated-sources/modbus/src/modbus_ascii_adu.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <stdio.h>
-#include <plc4c/spi/evaluation_helper.h>
-#include "modbus_ascii_adu.h"
-
-// Code generated by code-generation. DO NOT EDIT.
-
-
-// Constant values.
-static const uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_START_const = 0x3A;
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_START() {
-  return PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_START_const;
-}
-static const uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_CR_const = 0x0D;
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_CR() {
-  return PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_CR_const;
-}
-static const uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_LF_const = 0x0A;
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_LF() {
-  return PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_LF_const;
-}
-
-// Parse function.
-plc4c_return_code plc4c_modbus_read_write_modbus_ascii_adu_parse(plc4c_spi_read_buffer* readBuffer, bool response, plc4c_modbus_read_write_modbus_ascii_adu** _message) {
-  uint16_t startPos = plc4c_spi_read_get_pos(readBuffer);
-  plc4c_return_code _res = OK;
-
-  // Allocate enough memory to contain this data structure.
-  (*_message) = malloc(sizeof(plc4c_modbus_read_write_modbus_ascii_adu));
-  if(*_message == NULL) {
-    return NO_MEMORY;
-  }
-
-  // Const Field (start)
-  uint8_t start = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &start);
-  if(_res != OK) {
-    return _res;
-  }
-  if(start != PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_START()) {
-    return PARSE_ERROR;
-    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_START + " but got " + start);
-  }
-
-  // Simple Field (address)
-  uint8_t address = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &address);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->address = address;
-
-  // Simple Field (pdu)
-  plc4c_modbus_read_write_modbus_pdu* pdu;
-  _res = plc4c_modbus_read_write_modbus_pdu_parse(readBuffer, response, (void*) &pdu);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->pdu = pdu;
-
-  // Const Field (cr)
-  uint8_t cr = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &cr);
-  if(_res != OK) {
-    return _res;
-  }
-  if(cr != PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_CR()) {
-    return PARSE_ERROR;
-    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_CR + " but got " + cr);
-  }
-
-  // Const Field (lf)
-  uint8_t lf = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &lf);
-  if(_res != OK) {
-    return _res;
-  }
-  if(lf != PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_LF()) {
-    return PARSE_ERROR;
-    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_LF + " but got " + lf);
-  }
-
-  return OK;
-}
-
-plc4c_return_code plc4c_modbus_read_write_modbus_ascii_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_ascii_adu* _message) {
-  plc4c_return_code _res = OK;
-
-  // Const Field (start)
-  plc4c_spi_write_unsigned_byte(writeBuffer, 8, PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_START());
-
-  // Simple Field (address)
-  _res = plc4c_spi_write_unsigned_byte(writeBuffer, 8, _message->address);
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Simple Field (pdu)
-  _res = plc4c_modbus_read_write_modbus_pdu_serialize(writeBuffer, _message->pdu);
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Const Field (cr)
-  plc4c_spi_write_unsigned_byte(writeBuffer, 8, PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_CR());
-
-  // Const Field (lf)
-  plc4c_spi_write_unsigned_byte(writeBuffer, 8, PLC4C_MODBUS_READ_WRITE_MODBUS_ASCII_ADU_LF());
-
-  return OK;
-}
-
-uint16_t plc4c_modbus_read_write_modbus_ascii_adu_length_in_bytes(plc4c_modbus_read_write_modbus_ascii_adu* _message) {
-  return plc4c_modbus_read_write_modbus_ascii_adu_length_in_bits(_message) / 8;
-}
-
-uint16_t plc4c_modbus_read_write_modbus_ascii_adu_length_in_bits(plc4c_modbus_read_write_modbus_ascii_adu* _message) {
-  uint16_t lengthInBits = 0;
-
-  // Const Field (start)
-  lengthInBits += 8;
-
-  // Simple field (address)
-  lengthInBits += 8;
-
-  // Simple field (pdu)
-  lengthInBits += plc4c_modbus_read_write_modbus_pdu_length_in_bits(_message->pdu);
-
-  // Const Field (cr)
-  lengthInBits += 8;
-
-  // Const Field (lf)
-  lengthInBits += 8;
-
-  return lengthInBits;
-}
-
diff --git a/plc4c/generated-sources/modbus/src/modbus_constants.c b/plc4c/generated-sources/modbus/src/modbus_constants.c
index e7a7627..f956c24 100644
--- a/plc4c/generated-sources/modbus/src/modbus_constants.c
+++ b/plc4c/generated-sources/modbus/src/modbus_constants.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_modbus_static_helper.h>
 #include "modbus_constants.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/modbus/src/modbus_device_information_object.c b/plc4c/generated-sources/modbus/src/modbus_device_information_object.c
index 533a730..b6258a7 100644
--- a/plc4c/generated-sources/modbus/src/modbus_device_information_object.c
+++ b/plc4c/generated-sources/modbus/src/modbus_device_information_object.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_modbus_static_helper.h>
 #include "modbus_device_information_object.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/modbus/src/modbus_pdu.c b/plc4c/generated-sources/modbus/src/modbus_pdu.c
index c18efba..ff4d135 100644
--- a/plc4c/generated-sources/modbus/src/modbus_pdu.c
+++ b/plc4c/generated-sources/modbus/src/modbus_pdu.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_modbus_static_helper.h>
 #include "modbus_pdu.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_modbus_read_write_modbus_pdu_discriminator plc4c_modbus_read_write_modbus_pdu_discriminators[] = {
   {/* plc4c_modbus_read_write_modbus_pdu_error */
    .errorFlag = true, .functionFlag = -1, .response = -1 },
diff --git a/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_request_item.c b/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_request_item.c
index 86a7b10..4a7c90d 100644
--- a/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_request_item.c
+++ b/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_request_item.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_modbus_static_helper.h>
 #include "modbus_pdu_read_file_record_request_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_response_item.c b/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_response_item.c
index 003a113..ecfcb90 100644
--- a/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_response_item.c
+++ b/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_response_item.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_modbus_static_helper.h>
 #include "modbus_pdu_read_file_record_response_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_request_item.c b/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_request_item.c
index c0a43a8..cbc3844 100644
--- a/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_request_item.c
+++ b/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_request_item.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_modbus_static_helper.h>
 #include "modbus_pdu_write_file_record_request_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_response_item.c b/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_response_item.c
index d51d9a8..8b2e392 100644
--- a/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_response_item.c
+++ b/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_response_item.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_modbus_static_helper.h>
 #include "modbus_pdu_write_file_record_response_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/modbus/src/modbus_rtu_adu.c b/plc4c/generated-sources/modbus/src/modbus_rtu_adu.c
deleted file mode 100644
index c30c242..0000000
--- a/plc4c/generated-sources/modbus/src/modbus_rtu_adu.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <stdio.h>
-#include <plc4c/spi/evaluation_helper.h>
-#include "modbus_rtu_adu.h"
-
-// Code generated by code-generation. DO NOT EDIT.
-
-
-// Constant values.
-static const uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE1_const = 0x00;
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE1() {
-  return PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE1_const;
-}
-static const uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE2_const = 0x00;
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE2() {
-  return PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE2_const;
-}
-static const uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE3_const = 0x00;
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE3() {
-  return PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE3_const;
-}
-static const uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE4_const = 0x00;
-uint8_t PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE4() {
-  return PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE4_const;
-}
-
-// Parse function.
-plc4c_return_code plc4c_modbus_read_write_modbus_rtu_adu_parse(plc4c_spi_read_buffer* readBuffer, bool response, plc4c_modbus_read_write_modbus_rtu_adu** _message) {
-  uint16_t startPos = plc4c_spi_read_get_pos(readBuffer);
-  plc4c_return_code _res = OK;
-
-  // Allocate enough memory to contain this data structure.
-  (*_message) = malloc(sizeof(plc4c_modbus_read_write_modbus_rtu_adu));
-  if(*_message == NULL) {
-    return NO_MEMORY;
-  }
-
-  // Const Field (space1)
-  uint8_t space1 = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &space1);
-  if(_res != OK) {
-    return _res;
-  }
-  if(space1 != PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE1()) {
-    return PARSE_ERROR;
-    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE1 + " but got " + space1);
-  }
-
-  // Const Field (space2)
-  uint8_t space2 = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &space2);
-  if(_res != OK) {
-    return _res;
-  }
-  if(space2 != PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE2()) {
-    return PARSE_ERROR;
-    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE2 + " but got " + space2);
-  }
-
-  // Const Field (space3)
-  uint8_t space3 = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &space3);
-  if(_res != OK) {
-    return _res;
-  }
-  if(space3 != PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE3()) {
-    return PARSE_ERROR;
-    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE3 + " but got " + space3);
-  }
-
-  // Const Field (space4)
-  uint8_t space4 = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &space4);
-  if(_res != OK) {
-    return _res;
-  }
-  if(space4 != PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE4()) {
-    return PARSE_ERROR;
-    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE4 + " but got " + space4);
-  }
-
-  // Simple Field (address)
-  uint8_t address = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &address);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->address = address;
-
-  // Simple Field (pdu)
-  plc4c_modbus_read_write_modbus_pdu* pdu;
-  _res = plc4c_modbus_read_write_modbus_pdu_parse(readBuffer, response, (void*) &pdu);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->pdu = pdu;
-
-  return OK;
-}
-
-plc4c_return_code plc4c_modbus_read_write_modbus_rtu_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_rtu_adu* _message) {
-  plc4c_return_code _res = OK;
-
-  // Const Field (space1)
-  plc4c_spi_write_unsigned_byte(writeBuffer, 8, PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE1());
-
-  // Const Field (space2)
-  plc4c_spi_write_unsigned_byte(writeBuffer, 8, PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE2());
-
-  // Const Field (space3)
-  plc4c_spi_write_unsigned_byte(writeBuffer, 8, PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE3());
-
-  // Const Field (space4)
-  plc4c_spi_write_unsigned_byte(writeBuffer, 8, PLC4C_MODBUS_READ_WRITE_MODBUS_RTU_ADU_SPACE4());
-
-  // Simple Field (address)
-  _res = plc4c_spi_write_unsigned_byte(writeBuffer, 8, _message->address);
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Simple Field (pdu)
-  _res = plc4c_modbus_read_write_modbus_pdu_serialize(writeBuffer, _message->pdu);
-  if(_res != OK) {
-    return _res;
-  }
-
-  return OK;
-}
-
-uint16_t plc4c_modbus_read_write_modbus_rtu_adu_length_in_bytes(plc4c_modbus_read_write_modbus_rtu_adu* _message) {
-  return plc4c_modbus_read_write_modbus_rtu_adu_length_in_bits(_message) / 8;
-}
-
-uint16_t plc4c_modbus_read_write_modbus_rtu_adu_length_in_bits(plc4c_modbus_read_write_modbus_rtu_adu* _message) {
-  uint16_t lengthInBits = 0;
-
-  // Const Field (space1)
-  lengthInBits += 8;
-
-  // Const Field (space2)
-  lengthInBits += 8;
-
-  // Const Field (space3)
-  lengthInBits += 8;
-
-  // Const Field (space4)
-  lengthInBits += 8;
-
-  // Simple field (address)
-  lengthInBits += 8;
-
-  // Simple field (pdu)
-  lengthInBits += plc4c_modbus_read_write_modbus_pdu_length_in_bits(_message->pdu);
-
-  return lengthInBits;
-}
-
diff --git a/plc4c/generated-sources/modbus/src/modbus_serial_adu.c b/plc4c/generated-sources/modbus/src/modbus_serial_adu.c
deleted file mode 100644
index f66000a..0000000
--- a/plc4c/generated-sources/modbus/src/modbus_serial_adu.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <stdio.h>
-#include <plc4c/spi/evaluation_helper.h>
-#include "modbus_serial_adu.h"
-
-// Code generated by code-generation. DO NOT EDIT.
-
-
-// Parse function.
-plc4c_return_code plc4c_modbus_read_write_modbus_serial_adu_parse(plc4c_spi_read_buffer* readBuffer, bool response, plc4c_modbus_read_write_modbus_serial_adu** _message) {
-  uint16_t startPos = plc4c_spi_read_get_pos(readBuffer);
-  plc4c_return_code _res = OK;
-
-  // Allocate enough memory to contain this data structure.
-  (*_message) = malloc(sizeof(plc4c_modbus_read_write_modbus_serial_adu));
-  if(*_message == NULL) {
-    return NO_MEMORY;
-  }
-
-  // Simple Field (address)
-  uint8_t address = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &address);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->address = address;
-
-  // Simple Field (pdu)
-  plc4c_modbus_read_write_modbus_pdu* pdu;
-  _res = plc4c_modbus_read_write_modbus_pdu_parse(readBuffer, response, (void*) &pdu);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->pdu = pdu;
-
-  // Checksum Field (crc)
-  {
-    // Create an array of all the bytes read in this message element so far.
-    uint16_t _checksumRef = 0;
-    _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &_checksumRef);
-    if(_res != OK) {
-      return _res;
-    }
-    uint16_t _checksum = (uint16_t) (plc4c_modbus_read_write_crc_check(address, pdu));
-    if(_checksum != _checksumRef) {
-      return PARSE_ERROR;
-      // throw new ParseException(String.format("Checksum verification failed. Expected %04X but got %04X",_checksumRef & 0xFFFF, _checksum & 0xFFFF));
-    }
-  }
-
-  return OK;
-}
-
-plc4c_return_code plc4c_modbus_read_write_modbus_serial_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_serial_adu* _message) {
-  plc4c_return_code _res = OK;
-
-  // Simple Field (address)
-  _res = plc4c_spi_write_unsigned_byte(writeBuffer, 8, _message->address);
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Simple Field (pdu)
-  _res = plc4c_modbus_read_write_modbus_pdu_serialize(writeBuffer, _message->pdu);
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Checksum Field (crc)
-  {
-    // Create an array of all the bytes read in this message element so far.
-    uint16_t _checksum = (uint16_t) (plc4c_modbus_read_write_crc_check(_message->address, _message->pdu));
-    plc4c_spi_write_unsigned_short(writeBuffer, 16, _checksum);
-  }
-
-  return OK;
-}
-
-uint16_t plc4c_modbus_read_write_modbus_serial_adu_length_in_bytes(plc4c_modbus_read_write_modbus_serial_adu* _message) {
-  return plc4c_modbus_read_write_modbus_serial_adu_length_in_bits(_message) / 8;
-}
-
-uint16_t plc4c_modbus_read_write_modbus_serial_adu_length_in_bits(plc4c_modbus_read_write_modbus_serial_adu* _message) {
-  uint16_t lengthInBits = 0;
-
-  // Simple field (address)
-  lengthInBits += 8;
-
-  // Simple field (pdu)
-  lengthInBits += plc4c_modbus_read_write_modbus_pdu_length_in_bits(_message->pdu);
-
-  // Checksum Field (checksum)
-  lengthInBits += 16;
-
-  return lengthInBits;
-}
-
diff --git a/plc4c/generated-sources/modbus/src/modbus_tcp_adu.c b/plc4c/generated-sources/modbus/src/modbus_tcp_adu.c
deleted file mode 100644
index 2d9014f..0000000
--- a/plc4c/generated-sources/modbus/src/modbus_tcp_adu.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <stdio.h>
-#include <plc4c/spi/evaluation_helper.h>
-#include "modbus_tcp_adu.h"
-
-// Code generated by code-generation. DO NOT EDIT.
-
-
-// Constant values.
-static const uint16_t PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER_const = 0x0000;
-uint16_t PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER() {
-  return PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER_const;
-}
-
-// Parse function.
-plc4c_return_code plc4c_modbus_read_write_modbus_tcp_adu_parse(plc4c_spi_read_buffer* readBuffer, bool response, plc4c_modbus_read_write_modbus_tcp_adu** _message) {
-  uint16_t startPos = plc4c_spi_read_get_pos(readBuffer);
-  plc4c_return_code _res = OK;
-
-  // Allocate enough memory to contain this data structure.
-  (*_message) = malloc(sizeof(plc4c_modbus_read_write_modbus_tcp_adu));
-  if(*_message == NULL) {
-    return NO_MEMORY;
-  }
-
-  // Simple Field (transactionIdentifier)
-  uint16_t transactionIdentifier = 0;
-  _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &transactionIdentifier);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->transaction_identifier = transactionIdentifier;
-
-  // Const Field (protocolIdentifier)
-  uint16_t protocolIdentifier = 0;
-  _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &protocolIdentifier);
-  if(_res != OK) {
-    return _res;
-  }
-  if(protocolIdentifier != PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER()) {
-    return PARSE_ERROR;
-    // throw new ParseException("Expected constant value " + PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER + " but got " + protocolIdentifier);
-  }
-
-  // Implicit Field (length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-  uint16_t length = 0;
-  _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &length);
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Simple Field (unitIdentifier)
-  uint8_t unitIdentifier = 0;
-  _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &unitIdentifier);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->unit_identifier = unitIdentifier;
-
-  // Simple Field (pdu)
-  plc4c_modbus_read_write_modbus_pdu* pdu;
-  _res = plc4c_modbus_read_write_modbus_pdu_parse(readBuffer, response, (void*) &pdu);
-  if(_res != OK) {
-    return _res;
-  }
-  (*_message)->pdu = pdu;
-
-  return OK;
-}
-
-plc4c_return_code plc4c_modbus_read_write_modbus_tcp_adu_serialize(plc4c_spi_write_buffer* writeBuffer, plc4c_modbus_read_write_modbus_tcp_adu* _message) {
-  plc4c_return_code _res = OK;
-
-  // Simple Field (transactionIdentifier)
-  _res = plc4c_spi_write_unsigned_short(writeBuffer, 16, _message->transaction_identifier);
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Const Field (protocolIdentifier)
-  plc4c_spi_write_unsigned_short(writeBuffer, 16, PLC4C_MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER());
-
-  // Implicit Field (length) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-  _res = plc4c_spi_write_unsigned_short(writeBuffer, 16, (plc4c_modbus_read_write_modbus_pdu_length_in_bytes(_message->pdu)) + (1));
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Simple Field (unitIdentifier)
-  _res = plc4c_spi_write_unsigned_byte(writeBuffer, 8, _message->unit_identifier);
-  if(_res != OK) {
-    return _res;
-  }
-
-  // Simple Field (pdu)
-  _res = plc4c_modbus_read_write_modbus_pdu_serialize(writeBuffer, _message->pdu);
-  if(_res != OK) {
-    return _res;
-  }
-
-  return OK;
-}
-
-uint16_t plc4c_modbus_read_write_modbus_tcp_adu_length_in_bytes(plc4c_modbus_read_write_modbus_tcp_adu* _message) {
-  return plc4c_modbus_read_write_modbus_tcp_adu_length_in_bits(_message) / 8;
-}
-
-uint16_t plc4c_modbus_read_write_modbus_tcp_adu_length_in_bits(plc4c_modbus_read_write_modbus_tcp_adu* _message) {
-  uint16_t lengthInBits = 0;
-
-  // Simple field (transactionIdentifier)
-  lengthInBits += 16;
-
-  // Const Field (protocolIdentifier)
-  lengthInBits += 16;
-
-  // Implicit Field (length)
-  lengthInBits += 16;
-
-  // Simple field (unitIdentifier)
-  lengthInBits += 8;
-
-  // Simple field (pdu)
-  lengthInBits += plc4c_modbus_read_write_modbus_pdu_length_in_bits(_message->pdu);
-
-  return lengthInBits;
-}
-
diff --git a/plc4c/generated-sources/s7/include/cotp_packet.h b/plc4c/generated-sources/s7/include/cotp_packet.h
index 06935f8..5bf020c 100644
--- a/plc4c/generated-sources/s7/include/cotp_packet.h
+++ b/plc4c/generated-sources/s7/include/cotp_packet.h
@@ -43,7 +43,7 @@ struct plc4c_s7_read_write_cotp_packet_discriminator {
 };
 typedef struct plc4c_s7_read_write_cotp_packet_discriminator plc4c_s7_read_write_cotp_packet_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_cotp_packet_type {
   plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_data = 0,
   plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_connection_request = 1,
diff --git a/plc4c/generated-sources/s7/include/cotp_parameter.h b/plc4c/generated-sources/s7/include/cotp_parameter.h
index 87b7af7..668d5af 100644
--- a/plc4c/generated-sources/s7/include/cotp_parameter.h
+++ b/plc4c/generated-sources/s7/include/cotp_parameter.h
@@ -41,7 +41,7 @@ struct plc4c_s7_read_write_cotp_parameter_discriminator {
 };
 typedef struct plc4c_s7_read_write_cotp_parameter_discriminator plc4c_s7_read_write_cotp_parameter_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_cotp_parameter_type {
   plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_tpdu_size = 0,
   plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_calling_tsap = 1,
diff --git a/plc4c/generated-sources/s7/include/s7_address.h b/plc4c/generated-sources/s7/include/s7_address.h
index 44eb358..596172f 100644
--- a/plc4c/generated-sources/s7/include/s7_address.h
+++ b/plc4c/generated-sources/s7/include/s7_address.h
@@ -42,7 +42,7 @@ struct plc4c_s7_read_write_s7_address_discriminator {
 };
 typedef struct plc4c_s7_read_write_s7_address_discriminator plc4c_s7_read_write_s7_address_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_s7_address_type {
   plc4c_s7_read_write_s7_address_type_plc4c_s7_read_write_s7_address_any = 0};
 typedef enum plc4c_s7_read_write_s7_address_type plc4c_s7_read_write_s7_address_type;
diff --git a/plc4c/generated-sources/s7/include/s7_data_alarm_message.h b/plc4c/generated-sources/s7/include/s7_data_alarm_message.h
index a93b314..45799f6 100644
--- a/plc4c/generated-sources/s7/include/s7_data_alarm_message.h
+++ b/plc4c/generated-sources/s7/include/s7_data_alarm_message.h
@@ -45,7 +45,7 @@ struct plc4c_s7_read_write_s7_data_alarm_message_discriminator {
 };
 typedef struct plc4c_s7_read_write_s7_data_alarm_message_discriminator plc4c_s7_read_write_s7_data_alarm_message_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_s7_data_alarm_message_type {
   plc4c_s7_read_write_s7_data_alarm_message_type_plc4c_s7_read_write_s7_message_object_request = 0,
   plc4c_s7_read_write_s7_data_alarm_message_type_plc4c_s7_read_write_s7_message_object_response = 1};
diff --git a/plc4c/generated-sources/s7/include/s7_message.h b/plc4c/generated-sources/s7/include/s7_message.h
index 5fe2ef5..e8b2640 100644
--- a/plc4c/generated-sources/s7/include/s7_message.h
+++ b/plc4c/generated-sources/s7/include/s7_message.h
@@ -42,7 +42,7 @@ struct plc4c_s7_read_write_s7_message_discriminator {
 };
 typedef struct plc4c_s7_read_write_s7_message_discriminator plc4c_s7_read_write_s7_message_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_s7_message_type {
   plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_request = 0,
   plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_response = 1,
diff --git a/plc4c/generated-sources/s7/include/s7_parameter.h b/plc4c/generated-sources/s7/include/s7_parameter.h
index 4989b4a..b896a06 100644
--- a/plc4c/generated-sources/s7/include/s7_parameter.h
+++ b/plc4c/generated-sources/s7/include/s7_parameter.h
@@ -43,7 +43,7 @@ struct plc4c_s7_read_write_s7_parameter_discriminator {
 };
 typedef struct plc4c_s7_read_write_s7_parameter_discriminator plc4c_s7_read_write_s7_parameter_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_s7_parameter_type {
   plc4c_s7_read_write_s7_parameter_type_plc4c_s7_read_write_s7_parameter_setup_communication = 0,
   plc4c_s7_read_write_s7_parameter_type_plc4c_s7_read_write_s7_parameter_read_var_request = 1,
diff --git a/plc4c/generated-sources/s7/include/s7_parameter_user_data_item.h b/plc4c/generated-sources/s7/include/s7_parameter_user_data_item.h
index d8de1d4..190b698 100644
--- a/plc4c/generated-sources/s7/include/s7_parameter_user_data_item.h
+++ b/plc4c/generated-sources/s7/include/s7_parameter_user_data_item.h
@@ -40,7 +40,7 @@ struct plc4c_s7_read_write_s7_parameter_user_data_item_discriminator {
 };
 typedef struct plc4c_s7_read_write_s7_parameter_user_data_item_discriminator plc4c_s7_read_write_s7_parameter_user_data_item_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_s7_parameter_user_data_item_type {
   plc4c_s7_read_write_s7_parameter_user_data_item_type_plc4c_s7_read_write_s7_parameter_user_data_item_cpu_functions = 0};
 typedef enum plc4c_s7_read_write_s7_parameter_user_data_item_type plc4c_s7_read_write_s7_parameter_user_data_item_type;
diff --git a/plc4c/generated-sources/s7/include/s7_payload.h b/plc4c/generated-sources/s7/include/s7_payload.h
index 3a4f6f5..3784ea2 100644
--- a/plc4c/generated-sources/s7/include/s7_payload.h
+++ b/plc4c/generated-sources/s7/include/s7_payload.h
@@ -45,7 +45,7 @@ struct plc4c_s7_read_write_s7_payload_discriminator {
 };
 typedef struct plc4c_s7_read_write_s7_payload_discriminator plc4c_s7_read_write_s7_payload_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_s7_payload_type {
   plc4c_s7_read_write_s7_payload_type_plc4c_s7_read_write_s7_payload_read_var_response = 0,
   plc4c_s7_read_write_s7_payload_type_plc4c_s7_read_write_s7_payload_write_var_request = 1,
diff --git a/plc4c/generated-sources/s7/include/s7_payload_user_data_item.h b/plc4c/generated-sources/s7/include/s7_payload_user_data_item.h
index 025d818..9238f1d 100644
--- a/plc4c/generated-sources/s7/include/s7_payload_user_data_item.h
+++ b/plc4c/generated-sources/s7/include/s7_payload_user_data_item.h
@@ -54,7 +54,7 @@ struct plc4c_s7_read_write_s7_payload_user_data_item_discriminator {
 };
 typedef struct plc4c_s7_read_write_s7_payload_user_data_item_discriminator plc4c_s7_read_write_s7_payload_user_data_item_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_s7_payload_user_data_item_type {
   plc4c_s7_read_write_s7_payload_user_data_item_type_plc4c_s7_read_write_s7_payload_diagnostic_message = 0,
   plc4c_s7_read_write_s7_payload_user_data_item_type_plc4c_s7_read_write_s7_payload_alarm8 = 1,
diff --git a/plc4c/generated-sources/s7/include/s7_var_request_parameter_item.h b/plc4c/generated-sources/s7/include/s7_var_request_parameter_item.h
index e826511..80dc362 100644
--- a/plc4c/generated-sources/s7/include/s7_var_request_parameter_item.h
+++ b/plc4c/generated-sources/s7/include/s7_var_request_parameter_item.h
@@ -41,7 +41,7 @@ struct plc4c_s7_read_write_s7_var_request_parameter_item_discriminator {
 };
 typedef struct plc4c_s7_read_write_s7_var_request_parameter_item_discriminator plc4c_s7_read_write_s7_var_request_parameter_item_discriminator;
 
-// Enum assigning each sub-type an individual id.
+// Enum assigning each subtype an individual id.
 enum plc4c_s7_read_write_s7_var_request_parameter_item_type {
   plc4c_s7_read_write_s7_var_request_parameter_item_type_plc4c_s7_read_write_s7_var_request_parameter_item_address = 0};
 typedef enum plc4c_s7_read_write_s7_var_request_parameter_item_type plc4c_s7_read_write_s7_var_request_parameter_item_type;
diff --git a/plc4c/generated-sources/s7/src/alarm_message_ack_object_push_type.c b/plc4c/generated-sources/s7/src/alarm_message_ack_object_push_type.c
index ba2fa96..6ebf8cc 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_ack_object_push_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_ack_object_push_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_ack_object_push_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/alarm_message_ack_push_type.c b/plc4c/generated-sources/s7/src/alarm_message_ack_push_type.c
index 9ec8ccc..4096a5e 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_ack_push_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_ack_push_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_ack_push_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/alarm_message_ack_response_type.c b/plc4c/generated-sources/s7/src/alarm_message_ack_response_type.c
index 81c2d9e..41ea1f3 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_ack_response_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_ack_response_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_ack_response_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/alarm_message_ack_type.c b/plc4c/generated-sources/s7/src/alarm_message_ack_type.c
index 5b4ba06..8c7603b 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_ack_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_ack_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_ack_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/alarm_message_object_ack_type.c b/plc4c/generated-sources/s7/src/alarm_message_object_ack_type.c
index b375594..009f051 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_object_ack_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_object_ack_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_object_ack_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/alarm_message_object_push_type.c b/plc4c/generated-sources/s7/src/alarm_message_object_push_type.c
index 31b4045..5cc4cb4 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_object_push_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_object_push_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_object_push_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/alarm_message_object_query_type.c b/plc4c/generated-sources/s7/src/alarm_message_object_query_type.c
index f2f2e80..4febb6e 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_object_query_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_object_query_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_object_query_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/alarm_message_push_type.c b/plc4c/generated-sources/s7/src/alarm_message_push_type.c
index cc8d6de..3bc6f75 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_push_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_push_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_push_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/alarm_message_query_type.c b/plc4c/generated-sources/s7/src/alarm_message_query_type.c
index 0add81f..34e186a 100644
--- a/plc4c/generated-sources/s7/src/alarm_message_query_type.c
+++ b/plc4c/generated-sources/s7/src/alarm_message_query_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "alarm_message_query_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/associated_value_type.c b/plc4c/generated-sources/s7/src/associated_value_type.c
index 899327e..ab7a32d 100644
--- a/plc4c/generated-sources/s7/src/associated_value_type.c
+++ b/plc4c/generated-sources/s7/src/associated_value_type.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "associated_value_type.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/cotp_packet.c b/plc4c/generated-sources/s7/src/cotp_packet.c
index e9c74f4..ffd32a4 100644
--- a/plc4c/generated-sources/s7/src/cotp_packet.c
+++ b/plc4c/generated-sources/s7/src/cotp_packet.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "cotp_packet.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_cotp_packet_discriminator plc4c_s7_read_write_cotp_packet_discriminators[] = {
   {/* plc4c_s7_read_write_cotp_packet_data */
    .tpduCode = 0xF0 },
diff --git a/plc4c/generated-sources/s7/src/cotp_parameter.c b/plc4c/generated-sources/s7/src/cotp_parameter.c
index 689869c..0838104 100644
--- a/plc4c/generated-sources/s7/src/cotp_parameter.c
+++ b/plc4c/generated-sources/s7/src/cotp_parameter.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "cotp_parameter.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_cotp_parameter_discriminator plc4c_s7_read_write_cotp_parameter_discriminators[] = {
   {/* plc4c_s7_read_write_cotp_parameter_tpdu_size */
    .parameterType = 0xC0 },
diff --git a/plc4c/generated-sources/s7/src/date_and_time.c b/plc4c/generated-sources/s7/src/date_and_time.c
index ef686f1..f1ff885 100644
--- a/plc4c/generated-sources/s7/src/date_and_time.c
+++ b/plc4c/generated-sources/s7/src/date_and_time.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "date_and_time.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/s7_address.c b/plc4c/generated-sources/s7/src/s7_address.c
index a2833a2..dd7e7b1 100644
--- a/plc4c/generated-sources/s7/src/s7_address.c
+++ b/plc4c/generated-sources/s7/src/s7_address.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_address.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_s7_address_discriminator plc4c_s7_read_write_s7_address_discriminators[] = {
   {/* plc4c_s7_read_write_s7_address_any */
    .addressType = 0x10 }
diff --git a/plc4c/generated-sources/s7/src/s7_data_alarm_message.c b/plc4c/generated-sources/s7/src/s7_data_alarm_message.c
index 5b9ea00..33080d9 100644
--- a/plc4c/generated-sources/s7/src/s7_data_alarm_message.c
+++ b/plc4c/generated-sources/s7/src/s7_data_alarm_message.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_data_alarm_message.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_s7_data_alarm_message_discriminator plc4c_s7_read_write_s7_data_alarm_message_discriminators[] = {
   {/* plc4c_s7_read_write_s7_message_object_request */
    .cpuFunctionType = 0x04 },
diff --git a/plc4c/generated-sources/s7/src/s7_message.c b/plc4c/generated-sources/s7/src/s7_message.c
index d33f7a3..52eb6ab 100644
--- a/plc4c/generated-sources/s7/src/s7_message.c
+++ b/plc4c/generated-sources/s7/src/s7_message.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_message.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_s7_message_discriminator plc4c_s7_read_write_s7_message_discriminators[] = {
   {/* plc4c_s7_read_write_s7_message_request */
    .messageType = 0x01 },
diff --git a/plc4c/generated-sources/s7/src/s7_parameter.c b/plc4c/generated-sources/s7/src/s7_parameter.c
index 2b21dc4..65805ba 100644
--- a/plc4c/generated-sources/s7/src/s7_parameter.c
+++ b/plc4c/generated-sources/s7/src/s7_parameter.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_parameter.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_s7_parameter_discriminator plc4c_s7_read_write_s7_parameter_discriminators[] = {
   {/* plc4c_s7_read_write_s7_parameter_setup_communication */
    .parameterType = 0xF0, .messageType = -1 },
diff --git a/plc4c/generated-sources/s7/src/s7_parameter_user_data_item.c b/plc4c/generated-sources/s7/src/s7_parameter_user_data_item.c
index 0605199..0025656 100644
--- a/plc4c/generated-sources/s7/src/s7_parameter_user_data_item.c
+++ b/plc4c/generated-sources/s7/src/s7_parameter_user_data_item.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_parameter_user_data_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_s7_parameter_user_data_item_discriminator plc4c_s7_read_write_s7_parameter_user_data_item_discriminators[] = {
   {/* plc4c_s7_read_write_s7_parameter_user_data_item_cpu_functions */
    .itemType = 0x12 }
diff --git a/plc4c/generated-sources/s7/src/s7_payload.c b/plc4c/generated-sources/s7/src/s7_payload.c
index bf22aeb..7178a2d 100644
--- a/plc4c/generated-sources/s7/src/s7_payload.c
+++ b/plc4c/generated-sources/s7/src/s7_payload.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_payload.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_s7_payload_discriminator plc4c_s7_read_write_s7_payload_discriminators[] = {
   {/* plc4c_s7_read_write_s7_payload_read_var_response */
    .parameterParameterType = 0x04, .messageType = 0x03 },
diff --git a/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c b/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
index 07dcc98..f942afd 100644
--- a/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
+++ b/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_payload_user_data_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_s7_payload_user_data_item_discriminator plc4c_s7_read_write_s7_payload_user_data_item_discriminators[] = {
   {/* plc4c_s7_read_write_s7_payload_diagnostic_message */
    .cpuFunctionType = 0x00, .cpuSubfunction = 0x03, .dataLength = -1 },
diff --git a/plc4c/generated-sources/s7/src/s7_var_payload_data_item.c b/plc4c/generated-sources/s7/src/s7_var_payload_data_item.c
index 7b175ba..c23ff8d 100644
--- a/plc4c/generated-sources/s7/src/s7_var_payload_data_item.c
+++ b/plc4c/generated-sources/s7/src/s7_var_payload_data_item.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_var_payload_data_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/s7_var_payload_status_item.c b/plc4c/generated-sources/s7/src/s7_var_payload_status_item.c
index 81b4c68..550a709 100644
--- a/plc4c/generated-sources/s7/src/s7_var_payload_status_item.c
+++ b/plc4c/generated-sources/s7/src/s7_var_payload_status_item.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_var_payload_status_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/s7_var_request_parameter_item.c b/plc4c/generated-sources/s7/src/s7_var_request_parameter_item.c
index 2c2854c..18e6c77 100644
--- a/plc4c/generated-sources/s7/src/s7_var_request_parameter_item.c
+++ b/plc4c/generated-sources/s7/src/s7_var_request_parameter_item.c
@@ -19,13 +19,14 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "s7_var_request_parameter_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
 
 // Array of discriminator values that match the enum type constants.
-// (The order is identical to the enum constants so we can use the
-// enum constant to directly access a given types discriminator values)
+// (The order is identical to the enum constants, so we can use the
+// enum constant to directly access a given type's discriminator values)
 const plc4c_s7_read_write_s7_var_request_parameter_item_discriminator plc4c_s7_read_write_s7_var_request_parameter_item_discriminators[] = {
   {/* plc4c_s7_read_write_s7_var_request_parameter_item_address */
    .itemType = 0x12 }
diff --git a/plc4c/generated-sources/s7/src/state.c b/plc4c/generated-sources/s7/src/state.c
index c91a467..745ba62 100644
--- a/plc4c/generated-sources/s7/src/state.c
+++ b/plc4c/generated-sources/s7/src/state.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "state.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/szl_data_tree_item.c b/plc4c/generated-sources/s7/src/szl_data_tree_item.c
index fbbb29c..7a2e19b 100644
--- a/plc4c/generated-sources/s7/src/szl_data_tree_item.c
+++ b/plc4c/generated-sources/s7/src/szl_data_tree_item.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "szl_data_tree_item.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/szl_id.c b/plc4c/generated-sources/s7/src/szl_id.c
index e37a996..6cd2281 100644
--- a/plc4c/generated-sources/s7/src/szl_id.c
+++ b/plc4c/generated-sources/s7/src/szl_id.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "szl_id.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4c/generated-sources/s7/src/tpkt_packet.c b/plc4c/generated-sources/s7/src/tpkt_packet.c
index 1791493..05811ca 100644
--- a/plc4c/generated-sources/s7/src/tpkt_packet.c
+++ b/plc4c/generated-sources/s7/src/tpkt_packet.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <plc4c/spi/evaluation_helper.h>
+#include <plc4c/driver_s7_static_helper.h>
 #include "tpkt_packet.h"
 
 // Code generated by code-generation. DO NOT EDIT.
diff --git a/plc4go/assets/testing/protocols/modbus/DriverTestsuite.xml b/plc4go/assets/testing/protocols/modbus/DriverTestsuite.xml
index cadd145..309e271 100644
--- a/plc4go/assets/testing/protocols/modbus/DriverTestsuite.xml
+++ b/plc4go/assets/testing/protocols/modbus/DriverTestsuite.xml
@@ -27,7 +27,7 @@
   <protocolName>modbus</protocolName>
   <outputFlavor>read-write</outputFlavor>
 
-  <driver-name>modbus</driver-name>
+  <driver-name>modbus-tcp</driver-name>
 
   <testcase>
     <name>Single element read request</name>
@@ -44,45 +44,51 @@
       </api-request>
       <outgoing-plc-message name="Send Modbus Input-Register Read Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-              </ModbusPDUReadHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                </ModbusPDUReadHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Modbus Input-Register Read Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">7</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersResponse>
-                <byteCount dataType="uint" bitLength="8">4</byteCount>
-                <value dataType="byte" bitLength="32">0x40490fdb</value>
-              </ModbusPDUReadHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">7</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersResponse>
+                  <byteCount dataType="uint" bitLength="8">4</byteCount>
+                  <value dataType="byte" bitLength="32">0x40490fdb</value>
+                </ModbusPDUReadHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Read Response to application">
         <PlcReadResponse>
@@ -125,45 +131,51 @@
       </api-request>
       <outgoing-plc-message name="Send Modbus Input-Register Read Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">4</quantity>
-              </ModbusPDUReadHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">4</quantity>
+                </ModbusPDUReadHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Modbus Input-Register Read Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">11</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersResponse>
-                <byteCount dataType="uint" bitLength="8">8</byteCount>
-                <value dataType="byte" bitLength="64">0x40490fdb40490fdb</value>
-              </ModbusPDUReadHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">11</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersResponse>
+                  <byteCount dataType="uint" bitLength="8">8</byteCount>
+                  <value dataType="byte" bitLength="64">0x40490fdb40490fdb</value>
+                </ModbusPDUReadHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Read Response to application">
         <PlcReadResponse>
@@ -213,87 +225,99 @@
       </api-request>
       <outgoing-plc-message name="Send First Item Modbus Input-Register Read Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-              </ModbusPDUReadHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                </ModbusPDUReadHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive First Item Modbus Input-Register Read Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">7</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersResponse>
-                <byteCount dataType="uint" bitLength="8">4</byteCount>
-                <value dataType="byte" bitLength="32">0x40490fdb</value>
-              </ModbusPDUReadHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">7</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersResponse>
+                  <byteCount dataType="uint" bitLength="8">4</byteCount>
+                  <value dataType="byte" bitLength="32">0x40490fdb</value>
+                </ModbusPDUReadHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <outgoing-plc-message name="Send Second Item Modbus Input-Register Read Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">2</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">2</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-              </ModbusPDUReadHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">2</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">2</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                </ModbusPDUReadHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Second Item Modbus Input-Register Read Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">2</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">7</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersResponse>
-                <byteCount dataType="uint" bitLength="8">4</byteCount>
-                <value dataType="byte" bitLength="32">0x40490fdb</value>
-              </ModbusPDUReadHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">2</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">7</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersResponse>
+                  <byteCount dataType="uint" bitLength="8">4</byteCount>
+                  <value dataType="byte" bitLength="32">0x40490fdb</value>
+                </ModbusPDUReadHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Read Response to application">
         <PlcReadResponse>
@@ -350,47 +374,53 @@
       </api-request>
       <outgoing-plc-message name="Send Modbus Input-Register Write Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">11</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">16</functionFlag>
-              <ModbusPDUWriteMultipleHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-                <byteCount dataType="uint" bitLength="8">4</byteCount>
-                <value dataType="byte" bitLength="32">0x40490fdb</value>
-              </ModbusPDUWriteMultipleHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">11</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">16</functionFlag>
+                <ModbusPDUWriteMultipleHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                  <byteCount dataType="uint" bitLength="8">4</byteCount>
+                  <value dataType="byte" bitLength="32">0x40490fdb</value>
+                </ModbusPDUWriteMultipleHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Modbus Input-Register Write Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">16</functionFlag>
-              <ModbusPDUWriteMultipleHoldingRegistersResponse>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-              </ModbusPDUWriteMultipleHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">16</functionFlag>
+                <ModbusPDUWriteMultipleHoldingRegistersResponse>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                </ModbusPDUWriteMultipleHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Write Response to application">
         <PlcWriteResponse>
@@ -431,47 +461,53 @@
       </api-request>
       <outgoing-plc-message name="Send Modbus Input-Register Write Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">15</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">16</functionFlag>
-              <ModbusPDUWriteMultipleHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">4</quantity>
-                <byteCount dataType="uint" bitLength="8">8</byteCount>
-                <value dataType="byte" bitLength="64">0x40490fdb40490fdb</value>
-              </ModbusPDUWriteMultipleHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">15</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">16</functionFlag>
+                <ModbusPDUWriteMultipleHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">4</quantity>
+                  <byteCount dataType="uint" bitLength="8">8</byteCount>
+                  <value dataType="byte" bitLength="64">0x40490fdb40490fdb</value>
+                </ModbusPDUWriteMultipleHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Modbus Input-Register Write Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">16</functionFlag>
-              <ModbusPDUWriteMultipleHoldingRegistersResponse>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">4</quantity>
-              </ModbusPDUWriteMultipleHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">16</functionFlag>
+                <ModbusPDUWriteMultipleHoldingRegistersResponse>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">4</quantity>
+                </ModbusPDUWriteMultipleHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Write Response to application">
         <PlcWriteResponse>
diff --git a/plc4go/assets/testing/protocols/modbus/ParserSerializerTestsuite.xml b/plc4go/assets/testing/protocols/modbus/ParserSerializerTestsuite.xml
index f3cc5b3..9463e1c 100644
--- a/plc4go/assets/testing/protocols/modbus/ParserSerializerTestsuite.xml
+++ b/plc4go/assets/testing/protocols/modbus/ParserSerializerTestsuite.xml
@@ -28,27 +28,30 @@
   <testcase>
     <name>Read Input Registers Request</name>
     <raw>000000000006ff0408d20002</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>false</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">0</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">6</length>
-        <unitIdentifier dataType="uint" bitLength="8">255</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">4</functionFlag>
-            <ModbusPDUReadInputRegistersRequest>
-              <startingAddress dataType="uint" bitLength="16">2258</startingAddress>
-              <quantity dataType="uint" bitLength="16">2</quantity>
-            </ModbusPDUReadInputRegistersRequest>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">0</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">6</length>
+          <unitIdentifier dataType="uint" bitLength="8">255</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">4</functionFlag>
+              <ModbusPDUReadInputRegistersRequest>
+                <startingAddress dataType="uint" bitLength="16">2258</startingAddress>
+                <quantity dataType="uint" bitLength="16">2</quantity>
+              </ModbusPDUReadInputRegistersRequest>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
@@ -57,105 +60,114 @@
     <raw>
       7cfe000000c9ff04c600000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000004000000000000000000000000000001db000001d600004a380000000000000000000000000000000000000000000000000000000000006461696d006e0000000000000000000000000000303100300000000000000000000000000000000000000000000000000000000000000000000000000000
     </raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>true</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">31998</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">201</length>
-        <unitIdentifier dataType="uint" bitLength="8">255</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">4</functionFlag>
-            <ModbusPDUReadInputRegistersResponse>
-              <byteCount dataType="uint" bitLength="8">198</byteCount>
-              <value dataType="byte" bitLength="1584">0x00000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000004000000000000000000000000000001db000001d600004a380000000000000000000000000000000000000000000000000000000000006461696d006e0000000000000000000000000000303100300000000000000000000000000000000000000000000000000000000000000000000000000000</value>
-            </ModbusPDUReadInputRegistersResponse>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">31998</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">201</length>
+          <unitIdentifier dataType="uint" bitLength="8">255</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">4</functionFlag>
+              <ModbusPDUReadInputRegistersResponse>
+                <byteCount dataType="uint" bitLength="8">198</byteCount>
+                <value dataType="byte" bitLength="1584">0x00000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000004000000000000000000000000000001db000001d600004a380000000000000000000000000000000000000000000000000000000000006461696d006e0000000000000000000000000000303100300000000000000000000000000000000000000000000000000000000000000000000000000000</value>
+              </ModbusPDUReadInputRegistersResponse>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
   <testcase>
     <name>Read Extended Registers Request Split File Record</name>
     <raw>000a0000001101140e060003270e000206000400000008</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>false</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">17</length>
-        <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">20</functionFlag>
-            <ModbusPDUReadFileRecordRequest>
-              <byteCount dataType="uint" bitLength="8">14</byteCount>
-              <items isList="true">
-                <ModbusPDUReadFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">3</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">9998</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">2</recordLength>
-                </ModbusPDUReadFileRecordRequestItem>
-                <ModbusPDUReadFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">4</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">0</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">8</recordLength>
-                </ModbusPDUReadFileRecordRequestItem>
-              </items>
-            </ModbusPDUReadFileRecordRequest>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">17</length>
+          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">20</functionFlag>
+              <ModbusPDUReadFileRecordRequest>
+                <byteCount dataType="uint" bitLength="8">14</byteCount>
+                <items isList="true">
+                  <ModbusPDUReadFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">3</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">9998</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">2</recordLength>
+                  </ModbusPDUReadFileRecordRequestItem>
+                  <ModbusPDUReadFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">4</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">0</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">8</recordLength>
+                  </ModbusPDUReadFileRecordRequestItem>
+                </items>
+              </ModbusPDUReadFileRecordRequest>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
   <testcase>
     <name>Read Extended Registers Response Split File Record</name>
     <raw>000a0000001b011418050600000000110600000000000000000000000000000000</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>true</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">27</length>
-        <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">20</functionFlag>
-            <ModbusPDUReadFileRecordResponse>
-              <byteCount dataType="uint" bitLength="8">24</byteCount>
-              <items isList="true">
-                <ModbusPDUReadFileRecordResponseItem>
-                  <dataLength dataType="uint" bitLength="8">5</dataLength>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <data dataType="byte" bitLength="32">0x00000000</data>
-                </ModbusPDUReadFileRecordResponseItem>
-                <ModbusPDUReadFileRecordResponseItem>
-                  <dataLength dataType="uint" bitLength="8">17</dataLength>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <data dataType="byte" bitLength="128">0x00000000000000000000000000000000</data>
-                </ModbusPDUReadFileRecordResponseItem>
-              </items>
-            </ModbusPDUReadFileRecordResponse>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">27</length>
+          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">20</functionFlag>
+              <ModbusPDUReadFileRecordResponse>
+                <byteCount dataType="uint" bitLength="8">24</byteCount>
+                <items isList="true">
+                  <ModbusPDUReadFileRecordResponseItem>
+                    <dataLength dataType="uint" bitLength="8">5</dataLength>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <data dataType="byte" bitLength="32">0x00000000</data>
+                  </ModbusPDUReadFileRecordResponseItem>
+                  <ModbusPDUReadFileRecordResponseItem>
+                    <dataLength dataType="uint" bitLength="8">17</dataLength>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <data dataType="byte" bitLength="128">0x00000000000000000000000000000000</data>
+                  </ModbusPDUReadFileRecordResponseItem>
+                </items>
+              </ModbusPDUReadFileRecordResponse>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
@@ -163,77 +175,83 @@
     <name>Write Extended Registers Request File Record</name>
 
     <raw>000a0000000c011509060002000000010008</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>false</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">12</length>
-        <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">21</functionFlag>
-            <ModbusPDUWriteFileRecordRequest>
-              <byteCount dataType="uint" bitLength="8">9</byteCount>
-              <items isList="true">
-                <ModbusPDUWriteFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">2</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">0</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">1</recordLength>
-                  <recordData dataType="byte" bitLength="16">0x0008</recordData>
-                </ModbusPDUWriteFileRecordRequestItem>
-              </items>
-            </ModbusPDUWriteFileRecordRequest>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">12</length>
+          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">21</functionFlag>
+              <ModbusPDUWriteFileRecordRequest>
+                <byteCount dataType="uint" bitLength="8">9</byteCount>
+                <items isList="true">
+                  <ModbusPDUWriteFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">2</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">0</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">1</recordLength>
+                    <recordData dataType="byte" bitLength="16">0x0008</recordData>
+                  </ModbusPDUWriteFileRecordRequestItem>
+                </items>
+              </ModbusPDUWriteFileRecordRequest>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
   <testcase>
     <name>Write Extended Registers Request Split File Record</name>
     <raw>000a00000015011512060001270F00010000060002000000010000</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>false</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">21</length>
-        <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">21</functionFlag>
-            <ModbusPDUWriteFileRecordRequest>
-              <byteCount dataType="uint" bitLength="8">18</byteCount>
-              <items isList="true">
-                <ModbusPDUWriteFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">1</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">9999</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">1</recordLength>
-                  <recordData dataType="byte" bitLength="16">0x0000</recordData>
-                </ModbusPDUWriteFileRecordRequestItem>
-                <ModbusPDUWriteFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">2</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">0</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">1</recordLength>
-                  <recordData dataType="byte" bitLength="16">0x0000</recordData>
-                </ModbusPDUWriteFileRecordRequestItem>
-              </items>
-            </ModbusPDUWriteFileRecordRequest>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">21</length>
+          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">21</functionFlag>
+              <ModbusPDUWriteFileRecordRequest>
+                <byteCount dataType="uint" bitLength="8">18</byteCount>
+                <items isList="true">
+                  <ModbusPDUWriteFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">1</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">9999</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">1</recordLength>
+                    <recordData dataType="byte" bitLength="16">0x0000</recordData>
+                  </ModbusPDUWriteFileRecordRequestItem>
+                  <ModbusPDUWriteFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">2</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">0</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">1</recordLength>
+                    <recordData dataType="byte" bitLength="16">0x0000</recordData>
+                  </ModbusPDUWriteFileRecordRequestItem>
+                </items>
+              </ModbusPDUWriteFileRecordRequest>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
diff --git a/plc4go/cmd/main/drivers/tests/modbus_driver_test.go b/plc4go/cmd/main/drivers/tests/modbus_driver_test.go
index 39fab57..815c6ae 100644
--- a/plc4go/cmd/main/drivers/tests/modbus_driver_test.go
+++ b/plc4go/cmd/main/drivers/tests/modbus_driver_test.go
@@ -31,7 +31,7 @@ import (
 
 func TestModbusDriver(t *testing.T) {
 	options := []testutils.WithOption{testutils.WithRootTypeParser(func(readBufferByteBased utils.ReadBufferByteBased) (interface{}, error) {
-		return modbusModel.ModbusTcpADUParse(readBufferByteBased, false)
+		return modbusModel.ModbusTcpADUParse(readBufferByteBased, modbusModel.DriverType_MODBUS_TCP, false)
 	})}
-	testutils.RunDriverTestsuiteWithOptions(t, modbus.NewDriver(), "assets/testing/protocols/modbus/DriverTestsuite.xml", modbusIO.ModbusXmlParserHelper{}, options)
+	testutils.RunDriverTestsuiteWithOptions(t, modbus.NewModbusTcpDriver(), "assets/testing/protocols/modbus/DriverTestsuite.xml", modbusIO.ModbusXmlParserHelper{}, options)
 }
diff --git a/plc4go/examples/read/hello_world_plc4go_read.go b/plc4go/examples/read/hello_world_plc4go_read.go
index a0abb01..65a082b 100644
--- a/plc4go/examples/read/hello_world_plc4go_read.go
+++ b/plc4go/examples/read/hello_world_plc4go_read.go
@@ -28,10 +28,10 @@ import (
 
 func main() {
 	driverManager := plc4go.NewPlcDriverManager()
-	drivers.RegisterModbusDriver(driverManager)
+	drivers.RegisterModbusTcpDriver(driverManager)
 
 	// Get a connection to a remote PLC
-	crc := driverManager.GetConnection("modbus:tcp://192.168.23.30")
+	crc := driverManager.GetConnection("modbus-tcp://192.168.23.30")
 
 	// Wait for the driver to connect (or not)
 	connectionResult := <-crc
diff --git a/plc4go/examples/write/hello_world_plc4go_write.go b/plc4go/examples/write/hello_world_plc4go_write.go
index 1ee1c7c..ecd54e7 100644
--- a/plc4go/examples/write/hello_world_plc4go_write.go
+++ b/plc4go/examples/write/hello_world_plc4go_write.go
@@ -28,10 +28,10 @@ import (
 
 func main() {
 	driverManager := plc4go.NewPlcDriverManager()
-	drivers.RegisterModbusDriver(driverManager)
+	drivers.RegisterModbusTcpDriver(driverManager)
 
 	// Get a connection to a remote PLC
-	crc := driverManager.GetConnection("modbus:tcp://192.168.23.30")
+	crc := driverManager.GetConnection("modbus-tcp://192.168.23.30")
 
 	// Wait for the driver to connect (or not)
 	connectionResult := <-crc
diff --git a/plc4go/internal/plc4go/ads/readwrite/ParserHelper.go b/plc4go/internal/plc4go/ads/readwrite/ParserHelper.go
index 1544c3c..e022da6 100644
--- a/plc4go/internal/plc4go/ads/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/ads/readwrite/ParserHelper.go
@@ -53,7 +53,7 @@ func (m AdsParserHelper) Parse(typeName string, arguments []string, io utils.Rea
 	case "AmsSerialAcknowledgeFrame":
 		return model.AmsSerialAcknowledgeFrameParse(io)
 	case "AdsData":
-		var commandId model.CommandId
+		commandId := model.CommandIdByName(arguments[0])
 		response, err := utils.StrToBool(arguments[1])
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go b/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
index 0e64737..260299f 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
@@ -37,7 +37,7 @@ func (m BacnetipParserHelper) Parse(typeName string, arguments []string, io util
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
 		}
-		var dataType model.BACnetDataType
+		dataType := model.BACnetDataTypeByName(arguments[1])
 		return model.BACnetContextTagParse(io, tagNumberArgument, dataType)
 	case "BACnetStatusFlags":
 		tagNumber, err := utils.StrToUint8(arguments[0])
@@ -98,7 +98,7 @@ func (m BacnetipParserHelper) Parse(typeName string, arguments []string, io util
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
 		}
-		var objectType model.BACnetObjectType
+		objectType := model.BACnetObjectTypeByName(arguments[1])
 		var propertyIdentifierArgument model.BACnetContextTagPropertyIdentifier
 		return model.BACnetConstructedDataParse(io, tagNumber, objectType, &propertyIdentifierArgument)
 	case "BACnetSegmentation":
@@ -162,7 +162,7 @@ func (m BacnetipParserHelper) Parse(typeName string, arguments []string, io util
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
 		}
-		var objectType model.BACnetObjectType
+		objectType := model.BACnetObjectTypeByName(arguments[1])
 		return model.BACnetNotificationParametersParse(io, tagNumber, objectType)
 	case "BACnetConfirmedServiceRequest":
 		len, err := utils.StrToUint16(arguments[0])
@@ -193,7 +193,7 @@ func (m BacnetipParserHelper) Parse(typeName string, arguments []string, io util
 		}
 		return model.BACnetDeviceObjectPropertyReferenceParse(io, tagNumber)
 	case "BACnetConstructedDataElement":
-		var objectType model.BACnetObjectType
+		objectType := model.BACnetObjectTypeByName(arguments[0])
 		var propertyIdentifier model.BACnetContextTagPropertyIdentifier
 		return model.BACnetConstructedDataElementParse(io, objectType, &propertyIdentifier)
 	case "BACnetPropertyValues":
@@ -201,7 +201,7 @@ func (m BacnetipParserHelper) Parse(typeName string, arguments []string, io util
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
 		}
-		var objectType model.BACnetObjectType
+		objectType := model.BACnetObjectTypeByName(arguments[1])
 		return model.BACnetPropertyValuesParse(io, tagNumber, objectType)
 	case "BACnetTagHeader":
 		return model.BACnetTagHeaderParse(io)
@@ -214,7 +214,7 @@ func (m BacnetipParserHelper) Parse(typeName string, arguments []string, io util
 	case "BACnetTagPayloadDouble":
 		return model.BACnetTagPayloadDoubleParse(io)
 	case "BACnetPropertyValue":
-		var objectType model.BACnetObjectType
+		objectType := model.BACnetObjectTypeByName(arguments[0])
 		return model.BACnetPropertyValueParse(io, objectType)
 	case "NLMInitalizeRoutingTablePortMapping":
 		return model.NLMInitalizeRoutingTablePortMappingParse(io)
diff --git a/plc4go/internal/plc4go/cbus/readwrite/ParserHelper.go b/plc4go/internal/plc4go/cbus/readwrite/ParserHelper.go
index 763d125..b6684fc 100644
--- a/plc4go/internal/plc4go/cbus/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/cbus/readwrite/ParserHelper.go
@@ -57,7 +57,7 @@ func (m CbusParserHelper) Parse(typeName string, arguments []string, io utils.Re
 		}
 		return model.CBusCommandParse(io, srchk)
 	case "IdentifyReplyCommand":
-		var attribute model.Attribute
+		attribute := model.AttributeByName(arguments[0])
 		return model.IdentifyReplyCommandParse(io, attribute)
 	case "BridgeCount":
 		return model.BridgeCountParse(io)
diff --git a/plc4go/internal/plc4go/df1/readwrite/model/DF1SymbolMessageFrame.go b/plc4go/internal/plc4go/df1/readwrite/model/DF1SymbolMessageFrame.go
index 86e5cf6..954e90d 100644
--- a/plc4go/internal/plc4go/df1/readwrite/model/DF1SymbolMessageFrame.go
+++ b/plc4go/internal/plc4go/df1/readwrite/model/DF1SymbolMessageFrame.go
@@ -234,7 +234,10 @@ func DF1SymbolMessageFrameParse(readBuffer utils.ReadBuffer) (*DF1SymbolMessageF
 		if _checksumRefErr != nil {
 			return nil, errors.Wrap(_checksumRefErr, "Error parsing 'checksum' field")
 		}
-		checksum := CrcCheck(destinationAddress, sourceAddress, command)
+		checksum, _checksumErr := CrcCheck(destinationAddress, sourceAddress, command)
+		if _checksumErr != nil {
+			return nil, errors.Wrap(_checksumErr, "Checksum verification failed")
+		}
 		if checksum != checksumRef {
 			return nil, errors.Errorf("Checksum verification failed. Expected %x but got %x", checksumRef, checksum)
 		}
@@ -301,10 +304,13 @@ func (m *DF1SymbolMessageFrame) Serialize(writeBuffer utils.WriteBuffer) error {
 
 		// Checksum Field (checksum) (Calculated)
 		{
-			_checksum := CrcCheck(m.GetDestinationAddress(), m.GetSourceAddress(), m.GetCommand())
-			_checksumErr := writeBuffer.WriteUint16("checksum", 16, (_checksum))
+			_checksum, _checksumErr := CrcCheck(m.GetDestinationAddress(), m.GetSourceAddress(), m.GetCommand())
 			if _checksumErr != nil {
-				return errors.Wrap(_checksumErr, "Error serializing 'checksum' field")
+				return errors.Wrap(_checksumErr, "Checksum calculation failed")
+			}
+			_checksumWriteErr := writeBuffer.WriteUint16("checksum", 16, (_checksum))
+			if _checksumWriteErr != nil {
+				return errors.Wrap(_checksumWriteErr, "Error serializing 'checksum' field")
 			}
 		}
 
diff --git a/plc4go/internal/plc4go/df1/readwrite/model/StaticHelper.go b/plc4go/internal/plc4go/df1/readwrite/model/StaticHelper.go
index 88eb5e6..9945aaa 100644
--- a/plc4go/internal/plc4go/df1/readwrite/model/StaticHelper.go
+++ b/plc4go/internal/plc4go/df1/readwrite/model/StaticHelper.go
@@ -31,20 +31,18 @@ func init() {
 	table = crc.NewTable(&crc.Parameters{Width: 16, Polynomial: 0x8005, Init: 0x0000, ReflectIn: true, ReflectOut: true, FinalXor: 0x0000})
 }
 
-func CrcCheck(destinationAddress uint8, sourceAddress uint8, command *DF1Command) uint16 {
+func CrcCheck(destinationAddress uint8, sourceAddress uint8, command *DF1Command) (uint16, error) {
 	df1Crc := table.InitCrc()
 	df1Crc = table.UpdateCrc(df1Crc, []byte{destinationAddress, sourceAddress})
 	bufferByteBased := utils.NewWriteBufferByteBased()
 	err := command.Serialize(bufferByteBased)
 	if err != nil {
-		// TODO: handle error
-		_ = err
-		return 0
+		return 0, err
 	}
 	bytes := bufferByteBased.GetBytes()
 	df1Crc = table.UpdateCrc(df1Crc, bytes)
 	df1Crc = table.UpdateCrc(df1Crc, []byte{0x03})
-	return table.CRC16(df1Crc)
+	return table.CRC16(df1Crc), nil
 }
 
 func DataTerminate(io utils.ReadBuffer) bool {
diff --git a/plc4go/internal/plc4go/df1/readwrite/model/StaticHelper_test.go b/plc4go/internal/plc4go/df1/readwrite/model/StaticHelper_test.go
index 307736d..c3b579e 100644
--- a/plc4go/internal/plc4go/df1/readwrite/model/StaticHelper_test.go
+++ b/plc4go/internal/plc4go/df1/readwrite/model/StaticHelper_test.go
@@ -63,7 +63,10 @@ func TestDF1UtilsCrcCheck(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			got := CrcCheck(tt.args.destinationAddress, tt.args.sourceAddress, tt.args.command)
+			got, err := CrcCheck(tt.args.destinationAddress, tt.args.sourceAddress, tt.args.command)
+			if err != nil {
+				t.Errorf("DF1UtilsCrcCheck() got error: %#v", err)
+			}
 			if got != tt.want {
 				t.Errorf("DF1UtilsCrcCheck() got = %#v, want %#v", got, tt.want)
 			}
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/ParserHelper.go b/plc4go/internal/plc4go/knxnetip/readwrite/ParserHelper.go
index 526f5c6..99591ae 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/ParserHelper.go
@@ -33,7 +33,7 @@ type KnxnetipParserHelper struct {
 func (m KnxnetipParserHelper) Parse(typeName string, arguments []string, io utils.ReadBuffer) (interface{}, error) {
 	switch typeName {
 	case "KnxProperty":
-		var propertyType model.KnxPropertyDataType
+		propertyType := model.KnxPropertyDataTypeByName(arguments[0])
 		dataLengthInBytes, err := utils.StrToUint8(arguments[1])
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
@@ -84,7 +84,7 @@ func (m KnxnetipParserHelper) Parse(typeName string, arguments []string, io util
 	case "CEMIAdditionalInformation":
 		return model.CEMIAdditionalInformationParse(io)
 	case "ComObjectTable":
-		var firmwareType model.FirmwareType
+		firmwareType := model.FirmwareTypeByName(arguments[0])
 		return model.ComObjectTableParse(io, firmwareType)
 	case "KnxAddress":
 		return model.KnxAddressParse(io)
@@ -131,7 +131,7 @@ func (m KnxnetipParserHelper) Parse(typeName string, arguments []string, io util
 	case "GroupObjectDescriptorRealisationType1":
 		return model.GroupObjectDescriptorRealisationType1Parse(io)
 	case "KnxDatapoint":
-		var datapointType model.KnxDatapointType
+		datapointType := model.KnxDatapointTypeByName(arguments[0])
 		return model.KnxDatapointParse(io, datapointType)
 	}
 	return nil, errors.Errorf("Unsupported type %s", typeName)
diff --git a/plc4go/internal/plc4go/modbus/MessageCodec.go b/plc4go/internal/plc4go/modbus/MessageCodec.go
index 99889ac..b675483 100644
--- a/plc4go/internal/plc4go/modbus/MessageCodec.go
+++ b/plc4go/internal/plc4go/modbus/MessageCodec.go
@@ -88,7 +88,7 @@ func (m *MessageCodec) Receive() (interface{}, error) {
 			return nil, nil
 		}
 		rb := utils.NewReadBufferByteBased(data)
-		tcpAdu, err := model.ModbusTcpADUParse(rb, true)
+		tcpAdu, err := model.ModbusTcpADUParse(rb, model.DriverType_MODBUS_TCP, true)
 		if err != nil {
 			log.Warn().Err(err).Msg("error parsing")
 			// TODO: Possibly clean up ...
diff --git a/plc4go/internal/plc4go/modbus/Driver.go b/plc4go/internal/plc4go/modbus/ModbusAsciiDriver.go
similarity index 90%
copy from plc4go/internal/plc4go/modbus/Driver.go
copy to plc4go/internal/plc4go/modbus/ModbusAsciiDriver.go
index f6744ab..64ed3f2 100644
--- a/plc4go/internal/plc4go/modbus/Driver.go
+++ b/plc4go/internal/plc4go/modbus/ModbusAsciiDriver.go
@@ -31,17 +31,17 @@ import (
 	"strconv"
 )
 
-type Driver struct {
+type ModbusAsciiDriver struct {
 	_default.DefaultDriver
 }
 
-func NewDriver() *Driver {
-	return &Driver{
-		DefaultDriver: _default.NewDefaultDriver("modbus", "Modbus", "tcp", NewFieldHandler()),
+func NewModbusAsciiDriver() *ModbusAsciiDriver {
+	return &ModbusAsciiDriver{
+		DefaultDriver: _default.NewDefaultDriver("modbus-ascii", "Modbus ASCII", "serial", NewFieldHandler()),
 	}
 }
 
-func (m Driver) GetConnection(transportUrl url.URL, transports map[string]transports.Transport, options map[string][]string) <-chan plc4go.PlcConnectionConnectResult {
+func (m ModbusAsciiDriver) GetConnection(transportUrl url.URL, transports map[string]transports.Transport, options map[string][]string) <-chan plc4go.PlcConnectionConnectResult {
 	log.Debug().Stringer("transportUrl", &transportUrl).Msgf("Get connection for transport url with %d transport(s) and %d option(s)", len(transports), len(options))
 	// Get an the transport specified in the url
 	transport, ok := transports[transportUrl.Scheme]
diff --git a/plc4go/internal/plc4go/modbus/Driver.go b/plc4go/internal/plc4go/modbus/ModbusRtuDriver.go
similarity index 90%
copy from plc4go/internal/plc4go/modbus/Driver.go
copy to plc4go/internal/plc4go/modbus/ModbusRtuDriver.go
index f6744ab..bd094e5 100644
--- a/plc4go/internal/plc4go/modbus/Driver.go
+++ b/plc4go/internal/plc4go/modbus/ModbusRtuDriver.go
@@ -31,17 +31,17 @@ import (
 	"strconv"
 )
 
-type Driver struct {
+type ModbusRtuDriver struct {
 	_default.DefaultDriver
 }
 
-func NewDriver() *Driver {
-	return &Driver{
-		DefaultDriver: _default.NewDefaultDriver("modbus", "Modbus", "tcp", NewFieldHandler()),
+func NewModbusRtuDriver() *ModbusRtuDriver {
+	return &ModbusRtuDriver{
+		DefaultDriver: _default.NewDefaultDriver("modbus-rtu", "Modbus RTU", "serial", NewFieldHandler()),
 	}
 }
 
-func (m Driver) GetConnection(transportUrl url.URL, transports map[string]transports.Transport, options map[string][]string) <-chan plc4go.PlcConnectionConnectResult {
+func (m ModbusRtuDriver) GetConnection(transportUrl url.URL, transports map[string]transports.Transport, options map[string][]string) <-chan plc4go.PlcConnectionConnectResult {
 	log.Debug().Stringer("transportUrl", &transportUrl).Msgf("Get connection for transport url with %d transport(s) and %d option(s)", len(transports), len(options))
 	// Get an the transport specified in the url
 	transport, ok := transports[transportUrl.Scheme]
diff --git a/plc4go/internal/plc4go/modbus/Driver.go b/plc4go/internal/plc4go/modbus/ModbusTcpDriver.go
similarity index 91%
rename from plc4go/internal/plc4go/modbus/Driver.go
rename to plc4go/internal/plc4go/modbus/ModbusTcpDriver.go
index f6744ab..a0552d8 100644
--- a/plc4go/internal/plc4go/modbus/Driver.go
+++ b/plc4go/internal/plc4go/modbus/ModbusTcpDriver.go
@@ -31,17 +31,17 @@ import (
 	"strconv"
 )
 
-type Driver struct {
+type ModbusTcpDriver struct {
 	_default.DefaultDriver
 }
 
-func NewDriver() *Driver {
-	return &Driver{
-		DefaultDriver: _default.NewDefaultDriver("modbus", "Modbus", "tcp", NewFieldHandler()),
+func NewModbusTcpDriver() *ModbusTcpDriver {
+	return &ModbusTcpDriver{
+		DefaultDriver: _default.NewDefaultDriver("modbus-tcp", "Modbus TCP", "tcp", NewFieldHandler()),
 	}
 }
 
-func (m Driver) GetConnection(transportUrl url.URL, transports map[string]transports.Transport, options map[string][]string) <-chan plc4go.PlcConnectionConnectResult {
+func (m ModbusTcpDriver) GetConnection(transportUrl url.URL, transports map[string]transports.Transport, options map[string][]string) <-chan plc4go.PlcConnectionConnectResult {
 	log.Debug().Stringer("transportUrl", &transportUrl).Msgf("Get connection for transport url with %d transport(s) and %d option(s)", len(transports), len(options))
 	// Get an the transport specified in the url
 	transport, ok := transports[transportUrl.Scheme]
diff --git a/plc4go/internal/plc4go/modbus/readwrite/ParserHelper.go b/plc4go/internal/plc4go/modbus/readwrite/ParserHelper.go
index a99f977..6ebb195 100644
--- a/plc4go/internal/plc4go/modbus/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/modbus/readwrite/ParserHelper.go
@@ -35,7 +35,7 @@ func (m ModbusParserHelper) Parse(typeName string, arguments []string, io utils.
 	case "ModbusPDUWriteFileRecordRequestItem":
 		return model.ModbusPDUWriteFileRecordRequestItemParse(io)
 	case "DataItem":
-		var dataType model.ModbusDataType
+		dataType := model.ModbusDataTypeByName(arguments[0])
 		numberOfValues, err := utils.StrToUint16(arguments[1])
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
@@ -47,12 +47,6 @@ func (m ModbusParserHelper) Parse(typeName string, arguments []string, io utils.
 		return model.ModbusDeviceInformationObjectParse(io)
 	case "ModbusConstants":
 		return model.ModbusConstantsParse(io)
-	case "ModbusTcpADU":
-		response, err := utils.StrToBool(arguments[0])
-		if err != nil {
-			return nil, errors.Wrap(err, "Error parsing")
-		}
-		return model.ModbusTcpADUParse(io, response)
 	case "ModbusPDUWriteFileRecordResponseItem":
 		return model.ModbusPDUWriteFileRecordResponseItemParse(io)
 	case "ModbusPDU":
@@ -63,12 +57,13 @@ func (m ModbusParserHelper) Parse(typeName string, arguments []string, io utils.
 		return model.ModbusPDUParse(io, response)
 	case "ModbusPDUReadFileRecordRequestItem":
 		return model.ModbusPDUReadFileRecordRequestItemParse(io)
-	case "ModbusSerialADU":
-		response, err := utils.StrToBool(arguments[0])
+	case "ModbusADU":
+		driverType := model.DriverTypeByName(arguments[0])
+		response, err := utils.StrToBool(arguments[1])
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
 		}
-		return model.ModbusSerialADUParse(io, response)
+		return model.ModbusADUParse(io, driverType, response)
 	}
 	return nil, errors.Errorf("Unsupported type %s", typeName)
 }
diff --git a/plc4go/internal/plc4go/modbus/readwrite/XmlParserHelper.go b/plc4go/internal/plc4go/modbus/readwrite/XmlParserHelper.go
index a8a6781..c744a91 100644
--- a/plc4go/internal/plc4go/modbus/readwrite/XmlParserHelper.go
+++ b/plc4go/internal/plc4go/modbus/readwrite/XmlParserHelper.go
@@ -58,9 +58,6 @@ func (m ModbusXmlParserHelper) Parse(typeName string, xmlString string, parserAr
 		return model.ModbusDeviceInformationObjectParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "ModbusConstants":
 		return model.ModbusConstantsParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
-	case "ModbusTcpADU":
-		response := parserArguments[0] == "true"
-		return model.ModbusTcpADUParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), response)
 	case "ModbusPDUWriteFileRecordResponseItem":
 		return model.ModbusPDUWriteFileRecordResponseItemParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "ModbusPDU":
@@ -68,9 +65,10 @@ func (m ModbusXmlParserHelper) Parse(typeName string, xmlString string, parserAr
 		return model.ModbusPDUParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), response)
 	case "ModbusPDUReadFileRecordRequestItem":
 		return model.ModbusPDUReadFileRecordRequestItemParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
-	case "ModbusSerialADU":
-		response := parserArguments[0] == "true"
-		return model.ModbusSerialADUParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), response)
+	case "ModbusADU":
+		driverType := model.DriverTypeByName(parserArguments[0])
+		response := parserArguments[1] == "true"
+		return model.ModbusADUParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), driverType, response)
 	}
 	return nil, errors.Errorf("Unsupported type %s", typeName)
 }
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/DriverType.go b/plc4go/internal/plc4go/modbus/readwrite/model/DriverType.go
new file mode 100644
index 0000000..1acd708
--- /dev/null
+++ b/plc4go/internal/plc4go/modbus/readwrite/model/DriverType.go
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+type DriverType uint32
+
+type IDriverType interface {
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+const (
+	DriverType_MODBUS_TCP   DriverType = 0x01
+	DriverType_MODBUS_RTU   DriverType = 0x02
+	DriverType_MODBUS_ASCII DriverType = 0x03
+)
+
+var DriverTypeValues []DriverType
+
+func init() {
+	_ = errors.New
+	DriverTypeValues = []DriverType{
+		DriverType_MODBUS_TCP,
+		DriverType_MODBUS_RTU,
+		DriverType_MODBUS_ASCII,
+	}
+}
+
+func DriverTypeByValue(value uint32) DriverType {
+	switch value {
+	case 0x01:
+		return DriverType_MODBUS_TCP
+	case 0x02:
+		return DriverType_MODBUS_RTU
+	case 0x03:
+		return DriverType_MODBUS_ASCII
+	}
+	return 0
+}
+
+func DriverTypeByName(value string) DriverType {
+	switch value {
+	case "MODBUS_TCP":
+		return DriverType_MODBUS_TCP
+	case "MODBUS_RTU":
+		return DriverType_MODBUS_RTU
+	case "MODBUS_ASCII":
+		return DriverType_MODBUS_ASCII
+	}
+	return 0
+}
+
+func DriverTypeKnows(value uint32) bool {
+	for _, typeValue := range DriverTypeValues {
+		if uint32(typeValue) == value {
+			return true
+		}
+	}
+	return false
+}
+
+func CastDriverType(structType interface{}) DriverType {
+	castFunc := func(typ interface{}) DriverType {
+		if sDriverType, ok := typ.(DriverType); ok {
+			return sDriverType
+		}
+		return 0
+	}
+	return castFunc(structType)
+}
+
+func (m DriverType) GetLengthInBits() uint16 {
+	return 32
+}
+
+func (m DriverType) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func DriverTypeParse(readBuffer utils.ReadBuffer) (DriverType, error) {
+	val, err := readBuffer.ReadUint32("DriverType", 32)
+	if err != nil {
+		return 0, nil
+	}
+	return DriverTypeByValue(val), nil
+}
+
+func (e DriverType) Serialize(writeBuffer utils.WriteBuffer) error {
+	return writeBuffer.WriteUint32("DriverType", 32, uint32(e), utils.WithAdditionalStringRepresentation(e.name()))
+}
+
+func (e DriverType) name() string {
+	switch e {
+	case DriverType_MODBUS_TCP:
+		return "MODBUS_TCP"
+	case DriverType_MODBUS_RTU:
+		return "MODBUS_RTU"
+	case DriverType_MODBUS_ASCII:
+		return "MODBUS_ASCII"
+	}
+	return ""
+}
+
+func (e DriverType) String() string {
+	return e.name()
+}
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusADU.go b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusADU.go
new file mode 100644
index 0000000..c182169
--- /dev/null
+++ b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusADU.go
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type ModbusADU struct {
+
+	// Arguments.
+	Response bool
+	Child    IModbusADUChild
+}
+
+// The corresponding interface
+type IModbusADU interface {
+	// GetDriverType returns DriverType (discriminator field)
+	GetDriverType() DriverType
+	// GetLengthInBytes returns the length in bytes
+	GetLengthInBytes() uint16
+	// GetLengthInBits returns the length in bits
+	GetLengthInBits() uint16
+	// Serialize serializes this type
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+type IModbusADUParent interface {
+	SerializeParent(writeBuffer utils.WriteBuffer, child IModbusADU, serializeChildFunction func() error) error
+	GetTypeName() string
+}
+
+type IModbusADUChild interface {
+	Serialize(writeBuffer utils.WriteBuffer) error
+	InitializeParent(parent *ModbusADU)
+	GetParent() *ModbusADU
+
+	GetTypeName() string
+	IModbusADU
+}
+
+// NewModbusADU factory function for ModbusADU
+func NewModbusADU(response bool) *ModbusADU {
+	return &ModbusADU{Response: response}
+}
+
+func CastModbusADU(structType interface{}) *ModbusADU {
+	if casted, ok := structType.(ModbusADU); ok {
+		return &casted
+	}
+	if casted, ok := structType.(*ModbusADU); ok {
+		return casted
+	}
+	if casted, ok := structType.(IModbusADUChild); ok {
+		return casted.GetParent()
+	}
+	return nil
+}
+
+func (m *ModbusADU) GetTypeName() string {
+	return "ModbusADU"
+}
+
+func (m *ModbusADU) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *ModbusADU) GetLengthInBitsConditional(lastItem bool) uint16 {
+	return m.Child.GetLengthInBits()
+}
+
+func (m *ModbusADU) GetParentLengthInBits() uint16 {
+	lengthInBits := uint16(0)
+
+	return lengthInBits
+}
+
+func (m *ModbusADU) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func ModbusADUParse(readBuffer utils.ReadBuffer, driverType DriverType, response bool) (*ModbusADU, error) {
+	if pullErr := readBuffer.PullContext("ModbusADU"); pullErr != nil {
+		return nil, pullErr
+	}
+	currentPos := readBuffer.GetPos()
+	_ = currentPos
+
+	// Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
+	type ModbusADUChild interface {
+		InitializeParent(*ModbusADU)
+		GetParent() *ModbusADU
+	}
+	var _child ModbusADUChild
+	var typeSwitchError error
+	switch {
+	case driverType == DriverType_MODBUS_TCP: // ModbusTcpADU
+		_child, typeSwitchError = ModbusTcpADUParse(readBuffer, driverType, response)
+	case driverType == DriverType_MODBUS_RTU: // ModbusRtuADU
+		_child, typeSwitchError = ModbusRtuADUParse(readBuffer, driverType, response)
+	case driverType == DriverType_MODBUS_ASCII: // ModbusAsciiADU
+		_child, typeSwitchError = ModbusAsciiADUParse(readBuffer, driverType, response)
+	default:
+		// TODO: return actual type
+		typeSwitchError = errors.New("Unmapped type")
+	}
+	if typeSwitchError != nil {
+		return nil, errors.Wrap(typeSwitchError, "Error parsing sub-type for type-switch.")
+	}
+
+	if closeErr := readBuffer.CloseContext("ModbusADU"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Finish initializing
+	_child.InitializeParent(_child.GetParent())
+	return _child.GetParent(), nil
+}
+
+func (m *ModbusADU) Serialize(writeBuffer utils.WriteBuffer) error {
+	return m.Child.Serialize(writeBuffer)
+}
+
+func (m *ModbusADU) SerializeParent(writeBuffer utils.WriteBuffer, child IModbusADU, serializeChildFunction func() error) error {
+	if pushErr := writeBuffer.PushContext("ModbusADU"); pushErr != nil {
+		return pushErr
+	}
+
+	// Switch field (Depending on the discriminator values, passes the serialization to a sub-type)
+	if _typeSwitchErr := serializeChildFunction(); _typeSwitchErr != nil {
+		return errors.Wrap(_typeSwitchErr, "Error serializing sub-type field")
+	}
+
+	if popErr := writeBuffer.PopContext("ModbusADU"); popErr != nil {
+		return popErr
+	}
+	return nil
+}
+
+func (m *ModbusADU) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := m.Serialize(buffer); err != nil {
+		return err.Error()
+	}
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusAsciiADU.go b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusAsciiADU.go
index d5b7282..5f23643 100644
--- a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusAsciiADU.go
+++ b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusAsciiADU.go
@@ -20,20 +20,15 @@
 package model
 
 import (
-	"fmt"
 	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
 	"github.com/pkg/errors"
 )
 
 // Code generated by code-generation. DO NOT EDIT.
 
-// Constant values.
-const ModbusAsciiADU_START uint8 = 0x3A
-const ModbusAsciiADU_CR uint8 = 0x0D
-const ModbusAsciiADU_LF uint8 = 0x0A
-
 // The data-structure of this message
 type ModbusAsciiADU struct {
+	*ModbusADU
 	Address uint8
 	Pdu     *ModbusPDU
 
@@ -43,9 +38,10 @@ type ModbusAsciiADU struct {
 
 // The corresponding interface
 type IModbusAsciiADU interface {
-	// GetAddress returns Address
+	IModbusADU
+	// GetAddress returns Address (property field)
 	GetAddress() uint8
-	// GetPdu returns Pdu
+	// GetPdu returns Pdu (property field)
 	GetPdu() *ModbusPDU
 	// GetLengthInBytes returns the length in bytes
 	GetLengthInBytes() uint16
@@ -56,8 +52,28 @@ type IModbusAsciiADU interface {
 }
 
 ///////////////////////////////////////////////////////////
-// Accessors for property fields.
 ///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+func (m *ModbusAsciiADU) GetDriverType() DriverType {
+	return DriverType_MODBUS_ASCII
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *ModbusAsciiADU) InitializeParent(parent *ModbusADU) {}
+
+func (m *ModbusAsciiADU) GetParent() *ModbusADU {
+	return m.ModbusADU
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
 func (m *ModbusAsciiADU) GetAddress() uint8 {
 	return m.Address
 }
@@ -66,26 +82,36 @@ func (m *ModbusAsciiADU) GetPdu() *ModbusPDU {
 	return m.Pdu
 }
 
+///////////////////////
+///////////////////////
 ///////////////////////////////////////////////////////////
-// Accessors for virtual fields.
 ///////////////////////////////////////////////////////////
 
 // NewModbusAsciiADU factory function for ModbusAsciiADU
 func NewModbusAsciiADU(address uint8, pdu *ModbusPDU, response bool) *ModbusAsciiADU {
-	return &ModbusAsciiADU{Address: address, Pdu: pdu, Response: response}
+	_result := &ModbusAsciiADU{
+		Address:   address,
+		Pdu:       pdu,
+		ModbusADU: NewModbusADU(response),
+	}
+	_result.Child = _result
+	return _result
 }
 
 func CastModbusAsciiADU(structType interface{}) *ModbusAsciiADU {
-	castFunc := func(typ interface{}) *ModbusAsciiADU {
-		if casted, ok := typ.(ModbusAsciiADU); ok {
-			return &casted
-		}
-		if casted, ok := typ.(*ModbusAsciiADU); ok {
-			return casted
-		}
-		return nil
+	if casted, ok := structType.(ModbusAsciiADU); ok {
+		return &casted
 	}
-	return castFunc(structType)
+	if casted, ok := structType.(*ModbusAsciiADU); ok {
+		return casted
+	}
+	if casted, ok := structType.(ModbusADU); ok {
+		return CastModbusAsciiADU(casted.Child)
+	}
+	if casted, ok := structType.(*ModbusADU); ok {
+		return CastModbusAsciiADU(casted.Child)
+	}
+	return nil
 }
 
 func (m *ModbusAsciiADU) GetTypeName() string {
@@ -97,10 +123,7 @@ func (m *ModbusAsciiADU) GetLengthInBits() uint16 {
 }
 
 func (m *ModbusAsciiADU) GetLengthInBitsConditional(lastItem bool) uint16 {
-	lengthInBits := uint16(0)
-
-	// Const Field (start)
-	lengthInBits += 8
+	lengthInBits := uint16(m.GetParentLengthInBits())
 
 	// Simple field (address)
 	lengthInBits += 8
@@ -108,10 +131,7 @@ func (m *ModbusAsciiADU) GetLengthInBitsConditional(lastItem bool) uint16 {
 	// Simple field (pdu)
 	lengthInBits += m.Pdu.GetLengthInBits()
 
-	// Const Field (cr)
-	lengthInBits += 8
-
-	// Const Field (lf)
+	// Checksum Field (checksum)
 	lengthInBits += 8
 
 	return lengthInBits
@@ -121,22 +141,13 @@ func (m *ModbusAsciiADU) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func ModbusAsciiADUParse(readBuffer utils.ReadBuffer, response bool) (*ModbusAsciiADU, error) {
+func ModbusAsciiADUParse(readBuffer utils.ReadBuffer, driverType DriverType, response bool) (*ModbusAsciiADU, error) {
 	if pullErr := readBuffer.PullContext("ModbusAsciiADU"); pullErr != nil {
 		return nil, pullErr
 	}
 	currentPos := readBuffer.GetPos()
 	_ = currentPos
 
-	// Const Field (start)
-	start, _startErr := readBuffer.ReadUint8("start", 8)
-	if _startErr != nil {
-		return nil, errors.Wrap(_startErr, "Error parsing 'start' field")
-	}
-	if start != ModbusAsciiADU_START {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", ModbusAsciiADU_START) + " but got " + fmt.Sprintf("%d", start))
-	}
-
 	// Simple Field (address)
 	_address, _addressErr := readBuffer.ReadUint8("address", 8)
 	if _addressErr != nil {
@@ -157,78 +168,78 @@ func ModbusAsciiADUParse(readBuffer utils.ReadBuffer, response bool) (*ModbusAsc
 		return nil, closeErr
 	}
 
-	// Const Field (cr)
-	cr, _crErr := readBuffer.ReadUint8("cr", 8)
-	if _crErr != nil {
-		return nil, errors.Wrap(_crErr, "Error parsing 'cr' field")
-	}
-	if cr != ModbusAsciiADU_CR {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", ModbusAsciiADU_CR) + " but got " + fmt.Sprintf("%d", cr))
-	}
-
-	// Const Field (lf)
-	lf, _lfErr := readBuffer.ReadUint8("lf", 8)
-	if _lfErr != nil {
-		return nil, errors.Wrap(_lfErr, "Error parsing 'lf' field")
-	}
-	if lf != ModbusAsciiADU_LF {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", ModbusAsciiADU_LF) + " but got " + fmt.Sprintf("%d", lf))
+	// Checksum Field (checksum)
+	{
+		checksumRef, _checksumRefErr := readBuffer.ReadUint8("checksum", 8)
+		if _checksumRefErr != nil {
+			return nil, errors.Wrap(_checksumRefErr, "Error parsing 'checksum' field")
+		}
+		checksum, _checksumErr := AsciiLrcCheck(address, pdu)
+		if _checksumErr != nil {
+			return nil, errors.Wrap(_checksumErr, "Checksum verification failed")
+		}
+		if checksum != checksumRef {
+			return nil, errors.Errorf("Checksum verification failed. Expected %x but got %x", checksumRef, checksum)
+		}
 	}
 
 	if closeErr := readBuffer.CloseContext("ModbusAsciiADU"); closeErr != nil {
 		return nil, closeErr
 	}
 
-	// Create the instance
-	return NewModbusAsciiADU(address, pdu, response), nil
+	// Create a partially initialized instance
+	_child := &ModbusAsciiADU{
+		Address:   address,
+		Pdu:       CastModbusPDU(pdu),
+		ModbusADU: &ModbusADU{},
+	}
+	_child.ModbusADU.Child = _child
+	return _child, nil
 }
 
 func (m *ModbusAsciiADU) Serialize(writeBuffer utils.WriteBuffer) error {
-	if pushErr := writeBuffer.PushContext("ModbusAsciiADU"); pushErr != nil {
-		return pushErr
-	}
-
-	// Const Field (start)
-	_startErr := writeBuffer.WriteUint8("start", 8, 0x3A)
-	if _startErr != nil {
-		return errors.Wrap(_startErr, "Error serializing 'start' field")
-	}
-
-	// Simple Field (address)
-	address := uint8(m.Address)
-	_addressErr := writeBuffer.WriteUint8("address", 8, (address))
-	if _addressErr != nil {
-		return errors.Wrap(_addressErr, "Error serializing 'address' field")
-	}
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("ModbusAsciiADU"); pushErr != nil {
+			return pushErr
+		}
 
-	// Simple Field (pdu)
-	if pushErr := writeBuffer.PushContext("pdu"); pushErr != nil {
-		return pushErr
-	}
-	_pduErr := m.Pdu.Serialize(writeBuffer)
-	if popErr := writeBuffer.PopContext("pdu"); popErr != nil {
-		return popErr
-	}
-	if _pduErr != nil {
-		return errors.Wrap(_pduErr, "Error serializing 'pdu' field")
-	}
+		// Simple Field (address)
+		address := uint8(m.Address)
+		_addressErr := writeBuffer.WriteUint8("address", 8, (address))
+		if _addressErr != nil {
+			return errors.Wrap(_addressErr, "Error serializing 'address' field")
+		}
 
-	// Const Field (cr)
-	_crErr := writeBuffer.WriteUint8("cr", 8, 0x0D)
-	if _crErr != nil {
-		return errors.Wrap(_crErr, "Error serializing 'cr' field")
-	}
+		// Simple Field (pdu)
+		if pushErr := writeBuffer.PushContext("pdu"); pushErr != nil {
+			return pushErr
+		}
+		_pduErr := m.Pdu.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("pdu"); popErr != nil {
+			return popErr
+		}
+		if _pduErr != nil {
+			return errors.Wrap(_pduErr, "Error serializing 'pdu' field")
+		}
 
-	// Const Field (lf)
-	_lfErr := writeBuffer.WriteUint8("lf", 8, 0x0A)
-	if _lfErr != nil {
-		return errors.Wrap(_lfErr, "Error serializing 'lf' field")
-	}
+		// Checksum Field (checksum) (Calculated)
+		{
+			_checksum, _checksumErr := AsciiLrcCheck(m.GetAddress(), m.GetPdu())
+			if _checksumErr != nil {
+				return errors.Wrap(_checksumErr, "Checksum calculation failed")
+			}
+			_checksumWriteErr := writeBuffer.WriteUint8("checksum", 8, (_checksum))
+			if _checksumWriteErr != nil {
+				return errors.Wrap(_checksumWriteErr, "Error serializing 'checksum' field")
+			}
+		}
 
-	if popErr := writeBuffer.PopContext("ModbusAsciiADU"); popErr != nil {
-		return popErr
+		if popErr := writeBuffer.PopContext("ModbusAsciiADU"); popErr != nil {
+			return popErr
+		}
+		return nil
 	}
-	return nil
+	return m.SerializeParent(writeBuffer, m, ser)
 }
 
 func (m *ModbusAsciiADU) String() string {
@@ -236,6 +247,8 @@ func (m *ModbusAsciiADU) String() string {
 		return "<nil>"
 	}
 	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
-	m.Serialize(buffer)
+	if err := m.Serialize(buffer); err != nil {
+		return err.Error()
+	}
 	return buffer.GetBox().String()
 }
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusRtuADU.go b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusRtuADU.go
index 8004c3a..f32f918 100644
--- a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusRtuADU.go
+++ b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusRtuADU.go
@@ -20,21 +20,15 @@
 package model
 
 import (
-	"fmt"
 	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
 	"github.com/pkg/errors"
 )
 
 // Code generated by code-generation. DO NOT EDIT.
 
-// Constant values.
-const ModbusRtuADU_SPACE1 uint8 = 0x00
-const ModbusRtuADU_SPACE2 uint8 = 0x00
-const ModbusRtuADU_SPACE3 uint8 = 0x00
-const ModbusRtuADU_SPACE4 uint8 = 0x00
-
 // The data-structure of this message
 type ModbusRtuADU struct {
+	*ModbusADU
 	Address uint8
 	Pdu     *ModbusPDU
 
@@ -44,9 +38,10 @@ type ModbusRtuADU struct {
 
 // The corresponding interface
 type IModbusRtuADU interface {
-	// GetAddress returns Address
+	IModbusADU
+	// GetAddress returns Address (property field)
 	GetAddress() uint8
-	// GetPdu returns Pdu
+	// GetPdu returns Pdu (property field)
 	GetPdu() *ModbusPDU
 	// GetLengthInBytes returns the length in bytes
 	GetLengthInBytes() uint16
@@ -57,8 +52,28 @@ type IModbusRtuADU interface {
 }
 
 ///////////////////////////////////////////////////////////
-// Accessors for property fields.
 ///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+func (m *ModbusRtuADU) GetDriverType() DriverType {
+	return DriverType_MODBUS_RTU
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *ModbusRtuADU) InitializeParent(parent *ModbusADU) {}
+
+func (m *ModbusRtuADU) GetParent() *ModbusADU {
+	return m.ModbusADU
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
 func (m *ModbusRtuADU) GetAddress() uint8 {
 	return m.Address
 }
@@ -67,26 +82,36 @@ func (m *ModbusRtuADU) GetPdu() *ModbusPDU {
 	return m.Pdu
 }
 
+///////////////////////
+///////////////////////
 ///////////////////////////////////////////////////////////
-// Accessors for virtual fields.
 ///////////////////////////////////////////////////////////
 
 // NewModbusRtuADU factory function for ModbusRtuADU
 func NewModbusRtuADU(address uint8, pdu *ModbusPDU, response bool) *ModbusRtuADU {
-	return &ModbusRtuADU{Address: address, Pdu: pdu, Response: response}
+	_result := &ModbusRtuADU{
+		Address:   address,
+		Pdu:       pdu,
+		ModbusADU: NewModbusADU(response),
+	}
+	_result.Child = _result
+	return _result
 }
 
 func CastModbusRtuADU(structType interface{}) *ModbusRtuADU {
-	castFunc := func(typ interface{}) *ModbusRtuADU {
-		if casted, ok := typ.(ModbusRtuADU); ok {
-			return &casted
-		}
-		if casted, ok := typ.(*ModbusRtuADU); ok {
-			return casted
-		}
-		return nil
+	if casted, ok := structType.(ModbusRtuADU); ok {
+		return &casted
+	}
+	if casted, ok := structType.(*ModbusRtuADU); ok {
+		return casted
+	}
+	if casted, ok := structType.(ModbusADU); ok {
+		return CastModbusRtuADU(casted.Child)
+	}
+	if casted, ok := structType.(*ModbusADU); ok {
+		return CastModbusRtuADU(casted.Child)
 	}
-	return castFunc(structType)
+	return nil
 }
 
 func (m *ModbusRtuADU) GetTypeName() string {
@@ -98,19 +123,7 @@ func (m *ModbusRtuADU) GetLengthInBits() uint16 {
 }
 
 func (m *ModbusRtuADU) GetLengthInBitsConditional(lastItem bool) uint16 {
-	lengthInBits := uint16(0)
-
-	// Const Field (space1)
-	lengthInBits += 8
-
-	// Const Field (space2)
-	lengthInBits += 8
-
-	// Const Field (space3)
-	lengthInBits += 8
-
-	// Const Field (space4)
-	lengthInBits += 8
+	lengthInBits := uint16(m.GetParentLengthInBits())
 
 	// Simple field (address)
 	lengthInBits += 8
@@ -118,6 +131,9 @@ func (m *ModbusRtuADU) GetLengthInBitsConditional(lastItem bool) uint16 {
 	// Simple field (pdu)
 	lengthInBits += m.Pdu.GetLengthInBits()
 
+	// Checksum Field (checksum)
+	lengthInBits += 16
+
 	return lengthInBits
 }
 
@@ -125,49 +141,13 @@ func (m *ModbusRtuADU) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func ModbusRtuADUParse(readBuffer utils.ReadBuffer, response bool) (*ModbusRtuADU, error) {
+func ModbusRtuADUParse(readBuffer utils.ReadBuffer, driverType DriverType, response bool) (*ModbusRtuADU, error) {
 	if pullErr := readBuffer.PullContext("ModbusRtuADU"); pullErr != nil {
 		return nil, pullErr
 	}
 	currentPos := readBuffer.GetPos()
 	_ = currentPos
 
-	// Const Field (space1)
-	space1, _space1Err := readBuffer.ReadUint8("space1", 8)
-	if _space1Err != nil {
-		return nil, errors.Wrap(_space1Err, "Error parsing 'space1' field")
-	}
-	if space1 != ModbusRtuADU_SPACE1 {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", ModbusRtuADU_SPACE1) + " but got " + fmt.Sprintf("%d", space1))
-	}
-
-	// Const Field (space2)
-	space2, _space2Err := readBuffer.ReadUint8("space2", 8)
-	if _space2Err != nil {
-		return nil, errors.Wrap(_space2Err, "Error parsing 'space2' field")
-	}
-	if space2 != ModbusRtuADU_SPACE2 {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", ModbusRtuADU_SPACE2) + " but got " + fmt.Sprintf("%d", space2))
-	}
-
-	// Const Field (space3)
-	space3, _space3Err := readBuffer.ReadUint8("space3", 8)
-	if _space3Err != nil {
-		return nil, errors.Wrap(_space3Err, "Error parsing 'space3' field")
-	}
-	if space3 != ModbusRtuADU_SPACE3 {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", ModbusRtuADU_SPACE3) + " but got " + fmt.Sprintf("%d", space3))
-	}
-
-	// Const Field (space4)
-	space4, _space4Err := readBuffer.ReadUint8("space4", 8)
-	if _space4Err != nil {
-		return nil, errors.Wrap(_space4Err, "Error parsing 'space4' field")
-	}
-	if space4 != ModbusRtuADU_SPACE4 {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", ModbusRtuADU_SPACE4) + " but got " + fmt.Sprintf("%d", space4))
-	}
-
 	// Simple Field (address)
 	_address, _addressErr := readBuffer.ReadUint8("address", 8)
 	if _addressErr != nil {
@@ -188,66 +168,78 @@ func ModbusRtuADUParse(readBuffer utils.ReadBuffer, response bool) (*ModbusRtuAD
 		return nil, closeErr
 	}
 
+	// Checksum Field (checksum)
+	{
+		checksumRef, _checksumRefErr := readBuffer.ReadUint16("checksum", 16)
+		if _checksumRefErr != nil {
+			return nil, errors.Wrap(_checksumRefErr, "Error parsing 'checksum' field")
+		}
+		checksum, _checksumErr := RtuCrcCheck(address, pdu)
+		if _checksumErr != nil {
+			return nil, errors.Wrap(_checksumErr, "Checksum verification failed")
+		}
+		if checksum != checksumRef {
+			return nil, errors.Errorf("Checksum verification failed. Expected %x but got %x", checksumRef, checksum)
+		}
+	}
+
 	if closeErr := readBuffer.CloseContext("ModbusRtuADU"); closeErr != nil {
 		return nil, closeErr
 	}
 
-	// Create the instance
-	return NewModbusRtuADU(address, pdu, response), nil
+	// Create a partially initialized instance
+	_child := &ModbusRtuADU{
+		Address:   address,
+		Pdu:       CastModbusPDU(pdu),
+		ModbusADU: &ModbusADU{},
+	}
+	_child.ModbusADU.Child = _child
+	return _child, nil
 }
 
 func (m *ModbusRtuADU) Serialize(writeBuffer utils.WriteBuffer) error {
-	if pushErr := writeBuffer.PushContext("ModbusRtuADU"); pushErr != nil {
-		return pushErr
-	}
-
-	// Const Field (space1)
-	_space1Err := writeBuffer.WriteUint8("space1", 8, 0x00)
-	if _space1Err != nil {
-		return errors.Wrap(_space1Err, "Error serializing 'space1' field")
-	}
-
-	// Const Field (space2)
-	_space2Err := writeBuffer.WriteUint8("space2", 8, 0x00)
-	if _space2Err != nil {
-		return errors.Wrap(_space2Err, "Error serializing 'space2' field")
-	}
-
-	// Const Field (space3)
-	_space3Err := writeBuffer.WriteUint8("space3", 8, 0x00)
-	if _space3Err != nil {
-		return errors.Wrap(_space3Err, "Error serializing 'space3' field")
-	}
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("ModbusRtuADU"); pushErr != nil {
+			return pushErr
+		}
 
-	// Const Field (space4)
-	_space4Err := writeBuffer.WriteUint8("space4", 8, 0x00)
-	if _space4Err != nil {
-		return errors.Wrap(_space4Err, "Error serializing 'space4' field")
-	}
+		// Simple Field (address)
+		address := uint8(m.Address)
+		_addressErr := writeBuffer.WriteUint8("address", 8, (address))
+		if _addressErr != nil {
+			return errors.Wrap(_addressErr, "Error serializing 'address' field")
+		}
 
-	// Simple Field (address)
-	address := uint8(m.Address)
-	_addressErr := writeBuffer.WriteUint8("address", 8, (address))
-	if _addressErr != nil {
-		return errors.Wrap(_addressErr, "Error serializing 'address' field")
-	}
+		// Simple Field (pdu)
+		if pushErr := writeBuffer.PushContext("pdu"); pushErr != nil {
+			return pushErr
+		}
+		_pduErr := m.Pdu.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("pdu"); popErr != nil {
+			return popErr
+		}
+		if _pduErr != nil {
+			return errors.Wrap(_pduErr, "Error serializing 'pdu' field")
+		}
 
-	// Simple Field (pdu)
-	if pushErr := writeBuffer.PushContext("pdu"); pushErr != nil {
-		return pushErr
-	}
-	_pduErr := m.Pdu.Serialize(writeBuffer)
-	if popErr := writeBuffer.PopContext("pdu"); popErr != nil {
-		return popErr
-	}
-	if _pduErr != nil {
-		return errors.Wrap(_pduErr, "Error serializing 'pdu' field")
-	}
+		// Checksum Field (checksum) (Calculated)
+		{
+			_checksum, _checksumErr := RtuCrcCheck(m.GetAddress(), m.GetPdu())
+			if _checksumErr != nil {
+				return errors.Wrap(_checksumErr, "Checksum calculation failed")
+			}
+			_checksumWriteErr := writeBuffer.WriteUint16("checksum", 16, (_checksum))
+			if _checksumWriteErr != nil {
+				return errors.Wrap(_checksumWriteErr, "Error serializing 'checksum' field")
+			}
+		}
 
-	if popErr := writeBuffer.PopContext("ModbusRtuADU"); popErr != nil {
-		return popErr
+		if popErr := writeBuffer.PopContext("ModbusRtuADU"); popErr != nil {
+			return popErr
+		}
+		return nil
 	}
-	return nil
+	return m.SerializeParent(writeBuffer, m, ser)
 }
 
 func (m *ModbusRtuADU) String() string {
@@ -255,6 +247,8 @@ func (m *ModbusRtuADU) String() string {
 		return "<nil>"
 	}
 	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
-	m.Serialize(buffer)
+	if err := m.Serialize(buffer); err != nil {
+		return err.Error()
+	}
 	return buffer.GetBox().String()
 }
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusSerialADU.go b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusSerialADU.go
deleted file mode 100644
index 4981468..0000000
--- a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusSerialADU.go
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package model
-
-import (
-	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
-	"github.com/pkg/errors"
-)
-
-// Code generated by code-generation. DO NOT EDIT.
-
-// The data-structure of this message
-type ModbusSerialADU struct {
-	Address uint8
-	Pdu     *ModbusPDU
-
-	// Arguments.
-	Response bool
-}
-
-// The corresponding interface
-type IModbusSerialADU interface {
-	// GetAddress returns Address (property field)
-	GetAddress() uint8
-	// GetPdu returns Pdu (property field)
-	GetPdu() *ModbusPDU
-	// GetLengthInBytes returns the length in bytes
-	GetLengthInBytes() uint16
-	// GetLengthInBits returns the length in bits
-	GetLengthInBits() uint16
-	// Serialize serializes this type
-	Serialize(writeBuffer utils.WriteBuffer) error
-}
-
-///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////
-/////////////////////// Accessors for property fields.
-///////////////////////
-func (m *ModbusSerialADU) GetAddress() uint8 {
-	return m.Address
-}
-
-func (m *ModbusSerialADU) GetPdu() *ModbusPDU {
-	return m.Pdu
-}
-
-///////////////////////
-///////////////////////
-///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////
-
-// NewModbusSerialADU factory function for ModbusSerialADU
-func NewModbusSerialADU(address uint8, pdu *ModbusPDU, response bool) *ModbusSerialADU {
-	return &ModbusSerialADU{Address: address, Pdu: pdu, Response: response}
-}
-
-func CastModbusSerialADU(structType interface{}) *ModbusSerialADU {
-	if casted, ok := structType.(ModbusSerialADU); ok {
-		return &casted
-	}
-	if casted, ok := structType.(*ModbusSerialADU); ok {
-		return casted
-	}
-	return nil
-}
-
-func (m *ModbusSerialADU) GetTypeName() string {
-	return "ModbusSerialADU"
-}
-
-func (m *ModbusSerialADU) GetLengthInBits() uint16 {
-	return m.GetLengthInBitsConditional(false)
-}
-
-func (m *ModbusSerialADU) GetLengthInBitsConditional(lastItem bool) uint16 {
-	lengthInBits := uint16(0)
-
-	// Simple field (address)
-	lengthInBits += 8
-
-	// Simple field (pdu)
-	lengthInBits += m.Pdu.GetLengthInBits()
-
-	// Checksum Field (checksum)
-	lengthInBits += 16
-
-	return lengthInBits
-}
-
-func (m *ModbusSerialADU) GetLengthInBytes() uint16 {
-	return m.GetLengthInBits() / 8
-}
-
-func ModbusSerialADUParse(readBuffer utils.ReadBuffer, response bool) (*ModbusSerialADU, error) {
-	if pullErr := readBuffer.PullContext("ModbusSerialADU"); pullErr != nil {
-		return nil, pullErr
-	}
-	currentPos := readBuffer.GetPos()
-	_ = currentPos
-
-	// Simple Field (address)
-	_address, _addressErr := readBuffer.ReadUint8("address", 8)
-	if _addressErr != nil {
-		return nil, errors.Wrap(_addressErr, "Error parsing 'address' field")
-	}
-	address := _address
-
-	// Simple Field (pdu)
-	if pullErr := readBuffer.PullContext("pdu"); pullErr != nil {
-		return nil, pullErr
-	}
-	_pdu, _pduErr := ModbusPDUParse(readBuffer, bool(response))
-	if _pduErr != nil {
-		return nil, errors.Wrap(_pduErr, "Error parsing 'pdu' field")
-	}
-	pdu := CastModbusPDU(_pdu)
-	if closeErr := readBuffer.CloseContext("pdu"); closeErr != nil {
-		return nil, closeErr
-	}
-
-	// Checksum Field (checksum)
-	{
-		checksumRef, _checksumRefErr := readBuffer.ReadUint16("checksum", 16)
-		if _checksumRefErr != nil {
-			return nil, errors.Wrap(_checksumRefErr, "Error parsing 'checksum' field")
-		}
-		checksum := CrcCheck(address, pdu)
-		if checksum != checksumRef {
-			return nil, errors.Errorf("Checksum verification failed. Expected %x but got %x", checksumRef, checksum)
-		}
-	}
-
-	if closeErr := readBuffer.CloseContext("ModbusSerialADU"); closeErr != nil {
-		return nil, closeErr
-	}
-
-	// Create the instance
-	return NewModbusSerialADU(address, pdu, response), nil
-}
-
-func (m *ModbusSerialADU) Serialize(writeBuffer utils.WriteBuffer) error {
-	if pushErr := writeBuffer.PushContext("ModbusSerialADU"); pushErr != nil {
-		return pushErr
-	}
-
-	// Simple Field (address)
-	address := uint8(m.Address)
-	_addressErr := writeBuffer.WriteUint8("address", 8, (address))
-	if _addressErr != nil {
-		return errors.Wrap(_addressErr, "Error serializing 'address' field")
-	}
-
-	// Simple Field (pdu)
-	if pushErr := writeBuffer.PushContext("pdu"); pushErr != nil {
-		return pushErr
-	}
-	_pduErr := m.Pdu.Serialize(writeBuffer)
-	if popErr := writeBuffer.PopContext("pdu"); popErr != nil {
-		return popErr
-	}
-	if _pduErr != nil {
-		return errors.Wrap(_pduErr, "Error serializing 'pdu' field")
-	}
-
-	// Checksum Field (checksum) (Calculated)
-	{
-		_checksum := CrcCheck(m.GetAddress(), m.GetPdu())
-		_checksumErr := writeBuffer.WriteUint16("checksum", 16, (_checksum))
-		if _checksumErr != nil {
-			return errors.Wrap(_checksumErr, "Error serializing 'checksum' field")
-		}
-	}
-
-	if popErr := writeBuffer.PopContext("ModbusSerialADU"); popErr != nil {
-		return popErr
-	}
-	return nil
-}
-
-func (m *ModbusSerialADU) String() string {
-	if m == nil {
-		return "<nil>"
-	}
-	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
-	if err := m.Serialize(buffer); err != nil {
-		return err.Error()
-	}
-	return buffer.GetBox().String()
-}
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusTcpADU.go b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusTcpADU.go
index b2f0c1a..04601f5 100644
--- a/plc4go/internal/plc4go/modbus/readwrite/model/ModbusTcpADU.go
+++ b/plc4go/internal/plc4go/modbus/readwrite/model/ModbusTcpADU.go
@@ -32,6 +32,7 @@ const ModbusTcpADU_PROTOCOLIDENTIFIER uint16 = 0x0000
 
 // The data-structure of this message
 type ModbusTcpADU struct {
+	*ModbusADU
 	TransactionIdentifier uint16
 	UnitIdentifier        uint8
 	Pdu                   *ModbusPDU
@@ -42,6 +43,7 @@ type ModbusTcpADU struct {
 
 // The corresponding interface
 type IModbusTcpADU interface {
+	IModbusADU
 	// GetTransactionIdentifier returns TransactionIdentifier (property field)
 	GetTransactionIdentifier() uint16
 	// GetUnitIdentifier returns UnitIdentifier (property field)
@@ -58,6 +60,25 @@ type IModbusTcpADU interface {
 
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+func (m *ModbusTcpADU) GetDriverType() DriverType {
+	return DriverType_MODBUS_TCP
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *ModbusTcpADU) InitializeParent(parent *ModbusADU) {}
+
+func (m *ModbusTcpADU) GetParent() *ModbusADU {
+	return m.ModbusADU
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
 /////////////////////// Accessors for property fields.
 ///////////////////////
 func (m *ModbusTcpADU) GetTransactionIdentifier() uint16 {
@@ -91,7 +112,14 @@ func (m *ModbusTcpADU) GetProtocolIdentifier() uint16 {
 
 // NewModbusTcpADU factory function for ModbusTcpADU
 func NewModbusTcpADU(transactionIdentifier uint16, unitIdentifier uint8, pdu *ModbusPDU, response bool) *ModbusTcpADU {
-	return &ModbusTcpADU{TransactionIdentifier: transactionIdentifier, UnitIdentifier: unitIdentifier, Pdu: pdu, Response: response}
+	_result := &ModbusTcpADU{
+		TransactionIdentifier: transactionIdentifier,
+		UnitIdentifier:        unitIdentifier,
+		Pdu:                   pdu,
+		ModbusADU:             NewModbusADU(response),
+	}
+	_result.Child = _result
+	return _result
 }
 
 func CastModbusTcpADU(structType interface{}) *ModbusTcpADU {
@@ -101,6 +129,12 @@ func CastModbusTcpADU(structType interface{}) *ModbusTcpADU {
 	if casted, ok := structType.(*ModbusTcpADU); ok {
 		return casted
 	}
+	if casted, ok := structType.(ModbusADU); ok {
+		return CastModbusTcpADU(casted.Child)
+	}
+	if casted, ok := structType.(*ModbusADU); ok {
+		return CastModbusTcpADU(casted.Child)
+	}
 	return nil
 }
 
@@ -113,7 +147,7 @@ func (m *ModbusTcpADU) GetLengthInBits() uint16 {
 }
 
 func (m *ModbusTcpADU) GetLengthInBitsConditional(lastItem bool) uint16 {
-	lengthInBits := uint16(0)
+	lengthInBits := uint16(m.GetParentLengthInBits())
 
 	// Simple field (transactionIdentifier)
 	lengthInBits += 16
@@ -137,7 +171,7 @@ func (m *ModbusTcpADU) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func ModbusTcpADUParse(readBuffer utils.ReadBuffer, response bool) (*ModbusTcpADU, error) {
+func ModbusTcpADUParse(readBuffer utils.ReadBuffer, driverType DriverType, response bool) (*ModbusTcpADU, error) {
 	if pullErr := readBuffer.PullContext("ModbusTcpADU"); pullErr != nil {
 		return nil, pullErr
 	}
@@ -191,58 +225,68 @@ func ModbusTcpADUParse(readBuffer utils.ReadBuffer, response bool) (*ModbusTcpAD
 		return nil, closeErr
 	}
 
-	// Create the instance
-	return NewModbusTcpADU(transactionIdentifier, unitIdentifier, pdu, response), nil
+	// Create a partially initialized instance
+	_child := &ModbusTcpADU{
+		TransactionIdentifier: transactionIdentifier,
+		UnitIdentifier:        unitIdentifier,
+		Pdu:                   CastModbusPDU(pdu),
+		ModbusADU:             &ModbusADU{},
+	}
+	_child.ModbusADU.Child = _child
+	return _child, nil
 }
 
 func (m *ModbusTcpADU) Serialize(writeBuffer utils.WriteBuffer) error {
-	if pushErr := writeBuffer.PushContext("ModbusTcpADU"); pushErr != nil {
-		return pushErr
-	}
-
-	// Simple Field (transactionIdentifier)
-	transactionIdentifier := uint16(m.TransactionIdentifier)
-	_transactionIdentifierErr := writeBuffer.WriteUint16("transactionIdentifier", 16, (transactionIdentifier))
-	if _transactionIdentifierErr != nil {
-		return errors.Wrap(_transactionIdentifierErr, "Error serializing 'transactionIdentifier' field")
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("ModbusTcpADU"); pushErr != nil {
+			return pushErr
+		}
+
+		// Simple Field (transactionIdentifier)
+		transactionIdentifier := uint16(m.TransactionIdentifier)
+		_transactionIdentifierErr := writeBuffer.WriteUint16("transactionIdentifier", 16, (transactionIdentifier))
+		if _transactionIdentifierErr != nil {
+			return errors.Wrap(_transactionIdentifierErr, "Error serializing 'transactionIdentifier' field")
+		}
+
+		// Const Field (protocolIdentifier)
+		_protocolIdentifierErr := writeBuffer.WriteUint16("protocolIdentifier", 16, 0x0000)
+		if _protocolIdentifierErr != nil {
+			return errors.Wrap(_protocolIdentifierErr, "Error serializing 'protocolIdentifier' field")
+		}
+
+		// Implicit Field (length) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
+		length := uint16(uint16(m.GetPdu().GetLengthInBytes()) + uint16(uint16(1)))
+		_lengthErr := writeBuffer.WriteUint16("length", 16, (length))
+		if _lengthErr != nil {
+			return errors.Wrap(_lengthErr, "Error serializing 'length' field")
+		}
+
+		// Simple Field (unitIdentifier)
+		unitIdentifier := uint8(m.UnitIdentifier)
+		_unitIdentifierErr := writeBuffer.WriteUint8("unitIdentifier", 8, (unitIdentifier))
+		if _unitIdentifierErr != nil {
+			return errors.Wrap(_unitIdentifierErr, "Error serializing 'unitIdentifier' field")
+		}
+
+		// Simple Field (pdu)
+		if pushErr := writeBuffer.PushContext("pdu"); pushErr != nil {
+			return pushErr
+		}
+		_pduErr := m.Pdu.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("pdu"); popErr != nil {
+			return popErr
+		}
+		if _pduErr != nil {
+			return errors.Wrap(_pduErr, "Error serializing 'pdu' field")
+		}
+
+		if popErr := writeBuffer.PopContext("ModbusTcpADU"); popErr != nil {
+			return popErr
+		}
+		return nil
 	}
-
-	// Const Field (protocolIdentifier)
-	_protocolIdentifierErr := writeBuffer.WriteUint16("protocolIdentifier", 16, 0x0000)
-	if _protocolIdentifierErr != nil {
-		return errors.Wrap(_protocolIdentifierErr, "Error serializing 'protocolIdentifier' field")
-	}
-
-	// Implicit Field (length) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-	length := uint16(uint16(m.GetPdu().GetLengthInBytes()) + uint16(uint16(1)))
-	_lengthErr := writeBuffer.WriteUint16("length", 16, (length))
-	if _lengthErr != nil {
-		return errors.Wrap(_lengthErr, "Error serializing 'length' field")
-	}
-
-	// Simple Field (unitIdentifier)
-	unitIdentifier := uint8(m.UnitIdentifier)
-	_unitIdentifierErr := writeBuffer.WriteUint8("unitIdentifier", 8, (unitIdentifier))
-	if _unitIdentifierErr != nil {
-		return errors.Wrap(_unitIdentifierErr, "Error serializing 'unitIdentifier' field")
-	}
-
-	// Simple Field (pdu)
-	if pushErr := writeBuffer.PushContext("pdu"); pushErr != nil {
-		return pushErr
-	}
-	_pduErr := m.Pdu.Serialize(writeBuffer)
-	if popErr := writeBuffer.PopContext("pdu"); popErr != nil {
-		return popErr
-	}
-	if _pduErr != nil {
-		return errors.Wrap(_pduErr, "Error serializing 'pdu' field")
-	}
-
-	if popErr := writeBuffer.PopContext("ModbusTcpADU"); popErr != nil {
-		return popErr
-	}
-	return nil
+	return m.SerializeParent(writeBuffer, m, ser)
 }
 
 func (m *ModbusTcpADU) String() string {
diff --git a/plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go b/plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go
index 07ff539..dde33e1 100644
--- a/plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go
+++ b/plc4go/internal/plc4go/modbus/readwrite/model/StaticHelper.go
@@ -19,7 +19,10 @@
 
 package model
 
-func CrcCheck(address uint8, modbusPDU *ModbusPDU) uint16 {
-	// TODO: implement me
-	return 0
+func AsciiLrcCheck(address uint8, pdu *ModbusPDU) (uint8, error) {
+	return 0, nil
+}
+
+func RtuCrcCheck(address uint8, pdu *ModbusPDU) (uint16, error) {
+	return 0, nil
 }
diff --git a/plc4go/pkg/plc4go/drivers/drivers.go b/plc4go/pkg/plc4go/drivers/drivers.go
index 880b9cc..fde3645 100644
--- a/plc4go/pkg/plc4go/drivers/drivers.go
+++ b/plc4go/pkg/plc4go/drivers/drivers.go
@@ -44,8 +44,20 @@ func RegisterKnxDriver(driverManager plc4go.PlcDriverManager) {
 	transports.RegisterUdpTransport(driverManager)
 }
 
-func RegisterModbusDriver(driverManager plc4go.PlcDriverManager) {
-	driverManager.RegisterDriver(modbus.NewDriver())
+func RegisterModbusTcpDriver(driverManager plc4go.PlcDriverManager) {
+	driverManager.RegisterDriver(modbus.NewModbusTcpDriver())
+	transports.RegisterTcpTransport(driverManager)
+}
+
+func RegisterModbusRtuDriver(driverManager plc4go.PlcDriverManager) {
+	driverManager.RegisterDriver(modbus.NewModbusRtuDriver())
+	transports.RegisterSerialTransport(driverManager)
+	transports.RegisterTcpTransport(driverManager)
+}
+
+func RegisterModbusAsciiDriver(driverManager plc4go.PlcDriverManager) {
+	driverManager.RegisterDriver(modbus.NewModbusAsciiDriver())
+	transports.RegisterSerialTransport(driverManager)
 	transports.RegisterTcpTransport(driverManager)
 }
 
diff --git a/plc4go/pkg/plc4go/transports/transports.go b/plc4go/pkg/plc4go/transports/transports.go
index 34c2895..6801c12 100644
--- a/plc4go/pkg/plc4go/transports/transports.go
+++ b/plc4go/pkg/plc4go/transports/transports.go
@@ -21,6 +21,7 @@ package transports
 
 import (
 	"github.com/apache/plc4x/plc4go/internal/plc4go/spi"
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/transports/serial"
 	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/transports/tcp"
 	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/transports/udp"
 	"github.com/apache/plc4x/plc4go/pkg/plc4go"
@@ -33,3 +34,7 @@ func RegisterTcpTransport(driverManager plc4go.PlcDriverManager) {
 func RegisterUdpTransport(driverManager plc4go.PlcDriverManager) {
 	driverManager.(spi.TransportAware).RegisterTransport(udp.NewTransport())
 }
+
+func RegisterSerialTransport(driverManager plc4go.PlcDriverManager) {
+	driverManager.(spi.TransportAware).RegisterTransport(serial.NewTransport())
+}
diff --git a/plc4j/drivers/modbus/pom.xml b/plc4j/drivers/modbus/pom.xml
index c61fc2f..de8eba5 100644
--- a/plc4j/drivers/modbus/pom.xml
+++ b/plc4j/drivers/modbus/pom.xml
@@ -89,7 +89,7 @@
           <instructions>
             <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
             <Bundle-Activator>org.apache.plc4x.java.osgi.DriverActivator</Bundle-Activator>
-            <Export-Service>org.apache.plc4x.java.api.PlcDriver,org.apache.plc4x.java.modbus.ModbusDriver</Export-Service>
+            <Export-Service>org.apache.plc4x.java.api.PlcDriver,org.apache.plc4x.java.modbus.tcp.ModbusTcpDriver</Export-Service>
             <Import-Package>
               com.fasterxml.jackson.annotation;resolution:=optional,
               *
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java
similarity index 68%
copy from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
copy to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java
index 9a15f3d..f4afd20 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java
@@ -16,64 +16,46 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus;
+package org.apache.plc4x.java.modbus.ascii;
 
 import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
-import org.apache.plc4x.java.api.metadata.PlcDriverMetadata;
-import org.apache.plc4x.java.modbus.config.ModbusConfiguration;
-import org.apache.plc4x.java.modbus.discovery.ModbusPlcDiscoverer;
-import org.apache.plc4x.java.modbus.field.ModbusField;
-import org.apache.plc4x.java.modbus.field.ModbusFieldHandler;
-import org.apache.plc4x.java.modbus.protocol.ModbusProtocolLogic;
-import org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU;
-import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryRequest;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
 import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.modbus.ascii.config.ModbusAsciiConfiguration;
+import org.apache.plc4x.java.modbus.ascii.protocol.ModbusAsciiProtocolLogic;
+import org.apache.plc4x.java.modbus.base.field.ModbusField;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldHandler;
+import org.apache.plc4x.java.modbus.readwrite.DriverType;
+import org.apache.plc4x.java.modbus.readwrite.ModbusAsciiADU;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.apache.plc4x.java.spi.optimizer.SingleFieldOptimizer;
+import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
 
 import java.util.function.ToIntFunction;
 
-public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
+public class ModbusAsciiDriver extends GeneratedDriverBase<ModbusAsciiADU> {
 
     @Override
     public String getProtocolCode() {
-        return "modbus";
+        return "modbus-ascii";
     }
 
     @Override
     public String getProtocolName() {
-        return "Modbus";
+        return "Modbus ASCII";
     }
 
     @Override
     protected Class<? extends Configuration> getConfigurationType() {
-        return ModbusConfiguration.class;
+        return ModbusAsciiConfiguration.class;
     }
 
     @Override
     protected String getDefaultTransport() {
-        return "tcp";
-    }
-
-    @Override
-    public PlcDriverMetadata getMetadata() {
-        return new PlcDriverMetadata() {
-            @Override
-            public boolean canDiscover() {
-                return true;
-            }
-        };
-    }
-
-    @Override
-    public PlcDiscoveryRequest.Builder discoveryRequestBuilder() {
-        return new DefaultPlcDiscoveryRequest.Builder(new ModbusPlcDiscoverer());
+        return "serial";
     }
 
     /**
@@ -120,12 +102,12 @@ public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
     }
 
     @Override
-    protected ProtocolStackConfigurer<ModbusTcpADU> getStackConfigurer() {
-        return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class, ModbusTcpADU::staticParse)
-            .withProtocol(ModbusProtocolLogic.class)
-            .withPacketSizeEstimator(ByteLengthEstimator.class)
+    protected ProtocolStackConfigurer<ModbusAsciiADU> getStackConfigurer() {
+        return SingleProtocolStackConfigurer.builder(ModbusAsciiADU.class,  (io, args) -> (ModbusAsciiADU) ModbusAsciiADU.staticParse(io, args))
+            .withProtocol(ModbusAsciiProtocolLogic.class)
+            .withPacketSizeEstimator(ModbusAsciiDriver.ByteLengthEstimator.class)
             // Every incoming message is to be treated as a response.
-            .withParserArgs(true)
+            .withParserArgs(DriverType.MODBUS_ASCII, true)
             .build();
     }
 
@@ -145,4 +127,4 @@ public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
         return ModbusField.of(query);
     }
 
-}
+}
\ No newline at end of file
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/config/ModbusAsciiConfiguration.java
similarity index 93%
copy from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java
copy to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/config/ModbusAsciiConfiguration.java
index 68441cf..475bdc8 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/config/ModbusAsciiConfiguration.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.config;
+package org.apache.plc4x.java.modbus.ascii.config;
 
 import org.apache.plc4x.java.modbus.readwrite.ModbusConstants;
 import org.apache.plc4x.java.spi.configuration.Configuration;
@@ -24,7 +24,7 @@ import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParamete
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.transport.tcp.TcpTransportConfiguration;
 
-public class ModbusConfiguration implements Configuration, TcpTransportConfiguration {
+public class ModbusAsciiConfiguration implements Configuration, TcpTransportConfiguration {
 
     @ConfigurationParameter("request-timeout")
     @IntDefaultValue(5_000)
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/protocol/ModbusAsciiProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/protocol/ModbusAsciiProtocolLogic.java
new file mode 100644
index 0000000..63a54f2
--- /dev/null
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/protocol/ModbusAsciiProtocolLogic.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.modbus.ascii.protocol;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.modbus.ascii.config.ModbusAsciiConfiguration;
+import org.apache.plc4x.java.modbus.base.field.ModbusField;
+import org.apache.plc4x.java.modbus.base.protocol.ModbusProtocolLogic;
+import org.apache.plc4x.java.modbus.readwrite.*;
+import org.apache.plc4x.java.modbus.rtu.config.ModbusRtuConfiguration;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse;
+import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.concurrent.CompletableFuture;
+
+public class ModbusAsciiProtocolLogic extends ModbusProtocolLogic<ModbusAsciiADU> implements HasConfiguration<ModbusAsciiConfiguration> {
+
+    public ModbusAsciiProtocolLogic() {
+        super(DriverType.MODBUS_ASCII);
+    }
+
+    @Override
+    public void setConfiguration(ModbusAsciiConfiguration configuration) {
+        this.requestTimeout = Duration.ofMillis(configuration.getRequestTimeout());
+        this.unitIdentifier = (short) configuration.getUnitIdentifier();
+        this.tm = new RequestTransactionManager(1);
+    }
+
+    @Override
+    public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
+        CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
+        DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
+
+        // 1. Sort all items by type:
+        //      - DiscreteInput     (read-only)     --> ModbusPduReadDiscreteInputsRequest
+        //      - Coil              (read-write)    --> ModbusPduReadCoilsRequest
+        //      - InputRegister     (read-only)     --> ModbusPduReadInputRegistersRequest
+        //      - HoldingRegister   (read-write)    --> ModbusPduReadHoldingRegistersRequest
+        //      - FifoQueue         (read-only)     --> ModbusPduReadFifoQueueRequest
+        //      - FileRecord        (read-write)    --> ModbusPduReadFileRecordRequest
+        // 2. Split up into multiple sub-requests
+
+        // Example for sending a request ...
+        if (request.getFieldNames().size() == 1) {
+            String fieldName = request.getFieldNames().iterator().next();
+            ModbusField field = (ModbusField) request.getField(fieldName);
+            final ModbusPDU requestPdu = getReadRequestPdu(field);
+
+            ModbusAsciiADU modbusAsciiADU = new ModbusAsciiADU(unitIdentifier, requestPdu, false);
+            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+            transaction.submit(() -> context.sendRequest(modbusAsciiADU)
+                .expectResponse(ModbusAsciiADU.class, requestTimeout)
+                .onTimeout(future::completeExceptionally)
+                .onError((p, e) -> future.completeExceptionally(e))
+                .unwrap(ModbusAsciiADU::getPdu)
+                .handle(responsePdu -> {
+                    // Try to decode the response data based on the corresponding request.
+                    PlcValue plcValue = null;
+                    PlcResponseCode responseCode;
+                    // Check if the response was an error response.
+                    if (responsePdu instanceof ModbusPDUError) {
+                        ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
+                        responseCode = getErrorCode(errorResponse);
+                    } else {
+                        try {
+                            plcValue = toPlcValue(requestPdu, responsePdu, field.getDataType());
+                            responseCode = PlcResponseCode.OK;
+                        } catch (ParseException e) {
+                            // Add an error response code ...
+                            responseCode = PlcResponseCode.INTERNAL_ERROR;
+                        }
+                    }
+
+                    // Prepare the response.
+                    PlcReadResponse response = new DefaultPlcReadResponse(request,
+                        Collections.singletonMap(fieldName, new ResponseItem<>(responseCode, plcValue)));
+
+                    // Pass the response back to the application.
+                    future.complete(response);
+
+                    // Finish the request-transaction.
+                    transaction.endRequest();
+                }));
+        } else {
+            future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
+        }
+        return future;
+    }
+
+    @Override
+    public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
+        CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
+        DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
+
+        // 1. Sort all items by type:
+        //      - DiscreteInput     (read-only)     --> Error
+        //      - Coil              (read-write)    --> ModbusPduWriteSingleCoilRequest / ModbusPduWriteMultipleCoilsRequest
+        //      - InputRegister     (read-only)     --> Error
+        //      - HoldingRegister   (read-write)    --> ModbusPduWriteSingleRegisterRequest / ModbusPduWriteMultipleRegistersRequest
+        //      - FifoQueue         (read-only)     --> Error
+        //      - FileRecord        (read-write)    --> ModbusPduWriteFileRecordRequest
+        // 2. Split up into multiple sub-requests
+        if (request.getFieldNames().size() == 1) {
+            String fieldName = request.getFieldNames().iterator().next();
+            PlcField field = request.getField(fieldName);
+            final ModbusPDU requestPdu = getWriteRequestPdu(field, writeRequest.getPlcValue(fieldName));
+            ModbusAsciiADU modbusAsciiADU = new ModbusAsciiADU(unitIdentifier, requestPdu, false);
+            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+            transaction.submit(() -> context.sendRequest(modbusAsciiADU)
+                .expectResponse(ModbusAsciiADU.class, requestTimeout)
+                .onTimeout(future::completeExceptionally)
+                .onError((p, e) -> future.completeExceptionally(e))
+                .unwrap(ModbusAsciiADU::getPdu)
+                .handle(responsePdu -> {
+                    // Try to decode the response data based on the corresponding request.
+                    PlcResponseCode responseCode;
+
+                    // Check if the response was an error response.
+                    if (responsePdu instanceof ModbusPDUError) {
+                        ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
+                        responseCode = getErrorCode(errorResponse);
+                    } else {
+                        responseCode = PlcResponseCode.OK;
+                        // TODO: Check the correct number of elements were written.
+                        if (responsePdu instanceof ModbusPDUWriteSingleCoilResponse) {
+                            ModbusPDUWriteSingleCoilResponse response = (ModbusPDUWriteSingleCoilResponse) responsePdu;
+                            ModbusPDUWriteSingleCoilRequest requestSingleCoil = (ModbusPDUWriteSingleCoilRequest) requestPdu;
+                            if (!((response.getValue() == requestSingleCoil.getValue()) && (response.getAddress() == requestSingleCoil.getAddress()))) {
+                                responseCode = PlcResponseCode.REMOTE_ERROR;
+                            }
+                        }
+                    }
+
+                    // Prepare the response.
+                    PlcWriteResponse response = new DefaultPlcWriteResponse(request,
+                        Collections.singletonMap(fieldName, responseCode));
+
+                    // Pass the response back to the application.
+                    future.complete(response);
+
+                    // Finish the request-transaction.
+                    transaction.endRequest();
+                }));
+
+        } else {
+            future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
+        }
+        return future;
+    }
+
+}
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusExtendedRegister.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusExtendedRegister.java
similarity index 98%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusExtendedRegister.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusExtendedRegister.java
index 14d355c..40dda0f 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusExtendedRegister.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusExtendedRegister.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.field;
+package org.apache.plc4x.java.modbus.base.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusField.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusField.java
similarity index 97%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusField.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusField.java
index d28ac78..9b3a6be 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusField.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusField.java
@@ -16,13 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.field;
+package org.apache.plc4x.java.modbus.base.field;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.modbus.readwrite.*;
-import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.java.spi.utils.Serializable;
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldCoil.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldCoil.java
similarity index 98%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldCoil.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldCoil.java
index 76a8912..631f557 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldCoil.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldCoil.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.field;
+package org.apache.plc4x.java.modbus.base.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldDiscreteInput.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldDiscreteInput.java
similarity index 98%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldDiscreteInput.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldDiscreteInput.java
index 2f41eec..bd365a6 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldDiscreteInput.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldDiscreteInput.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.field;
+package org.apache.plc4x.java.modbus.base.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldHandler.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHandler.java
similarity index 97%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldHandler.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHandler.java
index 306a9f4..c62d3d0 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldHandler.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHandler.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.field;
+package org.apache.plc4x.java.modbus.base.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldHoldingRegister.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHoldingRegister.java
similarity index 98%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldHoldingRegister.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHoldingRegister.java
index 82f5900..3872ffa 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldHoldingRegister.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHoldingRegister.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.field;
+package org.apache.plc4x.java.modbus.base.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldInputRegister.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldInputRegister.java
similarity index 98%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldInputRegister.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldInputRegister.java
index 9fe9082..6c26e27 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/field/ModbusFieldInputRegister.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldInputRegister.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.field;
+package org.apache.plc4x.java.modbus.base.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
similarity index 64%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
index 5aba306..1aa8fe1 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
@@ -16,20 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.protocol;
+package org.apache.plc4x.java.modbus.base.protocol;
 
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.value.*;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
-import org.apache.plc4x.java.modbus.config.ModbusConfiguration;
-import org.apache.plc4x.java.modbus.field.ModbusField;
-import org.apache.plc4x.java.modbus.field.ModbusFieldCoil;
-import org.apache.plc4x.java.modbus.field.ModbusFieldDiscreteInput;
-import org.apache.plc4x.java.modbus.field.ModbusFieldHoldingRegister;
-import org.apache.plc4x.java.modbus.field.ModbusFieldInputRegister;
-import org.apache.plc4x.java.modbus.field.ModbusExtendedRegister;
+import org.apache.plc4x.java.modbus.tcp.config.ModbusTcpConfiguration;
+import org.apache.plc4x.java.modbus.base.field.ModbusField;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldCoil;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldDiscreteInput;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldHoldingRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldInputRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusExtendedRegister;
 import org.apache.plc4x.java.modbus.readwrite.*;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
@@ -54,100 +54,31 @@ import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicInteger;
 
-public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> implements HasConfiguration<ModbusConfiguration> {
+public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProtocolBase<T> {
 
-    private Duration requestTimeout;
-    private short unitIdentifier;
-    private RequestTransactionManager tm;
-    private final AtomicInteger transactionIdentifierGenerator = new AtomicInteger(1);
-    private final static int FC_EXTENDED_REGISTERS_GROUP_HEADER_LENGTH = 2;
-    private final static int FC_EXTENDED_REGISTERS_FILE_RECORD_LENGTH = 10000;
+    protected final DriverType driverType;
+    protected Duration requestTimeout;
+    protected short unitIdentifier;
+    protected RequestTransactionManager tm;
+    protected final AtomicInteger transactionIdentifierGenerator = new AtomicInteger(1);
+    protected final static int FC_EXTENDED_REGISTERS_GROUP_HEADER_LENGTH = 2;
+    protected final static int FC_EXTENDED_REGISTERS_FILE_RECORD_LENGTH = 10000;
 
-    @Override
-    public void setConfiguration(ModbusConfiguration configuration) {
-        this.requestTimeout = Duration.ofMillis(configuration.getRequestTimeout());
-        this.unitIdentifier = (short) configuration.getUnitIdentifier();
-        this.tm = new RequestTransactionManager(1);
+    public ModbusProtocolLogic(DriverType driverType) {
+        this.driverType = driverType;
     }
 
     @Override
-    public void close(ConversationContext<ModbusTcpADU> context) {
+    public void close(ConversationContext<T> context) {
         // Nothing to do here ...
     }
 
     @Override
-    public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
-        CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
-        DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
-
-        // 1. Sort all items by type:
-        //      - DiscreteInput     (read-only)     --> ModbusPduReadDiscreteInputsRequest
-        //      - Coil              (read-write)    --> ModbusPduReadCoilsRequest
-        //      - InputRegister     (read-only)     --> ModbusPduReadInputRegistersRequest
-        //      - HoldingRegister   (read-write)    --> ModbusPduReadHoldingRegistersRequest
-        //      - FifoQueue         (read-only)     --> ModbusPduReadFifoQueueRequest
-        //      - FileRecord        (read-write)    --> ModbusPduReadFileRecordRequest
-        // 2. Split up into multiple sub-requests
-
-        // Example for sending a request ...
-        if (request.getFieldNames().size() == 1) {
-            String fieldName = request.getFieldNames().iterator().next();
-            ModbusField field = (ModbusField) request.getField(fieldName);
-            final ModbusPDU requestPdu = getReadRequestPdu(field);
-            int transactionIdentifier = transactionIdentifierGenerator.getAndIncrement();
-            // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
-            if (transactionIdentifierGenerator.get() == 0xFFFF) {
-                transactionIdentifierGenerator.set(1);
-            }
-            ModbusTcpADU modbusTcpADU = new ModbusTcpADU(transactionIdentifier, unitIdentifier, requestPdu, false);
-            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
-            transaction.submit(() -> context.sendRequest(modbusTcpADU)
-                .expectResponse(ModbusTcpADU.class, requestTimeout)
-                .onTimeout(future::completeExceptionally)
-                .onError((p, e) -> future.completeExceptionally(e))
-                .check(p -> ((p.getTransactionIdentifier() == transactionIdentifier) &&
-                    (p.getUnitIdentifier() == unitIdentifier)))
-                .unwrap(ModbusTcpADU::getPdu)
-                .handle(responsePdu -> {
-                    // Try to decode the response data based on the corresponding request.
-                    PlcValue plcValue = null;
-                    PlcResponseCode responseCode;
-                    // Check if the response was an error response.
-                    if (responsePdu instanceof ModbusPDUError) {
-                        ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
-                        responseCode = getErrorCode(errorResponse);
-                    } else {
-                        try {
-                            plcValue = toPlcValue(requestPdu, responsePdu, field.getDataType());
-                            responseCode = PlcResponseCode.OK;
-                        } catch (ParseException e) {
-                            // Add an error response code ...
-                            responseCode = PlcResponseCode.INTERNAL_ERROR;
-                        }
-                    }
-
-                    // Prepare the response.
-                    PlcReadResponse response = new DefaultPlcReadResponse(request,
-                        Collections.singletonMap(fieldName, new ResponseItem<>(responseCode, plcValue)));
-
-                    // Pass the response back to the application.
-                    future.complete(response);
-
-                    // Finish the request-transaction.
-                    transaction.endRequest();
-                }));
-        } else {
-            future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
-        }
-        return future;
-    }
-
-    @Override
-    protected void decode(ConversationContext<ModbusTcpADU> context, ModbusTcpADU msg) throws Exception {
+    protected void decode(ConversationContext<T> context, T msg) throws Exception {
         super.decode(context, msg);
     }
 
-    private PlcResponseCode getErrorCode(ModbusPDUError errorResponse) {
+    protected PlcResponseCode getErrorCode(ModbusPDUError errorResponse) {
         switch (errorResponse.getExceptionCode()) {
             case ILLEGAL_FUNCTION:
                 return PlcResponseCode.UNSUPPORTED;
@@ -175,74 +106,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme
         }
     }
 
-    @Override
-    public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
-        CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
-        DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
-
-        // 1. Sort all items by type:
-        //      - DiscreteInput     (read-only)     --> Error
-        //      - Coil              (read-write)    --> ModbusPduWriteSingleCoilRequest / ModbusPduWriteMultipleCoilsRequest
-        //      - InputRegister     (read-only)     --> Error
-        //      - HoldingRegister   (read-write)    --> ModbusPduWriteSingleRegisterRequest / ModbusPduWriteMultipleRegistersRequest
-        //      - FifoQueue         (read-only)     --> Error
-        //      - FileRecord        (read-write)    --> ModbusPduWriteFileRecordRequest
-        // 2. Split up into multiple sub-requests
-        if (request.getFieldNames().size() == 1) {
-            String fieldName = request.getFieldNames().iterator().next();
-            PlcField field = request.getField(fieldName);
-            final ModbusPDU requestPdu = getWriteRequestPdu(field, writeRequest.getPlcValue(fieldName));
-            int transactionIdentifier = transactionIdentifierGenerator.getAndIncrement();
-            // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
-            if (transactionIdentifierGenerator.get() == 0xFFFF) {
-                transactionIdentifierGenerator.set(1);
-            }
-            ModbusTcpADU modbusTcpADU = new ModbusTcpADU(transactionIdentifier, unitIdentifier, requestPdu, false);
-            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
-            transaction.submit(() -> context.sendRequest(modbusTcpADU)
-                .expectResponse(ModbusTcpADU.class, requestTimeout)
-                .onTimeout(future::completeExceptionally)
-                .onError((p, e) -> future.completeExceptionally(e))
-                .check(p -> p.getTransactionIdentifier() == transactionIdentifier)
-                .unwrap(ModbusTcpADU::getPdu)
-                .handle(responsePdu -> {
-                    // Try to decode the response data based on the corresponding request.
-                    PlcResponseCode responseCode;
-
-                    // Check if the response was an error response.
-                    if (responsePdu instanceof ModbusPDUError) {
-                        ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
-                        responseCode = getErrorCode(errorResponse);
-                    } else {
-                        responseCode = PlcResponseCode.OK;
-                        // TODO: Check the correct number of elements were written.
-                        if (responsePdu instanceof ModbusPDUWriteSingleCoilResponse) {
-                            ModbusPDUWriteSingleCoilResponse response = (ModbusPDUWriteSingleCoilResponse) responsePdu;
-                            ModbusPDUWriteSingleCoilRequest requestSingleCoil = (ModbusPDUWriteSingleCoilRequest) requestPdu;
-                            if (!((response.getValue() == requestSingleCoil.getValue()) && (response.getAddress() == requestSingleCoil.getAddress()))) {
-                                responseCode = PlcResponseCode.REMOTE_ERROR;
-                            }
-                        }
-                    }
-
-                    // Prepare the response.
-                    PlcWriteResponse response = new DefaultPlcWriteResponse(request,
-                        Collections.singletonMap(fieldName, responseCode));
-
-                    // Pass the response back to the application.
-                    future.complete(response);
-
-                    // Finish the request-transaction.
-                    transaction.endRequest();
-                }));
-
-        } else {
-            future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
-        }
-        return future;
-    }
-
-    private ModbusPDU getReadRequestPdu(PlcField field) {
+    protected ModbusPDU getReadRequestPdu(PlcField field) {
         if (field instanceof ModbusFieldDiscreteInput) {
             ModbusFieldDiscreteInput discreteInput = (ModbusFieldDiscreteInput) field;
             return new ModbusPDUReadDiscreteInputsRequest(discreteInput.getAddress(), discreteInput.getNumberOfElements());
@@ -287,7 +151,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme
         throw new PlcRuntimeException("Unsupported read field type " + field.getClass().getName());
     }
 
-    private ModbusPDU getWriteRequestPdu(PlcField field, PlcValue plcValue) {
+    protected ModbusPDU getWriteRequestPdu(PlcField field, PlcValue plcValue) {
         if (field instanceof ModbusFieldCoil) {
             ModbusFieldCoil coil = (ModbusFieldCoil) field;
             ModbusPDUWriteMultipleCoilsRequest request =
@@ -347,7 +211,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme
         throw new PlcRuntimeException("Unsupported write field type " + field.getClass().getName());
     }
 
-    private PlcValue toPlcValue(ModbusPDU request, ModbusPDU response, ModbusDataType dataType) throws ParseException {
+    protected PlcValue toPlcValue(ModbusPDU request, ModbusPDU response, ModbusDataType dataType) throws ParseException {
         short fieldDataTypeSize = dataType.getDataTypeSize();
 
         if (request instanceof ModbusPDUReadDiscreteInputsRequest) {
@@ -420,7 +284,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme
         return null;
     }
 
-    private byte[] fromPlcValue(PlcField field, PlcValue plcValue) {
+    protected byte[] fromPlcValue(PlcField field, PlcValue plcValue) {
         ModbusDataType fieldDataType = ((ModbusField) field).getDataType();
         try {
             if (plcValue instanceof PlcList) {
@@ -448,7 +312,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme
 
     }
 
-    private byte reverseBitsOfByte(byte b) {
+    protected byte reverseBitsOfByte(byte b) {
         BitSet bits = BitSet.valueOf(new byte[]{b});
         BitSet reverse = BitSet.valueOf(new byte[]{(byte) 0xFF});
         for (int j = 0; j < 8; j++) {
@@ -458,7 +322,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme
         return Arrays.copyOf(reverse.toByteArray(), 1)[0];
     }
 
-    private PlcValue readBooleanList(int count, byte[] data) throws ParseException {
+    protected PlcValue readBooleanList(int count, byte[] data) throws ParseException {
         ReadBuffer io = new ReadBufferByteBased(data);
         if (count == 1) {
             return DataItem.staticParse(io, ModbusDataType.BOOL, 1);
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
index a4e11e0..b865381 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
@@ -3,7 +3,7 @@
  * 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
+ * to you under the Apache License, (byte) 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
  *
@@ -11,19 +11,108 @@
  *
  * 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
+ * "AS IS" BASIS, (byte) WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, (byte) either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */
 package org.apache.plc4x.java.modbus.readwrite.utils;
 
 import org.apache.plc4x.java.modbus.readwrite.ModbusPDU;
+import org.apache.plc4x.java.spi.generation.SerializationException;
+import org.apache.plc4x.java.spi.generation.WriteBufferByteBased;
 
 public class StaticHelper {
 
-    public static int crcCheck(short address, ModbusPDU pdu) {
-        return 0;
+    // 8 Bit checksum, (byte) transported as 2 characters
+    public static short asciiLrcCheck(short address, ModbusPDU pdu) {
+        final WriteBufferByteBased writeBufferByteBased = new WriteBufferByteBased(pdu.getLengthInBytes() + 2);
+        try {
+            writeBufferByteBased.writeUnsignedShort(8, address);
+            pdu.serialize(writeBufferByteBased);
+        } catch (SerializationException e) {
+            throw new RuntimeException(e);
+        }
+        final byte[] bytes = writeBufferByteBased.getBytes();
+
+        // A procedure for generating an LRC is:
+        // 1. Add all bytes in the message, (byte) excluding the starting ‘colon’ and ending
+        //    CRLF. Add them into an 8–bit field, (byte) so that carries will be discarded.
+        // 2. Subtract the final field value from FF hex (all 1’s), (byte) to produce the
+        //    ones–complement.
+        // 3. Add 1 to produce the twos–complement
+        // 4. Convert the 8 bit checksum into it's 16 bit (2 char) hex representation.
+        //    (Handled in the transport layer)
+        short lrc = 0;
+        for (byte aByte : bytes) {
+            lrc = (short) (lrc + aByte);
+        }
+        lrc = (short) ((0xFF - lrc) + 1);
+        return (short) (lrc & 0xFF);
+    }
+
+    // Using the algorithm from PI_MBUS_300.pdf page 121
+    public static int rtuCrcCheck(short address, ModbusPDU pdu) {
+        final WriteBufferByteBased writeBufferByteBased = new WriteBufferByteBased(pdu.getLengthInBytes() + 2);
+        try {
+            writeBufferByteBased.writeUnsignedShort(8, address);
+            pdu.serialize(writeBufferByteBased);
+        } catch (SerializationException e) {
+            throw new RuntimeException(e);
+        }
+        final byte[] bytes = writeBufferByteBased.getBytes();
+
+        byte uchCRCHi = (byte) 0xFF;
+        byte uchCRCLo = (byte) 0xFF;
+        int uIndex;
+        for (byte aByte : bytes) {
+            uIndex = (uchCRCHi ^ aByte) & 0xFF;
+            uchCRCHi = (byte) (uchCRCLo ^ auchCRCHi[uIndex]);
+            uchCRCLo = auchCRCLo[uIndex];
+        }
+        return (((((int) uchCRCHi) << 8) & 0xFFFF) | ((int) uchCRCLo) & 0x00FF);
     }
 
+    static byte[] auchCRCHi = {
+        (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81,
+        (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
+        (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01,
+        (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
+        (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81,
+        (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0,
+        (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01,
+        (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
+        (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81,
+        (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
+        (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01,
+        (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
+        (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81,
+        (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
+        (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01,
+        (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
+        (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81,
+        (byte) 0x40
+    };
+
+    static byte[] auchCRCLo = {
+        (byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4,
+        (byte) 0x04, (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09,
+        (byte) 0x08, (byte) 0xC8, (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD,
+        (byte) 0x1D, (byte) 0x1C, (byte) 0xDC, (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12, (byte) 0x13, (byte) 0xD3,
+        (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10, (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7,
+        (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4, (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A,
+        (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38, (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA, (byte) 0xEE,
+        (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C, (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7, (byte) 0xE6, (byte) 0x26,
+        (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0, (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2,
+        (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4, (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F,
+        (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68, (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB,
+        (byte) 0x7B, (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C, (byte) 0xB4, (byte) 0x74, (byte) 0x75, (byte) 0xB5,
+        (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0, (byte) 0x50, (byte) 0x90, (byte) 0x91,
+        (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54, (byte) 0x9C, (byte) 0x5C,
+        (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98, (byte) 0x88,
+        (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D, (byte) 0x4C, (byte) 0x8C,
+        (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80,
+        (byte) 0x40
+    };
+
 }
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java
similarity index 68%
copy from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
copy to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java
index 9a15f3d..8841acc 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java
@@ -16,64 +16,46 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus;
+package org.apache.plc4x.java.modbus.rtu;
 
 import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
-import org.apache.plc4x.java.api.metadata.PlcDriverMetadata;
-import org.apache.plc4x.java.modbus.config.ModbusConfiguration;
-import org.apache.plc4x.java.modbus.discovery.ModbusPlcDiscoverer;
-import org.apache.plc4x.java.modbus.field.ModbusField;
-import org.apache.plc4x.java.modbus.field.ModbusFieldHandler;
-import org.apache.plc4x.java.modbus.protocol.ModbusProtocolLogic;
-import org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU;
-import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryRequest;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
 import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.modbus.base.field.ModbusField;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldHandler;
+import org.apache.plc4x.java.modbus.readwrite.DriverType;
+import org.apache.plc4x.java.modbus.readwrite.ModbusRtuADU;
+import org.apache.plc4x.java.modbus.rtu.config.ModbusRtuConfiguration;
+import org.apache.plc4x.java.modbus.rtu.protocol.ModbusRtuProtocolLogic;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.apache.plc4x.java.spi.optimizer.SingleFieldOptimizer;
+import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
 
 import java.util.function.ToIntFunction;
 
-public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
+public class ModbusRtuDriver extends GeneratedDriverBase<ModbusRtuADU> {
 
     @Override
     public String getProtocolCode() {
-        return "modbus";
+        return "modbus-rtu";
     }
 
     @Override
     public String getProtocolName() {
-        return "Modbus";
+        return "Modbus RTU";
     }
 
     @Override
     protected Class<? extends Configuration> getConfigurationType() {
-        return ModbusConfiguration.class;
+        return ModbusRtuConfiguration.class;
     }
 
     @Override
     protected String getDefaultTransport() {
-        return "tcp";
-    }
-
-    @Override
-    public PlcDriverMetadata getMetadata() {
-        return new PlcDriverMetadata() {
-            @Override
-            public boolean canDiscover() {
-                return true;
-            }
-        };
-    }
-
-    @Override
-    public PlcDiscoveryRequest.Builder discoveryRequestBuilder() {
-        return new DefaultPlcDiscoveryRequest.Builder(new ModbusPlcDiscoverer());
+        return "serial";
     }
 
     /**
@@ -120,12 +102,12 @@ public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
     }
 
     @Override
-    protected ProtocolStackConfigurer<ModbusTcpADU> getStackConfigurer() {
-        return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class, ModbusTcpADU::staticParse)
-            .withProtocol(ModbusProtocolLogic.class)
-            .withPacketSizeEstimator(ByteLengthEstimator.class)
+    protected ProtocolStackConfigurer<ModbusRtuADU> getStackConfigurer() {
+        return SingleProtocolStackConfigurer.builder(ModbusRtuADU.class,  (io, args) -> (ModbusRtuADU) ModbusRtuADU.staticParse(io, args))
+            .withProtocol(ModbusRtuProtocolLogic.class)
+            .withPacketSizeEstimator(ModbusRtuDriver.ByteLengthEstimator.class)
             // Every incoming message is to be treated as a response.
-            .withParserArgs(true)
+            .withParserArgs(DriverType.MODBUS_RTU, true)
             .build();
     }
 
@@ -145,4 +127,4 @@ public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
         return ModbusField.of(query);
     }
 
-}
+}
\ No newline at end of file
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/config/ModbusRtuConfiguration.java
similarity index 93%
copy from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java
copy to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/config/ModbusRtuConfiguration.java
index 68441cf..9a64344 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/config/ModbusRtuConfiguration.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.config;
+package org.apache.plc4x.java.modbus.rtu.config;
 
 import org.apache.plc4x.java.modbus.readwrite.ModbusConstants;
 import org.apache.plc4x.java.spi.configuration.Configuration;
@@ -24,7 +24,7 @@ import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParamete
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.transport.tcp.TcpTransportConfiguration;
 
-public class ModbusConfiguration implements Configuration, TcpTransportConfiguration {
+public class ModbusRtuConfiguration implements Configuration, TcpTransportConfiguration {
 
     @ConfigurationParameter("request-timeout")
     @IntDefaultValue(5_000)
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/protocol/ModbusRtuProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/protocol/ModbusRtuProtocolLogic.java
new file mode 100644
index 0000000..09accd2
--- /dev/null
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/protocol/ModbusRtuProtocolLogic.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.modbus.rtu.protocol;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.modbus.base.field.ModbusField;
+import org.apache.plc4x.java.modbus.base.protocol.ModbusProtocolLogic;
+import org.apache.plc4x.java.modbus.readwrite.*;
+import org.apache.plc4x.java.modbus.rtu.config.ModbusRtuConfiguration;
+import org.apache.plc4x.java.modbus.tcp.config.ModbusTcpConfiguration;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse;
+import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.concurrent.CompletableFuture;
+
+public class ModbusRtuProtocolLogic extends ModbusProtocolLogic<ModbusRtuADU> implements HasConfiguration<ModbusRtuConfiguration> {
+
+    public ModbusRtuProtocolLogic() {
+        super(DriverType.MODBUS_RTU);
+    }
+
+    @Override
+    public void setConfiguration(ModbusRtuConfiguration configuration) {
+        this.requestTimeout = Duration.ofMillis(configuration.getRequestTimeout());
+        this.unitIdentifier = (short) configuration.getUnitIdentifier();
+        this.tm = new RequestTransactionManager(1);
+    }
+
+    @Override
+    public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
+        CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
+        DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
+
+        // 1. Sort all items by type:
+        //      - DiscreteInput     (read-only)     --> ModbusPduReadDiscreteInputsRequest
+        //      - Coil              (read-write)    --> ModbusPduReadCoilsRequest
+        //      - InputRegister     (read-only)     --> ModbusPduReadInputRegistersRequest
+        //      - HoldingRegister   (read-write)    --> ModbusPduReadHoldingRegistersRequest
+        //      - FifoQueue         (read-only)     --> ModbusPduReadFifoQueueRequest
+        //      - FileRecord        (read-write)    --> ModbusPduReadFileRecordRequest
+        // 2. Split up into multiple sub-requests
+
+        // Example for sending a request ...
+        if (request.getFieldNames().size() == 1) {
+            String fieldName = request.getFieldNames().iterator().next();
+            ModbusField field = (ModbusField) request.getField(fieldName);
+            final ModbusPDU requestPdu = getReadRequestPdu(field);
+
+            ModbusRtuADU modbusRtuADU = new ModbusRtuADU(unitIdentifier, requestPdu, false);
+            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+            transaction.submit(() -> context.sendRequest(modbusRtuADU)
+                .expectResponse(ModbusRtuADU.class, requestTimeout)
+                .onTimeout(future::completeExceptionally)
+                .onError((p, e) -> future.completeExceptionally(e))
+                .unwrap(ModbusRtuADU::getPdu)
+                .handle(responsePdu -> {
+                    // Try to decode the response data based on the corresponding request.
+                    PlcValue plcValue = null;
+                    PlcResponseCode responseCode;
+                    // Check if the response was an error response.
+                    if (responsePdu instanceof ModbusPDUError) {
+                        ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
+                        responseCode = getErrorCode(errorResponse);
+                    } else {
+                        try {
+                            plcValue = toPlcValue(requestPdu, responsePdu, field.getDataType());
+                            responseCode = PlcResponseCode.OK;
+                        } catch (ParseException e) {
+                            // Add an error response code ...
+                            responseCode = PlcResponseCode.INTERNAL_ERROR;
+                        }
+                    }
+
+                    // Prepare the response.
+                    PlcReadResponse response = new DefaultPlcReadResponse(request,
+                        Collections.singletonMap(fieldName, new ResponseItem<>(responseCode, plcValue)));
+
+                    // Pass the response back to the application.
+                    future.complete(response);
+
+                    // Finish the request-transaction.
+                    transaction.endRequest();
+                }));
+        } else {
+            future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
+        }
+        return future;
+    }
+
+    @Override
+    public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
+        CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
+        DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
+
+        // 1. Sort all items by type:
+        //      - DiscreteInput     (read-only)     --> Error
+        //      - Coil              (read-write)    --> ModbusPduWriteSingleCoilRequest / ModbusPduWriteMultipleCoilsRequest
+        //      - InputRegister     (read-only)     --> Error
+        //      - HoldingRegister   (read-write)    --> ModbusPduWriteSingleRegisterRequest / ModbusPduWriteMultipleRegistersRequest
+        //      - FifoQueue         (read-only)     --> Error
+        //      - FileRecord        (read-write)    --> ModbusPduWriteFileRecordRequest
+        // 2. Split up into multiple sub-requests
+        if (request.getFieldNames().size() == 1) {
+            String fieldName = request.getFieldNames().iterator().next();
+            PlcField field = request.getField(fieldName);
+            final ModbusPDU requestPdu = getWriteRequestPdu(field, writeRequest.getPlcValue(fieldName));
+            ModbusRtuADU modbusRtuADU = new ModbusRtuADU(unitIdentifier, requestPdu, false);
+            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+            transaction.submit(() -> context.sendRequest(modbusRtuADU)
+                .expectResponse(ModbusRtuADU.class, requestTimeout)
+                .onTimeout(future::completeExceptionally)
+                .onError((p, e) -> future.completeExceptionally(e))
+                .unwrap(ModbusRtuADU::getPdu)
+                .handle(responsePdu -> {
+                    // Try to decode the response data based on the corresponding request.
+                    PlcResponseCode responseCode;
+
+                    // Check if the response was an error response.
+                    if (responsePdu instanceof ModbusPDUError) {
+                        ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
+                        responseCode = getErrorCode(errorResponse);
+                    } else {
+                        responseCode = PlcResponseCode.OK;
+                        // TODO: Check the correct number of elements were written.
+                        if (responsePdu instanceof ModbusPDUWriteSingleCoilResponse) {
+                            ModbusPDUWriteSingleCoilResponse response = (ModbusPDUWriteSingleCoilResponse) responsePdu;
+                            ModbusPDUWriteSingleCoilRequest requestSingleCoil = (ModbusPDUWriteSingleCoilRequest) requestPdu;
+                            if (!((response.getValue() == requestSingleCoil.getValue()) && (response.getAddress() == requestSingleCoil.getAddress()))) {
+                                responseCode = PlcResponseCode.REMOTE_ERROR;
+                            }
+                        }
+                    }
+
+                    // Prepare the response.
+                    PlcWriteResponse response = new DefaultPlcWriteResponse(request,
+                        Collections.singletonMap(fieldName, responseCode));
+
+                    // Pass the response back to the application.
+                    future.complete(response);
+
+                    // Finish the request-transaction.
+                    transaction.endRequest();
+                }));
+
+        } else {
+            future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
+        }
+        return future;
+    }
+
+}
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java
similarity index 83%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java
index 9a15f3d..24cf92f 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java
@@ -16,17 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus;
+package org.apache.plc4x.java.modbus.tcp;
 
 import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
 import org.apache.plc4x.java.api.metadata.PlcDriverMetadata;
-import org.apache.plc4x.java.modbus.config.ModbusConfiguration;
-import org.apache.plc4x.java.modbus.discovery.ModbusPlcDiscoverer;
-import org.apache.plc4x.java.modbus.field.ModbusField;
-import org.apache.plc4x.java.modbus.field.ModbusFieldHandler;
-import org.apache.plc4x.java.modbus.protocol.ModbusProtocolLogic;
+import org.apache.plc4x.java.modbus.readwrite.DriverType;
+import org.apache.plc4x.java.modbus.tcp.config.ModbusTcpConfiguration;
+import org.apache.plc4x.java.modbus.tcp.discovery.ModbusPlcDiscoverer;
+import org.apache.plc4x.java.modbus.base.field.ModbusField;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldHandler;
 import org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU;
+import org.apache.plc4x.java.modbus.tcp.protocol.ModbusTcpProtocolLogic;
 import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryRequest;
 import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
 import org.apache.plc4x.java.api.value.PlcValueHandler;
@@ -39,21 +40,21 @@ import org.apache.plc4x.java.spi.optimizer.SingleFieldOptimizer;
 
 import java.util.function.ToIntFunction;
 
-public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
+public class ModbusTcpDriver extends GeneratedDriverBase<ModbusTcpADU> {
 
     @Override
     public String getProtocolCode() {
-        return "modbus";
+        return "modbus-tcp";
     }
 
     @Override
     public String getProtocolName() {
-        return "Modbus";
+        return "Modbus TCP";
     }
 
     @Override
     protected Class<? extends Configuration> getConfigurationType() {
-        return ModbusConfiguration.class;
+        return ModbusTcpConfiguration.class;
     }
 
     @Override
@@ -121,11 +122,11 @@ public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
 
     @Override
     protected ProtocolStackConfigurer<ModbusTcpADU> getStackConfigurer() {
-        return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class, ModbusTcpADU::staticParse)
-            .withProtocol(ModbusProtocolLogic.class)
+        return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class, (io, args) -> (ModbusTcpADU) ModbusTcpADU.staticParse(io, args))
+            .withProtocol(ModbusTcpProtocolLogic.class)
             .withPacketSizeEstimator(ByteLengthEstimator.class)
             // Every incoming message is to be treated as a response.
-            .withParserArgs(true)
+            .withParserArgs(DriverType.MODBUS_TCP, true)
             .build();
     }
 
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/config/ModbusTcpConfiguration.java
similarity index 93%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/config/ModbusTcpConfiguration.java
index 68441cf..68e4325 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/config/ModbusConfiguration.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/config/ModbusTcpConfiguration.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.config;
+package org.apache.plc4x.java.modbus.tcp.config;
 
 import org.apache.plc4x.java.modbus.readwrite.ModbusConstants;
 import org.apache.plc4x.java.spi.configuration.Configuration;
@@ -24,7 +24,7 @@ import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParamete
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.transport.tcp.TcpTransportConfiguration;
 
-public class ModbusConfiguration implements Configuration, TcpTransportConfiguration {
+public class ModbusTcpConfiguration implements Configuration, TcpTransportConfiguration {
 
     @ConfigurationParameter("request-timeout")
     @IntDefaultValue(5_000)
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/discovery/ModbusPlcDiscoverer.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/discovery/ModbusPlcDiscoverer.java
similarity index 98%
rename from plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/discovery/ModbusPlcDiscoverer.java
rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/discovery/ModbusPlcDiscoverer.java
index 144ee21..2b89ea3 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/discovery/ModbusPlcDiscoverer.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/discovery/ModbusPlcDiscoverer.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.modbus.discovery;
+package org.apache.plc4x.java.modbus.tcp.discovery;
 
 import org.apache.plc4x.java.api.messages.PlcDiscoveryItem;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryItemHandler;
@@ -188,7 +188,7 @@ public class ModbusPlcDiscoverer implements PlcDiscoverer {
                     if (responseBytes != null) {
                         ReadBuffer readBuffer = new ReadBufferByteBased(responseBytes);
                         try {
-                            ModbusTcpADU response = ModbusTcpADU.staticParse(readBuffer, true);
+                            ModbusTcpADU response = (ModbusTcpADU) ModbusTcpADU.staticParse(readBuffer, true);
                             PlcDiscoveryItem discoveryItem;
                             if (!response.getPdu().getErrorFlag()) {
                                 discoveryItem = new DefaultPlcDiscoveryItem(
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/protocol/ModbusTcpProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/protocol/ModbusTcpProtocolLogic.java
new file mode 100644
index 0000000..e4aad24
--- /dev/null
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/protocol/ModbusTcpProtocolLogic.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.modbus.tcp.protocol;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.modbus.base.field.ModbusField;
+import org.apache.plc4x.java.modbus.base.protocol.ModbusProtocolLogic;
+import org.apache.plc4x.java.modbus.readwrite.*;
+import org.apache.plc4x.java.modbus.rtu.config.ModbusRtuConfiguration;
+import org.apache.plc4x.java.modbus.tcp.config.ModbusTcpConfiguration;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse;
+import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.concurrent.CompletableFuture;
+
+public class ModbusTcpProtocolLogic extends ModbusProtocolLogic<ModbusTcpADU> implements HasConfiguration<ModbusTcpConfiguration> {
+
+    public ModbusTcpProtocolLogic() {
+        super(DriverType.MODBUS_TCP);
+    }
+
+    @Override
+    public void setConfiguration(ModbusTcpConfiguration configuration) {
+        this.requestTimeout = Duration.ofMillis(configuration.getRequestTimeout());
+        this.unitIdentifier = (short) configuration.getUnitIdentifier();
+        this.tm = new RequestTransactionManager(1);
+    }
+
+    @Override
+    public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
+        CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
+        DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
+
+        // 1. Sort all items by type:
+        //      - DiscreteInput     (read-only)     --> ModbusPduReadDiscreteInputsRequest
+        //      - Coil              (read-write)    --> ModbusPduReadCoilsRequest
+        //      - InputRegister     (read-only)     --> ModbusPduReadInputRegistersRequest
+        //      - HoldingRegister   (read-write)    --> ModbusPduReadHoldingRegistersRequest
+        //      - FifoQueue         (read-only)     --> ModbusPduReadFifoQueueRequest
+        //      - FileRecord        (read-write)    --> ModbusPduReadFileRecordRequest
+        // 2. Split up into multiple sub-requests
+
+        // Example for sending a request ...
+        if (request.getFieldNames().size() == 1) {
+            String fieldName = request.getFieldNames().iterator().next();
+            ModbusField field = (ModbusField) request.getField(fieldName);
+            final ModbusPDU requestPdu = getReadRequestPdu(field);
+
+            int transactionIdentifier = transactionIdentifierGenerator.getAndIncrement();
+            // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
+            if (transactionIdentifierGenerator.get() == 0xFFFF) {
+                transactionIdentifierGenerator.set(1);
+            }
+            ModbusTcpADU modbusTcpADU = new ModbusTcpADU(transactionIdentifier, unitIdentifier, requestPdu, false);
+            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+            transaction.submit(() -> context.sendRequest(modbusTcpADU)
+                .expectResponse(ModbusTcpADU.class, requestTimeout)
+                .onTimeout(future::completeExceptionally)
+                .onError((p, e) -> future.completeExceptionally(e))
+                .check(p -> ((p.getTransactionIdentifier() == transactionIdentifier) &&
+                    (p.getUnitIdentifier() == unitIdentifier)))
+                .unwrap(ModbusTcpADU::getPdu)
+                .handle(responsePdu -> {
+                    // Try to decode the response data based on the corresponding request.
+                    PlcValue plcValue = null;
+                    PlcResponseCode responseCode;
+                    // Check if the response was an error response.
+                    if (responsePdu instanceof ModbusPDUError) {
+                        ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
+                        responseCode = getErrorCode(errorResponse);
+                    } else {
+                        try {
+                            plcValue = toPlcValue(requestPdu, responsePdu, field.getDataType());
+                            responseCode = PlcResponseCode.OK;
+                        } catch (ParseException e) {
+                            // Add an error response code ...
+                            responseCode = PlcResponseCode.INTERNAL_ERROR;
+                        }
+                    }
+
+                    // Prepare the response.
+                    PlcReadResponse response = new DefaultPlcReadResponse(request,
+                        Collections.singletonMap(fieldName, new ResponseItem<>(responseCode, plcValue)));
+
+                    // Pass the response back to the application.
+                    future.complete(response);
+
+                    // Finish the request-transaction.
+                    transaction.endRequest();
+                }));
+        } else {
+            future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
+        }
+        return future;
+    }
+
+    @Override
+    public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
+        CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
+        DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
+
+        // 1. Sort all items by type:
+        //      - DiscreteInput     (read-only)     --> Error
+        //      - Coil              (read-write)    --> ModbusPduWriteSingleCoilRequest / ModbusPduWriteMultipleCoilsRequest
+        //      - InputRegister     (read-only)     --> Error
+        //      - HoldingRegister   (read-write)    --> ModbusPduWriteSingleRegisterRequest / ModbusPduWriteMultipleRegistersRequest
+        //      - FifoQueue         (read-only)     --> Error
+        //      - FileRecord        (read-write)    --> ModbusPduWriteFileRecordRequest
+        // 2. Split up into multiple sub-requests
+        if (request.getFieldNames().size() == 1) {
+            String fieldName = request.getFieldNames().iterator().next();
+            PlcField field = request.getField(fieldName);
+            final ModbusPDU requestPdu = getWriteRequestPdu(field, writeRequest.getPlcValue(fieldName));
+            int transactionIdentifier = transactionIdentifierGenerator.getAndIncrement();
+            // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
+            if (transactionIdentifierGenerator.get() == 0xFFFF) {
+                transactionIdentifierGenerator.set(1);
+            }
+            ModbusTcpADU modbusTcpADU = new ModbusTcpADU(transactionIdentifier, unitIdentifier, requestPdu, false);
+            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+            transaction.submit(() -> context.sendRequest(modbusTcpADU)
+                .expectResponse(ModbusTcpADU.class, requestTimeout)
+                .onTimeout(future::completeExceptionally)
+                .onError((p, e) -> future.completeExceptionally(e))
+                .check(p -> p.getTransactionIdentifier() == transactionIdentifier)
+                .unwrap(ModbusTcpADU::getPdu)
+                .handle(responsePdu -> {
+                    // Try to decode the response data based on the corresponding request.
+                    PlcResponseCode responseCode;
+
+                    // Check if the response was an error response.
+                    if (responsePdu instanceof ModbusPDUError) {
+                        ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
+                        responseCode = getErrorCode(errorResponse);
+                    } else {
+                        responseCode = PlcResponseCode.OK;
+                        // TODO: Check the correct number of elements were written.
+                        if (responsePdu instanceof ModbusPDUWriteSingleCoilResponse) {
+                            ModbusPDUWriteSingleCoilResponse response = (ModbusPDUWriteSingleCoilResponse) responsePdu;
+                            ModbusPDUWriteSingleCoilRequest requestSingleCoil = (ModbusPDUWriteSingleCoilRequest) requestPdu;
+                            if (!((response.getValue() == requestSingleCoil.getValue()) && (response.getAddress() == requestSingleCoil.getAddress()))) {
+                                responseCode = PlcResponseCode.REMOTE_ERROR;
+                            }
+                        }
+                    }
+
+                    // Prepare the response.
+                    PlcWriteResponse response = new DefaultPlcWriteResponse(request,
+                        Collections.singletonMap(fieldName, responseCode));
+
+                    // Pass the response back to the application.
+                    future.complete(response);
+
+                    // Finish the request-transaction.
+                    transaction.endRequest();
+                }));
+
+        } else {
+            future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
+        }
+        return future;
+    }
+
+}
diff --git a/plc4j/drivers/modbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver b/plc4j/drivers/modbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
index abed59a..ad318fe 100644
--- a/plc4j/drivers/modbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
+++ b/plc4j/drivers/modbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
@@ -16,4 +16,4 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-org.apache.plc4x.java.modbus.ModbusDriver
+org.apache.plc4x.java.modbus.tcp.ModbusTcpDriver
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDriverTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDriverTest.java
index 20c3c4d..6763ffe 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDriverTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDriverTest.java
@@ -68,7 +68,7 @@ public class ManualModbusDriverTest extends ManualTest {
     }
 
     public static void main(String[] args) throws Exception {
-        ManualModbusDriverTest test = new ManualModbusDriverTest("modbus:tcp://192.168.23.30");
+        ManualModbusDriverTest test = new ManualModbusDriverTest("modbus-tcp://192.168.23.30");
         test.addTestCase("holding-register:1:BOOL", true); // 0001
         test.addTestCase("holding-register:2:BYTE", Arrays.asList(false, false, true, false, true, false, true, false)); // 002A
         test.addTestCase("holding-register:3:WORD", Arrays.asList(true, false, true, false, false, true, false, true, true, false, true, true, true, false, false, false)); // A5B8
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java
index 4f22f61..4ecfc3d 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.plc4x.java.modbus;
 
-import org.apache.plc4x.java.modbus.field.ModbusFieldHoldingRegister;
-import org.apache.plc4x.java.modbus.field.ModbusFieldCoil;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldHoldingRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldCoil;
 import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
 import org.apache.plc4x.java.spi.values.PlcList;
 import org.junit.jupiter.api.Assertions;
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldDataTypeTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldDataTypeTest.java
index 3035271..14317c6 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldDataTypeTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldDataTypeTest.java
@@ -18,11 +18,11 @@
  */
 package org.apache.plc4x.java.modbus;
 
-import org.apache.plc4x.java.modbus.field.ModbusFieldHoldingRegister;
-import org.apache.plc4x.java.modbus.field.ModbusFieldInputRegister;
-import org.apache.plc4x.java.modbus.field.ModbusExtendedRegister;
-import org.apache.plc4x.java.modbus.field.ModbusFieldDiscreteInput;
-import org.apache.plc4x.java.modbus.field.ModbusFieldCoil;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldHoldingRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldInputRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusExtendedRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldDiscreteInput;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldCoil;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldTest.java
index 09d06c7..90231b0 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldTest.java
@@ -18,11 +18,11 @@
  */
 package org.apache.plc4x.java.modbus;
 
-import org.apache.plc4x.java.modbus.field.ModbusFieldHoldingRegister;
-import org.apache.plc4x.java.modbus.field.ModbusFieldInputRegister;
-import org.apache.plc4x.java.modbus.field.ModbusExtendedRegister;
-import org.apache.plc4x.java.modbus.field.ModbusFieldDiscreteInput;
-import org.apache.plc4x.java.modbus.field.ModbusFieldCoil;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldHoldingRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldInputRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusExtendedRegister;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldDiscreteInput;
+import org.apache.plc4x.java.modbus.base.field.ModbusFieldCoil;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/plc4j/drivers/modbus/src/test/resources/logback.xml b/plc4j/drivers/modbus/src/test/resources/logback.xml
index 8c9990d..266fa97 100644
--- a/plc4j/drivers/modbus/src/test/resources/logback.xml
+++ b/plc4j/drivers/modbus/src/test/resources/logback.xml
@@ -29,7 +29,7 @@
     </encoder>
   </appender>
 
-  <root level="info">
+  <root level="debuc">
     <appender-ref ref="STDOUT" />
   </root>
 
diff --git a/plc4j/examples/hello-world-kotlin/src/main/kotlin/ReadModbusPal.kt b/plc4j/examples/hello-world-kotlin/src/main/kotlin/ReadModbusPal.kt
index 7e4d0e0..2dd089f 100644
--- a/plc4j/examples/hello-world-kotlin/src/main/kotlin/ReadModbusPal.kt
+++ b/plc4j/examples/hello-world-kotlin/src/main/kotlin/ReadModbusPal.kt
@@ -5,7 +5,7 @@ import kotlin.system.exitProcess
 
 fun main() {
     PlcDriverManager()
-        .getConnection("modbus://localhost:502")
+        .getConnection("modbus-tcp://localhost:502")
         .use { conn ->
             if (!conn.metadata.canRead()) {
                 println("Cannot read!!")
diff --git a/plc4j/integrations/apache-kafka/src/test/java/org/apache/plc4x/kafka/config/SourceConfigTest.java b/plc4j/integrations/apache-kafka/src/test/java/org/apache/plc4x/kafka/config/SourceConfigTest.java
index 42f41da..a044590 100644
--- a/plc4j/integrations/apache-kafka/src/test/java/org/apache/plc4x/kafka/config/SourceConfigTest.java
+++ b/plc4j/integrations/apache-kafka/src/test/java/org/apache/plc4x/kafka/config/SourceConfigTest.java
@@ -63,7 +63,7 @@ public class SourceConfigTest {
             "sources.machineB.topic=heartbeat\n" +
             "sources.machineB.jobReferences=s7-heartbeat\n" +
             "\n" +
-            "sources.machineC.connectionString=modbus://192.168.1.1:502\n" +
+            "sources.machineC.connectionString=modbus-tcp://192.168.1.1:502\n" +
             "sources.machineC.topic=heartbeat\n" +
             "sources.machineC.jobReferences=ads-heartbeat\n" +
             "\n" +
@@ -108,7 +108,7 @@ public class SourceConfigTest {
             "sources.machineB.topic=heartbeat\n" +
             "sources.machineB.jobReferences=s7-heartbeat\n" +
             "\n" +
-            "sources.machineC.connectionString=modbus://127.0.0.1\n" +
+            "sources.machineC.connectionString=modbus-tcp://127.0.0.1\n" +
             "sources.machineC.topic=heartbeat\n" +
             "sources.machineC.jobReferences=ads-heartbeat\n" +
             "\n" +
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java
index 94f6497..6595c72 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java
+++ b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java
@@ -85,7 +85,7 @@ public class PoolKeyFactory {
                 return new PoolKey(url, plcAuthentication) {
                     private final Pattern inetAddressPattern = Pattern.compile("tcp://(?<host>[\\w.]+)(:(?<port>\\d*))?");
                     private final Pattern serialPattern = Pattern.compile("serial://(?<serialDefinition>((?!/\\d).)*)");
-                    private final Pattern modbusUriPattern = Pattern.compile("^(?<poolablePart>modbus:(" + inetAddressPattern + "|" + serialPattern + "))/?" + "(?<params>\\?.*)?");
+                    private final Pattern modbusUriPattern = Pattern.compile("^(?<poolablePart>modbus-tcp:(" + inetAddressPattern + "|" + serialPattern + "))/?" + "(?<params>\\?.*)?");
 
                     @Override
                     public String getPoolableKey() {
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java
index df31343..2bb4a4f 100644
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java
+++ b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java
@@ -76,19 +76,19 @@ class PoolKeyFactoryTest implements WithAssertions {
     class Modbus {
         @Test
         void getPoolKey_TCP() throws Exception {
-            PoolKey poolKey = SUT.getPoolKey("modbus:tcp://10.10.64.40?someRandomOption=true", PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getUrl()).isEqualTo("modbus:tcp://10.10.64.40?someRandomOption=true");
+            PoolKey poolKey = SUT.getPoolKey("modbus-tcp://10.10.64.40?someRandomOption=true", PooledPlcDriverManager.noPlcAuthentication);
+            assertThat(poolKey.getUrl()).isEqualTo("modbus-tcp://10.10.64.40?someRandomOption=true");
             assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getPoolableKey()).isEqualTo("modbus:tcp://10.10.64.40");
+            assertThat(poolKey.getPoolableKey()).isEqualTo("modbus-tcp://10.10.64.40");
         }
 
         @Disabled("Modbus serial pooling doesn't work right now as intended")
         @Test
         void getPoolKey_SERIAL() throws Exception {
-            PoolKey poolKey = SUT.getPoolKey("modbus:serial:///dev/ttys003?someRandomOption=true", PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getUrl()).isEqualTo("modbus:serial:///dev/ttys003?someRandomOption=true");
+            PoolKey poolKey = SUT.getPoolKey("modbus-adu:///dev/ttys003?someRandomOption=true", PooledPlcDriverManager.noPlcAuthentication);
+            assertThat(poolKey.getUrl()).isEqualTo("modbus-adu:///dev/ttys003?someRandomOption=true");
             assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getPoolableKey()).isEqualTo("modbus:serial:///dev/ttys003");
+            assertThat(poolKey.getPoolableKey()).isEqualTo("modbus-adu:///dev/ttys003");
         }
     }
 
diff --git a/plc4j/tools/scraper/src/test/resources/example_triggered_scraper_modbus.yml b/plc4j/tools/scraper/src/test/resources/example_triggered_scraper_modbus.yml
index 6122ae9..6f3668b 100644
--- a/plc4j/tools/scraper/src/test/resources/example_triggered_scraper_modbus.yml
+++ b/plc4j/tools/scraper/src/test/resources/example_triggered_scraper_modbus.yml
@@ -18,7 +18,7 @@
 # ----------------------------------------------------------------------------
 ---
 sources:
-  LABJACK_PI: modbus:tcp://192.168.167.149:502
+  LABJACK_PI: modbus-tcp://192.168.167.149:502
 
 jobs:
   - name: scheduled-demo-job1
diff --git a/pom.xml b/pom.xml
index 332fe78..04e7b81 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,7 +164,7 @@
     <asciidoctorj.version>2.5.3</asciidoctorj.version>
     <asciidoctorj.diagram.version>2.2.1</asciidoctorj.diagram.version>
 
-    <skip-code-generation-tests>false</skip-code-generation-tests>
+    <skip-code-generation-tests>true</skip-code-generation-tests>
     <skip-dependency-cve-scan>true</skip-dependency-cve-scan>
   </properties>
 
diff --git a/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec b/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec
index 2d54c99..1136df7 100644
--- a/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec
+++ b/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec
@@ -25,36 +25,52 @@
     [const          uint 16     modbusTcpDefaultPort 502]
 ]
 
-[type ModbusTcpADU(bit response) byteOrder='BIG_ENDIAN'
-    // It is used for transaction pairing, the MODBUS server copies in the response the transaction
-    // identifier of the request.
-    [simple         uint 16     transactionIdentifier]
-
-    // It is used for intra-system multiplexing. The MODBUS protocol is identified by the value 0.
-    [const          uint 16     protocolIdentifier    0x0000]
-
-    // The length field is a byte count of the following fields, including the Unit Identifier and
-    // data fields.
-    [implicit       uint 16     length                'pdu.lengthInBytes + 1']
-
-    // This field is used for intra-system routing purpose. It is typically used to communicate to
-    // a MODBUS+ or a MODBUS serial line slave through a gateway between an Ethernet TCP-IP network
-    // and a MODBUS serial line. This field is set by the MODBUS Client in the request and must be
-    // returned with the same value in the response by the server.
-    [simple         uint 8      unitIdentifier]
-
-    // The actual modbus payload
-    [simple         ModbusPDU('response')   pdu]
+[enum DriverType
+    ['0x01' MODBUS_TCP  ]
+    ['0x02' MODBUS_RTU  ]
+    ['0x03' MODBUS_ASCII]
 ]
 
-// This is the base type used by both ModbusRTU and ModbusASCII
-[type ModbusSerialADU(bit response) byteOrder='LITTLE_ENDIAN'
-    [simple         uint 8      address]
+[discriminatedType ModbusADU(DriverType driverType, bit response) byteOrder='BIG_ENDIAN'
+    [typeSwitch driverType
+        ['MODBUS_TCP' ModbusTcpADU
+            // It is used for transaction pairing, the MODBUS server copies in the response the transaction
+            // identifier of the request.
+            [simple         uint 16     transactionIdentifier]
 
-    // The actual modbus payload
-    [simple         ModbusPDU('response')   pdu]
+            // It is used for intra-system multiplexing. The MODBUS protocol is identified by the value 0.
+            [const          uint 16     protocolIdentifier    0x0000]
 
-    [checksum       uint 16     crc         'STATIC_CALL("crcCheck", address, pdu)']
+            // The length field is a byte count of the following fields, including the Unit Identifier and
+            // data fields.
+            [implicit       uint 16     length                'pdu.lengthInBytes + 1']
+
+            // This field is used for intra-system routing purpose. It is typically used to communicate to
+            // a MODBUS+ or a MODBUS serial line slave through a gateway between an Ethernet TCP-IP network
+            // and a MODBUS serial line. This field is set by the MODBUS Client in the request and must be
+            // returned with the same value in the response by the server.
+            [simple         uint 8      unitIdentifier]
+
+            // The actual modbus payload
+            [simple         ModbusPDU('response')   pdu]
+        ]
+        ['MODBUS_RTU' ModbusRtuADU
+            [simple         uint 8                  address]
+
+            // The actual modbus payload
+            [simple         ModbusPDU('response')   pdu    ]
+
+            [checksum       uint 16                 crc     'STATIC_CALL("rtuCrcCheck", address, pdu)']
+        ]
+        ['MODBUS_ASCII' ModbusAsciiADU
+            [simple         uint 8                  address]
+
+            // The actual modbus payload
+            [simple         ModbusPDU('response')   pdu    ]
+
+            [checksum       uint 8                  crc     'STATIC_CALL("asciiLrcCheck", address, pdu)']
+        ]
+    ]
 ]
 
 [discriminatedType ModbusPDU(bit response)
diff --git a/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml b/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml
index cadd145..309e271 100644
--- a/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml
+++ b/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml
@@ -27,7 +27,7 @@
   <protocolName>modbus</protocolName>
   <outputFlavor>read-write</outputFlavor>
 
-  <driver-name>modbus</driver-name>
+  <driver-name>modbus-tcp</driver-name>
 
   <testcase>
     <name>Single element read request</name>
@@ -44,45 +44,51 @@
       </api-request>
       <outgoing-plc-message name="Send Modbus Input-Register Read Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-              </ModbusPDUReadHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                </ModbusPDUReadHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Modbus Input-Register Read Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">7</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersResponse>
-                <byteCount dataType="uint" bitLength="8">4</byteCount>
-                <value dataType="byte" bitLength="32">0x40490fdb</value>
-              </ModbusPDUReadHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">7</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersResponse>
+                  <byteCount dataType="uint" bitLength="8">4</byteCount>
+                  <value dataType="byte" bitLength="32">0x40490fdb</value>
+                </ModbusPDUReadHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Read Response to application">
         <PlcReadResponse>
@@ -125,45 +131,51 @@
       </api-request>
       <outgoing-plc-message name="Send Modbus Input-Register Read Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">4</quantity>
-              </ModbusPDUReadHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">4</quantity>
+                </ModbusPDUReadHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Modbus Input-Register Read Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">11</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersResponse>
-                <byteCount dataType="uint" bitLength="8">8</byteCount>
-                <value dataType="byte" bitLength="64">0x40490fdb40490fdb</value>
-              </ModbusPDUReadHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">11</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersResponse>
+                  <byteCount dataType="uint" bitLength="8">8</byteCount>
+                  <value dataType="byte" bitLength="64">0x40490fdb40490fdb</value>
+                </ModbusPDUReadHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Read Response to application">
         <PlcReadResponse>
@@ -213,87 +225,99 @@
       </api-request>
       <outgoing-plc-message name="Send First Item Modbus Input-Register Read Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-              </ModbusPDUReadHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                </ModbusPDUReadHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive First Item Modbus Input-Register Read Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">7</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersResponse>
-                <byteCount dataType="uint" bitLength="8">4</byteCount>
-                <value dataType="byte" bitLength="32">0x40490fdb</value>
-              </ModbusPDUReadHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">7</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersResponse>
+                  <byteCount dataType="uint" bitLength="8">4</byteCount>
+                  <value dataType="byte" bitLength="32">0x40490fdb</value>
+                </ModbusPDUReadHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <outgoing-plc-message name="Send Second Item Modbus Input-Register Read Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">2</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">2</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-              </ModbusPDUReadHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">2</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">2</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                </ModbusPDUReadHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Second Item Modbus Input-Register Read Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">2</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">7</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">3</functionFlag>
-              <ModbusPDUReadHoldingRegistersResponse>
-                <byteCount dataType="uint" bitLength="8">4</byteCount>
-                <value dataType="byte" bitLength="32">0x40490fdb</value>
-              </ModbusPDUReadHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">2</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">7</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">3</functionFlag>
+                <ModbusPDUReadHoldingRegistersResponse>
+                  <byteCount dataType="uint" bitLength="8">4</byteCount>
+                  <value dataType="byte" bitLength="32">0x40490fdb</value>
+                </ModbusPDUReadHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Read Response to application">
         <PlcReadResponse>
@@ -350,47 +374,53 @@
       </api-request>
       <outgoing-plc-message name="Send Modbus Input-Register Write Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">11</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">16</functionFlag>
-              <ModbusPDUWriteMultipleHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-                <byteCount dataType="uint" bitLength="8">4</byteCount>
-                <value dataType="byte" bitLength="32">0x40490fdb</value>
-              </ModbusPDUWriteMultipleHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">11</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">16</functionFlag>
+                <ModbusPDUWriteMultipleHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                  <byteCount dataType="uint" bitLength="8">4</byteCount>
+                  <value dataType="byte" bitLength="32">0x40490fdb</value>
+                </ModbusPDUWriteMultipleHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Modbus Input-Register Write Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">16</functionFlag>
-              <ModbusPDUWriteMultipleHoldingRegistersResponse>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">2</quantity>
-              </ModbusPDUWriteMultipleHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">16</functionFlag>
+                <ModbusPDUWriteMultipleHoldingRegistersResponse>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">2</quantity>
+                </ModbusPDUWriteMultipleHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Write Response to application">
         <PlcWriteResponse>
@@ -431,47 +461,53 @@
       </api-request>
       <outgoing-plc-message name="Send Modbus Input-Register Write Request">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>false</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">15</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">16</functionFlag>
-              <ModbusPDUWriteMultipleHoldingRegistersRequest>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">4</quantity>
-                <byteCount dataType="uint" bitLength="8">8</byteCount>
-                <value dataType="byte" bitLength="64">0x40490fdb40490fdb</value>
-              </ModbusPDUWriteMultipleHoldingRegistersRequest>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">15</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">16</functionFlag>
+                <ModbusPDUWriteMultipleHoldingRegistersRequest>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">4</quantity>
+                  <byteCount dataType="uint" bitLength="8">8</byteCount>
+                  <value dataType="byte" bitLength="64">0x40490fdb40490fdb</value>
+                </ModbusPDUWriteMultipleHoldingRegistersRequest>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </outgoing-plc-message>
       <incoming-plc-message name="Receive Modbus Input-Register Write Response">
         <parser-arguments>
+          <driverType>MODBUS_TCP</driverType>
           <response>true</response>
         </parser-arguments>
-        <ModbusTcpADU>
-          <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
-          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-          <length dataType="uint" bitLength="16">6</length>
-          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-          <pdu>
-            <ModbusPDU>
-              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-              <functionFlag dataType="uint" bitLength="7">16</functionFlag>
-              <ModbusPDUWriteMultipleHoldingRegistersResponse>
-                <startingAddress dataType="uint" bitLength="16">0</startingAddress>
-                <quantity dataType="uint" bitLength="16">4</quantity>
-              </ModbusPDUWriteMultipleHoldingRegistersResponse>
-            </ModbusPDU>
-          </pdu>
-        </ModbusTcpADU>
+        <ModbusADU>
+          <ModbusTcpADU>
+            <transactionIdentifier dataType="uint" bitLength="16">1</transactionIdentifier>
+            <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+            <length dataType="uint" bitLength="16">6</length>
+            <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+            <pdu>
+              <ModbusPDU>
+                <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+                <functionFlag dataType="uint" bitLength="7">16</functionFlag>
+                <ModbusPDUWriteMultipleHoldingRegistersResponse>
+                  <startingAddress dataType="uint" bitLength="16">0</startingAddress>
+                  <quantity dataType="uint" bitLength="16">4</quantity>
+                </ModbusPDUWriteMultipleHoldingRegistersResponse>
+              </ModbusPDU>
+            </pdu>
+          </ModbusTcpADU>
+        </ModbusADU>
       </incoming-plc-message>
       <api-response name="Report Write Response to application">
         <PlcWriteResponse>
diff --git a/protocols/modbus/src/test/resources/protocols/modbus/ParserSerializerTestsuite.xml b/protocols/modbus/src/test/resources/protocols/modbus/ParserSerializerTestsuite.xml
index f3cc5b3..9463e1c 100644
--- a/protocols/modbus/src/test/resources/protocols/modbus/ParserSerializerTestsuite.xml
+++ b/protocols/modbus/src/test/resources/protocols/modbus/ParserSerializerTestsuite.xml
@@ -28,27 +28,30 @@
   <testcase>
     <name>Read Input Registers Request</name>
     <raw>000000000006ff0408d20002</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>false</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">0</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">6</length>
-        <unitIdentifier dataType="uint" bitLength="8">255</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">4</functionFlag>
-            <ModbusPDUReadInputRegistersRequest>
-              <startingAddress dataType="uint" bitLength="16">2258</startingAddress>
-              <quantity dataType="uint" bitLength="16">2</quantity>
-            </ModbusPDUReadInputRegistersRequest>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">0</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">6</length>
+          <unitIdentifier dataType="uint" bitLength="8">255</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">4</functionFlag>
+              <ModbusPDUReadInputRegistersRequest>
+                <startingAddress dataType="uint" bitLength="16">2258</startingAddress>
+                <quantity dataType="uint" bitLength="16">2</quantity>
+              </ModbusPDUReadInputRegistersRequest>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
@@ -57,105 +60,114 @@
     <raw>
       7cfe000000c9ff04c600000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000004000000000000000000000000000001db000001d600004a380000000000000000000000000000000000000000000000000000000000006461696d006e0000000000000000000000000000303100300000000000000000000000000000000000000000000000000000000000000000000000000000
     </raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>true</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">31998</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">201</length>
-        <unitIdentifier dataType="uint" bitLength="8">255</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">4</functionFlag>
-            <ModbusPDUReadInputRegistersResponse>
-              <byteCount dataType="uint" bitLength="8">198</byteCount>
-              <value dataType="byte" bitLength="1584">0x00000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000004000000000000000000000000000001db000001d600004a380000000000000000000000000000000000000000000000000000000000006461696d006e0000000000000000000000000000303100300000000000000000000000000000000000000000000000000000000000000000000000000000</value>
-            </ModbusPDUReadInputRegistersResponse>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">31998</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">201</length>
+          <unitIdentifier dataType="uint" bitLength="8">255</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">4</functionFlag>
+              <ModbusPDUReadInputRegistersResponse>
+                <byteCount dataType="uint" bitLength="8">198</byteCount>
+                <value dataType="byte" bitLength="1584">0x00000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000004000000000000000000000000000001db000001d600004a380000000000000000000000000000000000000000000000000000000000006461696d006e0000000000000000000000000000303100300000000000000000000000000000000000000000000000000000000000000000000000000000</value>
+              </ModbusPDUReadInputRegistersResponse>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
   <testcase>
     <name>Read Extended Registers Request Split File Record</name>
     <raw>000a0000001101140e060003270e000206000400000008</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>false</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">17</length>
-        <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">20</functionFlag>
-            <ModbusPDUReadFileRecordRequest>
-              <byteCount dataType="uint" bitLength="8">14</byteCount>
-              <items isList="true">
-                <ModbusPDUReadFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">3</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">9998</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">2</recordLength>
-                </ModbusPDUReadFileRecordRequestItem>
-                <ModbusPDUReadFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">4</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">0</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">8</recordLength>
-                </ModbusPDUReadFileRecordRequestItem>
-              </items>
-            </ModbusPDUReadFileRecordRequest>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">17</length>
+          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">20</functionFlag>
+              <ModbusPDUReadFileRecordRequest>
+                <byteCount dataType="uint" bitLength="8">14</byteCount>
+                <items isList="true">
+                  <ModbusPDUReadFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">3</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">9998</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">2</recordLength>
+                  </ModbusPDUReadFileRecordRequestItem>
+                  <ModbusPDUReadFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">4</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">0</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">8</recordLength>
+                  </ModbusPDUReadFileRecordRequestItem>
+                </items>
+              </ModbusPDUReadFileRecordRequest>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
   <testcase>
     <name>Read Extended Registers Response Split File Record</name>
     <raw>000a0000001b011418050600000000110600000000000000000000000000000000</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>true</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">27</length>
-        <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">20</functionFlag>
-            <ModbusPDUReadFileRecordResponse>
-              <byteCount dataType="uint" bitLength="8">24</byteCount>
-              <items isList="true">
-                <ModbusPDUReadFileRecordResponseItem>
-                  <dataLength dataType="uint" bitLength="8">5</dataLength>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <data dataType="byte" bitLength="32">0x00000000</data>
-                </ModbusPDUReadFileRecordResponseItem>
-                <ModbusPDUReadFileRecordResponseItem>
-                  <dataLength dataType="uint" bitLength="8">17</dataLength>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <data dataType="byte" bitLength="128">0x00000000000000000000000000000000</data>
-                </ModbusPDUReadFileRecordResponseItem>
-              </items>
-            </ModbusPDUReadFileRecordResponse>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">27</length>
+          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">20</functionFlag>
+              <ModbusPDUReadFileRecordResponse>
+                <byteCount dataType="uint" bitLength="8">24</byteCount>
+                <items isList="true">
+                  <ModbusPDUReadFileRecordResponseItem>
+                    <dataLength dataType="uint" bitLength="8">5</dataLength>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <data dataType="byte" bitLength="32">0x00000000</data>
+                  </ModbusPDUReadFileRecordResponseItem>
+                  <ModbusPDUReadFileRecordResponseItem>
+                    <dataLength dataType="uint" bitLength="8">17</dataLength>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <data dataType="byte" bitLength="128">0x00000000000000000000000000000000</data>
+                  </ModbusPDUReadFileRecordResponseItem>
+                </items>
+              </ModbusPDUReadFileRecordResponse>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
@@ -163,77 +175,83 @@
     <name>Write Extended Registers Request File Record</name>
 
     <raw>000a0000000c011509060002000000010008</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>false</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">12</length>
-        <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">21</functionFlag>
-            <ModbusPDUWriteFileRecordRequest>
-              <byteCount dataType="uint" bitLength="8">9</byteCount>
-              <items isList="true">
-                <ModbusPDUWriteFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">2</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">0</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">1</recordLength>
-                  <recordData dataType="byte" bitLength="16">0x0008</recordData>
-                </ModbusPDUWriteFileRecordRequestItem>
-              </items>
-            </ModbusPDUWriteFileRecordRequest>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">12</length>
+          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">21</functionFlag>
+              <ModbusPDUWriteFileRecordRequest>
+                <byteCount dataType="uint" bitLength="8">9</byteCount>
+                <items isList="true">
+                  <ModbusPDUWriteFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">2</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">0</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">1</recordLength>
+                    <recordData dataType="byte" bitLength="16">0x0008</recordData>
+                  </ModbusPDUWriteFileRecordRequestItem>
+                </items>
+              </ModbusPDUWriteFileRecordRequest>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
   <testcase>
     <name>Write Extended Registers Request Split File Record</name>
     <raw>000a00000015011512060001270F00010000060002000000010000</raw>
-    <root-type>ModbusTcpADU</root-type>
+    <root-type>ModbusADU</root-type>
     <parser-arguments>
+      <driverType>MODBUS_TCP</driverType>
       <response>false</response>
     </parser-arguments>
     <xml>
-      <ModbusTcpADU>
-        <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
-        <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
-        <length dataType="uint" bitLength="16">21</length>
-        <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
-        <pdu>
-          <ModbusPDU>
-            <errorFlag dataType="bit" bitLength="1">false</errorFlag>
-            <functionFlag dataType="uint" bitLength="7">21</functionFlag>
-            <ModbusPDUWriteFileRecordRequest>
-              <byteCount dataType="uint" bitLength="8">18</byteCount>
-              <items isList="true">
-                <ModbusPDUWriteFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">1</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">9999</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">1</recordLength>
-                  <recordData dataType="byte" bitLength="16">0x0000</recordData>
-                </ModbusPDUWriteFileRecordRequestItem>
-                <ModbusPDUWriteFileRecordRequestItem>
-                  <referenceType dataType="uint" bitLength="8">6</referenceType>
-                  <fileNumber dataType="uint" bitLength="16">2</fileNumber>
-                  <recordNumber dataType="uint" bitLength="16">0</recordNumber>
-                  <recordLength dataType="uint" bitLength="16">1</recordLength>
-                  <recordData dataType="byte" bitLength="16">0x0000</recordData>
-                </ModbusPDUWriteFileRecordRequestItem>
-              </items>
-            </ModbusPDUWriteFileRecordRequest>
-          </ModbusPDU>
-        </pdu>
-      </ModbusTcpADU>
+      <ModbusADU>
+        <ModbusTcpADU>
+          <transactionIdentifier dataType="uint" bitLength="16">10</transactionIdentifier>
+          <protocolIdentifier dataType="uint" bitLength="16">0</protocolIdentifier>
+          <length dataType="uint" bitLength="16">21</length>
+          <unitIdentifier dataType="uint" bitLength="8">1</unitIdentifier>
+          <pdu>
+            <ModbusPDU>
+              <errorFlag dataType="bit" bitLength="1">false</errorFlag>
+              <functionFlag dataType="uint" bitLength="7">21</functionFlag>
+              <ModbusPDUWriteFileRecordRequest>
+                <byteCount dataType="uint" bitLength="8">18</byteCount>
+                <items isList="true">
+                  <ModbusPDUWriteFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">1</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">9999</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">1</recordLength>
+                    <recordData dataType="byte" bitLength="16">0x0000</recordData>
+                  </ModbusPDUWriteFileRecordRequestItem>
+                  <ModbusPDUWriteFileRecordRequestItem>
+                    <referenceType dataType="uint" bitLength="8">6</referenceType>
+                    <fileNumber dataType="uint" bitLength="16">2</fileNumber>
+                    <recordNumber dataType="uint" bitLength="16">0</recordNumber>
+                    <recordLength dataType="uint" bitLength="16">1</recordLength>
+                    <recordData dataType="byte" bitLength="16">0x0000</recordData>
+                  </ModbusPDUWriteFileRecordRequestItem>
+                </items>
+              </ModbusPDUWriteFileRecordRequest>
+            </ModbusPDU>
+          </pdu>
+        </ModbusTcpADU>
+      </ModbusADU>
     </xml>
   </testcase>
 
diff --git a/src/site/asciidoc/plc4go/index.adoc b/src/site/asciidoc/plc4go/index.adoc
index 42896e6..c260078 100644
--- a/src/site/asciidoc/plc4go/index.adoc
+++ b/src/site/asciidoc/plc4go/index.adoc
@@ -100,7 +100,7 @@ func HellpPlc4go() {
 	driverManager.RegisterTransport(tcp.NewTcpTransport())
 
 	// Get a connection to a remote PLC
-	crc := driverManager.GetConnection("modbus://192.168.23.30")
+	crc := driverManager.GetConnection("modbus-tcp://192.168.23.30")
 
 	// Wait for the driver to connect (or not)
 	connectionResult := <-crc
diff --git a/src/site/asciidoc/users/getting-started/plc4go.adoc b/src/site/asciidoc/users/getting-started/plc4go.adoc
index 6087212..e29a4c6 100644
--- a/src/site/asciidoc/users/getting-started/plc4go.adoc
+++ b/src/site/asciidoc/users/getting-started/plc4go.adoc
@@ -100,7 +100,7 @@ Now that the `PlcDriverManager` is configured, we can use it to get a new connec
 
 ----
    	// Get a connection to a remote PLC
-	connectionRequestChanel := driverManager.GetConnection("modbus://192.168.23.30?unit-identifier=1")
+	connectionRequestChanel := driverManager.GetConnection("modbus-tcp://192.168.23.30?unit-identifier=1")
 
 	// Wait for the driver to connect (or not)
 	connectionResult := <-connectionRequestChanel
diff --git a/src/site/asciidoc/users/getting-started/virtual-modbus.adoc b/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
index 6f279bd..c757e69 100644
--- a/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
+++ b/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
@@ -137,13 +137,13 @@ For Modbus the typical transports are:
 
 If we have setup ModbusPal as described above and are running this on the same computer, the connection string to connect to this should be:
 
-    modbus://localhost
+    modbus-tcp://localhost
 
 If you stated ModbusPal on a port different from Modbus' default port `502` you would have to also provide this port in the connection string.
 
 So assuming you started it on port 1502, then the connection string would look as follows:
 
-    modbus://localhost:1502
+    modbus-tcp://localhost:1502
 
 == Writing code
 
@@ -180,7 +180,7 @@ So as soon as your project has the API and a driver implementation available, yo
 This is done via the `PlcDriverManager` by asking this to create an instance for a given `PLC4X connection string`.
 
 ----
-String connectionString = "modbus://localhost";
+String connectionString = "modbus-tcp://localhost";
 
 try (PlcConnection plcConnection = new PlcDriverManager().getConnection(connectionString)) {
 
diff --git a/src/site/asciidoc/users/integrations/eclipse-milo.adoc b/src/site/asciidoc/users/integrations/eclipse-milo.adoc
index 96dcba5..c5cbcd3 100644
--- a/src/site/asciidoc/users/integrations/eclipse-milo.adoc
+++ b/src/site/asciidoc/users/integrations/eclipse-milo.adoc
@@ -66,7 +66,7 @@ name: "Plc4xOPCUAServer"
 disableInsecureEndpoint: true
 devices:
     - name: "ModbusDevice"
-      connectionString: "modbus://127.0.0.1:502"
+      connectionString: "modbus-tcp://127.0.0.1:502"
       tags:
         - alias: "TemporaryBOOLARRAY"
           address: "000001:BOOL[10]"
diff --git a/src/site/asciidoc/users/protocols/modbus.adoc b/src/site/asciidoc/users/protocols/modbus.adoc
index ccf1806..ba5124e 100644
--- a/src/site/asciidoc/users/protocols/modbus.adoc
+++ b/src/site/asciidoc/users/protocols/modbus.adoc
@@ -76,11 +76,11 @@
 
 Modbus has the following connection string format:-
 ----
-modbus:{transport}://{ip-address}:{port}?{options}
+modbus-tcp:{transport}://{ip-address}:{port}?{options}
 ----
 An example connection string would look like:-
 ----
-modbus:tcp://127.0.0.1:502
+modbus-tcp:tcp://127.0.0.1:502
 ----
 Note the transport, port and option fields are optional.