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 2020/10/28 20:32:50 UTC

[plc4x] branch feature/plc4go updated: - Continued working on the go integration-testsuite

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

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


The following commit(s) were added to refs/heads/feature/plc4go by this push:
     new 7d8c4bb  - Continued working on the go integration-testsuite
7d8c4bb is described below

commit 7d8c4bb60a5d74ce6311bc9961ecb060c5837b62
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Oct 28 21:32:42 2020 +0100

    - Continued working on the go integration-testsuite
---
 .../apache/plc4x/language/go/GoLanguageOutput.java |   5 +-
 .../resources/templates/go/model-template.ftlh     |  14 +-
 .../templates/go/xml-parser-factory-template.ftlh  |  88 +++++
 .../plc4x/java/modbus/field/ModbusField.java       |   4 +-
 .../java/modbus/protocol/ModbusProtocolLogic.java  |   3 +-
 .../plc4x/test/driver/DriverTestsuiteRunner.java   |   9 +-
 .../resources/protocols/modbus/DriverTestsuite.xml |  84 +++-
 .../testing}/protocols/modbus/DriverTestsuite.xml  |  84 +++-
 .../cmd/main/drivers/tests/modbus_driver_test.go   |  29 ++
 ...firmedServiceRequestConfirmedCOVNotification.go |  11 +-
 .../BACnetConfirmedServiceRequestReadProperty.go   |  11 +-
 .../BACnetConfirmedServiceRequestSubscribeCOV.go   |  11 +-
 .../BACnetConfirmedServiceRequestWriteProperty.go  |  11 +-
 .../readwrite/model/BACnetErrorReadProperty.go     |  22 +-
 .../model/BACnetServiceAckReadProperty.go          |  11 +-
 .../model/BACnetTagApplicationBitString.go         |  11 +-
 .../model/BACnetTagApplicationEnumerated.go        |  11 +-
 .../model/BACnetTagApplicationSignedInteger.go     |  11 +-
 .../model/BACnetTagApplicationUnsignedInteger.go   |  11 +-
 .../bacnetip/readwrite/model/BACnetTagContext.go   |  11 +-
 .../model/BACnetUnconfirmedServiceRequestIAm.go    |  11 +-
 ...rmedServiceRequestUnconfirmedPrivateTransfer.go |  11 +-
 .../model/BACnetUnconfirmedServiceRequestWhoHas.go |  11 +-
 .../model/BACnetUnconfirmedServiceRequestWhoIs.go  |  22 +-
 .../bacnetip/readwrite/model/XmlParserHelper.go    | 118 ++++++
 .../knxnetip/readwrite/model/CEMIDataFrame.go      |  22 +-
 .../knxnetip/readwrite/model/CEMIFrameData.go      |  22 +-
 .../knxnetip/readwrite/model/CEMIFrameDataExt.go   |  22 +-
 .../knxnetip/readwrite/model/DIBDeviceInfo.go      |  22 +-
 .../plc4go/knxnetip/readwrite/model/IPAddress.go   |  11 +-
 .../plc4go/knxnetip/readwrite/model/MACAddress.go  |  11 +-
 .../knxnetip/readwrite/model/UnknownMessage.go     |  11 +-
 .../knxnetip/readwrite/model/XmlParserHelper.go    | 202 ++++++++++
 .../internal/plc4go/modbus/ModbusConnection.go     |   9 +
 .../plc4go/internal/plc4go/modbus/ModbusDriver.go  |   2 +-
 .../plc4go/internal/plc4go/modbus/ModbusField.go   |   6 +-
 .../internal/plc4go/modbus/ModbusMessageCodec.go   |   4 +-
 .../model/ModbusPDUGetComEventLogResponse.go       |  11 +-
 .../readwrite/model/ModbusPDUReadCoilsResponse.go  |  11 +-
 .../model/ModbusPDUReadDiscreteInputsResponse.go   |  11 +-
 .../model/ModbusPDUReadFileRecordResponseItem.go   |  11 +-
 .../model/ModbusPDUReadHoldingRegistersResponse.go |  11 +-
 .../model/ModbusPDUReadInputRegistersResponse.go   |  11 +-
 ...sPDUReadWriteMultipleHoldingRegistersRequest.go |  11 +-
 ...PDUReadWriteMultipleHoldingRegistersResponse.go |  11 +-
 .../model/ModbusPDUReportServerIdResponse.go       |  11 +-
 .../model/ModbusPDUWriteFileRecordRequestItem.go   |  11 +-
 .../model/ModbusPDUWriteFileRecordResponseItem.go  |  11 +-
 .../model/ModbusPDUWriteMultipleCoilsRequest.go    |  11 +-
 ...odbusPDUWriteMultipleHoldingRegistersRequest.go |  11 +-
 .../modbus/readwrite/model/XmlParserHelper.go      |  90 +++++
 .../s7/readwrite/model/S7VarPayloadDataItem.go     |  11 +-
 .../plc4go/s7/readwrite/model/SzlDataTreeItem.go   |  11 +-
 .../plc4go/s7/readwrite/model/XmlParserHelper.go   | 132 +++++++
 .../plc4go/spi/TransportInstanceExposer.go         |  25 ++
 .../internal/plc4go/testutils/DriverTestRunner.go  | 433 +++++++++++++++++++++
 .../internal/plc4go/transports/tcp/TcpTransport.go |   4 -
 .../plc4go/transports/test/TestTransport.go        |  92 +++++
 sandbox/plc4go/internal/plc4go/utils/CastUtils.go  |   8 +
 59 files changed, 1767 insertions(+), 151 deletions(-)

diff --git a/build-utils/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageOutput.java b/build-utils/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageOutput.java
index a0f91a6..435a470 100644
--- a/build-utils/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageOutput.java
+++ b/build-utils/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageOutput.java
@@ -41,8 +41,9 @@ public class GoLanguageOutput extends FreemarkerLanguageOutput {
 
     @Override
     protected List<Template> getSpecTemplates(Configuration freemarkerConfiguration) throws IOException {
-        return Collections.singletonList(
-            freemarkerConfiguration.getTemplate("templates/go/parser-factory-template.ftlh"));
+        return Arrays.asList(
+            freemarkerConfiguration.getTemplate("templates/go/parser-factory-template.ftlh"),
+            freemarkerConfiguration.getTemplate("templates/go/xml-parser-factory-template.ftlh"));
     }
 
     @Override
diff --git a/build-utils/language-go/src/main/resources/templates/go/model-template.ftlh b/build-utils/language-go/src/main/resources/templates/go/model-template.ftlh
index cbb5ea7..e20ef9b 100644
--- a/build-utils/language-go/src/main/resources/templates/go/model-template.ftlh
+++ b/build-utils/language-go/src/main/resources/templates/go/model-template.ftlh
@@ -896,7 +896,19 @@ func (m *${type.name}) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
     <#if type.propertyFields?has_content>
         <#list type.propertyFields as field>
             case "${field.name}":
-            <#if helper.isComplexTypeReference(field.type) && helper.isDiscriminatedParentTypeDefinition(helper.getTypeDefinitionForTypeReference(field.type))>
+            <#-- int8 arrays are serialized in Base64 encoding -->
+            <#if helper.isArrayField(field) && (helper.getLanguageTypeNameForField(field) == 'int8')>
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.${field.name?cap_first} = utils.ByteToInt8(_decoded[0:_len])
+            <#elseif helper.isComplexTypeReference(field.type) && helper.isDiscriminatedParentTypeDefinition(helper.getTypeDefinitionForTypeReference(field.type))>
                 <#if helper.isArrayField(field)>
                 var _values []<#if helper.isComplexTypeReference(field.type)>I</#if>${helper.getLanguageTypeNameForTypeReference(field.type)}
                 </#if>
diff --git a/build-utils/language-go/src/main/resources/templates/go/xml-parser-factory-template.ftlh b/build-utils/language-go/src/main/resources/templates/go/xml-parser-factory-template.ftlh
new file mode 100644
index 0000000..cd3ef7e
--- /dev/null
+++ b/build-utils/language-go/src/main/resources/templates/go/xml-parser-factory-template.ftlh
@@ -0,0 +1,88 @@
+<#--
+  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.
+-->
+<#-- Prevent freemarker from escaping stuff -->
+<#outputformat "undefined">
+<#-- Declare the name and type of variables passed in to the template -->
+<#-- @ftlvariable name="languageName" type="java.lang.String" -->
+<#-- @ftlvariable name="protocolName" type="java.lang.String" -->
+<#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
+<#-- @ftlvariable name="helper" type="org.apache.plc4x.language.go.GoLanguageTemplateHelper" -->
+<#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
+<#-- Declare the name and type of variables declared locally inside the template -->
+<#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" -->
+<#-- @ftlvariable name="checksumField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ChecksumField" -->
+<#-- @ftlvariable name="constField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ConstField" -->
+<#-- @ftlvariable name="discriminatorField" type="org.apache.plc4x.plugins.codegenerator.types.fields.DiscriminatorField" -->
+<#-- @ftlvariable name="enumField" type="org.apache.plc4x.plugins.codegenerator.types.fields.EnumField" -->
+<#-- @ftlvariable name="implicitField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ImplicitField" -->
+<#-- @ftlvariable name="manualArrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ManualArrayField" -->
+<#-- @ftlvariable name="manualField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ManualField" -->
+<#-- @ftlvariable name="optionalField" type="org.apache.plc4x.plugins.codegenerator.types.fields.OptionalField" -->
+<#-- @ftlvariable name="paddingField" type="org.apache.plc4x.plugins.codegenerator.types.fields.PaddingField" -->
+<#-- @ftlvariable name="reservedField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ReservedField" -->
+<#-- @ftlvariable name="simpleField" type="org.apache.plc4x.plugins.codegenerator.types.fields.SimpleField" -->
+<#-- @ftlvariable name="switchField" type="org.apache.plc4x.plugins.codegenerator.types.fields.SwitchField" -->
+<#-- @ftlvariable name="virtualField" type="org.apache.plc4x.plugins.codegenerator.types.fields.VirtualField" -->
+<#-- @ftlvariable name="simpleTypeReference" type="org.apache.plc4x.plugins.codegenerator.types.references.SimpleTypeReference" -->
+<#-- @ftlvariable name="complexTypeReference" type="org.apache.plc4x.plugins.codegenerator.types.references.ComplexTypeReference" -->
+${helper.fileName(protocolName, languageName, outputFlavor)?replace(".", "/")}/model/XmlParserHelper.go
+//
+// 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 (
+    "encoding/xml"
+    "errors"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/spi"
+)
+
+type ${protocolName?cap_first}XmlParserHelper struct {
+}
+
+func (m ${protocolName?cap_first}XmlParserHelper) Parse(typeName string, xmlString string) (spi.Message, error) {
+    switch typeName {
+<#list helper.getComplexTypeRootDefinitions() as typeDefinition>
+    case "${typeDefinition.name}":
+        var obj ${helper.getLanguageTypeNameForTypeReference(typeDefinition.typeReference)}
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+</#list>
+    }
+    return nil, errors.New("Unsupported type " + typeName)
+}
+</#outputformat>
\ No newline at end of file
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/field/ModbusField.java
index a50e402..9e92901 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/field/ModbusField.java
@@ -60,11 +60,11 @@ public abstract class ModbusField implements PlcField {
     protected ModbusField(int address, Integer quantity, String dataType) {
         this.address = address;
         if ((this.address + PROTOCOL_ADDRESS_OFFSET) <= 0) {
-            throw new IllegalArgumentException("address must be greater then zero. Was " + (this.address + PROTOCOL_ADDRESS_OFFSET));
+            throw new IllegalArgumentException("address must be greater than zero. Was " + (this.address + PROTOCOL_ADDRESS_OFFSET));
         }
         this.quantity = quantity != null ? quantity : 1;
         if (this.quantity <= 0) {
-            throw new IllegalArgumentException("quantity must be greater then zero. Was " + this.quantity);
+            throw new IllegalArgumentException("quantity must be greater than zero. Was " + this.quantity);
         }
         this.dataType = dataType != null ? dataType : "INT";
         ModbusDataTypeSizes.enumForValue(this.dataType);
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/protocol/ModbusProtocolLogic.java
index 45ad0c9..df04f38 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/protocol/ModbusProtocolLogic.java
@@ -61,7 +61,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme
     private Duration requestTimeout;
     private short unitIdentifier;
     private RequestTransactionManager tm;
-    private AtomicInteger transactionIdentifierGenerator = new AtomicInteger(10);
+    private 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;
 
@@ -70,7 +70,6 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme
         this.requestTimeout = Duration.ofMillis(configuration.getRequestTimeout());
         this.unitIdentifier = (short) configuration.getUnitIdentifier();
         this.tm = new RequestTransactionManager(1);
-        this.transactionIdentifierGenerator = new AtomicInteger(10);
     }
 
     @Override
diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java
index c47bf77..a591515 100644
--- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java
+++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java
@@ -406,7 +406,9 @@ public class DriverTestsuiteRunner {
             final Object parsedOutput = messageIO.parse(readBuffer, parserArguments.toArray(new String[0]));
             final String xmlString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(parsedOutput);
             final String referenceXmlString = referenceXml.asXML();
-            final Diff diff = DiffBuilder.compare(referenceXmlString).withTest(xmlString).ignoreComments().ignoreWhitespace().build();
+            final Diff diff = DiffBuilder.compare(referenceXmlString)
+                .withTest(xmlString).checkForSimilar().ignoreComments().ignoreWhitespace()
+                .build();
             if (diff.hasDifferences()) {
                 LOGGER.warn(xmlString);
                 LOGGER.warn(diff.toString());
@@ -419,9 +421,12 @@ public class DriverTestsuiteRunner {
 
     private void validateApiMessage(Element referenceXml, String apiMessage) throws DriverTestsuiteException {
         final String referenceXmlString = referenceXml.asXML();
-        final Diff diff = DiffBuilder.compare(referenceXmlString).withTest(apiMessage).ignoreComments().ignoreWhitespace().build();
+        final Diff diff = DiffBuilder.compare(referenceXmlString)
+            .withTest(apiMessage).checkForSimilar().ignoreComments().ignoreWhitespace()
+            .build();
         if (diff.hasDifferences()) {
             LOGGER.warn(apiMessage);
+            LOGGER.warn(diff.toString());
             throw new DriverTestsuiteException("Differences were found after parsing.\n" + diff.toString());
         }
     }
diff --git a/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml b/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml
index 429997d..befd271 100644
--- a/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml
+++ b/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml
@@ -20,19 +20,24 @@
 <test:driver-testsuite xmlns:test="https://plc4x.apache.org/schemas/driver-testsuite.xsd"
                        bigEndian="true">
 
+  <!-- https://base64.guru/converter/encode/hex -->
+
   <name>Modbus</name>
 
   <driver-name>modbus</driver-name>
 
-  <testcase>
-    <name>Single element read request</name>
+  <!-- Single element read BOOL (Coil) -->
+
+
+  <!--testcase>
+    <name>Single element read BOOL</name>
     <steps>
       <api-request name="Receive Read Request from application">
         <TestReadRequest className="org.apache.plc4x.test.driver.model.api.TestReadRequest">
           <fields>
             <field className="org.apache.plc4x.test.driver.model.api.TestField">
               <name>hurz</name>
-              <address>holding-register:1:REAL[2]</address>
+              <address>holding-register:1:BOOL</address>
             </field>
           </fields>
         </TestReadRequest>
@@ -92,6 +97,79 @@
         </DefaultPlcReadResponse>
       </api-response>
     </steps>
+  </testcase-->
+
+
+  <testcase>
+    <name>Single element read request</name>
+    <steps>
+      <api-request name="Receive Read Request from application">
+        <TestReadRequest className="org.apache.plc4x.test.driver.model.api.TestReadRequest">
+          <fields>
+            <field className="org.apache.plc4x.test.driver.model.api.TestField">
+              <name>hurz</name>
+              <address>holding-register:1:REAL[2]</address>
+            </field>
+          </fields>
+        </TestReadRequest>
+      </api-request>
+      <outgoing-plc-message name="Send Modbus Input-Register Read Request">
+        <!-- 000a00000006010300000004 -->
+        <parser-arguments>
+          <response>false</response>
+        </parser-arguments>
+        <ModbusTcpADU className="org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU">
+          <transactionIdentifier>1</transactionIdentifier>
+          <unitIdentifier>1</unitIdentifier>
+          <pdu className="org.apache.plc4x.java.modbus.readwrite.ModbusPDUReadHoldingRegistersRequest">
+            <startingAddress>0</startingAddress>
+            <quantity>4</quantity>
+          </pdu>
+        </ModbusTcpADU>
+      </outgoing-plc-message>
+      <incoming-plc-message name="Receive Modbus Input-Register Read Response">
+        <!-- 000b0000000b0103080000000000000000 -->
+        <parser-arguments>
+          <response>true</response>
+        </parser-arguments>
+        <ModbusTcpADU className="org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU">
+          <transactionIdentifier>1</transactionIdentifier>
+          <unitIdentifier>1</unitIdentifier>
+          <pdu className="org.apache.plc4x.java.modbus.readwrite.ModbusPDUReadHoldingRegistersResponse">
+            <value>QEkP20BJD9s=</value>
+          </pdu>
+        </ModbusTcpADU>
+      </incoming-plc-message>
+      <api-response name="Report Read Response to application">
+        <DefaultPlcReadResponse className="org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse">
+          <request className="org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest">
+            <hurz className="org.apache.plc4x.java.modbus.field.ModbusFieldHoldingRegister">
+              <address>0</address>
+              <dataType>IEC61131_REAL</dataType>
+              <lengthWords>4</lengthWords>
+              <dataTypeSize>4</dataTypeSize>
+              <lengthBytes>8</lengthBytes>
+            </hurz>
+          </request>
+          <hurz>
+            <code>OK</code>
+            <value className="org.apache.plc4x.java.api.value.PlcList">
+              <object>java.util.Collections..UnmodifiableRandomAccessList</object>
+              <object>org.apache.plc4x.java.api.value.PlcREAL</object>
+              <object>
+                <object>java.lang.Float</object>
+                <object>3.1415927</object>
+              </object>
+              <object>org.apache.plc4x.java.api.value.PlcREAL</object>
+              <object>
+                <object>java.lang.Float</object>
+                <object>3.1415927</object>
+              </object>
+            </value>
+          </hurz>
+        </DefaultPlcReadResponse>
+      </api-response>
+    </steps>
   </testcase>
 
 </test:driver-testsuite>
diff --git a/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml b/sandbox/plc4go/assets/testing/protocols/modbus/DriverTestsuite.xml
similarity index 55%
copy from protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml
copy to sandbox/plc4go/assets/testing/protocols/modbus/DriverTestsuite.xml
index 429997d..befd271 100644
--- a/protocols/modbus/src/test/resources/protocols/modbus/DriverTestsuite.xml
+++ b/sandbox/plc4go/assets/testing/protocols/modbus/DriverTestsuite.xml
@@ -20,19 +20,24 @@
 <test:driver-testsuite xmlns:test="https://plc4x.apache.org/schemas/driver-testsuite.xsd"
                        bigEndian="true">
 
+  <!-- https://base64.guru/converter/encode/hex -->
+
   <name>Modbus</name>
 
   <driver-name>modbus</driver-name>
 
-  <testcase>
-    <name>Single element read request</name>
+  <!-- Single element read BOOL (Coil) -->
+
+
+  <!--testcase>
+    <name>Single element read BOOL</name>
     <steps>
       <api-request name="Receive Read Request from application">
         <TestReadRequest className="org.apache.plc4x.test.driver.model.api.TestReadRequest">
           <fields>
             <field className="org.apache.plc4x.test.driver.model.api.TestField">
               <name>hurz</name>
-              <address>holding-register:1:REAL[2]</address>
+              <address>holding-register:1:BOOL</address>
             </field>
           </fields>
         </TestReadRequest>
@@ -92,6 +97,79 @@
         </DefaultPlcReadResponse>
       </api-response>
     </steps>
+  </testcase-->
+
+
+  <testcase>
+    <name>Single element read request</name>
+    <steps>
+      <api-request name="Receive Read Request from application">
+        <TestReadRequest className="org.apache.plc4x.test.driver.model.api.TestReadRequest">
+          <fields>
+            <field className="org.apache.plc4x.test.driver.model.api.TestField">
+              <name>hurz</name>
+              <address>holding-register:1:REAL[2]</address>
+            </field>
+          </fields>
+        </TestReadRequest>
+      </api-request>
+      <outgoing-plc-message name="Send Modbus Input-Register Read Request">
+        <!-- 000a00000006010300000004 -->
+        <parser-arguments>
+          <response>false</response>
+        </parser-arguments>
+        <ModbusTcpADU className="org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU">
+          <transactionIdentifier>1</transactionIdentifier>
+          <unitIdentifier>1</unitIdentifier>
+          <pdu className="org.apache.plc4x.java.modbus.readwrite.ModbusPDUReadHoldingRegistersRequest">
+            <startingAddress>0</startingAddress>
+            <quantity>4</quantity>
+          </pdu>
+        </ModbusTcpADU>
+      </outgoing-plc-message>
+      <incoming-plc-message name="Receive Modbus Input-Register Read Response">
+        <!-- 000b0000000b0103080000000000000000 -->
+        <parser-arguments>
+          <response>true</response>
+        </parser-arguments>
+        <ModbusTcpADU className="org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU">
+          <transactionIdentifier>1</transactionIdentifier>
+          <unitIdentifier>1</unitIdentifier>
+          <pdu className="org.apache.plc4x.java.modbus.readwrite.ModbusPDUReadHoldingRegistersResponse">
+            <value>QEkP20BJD9s=</value>
+          </pdu>
+        </ModbusTcpADU>
+      </incoming-plc-message>
+      <api-response name="Report Read Response to application">
+        <DefaultPlcReadResponse className="org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse">
+          <request className="org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest">
+            <hurz className="org.apache.plc4x.java.modbus.field.ModbusFieldHoldingRegister">
+              <address>0</address>
+              <dataType>IEC61131_REAL</dataType>
+              <lengthWords>4</lengthWords>
+              <dataTypeSize>4</dataTypeSize>
+              <lengthBytes>8</lengthBytes>
+            </hurz>
+          </request>
+          <hurz>
+            <code>OK</code>
+            <value className="org.apache.plc4x.java.api.value.PlcList">
+              <object>java.util.Collections..UnmodifiableRandomAccessList</object>
+              <object>org.apache.plc4x.java.api.value.PlcREAL</object>
+              <object>
+                <object>java.lang.Float</object>
+                <object>3.1415927</object>
+              </object>
+              <object>org.apache.plc4x.java.api.value.PlcREAL</object>
+              <object>
+                <object>java.lang.Float</object>
+                <object>3.1415927</object>
+              </object>
+            </value>
+          </hurz>
+        </DefaultPlcReadResponse>
+      </api-response>
+    </steps>
   </testcase>
 
 </test:driver-testsuite>
diff --git a/sandbox/plc4go/cmd/main/drivers/tests/modbus_driver_test.go b/sandbox/plc4go/cmd/main/drivers/tests/modbus_driver_test.go
new file mode 100644
index 0000000..0cc07db
--- /dev/null
+++ b/sandbox/plc4go/cmd/main/drivers/tests/modbus_driver_test.go
@@ -0,0 +1,29 @@
+//
+// 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 tests
+
+import (
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/modbus"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/testutils"
+    "testing"
+)
+
+func TestModbusDriver(t *testing.T) {
+    testutils.RunDriverTestsuite(t, modbus.NewModbusDriver(), "assets/testing/protocols/modbus/DriverTestsuite.xml")
+}
\ No newline at end of file
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestConfirmedCOVNotification.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestConfirmedCOVNotification.go
index 448203a..ae854c4 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestConfirmedCOVNotification.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestConfirmedCOVNotification.go
@@ -432,11 +432,16 @@ func (m *BACnetConfirmedServiceRequestConfirmedCOVNotification) UnmarshalXML(d *
                 }
                 m.LifetimeLength = data
             case "lifetimeSeconds":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.LifetimeSeconds = data
+                m.LifetimeSeconds = utils.ByteToInt8(_decoded[0:_len])
             case "notifications":
                 var data []IBACnetTagWithContent
                 if err := d.DecodeElement(&data, &tok); err != nil {
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestReadProperty.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestReadProperty.go
index b9de9ac..4cdb3d3 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestReadProperty.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestReadProperty.go
@@ -250,11 +250,16 @@ func (m *BACnetConfirmedServiceRequestReadProperty) UnmarshalXML(d *xml.Decoder,
                 }
                 m.PropertyIdentifierLength = data
             case "propertyIdentifier":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.PropertyIdentifier = data
+                m.PropertyIdentifier = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestSubscribeCOV.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestSubscribeCOV.go
index bc59d30..e910164 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestSubscribeCOV.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestSubscribeCOV.go
@@ -353,11 +353,16 @@ func (m *BACnetConfirmedServiceRequestSubscribeCOV) UnmarshalXML(d *xml.Decoder,
                 }
                 m.LifetimeLength = data
             case "lifetimeSeconds":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.LifetimeSeconds = data
+                m.LifetimeSeconds = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
index 51e5139..e4331c3 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
@@ -345,11 +345,16 @@ func (m *BACnetConfirmedServiceRequestWriteProperty) UnmarshalXML(d *xml.Decoder
                 }
                 m.PropertyIdentifierLength = data
             case "propertyIdentifier":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.PropertyIdentifier = data
+                m.PropertyIdentifier = utils.ByteToInt8(_decoded[0:_len])
             case "value":
                 switch tok.Attr[0].Value {
                     case "org.apache.plc4x.java.bacnetip.readwrite.BACnetTagApplicationNull":
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetErrorReadProperty.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetErrorReadProperty.go
index 865cf8f..574c590 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetErrorReadProperty.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetErrorReadProperty.go
@@ -249,11 +249,16 @@ func (m *BACnetErrorReadProperty) UnmarshalXML(d *xml.Decoder, start xml.StartEl
                 }
                 m.ErrorClassLength = data
             case "errorClass":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.ErrorClass = data
+                m.ErrorClass = utils.ByteToInt8(_decoded[0:_len])
             case "errorCodeLength":
                 var data uint8
                 if err := d.DecodeElement(&data, &tok); err != nil {
@@ -261,11 +266,16 @@ func (m *BACnetErrorReadProperty) UnmarshalXML(d *xml.Decoder, start xml.StartEl
                 }
                 m.ErrorCodeLength = data
             case "errorCode":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.ErrorCode = data
+                m.ErrorCode = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
index 43ec5de..62e56d7 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
@@ -311,11 +311,16 @@ func (m *BACnetServiceAckReadProperty) UnmarshalXML(d *xml.Decoder, start xml.St
                 }
                 m.PropertyIdentifierLength = data
             case "propertyIdentifier":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.PropertyIdentifier = data
+                m.PropertyIdentifier = utils.ByteToInt8(_decoded[0:_len])
             case "value":
                 switch tok.Attr[0].Value {
                     case "org.apache.plc4x.java.bacnetip.readwrite.BACnetTagApplicationNull":
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationBitString.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationBitString.go
index f99d948..ccba29f 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationBitString.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationBitString.go
@@ -168,11 +168,16 @@ func (m *BACnetTagApplicationBitString) UnmarshalXML(d *xml.Decoder, start xml.S
                 }
                 m.UnusedBits = data
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Data = data
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationEnumerated.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationEnumerated.go
index 124aede..d5ce739 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationEnumerated.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationEnumerated.go
@@ -145,11 +145,16 @@ func (m *BACnetTagApplicationEnumerated) UnmarshalXML(d *xml.Decoder, start xml.
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Data = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationSignedInteger.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationSignedInteger.go
index 99e39e5..4fcc3c4 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationSignedInteger.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationSignedInteger.go
@@ -145,11 +145,16 @@ func (m *BACnetTagApplicationSignedInteger) UnmarshalXML(d *xml.Decoder, start x
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Data = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationUnsignedInteger.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationUnsignedInteger.go
index d1e2314..c2fdb76 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationUnsignedInteger.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagApplicationUnsignedInteger.go
@@ -145,11 +145,16 @@ func (m *BACnetTagApplicationUnsignedInteger) UnmarshalXML(d *xml.Decoder, start
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Data = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagContext.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagContext.go
index bdc8184..2f5cb00 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagContext.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetTagContext.go
@@ -145,11 +145,16 @@ func (m *BACnetTagContext) UnmarshalXML(d *xml.Decoder, start xml.StartElement)
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Data = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestIAm.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestIAm.go
index b952446..c22bba3 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestIAm.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestIAm.go
@@ -322,11 +322,16 @@ func (m *BACnetUnconfirmedServiceRequestIAm) UnmarshalXML(d *xml.Decoder, start
                 }
                 m.MaximumApduLengthAcceptedLength = data
             case "maximumApduLengthAccepted":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.MaximumApduLengthAccepted = data
+                m.MaximumApduLengthAccepted = utils.ByteToInt8(_decoded[0:_len])
             case "segmentationSupported":
                 var data uint8
                 if err := d.DecodeElement(&data, &tok); err != nil {
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestUnconfirmedPrivateTransfer.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestUnconfirmedPrivateTransfer.go
index c8b3736..0c03161 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestUnconfirmedPrivateTransfer.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestUnconfirmedPrivateTransfer.go
@@ -266,11 +266,16 @@ func (m *BACnetUnconfirmedServiceRequestUnconfirmedPrivateTransfer) UnmarshalXML
                 }
                 m.ServiceNumber = data
             case "values":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Values = data
+                m.Values = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
index cdae776..2293b79 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
@@ -286,11 +286,16 @@ func (m *BACnetUnconfirmedServiceRequestWhoHas) UnmarshalXML(d *xml.Decoder, sta
                 }
                 m.ObjectNameCharacterSet = data
             case "objectName":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.ObjectName = data
+                m.ObjectName = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoIs.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoIs.go
index 1f8a8b2..ea36252 100644
--- a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoIs.go
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoIs.go
@@ -249,11 +249,16 @@ func (m *BACnetUnconfirmedServiceRequestWhoIs) UnmarshalXML(d *xml.Decoder, star
                 }
                 m.DeviceInstanceRangeLowLimitLength = data
             case "deviceInstanceRangeLowLimit":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.DeviceInstanceRangeLowLimit = data
+                m.DeviceInstanceRangeLowLimit = utils.ByteToInt8(_decoded[0:_len])
             case "deviceInstanceRangeHighLimitLength":
                 var data uint8
                 if err := d.DecodeElement(&data, &tok); err != nil {
@@ -261,11 +266,16 @@ func (m *BACnetUnconfirmedServiceRequestWhoIs) UnmarshalXML(d *xml.Decoder, star
                 }
                 m.DeviceInstanceRangeHighLimitLength = data
             case "deviceInstanceRangeHighLimit":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.DeviceInstanceRangeHighLimit = data
+                m.DeviceInstanceRangeHighLimit = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/XmlParserHelper.go b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/XmlParserHelper.go
new file mode 100644
index 0000000..135dc59
--- /dev/null
+++ b/sandbox/plc4go/internal/plc4go/bacnetip/readwrite/model/XmlParserHelper.go
@@ -0,0 +1,118 @@
+//
+// 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 (
+    "encoding/xml"
+    "errors"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/spi"
+)
+
+type BacnetipXmlParserHelper struct {
+}
+
+func (m BacnetipXmlParserHelper) Parse(typeName string, xmlString string) (spi.Message, error) {
+    switch typeName {
+    case "APDU":
+        var obj APDU
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BACnetTag":
+        var obj BACnetTag
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BACnetTagWithContent":
+        var obj BACnetTagWithContent
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BACnetError":
+        var obj BACnetError
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "NLM":
+        var obj NLM
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BACnetConfirmedServiceRequest":
+        var obj BACnetConfirmedServiceRequest
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BACnetAddress":
+        var obj BACnetAddress
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BACnetConfirmedServiceACK":
+        var obj BACnetConfirmedServiceACK
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BACnetUnconfirmedServiceRequest":
+        var obj BACnetUnconfirmedServiceRequest
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BACnetServiceAck":
+        var obj BACnetServiceAck
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "BVLC":
+        var obj BVLC
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "NPDU":
+        var obj NPDU
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    }
+    return nil, errors.New("Unsupported type " + typeName)
+}
diff --git a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIDataFrame.go b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIDataFrame.go
index 4250bfe..b1ab309 100644
--- a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIDataFrame.go
+++ b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIDataFrame.go
@@ -501,11 +501,16 @@ func (m *CEMIDataFrame) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
                 }
                 m.SourceAddress = CastIKNXAddress(data)
             case "destinationAddress":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.DestinationAddress = data
+                m.DestinationAddress = utils.ByteToInt8(_decoded[0:_len])
             case "dataLength":
                 var data uint8
                 if err := d.DecodeElement(&data, &tok); err != nil {
@@ -537,11 +542,16 @@ func (m *CEMIDataFrame) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
                 }
                 m.DataFirstByte = data
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Data = data
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIFrameData.go b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIFrameData.go
index 29b702d..fb6b6a7 100644
--- a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIFrameData.go
+++ b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIFrameData.go
@@ -345,11 +345,16 @@ func (m *CEMIFrameData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
                 }
                 m.SourceAddress = CastIKNXAddress(data)
             case "destinationAddress":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.DestinationAddress = data
+                m.DestinationAddress = utils.ByteToInt8(_decoded[0:_len])
             case "groupAddress":
                 var data bool
                 if err := d.DecodeElement(&data, &tok); err != nil {
@@ -393,11 +398,16 @@ func (m *CEMIFrameData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
                 }
                 m.DataFirstByte = data
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Data = data
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             case "crc":
                 var data uint8
                 if err := d.DecodeElement(&data, &tok); err != nil {
diff --git a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIFrameDataExt.go b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIFrameDataExt.go
index 7464eb8..58200a2 100644
--- a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIFrameDataExt.go
+++ b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/CEMIFrameDataExt.go
@@ -380,11 +380,16 @@ func (m *CEMIFrameDataExt) UnmarshalXML(d *xml.Decoder, start xml.StartElement)
                 }
                 m.SourceAddress = CastIKNXAddress(data)
             case "destinationAddress":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.DestinationAddress = data
+                m.DestinationAddress = utils.ByteToInt8(_decoded[0:_len])
             case "dataLength":
                 var data uint8
                 if err := d.DecodeElement(&data, &tok); err != nil {
@@ -416,11 +421,16 @@ func (m *CEMIFrameDataExt) UnmarshalXML(d *xml.Decoder, start xml.StartElement)
                 }
                 m.DataFirstByte = data
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Data = data
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             case "crc":
                 var data uint8
                 if err := d.DecodeElement(&data, &tok); err != nil {
diff --git a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/DIBDeviceInfo.go b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/DIBDeviceInfo.go
index 9140222..72405e0 100644
--- a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/DIBDeviceInfo.go
+++ b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/DIBDeviceInfo.go
@@ -348,11 +348,16 @@ func (m *DIBDeviceInfo) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
                 }
                 m.ProjectInstallationIdentifier = CastIProjectInstallationIdentifier(data)
             case "knxNetIpDeviceSerialNumber":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.KnxNetIpDeviceSerialNumber = data
+                m.KnxNetIpDeviceSerialNumber = utils.ByteToInt8(_decoded[0:_len])
             case "knxNetIpDeviceMulticastAddress":
                 var data *IPAddress
                 if err := d.DecodeElement(&data, &tok); err != nil {
@@ -366,11 +371,16 @@ func (m *DIBDeviceInfo) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
                 }
                 m.KnxNetIpDeviceMacAddress = CastIMACAddress(data)
             case "deviceFriendlyName":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.DeviceFriendlyName = data
+                m.DeviceFriendlyName = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/IPAddress.go b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/IPAddress.go
index c984ccd..5d70098 100644
--- a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/IPAddress.go
+++ b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/IPAddress.go
@@ -129,11 +129,16 @@ func (m *IPAddress) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "addr":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Addr = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Addr = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/MACAddress.go b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/MACAddress.go
index b5afd36..c2fb589 100644
--- a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/MACAddress.go
+++ b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/MACAddress.go
@@ -129,11 +129,16 @@ func (m *MACAddress) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "addr":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Addr = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Addr = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/UnknownMessage.go b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/UnknownMessage.go
index 622a252..85e386b 100644
--- a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/UnknownMessage.go
+++ b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/UnknownMessage.go
@@ -140,11 +140,16 @@ func (m *UnknownMessage) UnmarshalXML(d *xml.Decoder, start xml.StartElement) er
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "unknownData":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.UnknownData = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.UnknownData = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/XmlParserHelper.go b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/XmlParserHelper.go
new file mode 100644
index 0000000..085a048
--- /dev/null
+++ b/sandbox/plc4go/internal/plc4go/knxnetip/readwrite/model/XmlParserHelper.go
@@ -0,0 +1,202 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+package model
+
+import (
+    "encoding/xml"
+    "errors"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/spi"
+)
+
+type KnxnetipXmlParserHelper struct {
+}
+
+func (m KnxnetipXmlParserHelper) Parse(typeName string, xmlString string) (spi.Message, error) {
+    switch typeName {
+    case "CEMIAdditionalInformation":
+        var obj CEMIAdditionalInformation
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "HPAIControlEndpoint":
+        var obj HPAIControlEndpoint
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "TunnelingResponseDataBlock":
+        var obj TunnelingResponseDataBlock
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ConnectionResponseDataBlock":
+        var obj ConnectionResponseDataBlock
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "TunnelingRequestDataBlock":
+        var obj TunnelingRequestDataBlock
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "KNXGroupAddress":
+        var obj KNXGroupAddress
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "DIBDeviceInfo":
+        var obj DIBDeviceInfo
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "DeviceConfigurationRequestDataBlock":
+        var obj DeviceConfigurationRequestDataBlock
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "DeviceConfigurationAckDataBlock":
+        var obj DeviceConfigurationAckDataBlock
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "DIBSuppSvcFamilies":
+        var obj DIBSuppSvcFamilies
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ConnectionRequestInformation":
+        var obj ConnectionRequestInformation
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "HPAIDiscoveryEndpoint":
+        var obj HPAIDiscoveryEndpoint
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ProjectInstallationIdentifier":
+        var obj ProjectInstallationIdentifier
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "KNXAddress":
+        var obj KNXAddress
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "CEMIDataFrame":
+        var obj CEMIDataFrame
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ServiceId":
+        var obj ServiceId
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "KNXNetIPMessage":
+        var obj KNXNetIPMessage
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "HPAIDataEndpoint":
+        var obj HPAIDataEndpoint
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "RelativeTimestamp":
+        var obj RelativeTimestamp
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "CEMI":
+        var obj CEMI
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "MACAddress":
+        var obj MACAddress
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "CEMIFrame":
+        var obj CEMIFrame
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "DeviceStatus":
+        var obj DeviceStatus
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "IPAddress":
+        var obj IPAddress
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    }
+    return nil, errors.New("Unsupported type " + typeName)
+}
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusConnection.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusConnection.go
index bf35b92..90c474c 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/ModbusConnection.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusConnection.go
@@ -21,6 +21,7 @@ package modbus
 import (
     internalModel "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/model"
     "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/spi"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/transports"
     "plc4x.apache.org/plc4go-modbus-driver/v0/pkg/plc4go"
     "plc4x.apache.org/plc4go-modbus-driver/v0/pkg/plc4go/model"
 )
@@ -106,3 +107,11 @@ func (m ModbusConnection) SubscriptionRequestBuilder() model.PlcSubscriptionRequ
 func (m ModbusConnection) UnsubscriptionRequestBuilder() model.PlcUnsubscriptionRequestBuilder {
 	panic("implement me")
 }
+
+func (m ModbusConnection) GetTransportInstance() transports.TransportInstance {
+    if mc, ok := m.messageCodec.(spi.TransportInstanceExposer); ok {
+        return mc.GetTransportInstance()
+    }
+    return nil
+}
+
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusDriver.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusDriver.go
index a7f3ab8..bb68052 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/ModbusDriver.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusDriver.go
@@ -40,7 +40,7 @@ type ModbusDriver struct {
 
 func NewModbusDriver() *ModbusDriver {
 	return &ModbusDriver{
-	    transactionIdCounter: 1,
+	    transactionIdCounter: 0,
 		fieldHandler: NewFieldHandler(),
 		valueHandler: NewValueHandler(),
 	}
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusField.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusField.go
index 9f214f3..65a31df 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/ModbusField.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusField.go
@@ -24,6 +24,10 @@ import (
 	"strconv"
 )
 
+const (
+    MODBUS_PROTOCOL_ADDRESS_OFFSET = 1
+)
+
 type ModbusPlcField struct {
 	FieldType uint8
 	Address   uint16
@@ -34,7 +38,7 @@ type ModbusPlcField struct {
 func NewModbusPlcField(fieldType uint8, address uint16, quantity uint16, datatype string) ModbusPlcField {
 	return ModbusPlcField{
 		FieldType: fieldType,
-		Address:   address,
+		Address:   address - MODBUS_PROTOCOL_ADDRESS_OFFSET,
 		Quantity:  quantity,
 		Datatype:  datatype,
 	}
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusMessageCodec.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusMessageCodec.go
index 1bb1f4e..d274349 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/ModbusMessageCodec.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusMessageCodec.go
@@ -153,4 +153,6 @@ func work(codec *ModbusMessageCodec) {
     }
 }
 
-
+func (m ModbusMessageCodec) GetTransportInstance() transports.TransportInstance {
+    return m.transportInstance
+}
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUGetComEventLogResponse.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUGetComEventLogResponse.go
index 4dcbec4..3dc9096 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUGetComEventLogResponse.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUGetComEventLogResponse.go
@@ -233,11 +233,16 @@ func (m *ModbusPDUGetComEventLogResponse) UnmarshalXML(d *xml.Decoder, start xml
                 }
                 m.MessageCount = data
             case "events":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Events = data
+                m.Events = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadCoilsResponse.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadCoilsResponse.go
index 1e76525..03a4d9c 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadCoilsResponse.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadCoilsResponse.go
@@ -164,11 +164,16 @@ func (m *ModbusPDUReadCoilsResponse) UnmarshalXML(d *xml.Decoder, start xml.Star
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Value = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadDiscreteInputsResponse.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadDiscreteInputsResponse.go
index 4e8309a..2d9d983 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadDiscreteInputsResponse.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadDiscreteInputsResponse.go
@@ -164,11 +164,16 @@ func (m *ModbusPDUReadDiscreteInputsResponse) UnmarshalXML(d *xml.Decoder, start
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Value = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadFileRecordResponseItem.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadFileRecordResponseItem.go
index 1e0768b..0e3e93c 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadFileRecordResponseItem.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadFileRecordResponseItem.go
@@ -169,11 +169,16 @@ func (m *ModbusPDUReadFileRecordResponseItem) UnmarshalXML(d *xml.Decoder, start
                 }
                 m.ReferenceType = data
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Data = data
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadHoldingRegistersResponse.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadHoldingRegistersResponse.go
index 76d913a..7ebf373 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadHoldingRegistersResponse.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadHoldingRegistersResponse.go
@@ -164,11 +164,16 @@ func (m *ModbusPDUReadHoldingRegistersResponse) UnmarshalXML(d *xml.Decoder, sta
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Value = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadInputRegistersResponse.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadInputRegistersResponse.go
index 6894b75..e71a767 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadInputRegistersResponse.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadInputRegistersResponse.go
@@ -164,11 +164,16 @@ func (m *ModbusPDUReadInputRegistersResponse) UnmarshalXML(d *xml.Decoder, start
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Value = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadWriteMultipleHoldingRegistersRequest.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadWriteMultipleHoldingRegistersRequest.go
index baf19c3..d9a954a 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadWriteMultipleHoldingRegistersRequest.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadWriteMultipleHoldingRegistersRequest.go
@@ -256,11 +256,16 @@ func (m *ModbusPDUReadWriteMultipleHoldingRegistersRequest) UnmarshalXML(d *xml.
                 }
                 m.WriteQuantity = data
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Value = data
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadWriteMultipleHoldingRegistersResponse.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadWriteMultipleHoldingRegistersResponse.go
index 78d214d..eddfada 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadWriteMultipleHoldingRegistersResponse.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReadWriteMultipleHoldingRegistersResponse.go
@@ -164,11 +164,16 @@ func (m *ModbusPDUReadWriteMultipleHoldingRegistersResponse) UnmarshalXML(d *xml
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Value = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReportServerIdResponse.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReportServerIdResponse.go
index 95c35a5..0d2970a 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReportServerIdResponse.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUReportServerIdResponse.go
@@ -164,11 +164,16 @@ func (m *ModbusPDUReportServerIdResponse) UnmarshalXML(d *xml.Decoder, start xml
             tok := token.(xml.StartElement)
             switch tok.Name.Local {
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
                     return err
                 }
-                m.Value = data
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
+                    return err
+                }
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteFileRecordRequestItem.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteFileRecordRequestItem.go
index 0e3a3a6..f647fc2 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteFileRecordRequestItem.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteFileRecordRequestItem.go
@@ -215,11 +215,16 @@ func (m *ModbusPDUWriteFileRecordRequestItem) UnmarshalXML(d *xml.Decoder, start
                 }
                 m.RecordNumber = data
             case "recordData":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.RecordData = data
+                m.RecordData = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteFileRecordResponseItem.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteFileRecordResponseItem.go
index 7c84ae7..8332092 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteFileRecordResponseItem.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteFileRecordResponseItem.go
@@ -215,11 +215,16 @@ func (m *ModbusPDUWriteFileRecordResponseItem) UnmarshalXML(d *xml.Decoder, star
                 }
                 m.RecordNumber = data
             case "recordData":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.RecordData = data
+                m.RecordData = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteMultipleCoilsRequest.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteMultipleCoilsRequest.go
index 76dd4ca..bdc8116 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteMultipleCoilsRequest.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteMultipleCoilsRequest.go
@@ -210,11 +210,16 @@ func (m *ModbusPDUWriteMultipleCoilsRequest) UnmarshalXML(d *xml.Decoder, start
                 }
                 m.Quantity = data
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Value = data
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteMultipleHoldingRegistersRequest.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteMultipleHoldingRegistersRequest.go
index 995b4df..1b5d031 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteMultipleHoldingRegistersRequest.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/ModbusPDUWriteMultipleHoldingRegistersRequest.go
@@ -210,11 +210,16 @@ func (m *ModbusPDUWriteMultipleHoldingRegistersRequest) UnmarshalXML(d *xml.Deco
                 }
                 m.Quantity = data
             case "value":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Value = data
+                m.Value = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/XmlParserHelper.go b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/XmlParserHelper.go
new file mode 100644
index 0000000..932c6a4
--- /dev/null
+++ b/sandbox/plc4go/internal/plc4go/modbus/readwrite/model/XmlParserHelper.go
@@ -0,0 +1,90 @@
+//
+// 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 (
+    "encoding/xml"
+    "errors"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/spi"
+)
+
+type ModbusXmlParserHelper struct {
+}
+
+func (m ModbusXmlParserHelper) Parse(typeName string, xmlString string) (spi.Message, error) {
+    switch typeName {
+    case "ModbusPDUWriteFileRecordRequestItem":
+        var obj ModbusPDUWriteFileRecordRequestItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ModbusPDUReadFileRecordResponseItem":
+        var obj ModbusPDUReadFileRecordResponseItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ModbusConstants":
+        var obj ModbusConstants
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ModbusTcpADU":
+        var obj ModbusTcpADU
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ModbusPDUWriteFileRecordResponseItem":
+        var obj ModbusPDUWriteFileRecordResponseItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ModbusPDU":
+        var obj ModbusPDU
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ModbusPDUReadFileRecordRequestItem":
+        var obj ModbusPDUReadFileRecordRequestItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "ModbusSerialADU":
+        var obj ModbusSerialADU
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    }
+    return nil, errors.New("Unsupported type " + typeName)
+}
diff --git a/sandbox/plc4go/internal/plc4go/s7/readwrite/model/S7VarPayloadDataItem.go b/sandbox/plc4go/internal/plc4go/s7/readwrite/model/S7VarPayloadDataItem.go
index ac14d8e..503daa7 100644
--- a/sandbox/plc4go/internal/plc4go/s7/readwrite/model/S7VarPayloadDataItem.go
+++ b/sandbox/plc4go/internal/plc4go/s7/readwrite/model/S7VarPayloadDataItem.go
@@ -222,11 +222,16 @@ func (m *S7VarPayloadDataItem) UnmarshalXML(d *xml.Decoder, start xml.StartEleme
                 }
                 m.TransportSize = data
             case "data":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Data = data
+                m.Data = utils.ByteToInt8(_decoded[0:_len])
             }
         }
     }
diff --git a/sandbox/plc4go/internal/plc4go/s7/readwrite/model/SzlDataTreeItem.go b/sandbox/plc4go/internal/plc4go/s7/readwrite/model/SzlDataTreeItem.go
index bc2d3b0..9678979 100644
--- a/sandbox/plc4go/internal/plc4go/s7/readwrite/model/SzlDataTreeItem.go
+++ b/sandbox/plc4go/internal/plc4go/s7/readwrite/model/SzlDataTreeItem.go
@@ -203,11 +203,16 @@ func (m *SzlDataTreeItem) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e
                 }
                 m.ItemIndex = data
             case "mlfb":
-                var data []int8
-                if err := d.DecodeElement(&data, &tok); err != nil {
+                var _encoded string
+                if err := d.DecodeElement(&_encoded, &tok); err != nil {
+                    return err
+                }
+                _decoded := make([]byte, base64.StdEncoding.DecodedLen(len(_encoded)))
+                _len, err := base64.StdEncoding.Decode(_decoded, []byte(_encoded))
+                if err != nil {
                     return err
                 }
-                m.Mlfb = data
+                m.Mlfb = utils.ByteToInt8(_decoded[0:_len])
             case "moduleTypeId":
                 var data uint16
                 if err := d.DecodeElement(&data, &tok); err != nil {
diff --git a/sandbox/plc4go/internal/plc4go/s7/readwrite/model/XmlParserHelper.go b/sandbox/plc4go/internal/plc4go/s7/readwrite/model/XmlParserHelper.go
new file mode 100644
index 0000000..228fe97
--- /dev/null
+++ b/sandbox/plc4go/internal/plc4go/s7/readwrite/model/XmlParserHelper.go
@@ -0,0 +1,132 @@
+//
+// 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 (
+    "encoding/xml"
+    "errors"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/spi"
+)
+
+type S7XmlParserHelper struct {
+}
+
+func (m S7XmlParserHelper) Parse(typeName string, xmlString string) (spi.Message, error) {
+    switch typeName {
+    case "SzlId":
+        var obj SzlId
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7Message":
+        var obj S7Message
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7VarPayloadStatusItem":
+        var obj S7VarPayloadStatusItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7Parameter":
+        var obj S7Parameter
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "SzlDataTreeItem":
+        var obj SzlDataTreeItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "COTPPacket":
+        var obj COTPPacket
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7PayloadUserDataItem":
+        var obj S7PayloadUserDataItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "COTPParameter":
+        var obj COTPParameter
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "TPKTPacket":
+        var obj TPKTPacket
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7Payload":
+        var obj S7Payload
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7VarRequestParameterItem":
+        var obj S7VarRequestParameterItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7VarPayloadDataItem":
+        var obj S7VarPayloadDataItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7Address":
+        var obj S7Address
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    case "S7ParameterUserDataItem":
+        var obj S7ParameterUserDataItem
+        err := xml.Unmarshal([]byte(xmlString), &obj)
+        if err != nil {
+            return nil, errors.New("error unmarshalling xml: " + err.Error())
+        }
+        return obj, nil
+    }
+    return nil, errors.New("Unsupported type " + typeName)
+}
diff --git a/sandbox/plc4go/internal/plc4go/spi/TransportInstanceExposer.go b/sandbox/plc4go/internal/plc4go/spi/TransportInstanceExposer.go
new file mode 100644
index 0000000..1a60698
--- /dev/null
+++ b/sandbox/plc4go/internal/plc4go/spi/TransportInstanceExposer.go
@@ -0,0 +1,25 @@
+//
+// 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 spi
+
+import "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/transports"
+
+type TransportInstanceExposer interface {
+    GetTransportInstance() transports.TransportInstance
+}
diff --git a/sandbox/plc4go/internal/plc4go/testutils/DriverTestRunner.go b/sandbox/plc4go/internal/plc4go/testutils/DriverTestRunner.go
new file mode 100644
index 0000000..5528bb5
--- /dev/null
+++ b/sandbox/plc4go/internal/plc4go/testutils/DriverTestRunner.go
@@ -0,0 +1,433 @@
+//
+// 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 testutils
+
+import (
+    "encoding/hex"
+    "errors"
+    "fmt"
+    "github.com/subchen/go-xmldom"
+    "os"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/modbus/readwrite/model"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/spi"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/transports/test"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/utils"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/pkg/plc4go"
+    api "plc4x.apache.org/plc4go-modbus-driver/v0/pkg/plc4go/model"
+    "strconv"
+    "testing"
+    "time"
+)
+
+type DriverTestsuite struct {
+    name             string
+    driverName       string
+    driverParameters map[string]string
+    setupSteps       []TestStep
+    teardownSteps    []TestStep
+    testcases        []Testcase
+}
+
+func (m DriverTestsuite) Run(driverManager plc4go.PlcDriverManager, testcase Testcase) error {
+    // Get a connection
+    connectionChan := driverManager.GetConnection(m.driverName + ":test://hurz")
+    connectionResult := <-connectionChan
+
+    if connectionResult.Err != nil {
+        return errors.New("error getting a connection: " + connectionResult.Err.Error())
+    }
+
+    // Run the setup steps
+    for _, testStep := range m.setupSteps {
+        m.ExecuteStep(connectionResult.Connection, &testcase, testStep)
+    }
+
+    // Run the actual scenario steps
+    for _, testStep := range testcase.steps {
+        m.ExecuteStep(connectionResult.Connection, &testcase, testStep)
+    }
+
+    // Run the teardown steps
+    for _, testStep := range m.teardownSteps {
+        m.ExecuteStep(connectionResult.Connection, &testcase, testStep)
+    }
+
+    return nil
+}
+
+func (m DriverTestsuite) ExecuteStep(connection plc4go.PlcConnection, testcase *Testcase, step TestStep) error {
+    mc, ok := connection.(spi.TransportInstanceExposer)
+    if !ok {
+        return errors.New("couldn't access connections transport instance")
+    }
+    transportInstance := mc.GetTransportInstance()
+
+    switch step.stepType {
+    case StepType_API_REQUEST:
+        switch step.payload.Name {
+        case "TestReadRequest":
+            // Assemble a read-request according to the information in the test xml
+            rrb := connection.ReadRequestBuilder()
+            for _, fieldNode := range step.payload.GetChild("fields").GetChildren("field") {
+                fieldName := fieldNode.GetChild("name").Text
+                fieldAddress := fieldNode.GetChild("address").Text
+                rrb.AddItem(fieldName, fieldAddress)
+            }
+            readRequest, err := rrb.Build()
+            if err != nil {
+                return errors.New("Error creating read-request: " + err.Error())
+            }
+
+            // Execute the read-request and store the response-channel in the testcase.
+            if testcase.readRequestResultChannel != nil {
+                return errors.New("testcase read-request result channel already occupied")
+            }
+            testcase.readRequestResultChannel = readRequest.Execute()
+        case "TestWriteRequest":
+            wrb := connection.WriteRequestBuilder()
+            for _, fieldNode := range step.payload.GetChild("fields").GetChildren("field") {
+                fieldName := fieldNode.GetChild("name").Text
+                fieldAddress := fieldNode.GetChild("address").Text
+                fieldValue := fieldNode.GetChild("value").Text
+                wrb.AddItem(fieldName, fieldAddress, fieldValue)
+            }
+            writeRequest, err := wrb.Build()
+            if err != nil {
+                return errors.New("Error creating write-request: " + err.Error())
+            }
+            if testcase.writeRequestResultChannel != nil {
+                return errors.New("testcase write-request result channel already occupied")
+            }
+            testcase.writeRequestResultChannel = writeRequest.Execute()
+        }
+    case StepType_API_RESPONSE:
+        switch step.payload.Name {
+        case "DefaultPlcReadResponse":
+            if testcase.readRequestResultChannel == nil {
+                return errors.New("no read response expected")
+            }
+            readResponse := <- testcase.readRequestResultChannel
+            // TODO: Implement this ...
+            fmt.Println(readResponse)
+        case "DefaultPlcWriteResponse":
+            if testcase.writeRequestResultChannel == nil {
+                return errors.New("no write response expected")
+            }
+            writeResponse := <- testcase.writeRequestResultChannel
+            // TODO: Implement this ...
+            fmt.Println(writeResponse)
+        }
+    case StepType_OUTGOING_PLC_MESSAGE:
+        typeName := step.payload.Name
+        payloadString := step.payload.XML()
+
+        // Parse the xml into a real model
+        message, err := model.ModbusXmlParserHelper{}.Parse(typeName, payloadString)
+        if err != nil {
+            return errors.New("error parsing xml: " + err.Error())
+        }
+
+        // Serialize the model into bytes
+        ser, ok := message.(utils.Serializable)
+        if !ok {
+            return errors.New("error converting type into Serializable type: " + err.Error())
+        }
+        wb := utils.WriteBufferNew()
+        err = ser.Serialize(*wb)
+        if err != nil {
+            return errors.New("error serializing message: " + err.Error())
+        }
+        expectedRawOutput := wb.GetBytes()
+
+        // Read exactly this amount of bytes from the transport
+        rawOutput, err := transportInstance.Read(uint32(len(expectedRawOutput)))
+        if err != nil {
+            return errors.New("error getting bytes from transport: " + err.Error())
+        }
+
+        // Compare the bytes read with the ones we expect
+        for i := range expectedRawOutput {
+            if expectedRawOutput[i] != rawOutput[i] {
+                return errors.New("actual output doesn't match expected output")
+            }
+        }
+        // If there's a difference, parse the input and display it to simplify debugging
+    case StepType_OUTGOING_PLC_BYTES:
+        // Read exactly this amount of bytes from the transport
+        expectedRawInput, err := hex.DecodeString(step.payload.Text)
+        if err != nil {
+            return errors.New("error decoding hex-encoded byte data: " + err.Error())
+        }
+        rawInput, err := transportInstance.Read(uint32(len(expectedRawInput)))
+        if err != nil {
+            return errors.New("error getting bytes from transport: " + err.Error())
+        }
+
+        // Compare the bytes read with the ones we expect
+        for i := range expectedRawInput {
+            if expectedRawInput[i] != rawInput[i] {
+                return errors.New("actual output doesn't match expected output")
+            }
+        }
+        // If there's a difference, parse the input and display it to simplify debugging
+    case StepType_INCOMING_PLC_MESSAGE:
+        typeName := step.payload.Name
+        payloadString := step.payload.XML()
+
+        // Parse the xml into a real model
+        message, err := model.ModbusXmlParserHelper{}.Parse(typeName, payloadString)
+        if err != nil {
+            return errors.New("error parsing xml: " + err.Error())
+        }
+
+        // Serialize the model into bytes
+        ser, ok := message.(utils.Serializable)
+        if !ok {
+            return errors.New("error converting type into Serializable type: " + err.Error())
+        }
+        wb := utils.WriteBufferNew()
+        err = ser.Serialize(*wb)
+        if err != nil {
+            return errors.New("error serializing message: " + err.Error())
+        }
+
+        // Send these bytes to the transport
+        err = transportInstance.Write(wb.GetBytes())
+        if err != nil {
+            return errors.New("error writing data to transport: " + err.Error())
+        }
+    case StepType_INCOMING_PLC_BYTES:
+        // Get the raw hex-data.
+        rawInput, err := hex.DecodeString(step.payload.Text)
+        if err != nil {
+            return errors.New("error decoding hex-encoded byte data: " + err.Error())
+        }
+
+        // Send these bytes to the transport
+        err = transportInstance.Write(rawInput)
+        if err != nil {
+            return errors.New("error writing data to transport: " + err.Error())
+        }
+    case StepType_DELAY:
+        // Get the number of milliseconds
+        delay, err := strconv.Atoi(step.payload.Text)
+        if err != nil {
+            return errors.New("invalid delay format: " + err.Error())
+        }
+        // Sleep for that long
+        time.Sleep(time.Duration(delay))
+    case StepType_TERMINATE:
+        // Simply close the transport connection
+        err := transportInstance.Close()
+        if err != nil {
+            return errors.New("error closing transport: " + err.Error())
+        }
+    }
+    return nil
+}
+
+func (m DriverTestsuite) ParseXml(referenceXml *xmldom.Node, parserArguments []string)  {
+    normalizeXml(referenceXml)
+    //referenceSerialized := referenceXml.FirstChild().XML()
+}
+
+type Testcase struct {
+    name  string
+    steps                    []TestStep
+    readRequestResultChannel <-chan api.PlcReadRequestResult
+    writeRequestResultChannel <-chan api.PlcWriteRequestResult
+}
+
+type TestStep struct {
+    name            string
+    stepType        StepType
+    parserArguments []string
+    payload         xmldom.Node
+}
+
+type StepType uint8
+
+const (
+    StepType_OUTGOING_PLC_MESSAGE StepType = 0x01
+    StepType_OUTGOING_PLC_BYTES   StepType = 0x02
+    StepType_INCOMING_PLC_MESSAGE StepType = 0x03
+    StepType_INCOMING_PLC_BYTES   StepType = 0x04
+    StepType_API_REQUEST          StepType = 0x05
+    StepType_API_RESPONSE         StepType = 0x06
+    StepType_DELAY                StepType = 0x07
+    StepType_TERMINATE            StepType = 0x08
+)
+
+func RunDriverTestsuite(t *testing.T, driver plc4go.PlcDriver, testPath string) {
+    // Read the test-specification as XML file
+    rootNode, err := ParseDriverTestsuiteXml(testPath)
+    if err != nil {
+        t.Error(err.Error())
+        t.Fail()
+        return
+    }
+
+    // Parse the contents of the test-specification
+    testsuite, err := ParseDriverTestsuite(*rootNode)
+    if err != nil {
+        t.Error(err.Error())
+        t.Fail()
+        return
+    }
+
+    // Initialize the driver manager
+    driverManager := plc4go.NewPlcDriverManager()
+    driverManager.RegisterTransport(test.NewTestTransport())
+    driverManager.RegisterDriver(driver)
+
+    for _, testcase := range testsuite.testcases {
+        testsuite.Run(driverManager, testcase)
+    }
+    // Execute the tests in the testsuite
+    fmt.Printf(testsuite.name)
+}
+
+func ParseDriverTestsuiteXml(testPath string) (*xmldom.Node, error) {
+    // Get the current working directory
+    path, err := os.Getwd()
+    if err != nil {
+        return nil, err
+    }
+
+    // Check if the test-file is available
+    info, err := os.Stat(path + "/../../../../" + testPath)
+    if os.IsNotExist(err) {
+        return nil, errors.New("test-File doesn't exist")
+    }
+    if info.IsDir() {
+        return nil, errors.New("test-file refers to a directory")
+    }
+
+    // Open a reader for this file
+    dat, err := os.Open(path + "/../../../../" + testPath)
+    if err != nil {
+        return nil, errors.New("error opening file")
+    }
+
+    // Read the xml
+    node := xmldom.Must(xmldom.Parse(dat)).Root
+    return node, nil
+}
+
+func ParseDriverTestsuite(node xmldom.Node) (*DriverTestsuite, error) {
+    if node.Name != "driver-testsuite" {
+        return nil, errors.New("invalid document structure")
+    }
+    var testsuiteName string
+    var driverName string
+    var setupSteps []TestStep
+    var teardownSteps []TestStep
+    var testcases []Testcase
+    for _, childPtr := range node.Children {
+        child := *childPtr
+        if child.Name == "name" {
+            testsuiteName = child.Text
+        } else if child.Name == "driver-name" {
+            driverName = child.Text
+        } else if child.Name == "setup" {
+            steps, err := ParseDriverTestsuiteSteps(child)
+            if err != nil {
+                return nil, errors.New("error parsing setup steps")
+            }
+            setupSteps = steps
+        } else if child.Name == "teardown" {
+            steps, err := ParseDriverTestsuiteSteps(child)
+            if err != nil {
+                return nil, errors.New("error teardown setup steps")
+            }
+            teardownSteps = steps
+        } else if child.Name == "testcase" {
+            testcaseName := child.FindOneByName("name").Text
+            stepsNode := child.FindOneByName("steps")
+            steps, err := ParseDriverTestsuiteSteps(*stepsNode)
+            if err != nil {
+                return nil, errors.New("error parsing testcase " + testcaseName + ": " + err.Error())
+            }
+            testcase := Testcase{
+                name:  testcaseName,
+                steps: steps,
+            }
+            testcases = append(testcases, testcase)
+        } else {
+            return nil, errors.New("invalid document structure")
+        }
+    }
+
+    return &DriverTestsuite{
+        name:          testsuiteName,
+        driverName:    driverName,
+        setupSteps:    setupSteps,
+        teardownSteps: teardownSteps,
+        testcases:     testcases,
+    }, nil
+}
+
+func ParseDriverTestsuiteSteps(node xmldom.Node) ([]TestStep, error) {
+    var testSteps []TestStep
+    for _, step := range node.Children {
+        name := step.GetAttributeValue("name")
+        var stepType StepType
+        switch step.Name {
+        case "api-request":
+            stepType = StepType_API_REQUEST
+        case "api-response":
+            stepType = StepType_API_RESPONSE
+        case "outgoing-plc-message":
+            stepType = StepType_OUTGOING_PLC_MESSAGE
+        case "incoming-plc-message":
+            stepType = StepType_INCOMING_PLC_MESSAGE
+        case "outgoing-plc-bytes":
+            stepType = StepType_OUTGOING_PLC_BYTES
+        case "incoming-plc-bytes":
+            stepType = StepType_INCOMING_PLC_BYTES
+        case "delay":
+            stepType = StepType_DELAY
+        case "terminate":
+            stepType = StepType_TERMINATE
+        }
+        var parserArguments []string
+        var payload *xmldom.Node
+        for _, childNode := range step.Children {
+            if childNode.Name == "parser-arguments" {
+                for _, parserArgumentNode := range childNode.Children {
+                    parserArguments = append(parserArguments, parserArgumentNode.Text)
+                }
+            } else if payload == nil {
+                payload = childNode
+            } else {
+                return nil, errors.New("test step can only contain a single payload element")
+            }
+        }
+        if payload == nil {
+            return nil, errors.New("missing payload element")
+        }
+        testSteps = append(testSteps, TestStep{
+            name:            name,
+            stepType:        stepType,
+            parserArguments: parserArguments,
+            payload:         *payload,
+        })
+    }
+    return testSteps, nil
+}
diff --git a/sandbox/plc4go/internal/plc4go/transports/tcp/TcpTransport.go b/sandbox/plc4go/internal/plc4go/transports/tcp/TcpTransport.go
index 637145d..09cd9dc 100644
--- a/sandbox/plc4go/internal/plc4go/transports/tcp/TcpTransport.go
+++ b/sandbox/plc4go/internal/plc4go/transports/tcp/TcpTransport.go
@@ -194,7 +194,3 @@ func (m *TcpTransportInstance) Write(data []uint8) error {
     }
     return errors.New("error writing to transport. No writer available")
 }
-
-
-
-
diff --git a/sandbox/plc4go/internal/plc4go/transports/test/TestTransport.go b/sandbox/plc4go/internal/plc4go/transports/test/TestTransport.go
new file mode 100644
index 0000000..d8eb716
--- /dev/null
+++ b/sandbox/plc4go/internal/plc4go/transports/test/TestTransport.go
@@ -0,0 +1,92 @@
+//
+// 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 test
+
+import (
+    "errors"
+    "net/url"
+    "plc4x.apache.org/plc4go-modbus-driver/v0/internal/plc4go/transports"
+)
+
+type TestTransport struct {
+    transports.Transport
+}
+
+func NewTestTransport() *TestTransport {
+    return &TestTransport{}
+}
+
+func (m TestTransport) GetTransportCode() string {
+    return "test"
+}
+
+func (m TestTransport) GetTransportName() string {
+    return "Test Transport"
+}
+
+func (m TestTransport) CreateTransportInstance(transportUrl url.URL, options map[string][]string) (transports.TransportInstance, error) {
+    transportInstance := NewTestTransportInstance(&m)
+
+    castFunc := func(typ interface{}) (transports.TransportInstance, error) {
+        if transportInstance, ok := typ.(transports.TransportInstance); ok {
+            return transportInstance, nil
+        }
+        return nil, errors.New("couldn't cast to TransportInstance")
+    }
+    return castFunc(transportInstance)
+}
+
+type TestTransportInstance struct {
+    buffer []byte
+    transport *TestTransport
+}
+
+func NewTestTransportInstance(transport *TestTransport) *TestTransportInstance {
+    return &TestTransportInstance {
+        buffer: []byte{},
+        transport: transport,
+    }
+}
+
+func (m *TestTransportInstance) Connect() error {
+    return nil
+}
+
+func (m *TestTransportInstance) Close() error {
+    return nil
+}
+
+func (m *TestTransportInstance) GetNumReadableBytes() (uint32, error) {
+    return uint32(len(m.buffer)), nil
+}
+
+func (m *TestTransportInstance) PeekReadableBytes(numBytes uint32) ([]uint8, error) {
+    return m.buffer[0:numBytes], nil
+}
+
+func (m *TestTransportInstance) Read(numBytes uint32) ([]uint8, error) {
+    data := m.buffer[0:int(numBytes)]
+    m.buffer = m.buffer[int(numBytes):]
+    return data, nil
+}
+
+func (m *TestTransportInstance) Write(data []uint8) error {
+    m.buffer = append(m.buffer, data...)
+    return nil
+}
diff --git a/sandbox/plc4go/internal/plc4go/utils/CastUtils.go b/sandbox/plc4go/internal/plc4go/utils/CastUtils.go
index 46c15a0..03bbce5 100644
--- a/sandbox/plc4go/internal/plc4go/utils/CastUtils.go
+++ b/sandbox/plc4go/internal/plc4go/utils/CastUtils.go
@@ -36,6 +36,14 @@ func Int8ToByte(input []int8) []byte {
     return output
 }
 
+func ByteToInt8(input []byte) []int8 {
+    output := make([]int8, len(input))
+    for i, _val := range input {
+        output[i] = int8(_val)
+    }
+    return output
+}
+
 func StrToBool(str string) (bool, error) {
     boolVal, err := strconv.ParseBool(str)
     if err != nil {