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

[plc4x] branch develop updated: refactor(codegen): Updated how CHAR, WCHAR, STRING and WSTRING fields are handled.

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 3d79f3d35 refactor(codegen): Updated how CHAR, WCHAR, STRING and WSTRING fields are handled.
3d79f3d35 is described below

commit 3d79f3d352c7f819935980ea2f99fd0eacf2bb58
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Sep 28 13:33:41 2022 +0200

    refactor(codegen): Updated how CHAR, WCHAR, STRING and WSTRING fields are handled.
    
    refactor(protocol/ads): Multiple changes:
    - Added LWORD to ADS
    - Bugfixing in the parsing of complex types
---
 .../language/go/GoLanguageTemplateHelper.java      | 16 ++++++--
 plc4c/generated-sources/modbus/src/data_item.c     | 24 ++++++------
 plc4c/generated-sources/s7/src/data_item.c         | 32 ++++++++++++----
 plc4go/protocols/ads/readwrite/model/DataItem.go   | 39 ++++++++++++-------
 .../protocols/ads/readwrite/model/StaticHelper.go  | 27 -------------
 .../knxnetip/readwrite/model/KnxDatapoint.go       | 18 ++++-----
 .../protocols/modbus/readwrite/model/DataItem.go   | 20 +++++-----
 plc4go/protocols/s7/readwrite/model/DataItem.go    | 22 +++++------
 .../protocols/s7/readwrite/model/StaticHelper.go   |  2 +-
 .../simulated/readwrite/model/DataItem.go          | 26 ++++++-------
 plc4go/spi/utils/ReadBuffer.go                     |  2 +-
 plc4go/spi/utils/ReadBufferByteBased.go            |  2 +-
 plc4go/spi/utils/ReadBufferByteBased_test.go       |  2 +-
 plc4go/spi/utils/ReadBufferJsonBased.go            |  2 +-
 plc4go/spi/utils/ReadBufferXmlBased.go             |  2 +-
 plc4go/spi/values/CHAR.go                          | 14 +++----
 plc4go/spi/values/IEC61131ValueHandler.go          | 44 ++++++++--------------
 plc4go/spi/values/WCHAR.go                         | 11 +++---
 plc4go/spi/values/WSTRING.go                       |  7 ++--
 plc4go/spi/values/value_combination_test.go        | 11 ++----
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  |  8 +++-
 .../knxnetip/readwrite/model/KnxDatapoint.cs       | 12 +++---
 .../ads/src/main/resources/protocols/ads/ads.mspec | 18 +++++----
 protocols/knxnetip/src/main/xslt/knx-types.xsl     |  4 +-
 .../main/resources/protocols/modbus/modbus.mspec   |  8 ++--
 .../s7/src/main/resources/protocols/s7/s7.mspec    |  6 +--
 .../resources/protocols/simulated/simulated.mspec  | 12 +++---
 27 files changed, 196 insertions(+), 195 deletions(-)

diff --git a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
index 858ef2c34..6d9c762f4 100644
--- a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
+++ b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
@@ -83,7 +83,12 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
             }
         }
         TypedField typedField = field.asTypedField().orElseThrow();
-        return getLanguageTypeNameForTypeReference(typedField.getType());
+        String encoding = null;
+        Optional<Term> encodingAttribute = field.getAttribute("encoding");
+        if(encodingAttribute.isPresent()) {
+            encoding = encodingAttribute.get().toString();
+        }
+        return getLanguageTypeNameForTypeReference(typedField.getType(), encoding);
     }
 
     public boolean isComplex(Field field) {
@@ -92,6 +97,10 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
 
     @Override
     public String getLanguageTypeNameForTypeReference(TypeReference typeReference) {
+        return getLanguageTypeNameForTypeReference(typeReference, null);
+    }
+
+    public String getLanguageTypeNameForTypeReference(TypeReference typeReference, String encoding) {
         if (typeReference == null) {
             // TODO: shouldn't this be an error case
             return "";
@@ -357,7 +366,7 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                 }
                 String encoding = ((StringLiteral) encodingTerm).getValue();
                 String length = Integer.toString(simpleTypeReference.getSizeInBits());
-                return "readBuffer.ReadString(\"" + logicalName + "\", uint32(" + length + "))";
+                return "readBuffer.ReadString(\"" + logicalName + "\", uint32(" + length + "), \"" + encoding + "\")";
             }
             case VSTRING: {
                 VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
@@ -365,8 +374,9 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                 if (!(encodingTerm instanceof StringLiteral)) {
                     throw new RuntimeException("Encoding must be a quoted string value");
                 }
+                String encoding = ((StringLiteral) encodingTerm).getValue();
                 String lengthExpression = toExpression(field, null, vstringTypeReference.getLengthExpression(), null, null, false, false);
-                return "readBuffer.ReadString(\"" + logicalName + "\", uint32(" + lengthExpression + "))";
+                return "readBuffer.ReadString(\"" + logicalName + "\", uint32(" + lengthExpression + "), \"" + encoding + "\")";
             }
             case TIME:
             case DATE:
diff --git a/plc4c/generated-sources/modbus/src/data_item.c b/plc4c/generated-sources/modbus/src/data_item.c
index a9deb6ff9..d3b82044e 100644
--- a/plc4c/generated-sources/modbus/src/data_item.c
+++ b/plc4c/generated-sources/modbus/src/data_item.c
@@ -496,8 +496,8 @@ plc4c_return_code plc4c_modbus_read_write_data_item_parse(plc4c_spi_read_buffer*
     } else         if((dataType == plc4c_modbus_read_write_modbus_data_type_CHAR) && (numberOfValues == 1)) { /* CHAR */
 
                 // Simple Field (value)
-                uint8_t value = 0;
-                _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) &value);
+                char* value = "";
+                _res = plc4c_spi_read_string(readBuffer, 8, "UTF-8", (char**) &value);
                 if(_res != OK) {
                     return _res;
                 }
@@ -512,12 +512,12 @@ plc4c_return_code plc4c_modbus_read_write_data_item_parse(plc4c_spi_read_buffer*
         plc4c_utils_list_create(&value);
         int itemCount = (int) numberOfValues;
         for(int curItem = 0; curItem < itemCount; curItem++) {
-            uint8_t* _val = malloc(sizeof(uint8_t) * 1);
-            _res = plc4c_spi_read_unsigned_byte(readBuffer, 8, (uint8_t*) _val);
+            char** _val = malloc(sizeof(char*) * 1);
+            _res = plc4c_spi_read_string(readBuffer, 8, "UTF-8", (char**) _val);
             if(_res != OK) {
                 return _res;
             }
-            plc4c_data* _item = plc4c_data_create_usint_data(*_val);
+            plc4c_data* _item = plc4c_data_create_char_data(*_val);
             plc4c_utils_list_insert_head_value(value, _item);
         }
         *data_item = plc4c_data_create_list_data(value);
@@ -525,8 +525,8 @@ plc4c_return_code plc4c_modbus_read_write_data_item_parse(plc4c_spi_read_buffer*
     } else         if((dataType == plc4c_modbus_read_write_modbus_data_type_WCHAR) && (numberOfValues == 1)) { /* WCHAR */
 
                 // Simple Field (value)
-                uint16_t value = 0;
-                _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) &value);
+                char* value = "";
+                _res = plc4c_spi_read_string(readBuffer, 16, "UTF-16", (char**) &value);
                 if(_res != OK) {
                     return _res;
                 }
@@ -541,12 +541,12 @@ plc4c_return_code plc4c_modbus_read_write_data_item_parse(plc4c_spi_read_buffer*
         plc4c_utils_list_create(&value);
         int itemCount = (int) numberOfValues;
         for(int curItem = 0; curItem < itemCount; curItem++) {
-            uint16_t* _val = malloc(sizeof(uint16_t) * 1);
-            _res = plc4c_spi_read_unsigned_short(readBuffer, 16, (uint16_t*) _val);
+            char** _val = malloc(sizeof(char*) * 1);
+            _res = plc4c_spi_read_string(readBuffer, 16, "UTF-16", (char**) _val);
             if(_res != OK) {
                 return _res;
             }
-            plc4c_data* _item = plc4c_data_create_uint_data(*_val);
+            plc4c_data* _item = plc4c_data_create_char_data(*_val);
             plc4c_utils_list_insert_head_value(value, _item);
         }
         *data_item = plc4c_data_create_list_data(value);
@@ -694,7 +694,7 @@ plc4c_return_code plc4c_modbus_read_write_data_item_serialize(plc4c_spi_write_bu
         } else         if((dataType == plc4c_modbus_read_write_modbus_data_type_CHAR) && (numberOfValues == 1)) { /* CHAR */
 
                     // Simple field (value)
-                    _res = plc4c_spi_write_unsigned_byte(writeBuffer, 8, (*data_item)->data.char_value);
+                    _res = plc4c_spi_write_string(writeBuffer, 8, "UTF-8", (*data_item)->data.char_value);
                     if(_res != OK) {
                         return _res;
                     }
@@ -704,7 +704,7 @@ plc4c_return_code plc4c_modbus_read_write_data_item_serialize(plc4c_spi_write_bu
         } else         if((dataType == plc4c_modbus_read_write_modbus_data_type_WCHAR) && (numberOfValues == 1)) { /* WCHAR */
 
                     // Simple field (value)
-                    _res = plc4c_spi_write_unsigned_short(writeBuffer, 16, (*data_item)->data.wchar_value);
+                    _res = plc4c_spi_write_string(writeBuffer, 16, "UTF-16", (*data_item)->data.wchar_value);
                     if(_res != OK) {
                         return _res;
                     }
diff --git a/plc4c/generated-sources/s7/src/data_item.c b/plc4c/generated-sources/s7/src/data_item.c
index 7c130d15e..0dc86a4a1 100644
--- a/plc4c/generated-sources/s7/src/data_item.c
+++ b/plc4c/generated-sources/s7/src/data_item.c
@@ -243,15 +243,23 @@ plc4c_return_code plc4c_s7_read_write_data_item_parse(plc4c_spi_read_buffer* rea
 
     } else         if(strcmp(dataProtocolId, "IEC61131_CHAR") == 0) { /* CHAR */
 
-                // Manual Field (value)
-                char* value = (char*) (plc4c_s7_read_write_parse_s7_char(readBuffer, "UTF-8"));
+                // Simple Field (value)
+                char* value = "";
+                _res = plc4c_spi_read_string(readBuffer, 8, "UTF-8", (char**) &value);
+                if(_res != OK) {
+                    return _res;
+                }
 
                 *data_item = plc4c_data_create_char_data(value);
 
     } else         if(strcmp(dataProtocolId, "IEC61131_WCHAR") == 0) { /* CHAR */
 
-                // Manual Field (value)
-                char* value = (char*) (plc4c_s7_read_write_parse_s7_char(readBuffer, "UTF-16"));
+                // Simple Field (value)
+                char* value = "";
+                _res = plc4c_spi_read_string(readBuffer, 16, "UTF-16", (char**) &value);
+                if(_res != OK) {
+                    return _res;
+                }
 
                 *data_item = plc4c_data_create_char_data(value);
 
@@ -494,10 +502,18 @@ plc4c_return_code plc4c_s7_read_write_data_item_serialize(plc4c_spi_write_buffer
                     }
         } else         if(strcmp(dataProtocolId, "IEC61131_CHAR") == 0) { /* CHAR */
 
-                    // Manual Field (value)
+                    // Simple field (value)
+                    _res = plc4c_spi_write_string(writeBuffer, 8, "UTF-8", (*data_item)->data.char_value);
+                    if(_res != OK) {
+                        return _res;
+                    }
         } else         if(strcmp(dataProtocolId, "IEC61131_WCHAR") == 0) { /* CHAR */
 
-                    // Manual Field (value)
+                    // Simple field (value)
+                    _res = plc4c_spi_write_string(writeBuffer, 16, "UTF-16", (*data_item)->data.char_value);
+                    if(_res != OK) {
+                        return _res;
+                    }
         } else         if(strcmp(dataProtocolId, "IEC61131_STRING") == 0) { /* STRING */
 
                     // Manual Field (value)
@@ -656,11 +672,11 @@ uint16_t plc4c_s7_read_write_data_item_length_in_bits(plc4c_data* data_item, cha
         lengthInBits += 64;
     } else     if(strcmp(dataProtocolId, "IEC61131_CHAR") == 0) { /* CHAR */
 
-        // Manual Field (value)
+        // Simple field (value)
         lengthInBits += 8;
     } else     if(strcmp(dataProtocolId, "IEC61131_WCHAR") == 0) { /* CHAR */
 
-        // Manual Field (value)
+        // Simple field (value)
         lengthInBits += 16;
     } else     if(strcmp(dataProtocolId, "IEC61131_STRING") == 0) { /* STRING */
 
diff --git a/plc4go/protocols/ads/readwrite/model/DataItem.go b/plc4go/protocols/ads/readwrite/model/DataItem.go
index 4eb0283da..b989797e2 100644
--- a/plc4go/protocols/ads/readwrite/model/DataItem.go
+++ b/plc4go/protocols/ads/readwrite/model/DataItem.go
@@ -69,6 +69,14 @@ func DataItemParse(readBuffer utils.ReadBuffer, plcValueType PlcValueType, strin
 		}
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcBitString(value), nil
+	case plcValueType == PlcValueType_LWORD: // BitString
+		// Simple Field (value)
+		value, _valueErr := readBuffer.ReadUint64("value", 64)
+		if _valueErr != nil {
+			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
+		}
+		readBuffer.CloseContext("DataItem")
+		return values.NewPlcBitString(value), nil
 	case plcValueType == PlcValueType_SINT: // SINT
 		// Simple Field (value)
 		value, _valueErr := readBuffer.ReadInt8("value", 8)
@@ -149,25 +157,25 @@ func DataItemParse(readBuffer utils.ReadBuffer, plcValueType PlcValueType, strin
 		}
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcLREAL(value), nil
-	case plcValueType == PlcValueType_CHAR: // STRING
+	case plcValueType == PlcValueType_CHAR: // CHAR
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(8))
+		value, _valueErr := readBuffer.ReadString("value", uint32(8), "UTF-8")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
 		readBuffer.CloseContext("DataItem")
-		return values.NewPlcSTRING(value), nil
-	case plcValueType == PlcValueType_WCHAR: // STRING
+		return values.NewPlcCHAR(value), nil
+	case plcValueType == PlcValueType_WCHAR: // WCHAR
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(16))
+		value, _valueErr := readBuffer.ReadString("value", uint32(16), "UTF-16LE")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
 		readBuffer.CloseContext("DataItem")
-		return values.NewPlcSTRING(value), nil
+		return values.NewPlcWCHAR(value), nil
 	case plcValueType == PlcValueType_STRING: // STRING
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32((stringLength)*(8)))
+		value, _valueErr := readBuffer.ReadString("value", uint32((stringLength)*(8)), "UTF-8")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -178,9 +186,9 @@ func DataItemParse(readBuffer utils.ReadBuffer, plcValueType PlcValueType, strin
 		}
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcSTRING(value), nil
-	case plcValueType == PlcValueType_WSTRING: // STRING
+	case plcValueType == PlcValueType_WSTRING: // WSTRING
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(((stringLength)*(8))*(2)))
+		value, _valueErr := readBuffer.ReadString("value", uint32(((stringLength)*(8))*(2)), "UTF-16LE")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -190,7 +198,7 @@ func DataItemParse(readBuffer utils.ReadBuffer, plcValueType PlcValueType, strin
 			return nil, errors.Wrap(_err, "Error parsing reserved field")
 		}
 		readBuffer.CloseContext("DataItem")
-		return values.NewPlcSTRING(value), nil
+		return values.NewPlcWSTRING(value), nil
 	case plcValueType == PlcValueType_TIME: // TIME
 		// Simple Field (value)
 		value, _valueErr := readBuffer.ReadUint32("value", 32)
@@ -273,6 +281,11 @@ func DataItemSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, plcVal
 		if _err := writeBuffer.WriteUint32("value", 32, value.GetUint32()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
+	case plcValueType == PlcValueType_LWORD: // BitString
+		// Simple Field (value)
+		if _err := writeBuffer.WriteUint64("value", 64, value.GetUint64()); _err != nil {
+			return errors.Wrap(_err, "Error serializing 'value' field")
+		}
 	case plcValueType == PlcValueType_SINT: // SINT
 		// Simple Field (value)
 		if _err := writeBuffer.WriteInt8("value", 8, value.GetInt8()); _err != nil {
@@ -323,12 +336,12 @@ func DataItemSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, plcVal
 		if _err := writeBuffer.WriteFloat64("value", 64, value.GetFloat64()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
-	case plcValueType == PlcValueType_CHAR: // STRING
+	case plcValueType == PlcValueType_CHAR: // CHAR
 		// Simple Field (value)
 		if _err := writeBuffer.WriteString("value", uint32(8), "UTF-8", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
-	case plcValueType == PlcValueType_WCHAR: // STRING
+	case plcValueType == PlcValueType_WCHAR: // WCHAR
 		// Simple Field (value)
 		if _err := writeBuffer.WriteString("value", uint32(16), "UTF-16LE", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
@@ -343,7 +356,7 @@ func DataItemSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, plcVal
 		if _err := writeBuffer.WriteUint8("reserved", 8, uint8(0x00)); _err != nil {
 			return errors.Wrap(_err, "Error serializing reserved field")
 		}
-	case plcValueType == PlcValueType_WSTRING: // STRING
+	case plcValueType == PlcValueType_WSTRING: // WSTRING
 		// Simple Field (value)
 		if _err := writeBuffer.WriteString("value", uint32(((stringLength)*(8))*(2)), "UTF-16LE", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
diff --git a/plc4go/protocols/ads/readwrite/model/StaticHelper.go b/plc4go/protocols/ads/readwrite/model/StaticHelper.go
index 4a84914a8..9e13fa1a8 100644
--- a/plc4go/protocols/ads/readwrite/model/StaticHelper.go
+++ b/plc4go/protocols/ads/readwrite/model/StaticHelper.go
@@ -19,33 +19,6 @@
 
 package model
 
-import (
-	"github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
-)
-
-func ParseAmsString(io utils.ReadBuffer, stringLength int32, encoding string) (string, error) {
-	var multiplier int32
-	switch encoding {
-	case "UTF-8":
-		multiplier = 8
-	case "UTF-16":
-		multiplier = 16
-	}
-	return io.ReadString("", uint32(stringLength*multiplier))
-}
-
-func SerializeAmsString(io utils.WriteBuffer, value values.PlcValue, stringLength int32, encoding string) error {
-	var multiplier int32
-	switch encoding {
-	case "UTF-8":
-		multiplier = 8
-	case "UTF-16":
-		multiplier = 16
-	}
-	return io.WriteString("", uint32(stringLength*multiplier), encoding, value.GetString())
-}
-
 func STR_LEN(str string) int {
 	return len(str)
 }
diff --git a/plc4go/protocols/knxnetip/readwrite/model/KnxDatapoint.go b/plc4go/protocols/knxnetip/readwrite/model/KnxDatapoint.go
index e494dccac..b00c1da35 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/KnxDatapoint.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/KnxDatapoint.go
@@ -234,7 +234,7 @@ func KnxDatapointParse(readBuffer utils.ReadBuffer, datapointType KnxDatapointTy
 		}
 
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadUint8("value", 8)
+		value, _valueErr := readBuffer.ReadString("value", uint32(8), "UTF-8")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -247,7 +247,7 @@ func KnxDatapointParse(readBuffer utils.ReadBuffer, datapointType KnxDatapointTy
 		}
 
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadUint16("value", 16)
+		value, _valueErr := readBuffer.ReadString("value", uint32(16), "UTF-16")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -1085,7 +1085,7 @@ func KnxDatapointParse(readBuffer utils.ReadBuffer, datapointType KnxDatapointTy
 		}
 
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(8))
+		value, _valueErr := readBuffer.ReadString("value", uint32(8), "ASCII")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -1098,7 +1098,7 @@ func KnxDatapointParse(readBuffer utils.ReadBuffer, datapointType KnxDatapointTy
 		}
 
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(8))
+		value, _valueErr := readBuffer.ReadString("value", uint32(8), "ISO-8859-1")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -3333,7 +3333,7 @@ func KnxDatapointParse(readBuffer utils.ReadBuffer, datapointType KnxDatapointTy
 		}
 
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(112))
+		value, _valueErr := readBuffer.ReadString("value", uint32(112), "ASCII")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -3346,7 +3346,7 @@ func KnxDatapointParse(readBuffer utils.ReadBuffer, datapointType KnxDatapointTy
 		}
 
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(112))
+		value, _valueErr := readBuffer.ReadString("value", uint32(112), "ISO-8859-1")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -6505,7 +6505,7 @@ func KnxDatapointParse(readBuffer utils.ReadBuffer, datapointType KnxDatapointTy
 		}
 
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(16))
+		value, _valueErr := readBuffer.ReadString("value", uint32(16), "ASCII")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -7726,7 +7726,7 @@ func KnxDatapointSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, da
 		}
 
 		// Simple Field (value)
-		if _err := writeBuffer.WriteUint8("value", 8, value.GetUint8()); _err != nil {
+		if _err := writeBuffer.WriteString("value", uint32(8), "UTF-8", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case datapointType == KnxDatapointType_WCHAR: // WCHAR
@@ -7736,7 +7736,7 @@ func KnxDatapointSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, da
 		}
 
 		// Simple Field (value)
-		if _err := writeBuffer.WriteUint16("value", 16, value.GetUint16()); _err != nil {
+		if _err := writeBuffer.WriteString("value", uint32(16), "UTF-16", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case datapointType == KnxDatapointType_TIME: // TIME
diff --git a/plc4go/protocols/modbus/readwrite/model/DataItem.go b/plc4go/protocols/modbus/readwrite/model/DataItem.go
index afbbb4cb7..9710262cf 100644
--- a/plc4go/protocols/modbus/readwrite/model/DataItem.go
+++ b/plc4go/protocols/modbus/readwrite/model/DataItem.go
@@ -333,7 +333,7 @@ func DataItemParse(readBuffer utils.ReadBuffer, dataType ModbusDataType, numberO
 		return values.NewPlcList(value), nil
 	case dataType == ModbusDataType_CHAR && numberOfValues == uint16(1): // CHAR
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadUint8("value", 8)
+		value, _valueErr := readBuffer.ReadString("value", uint32(8), "UTF-8")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -343,17 +343,17 @@ func DataItemParse(readBuffer utils.ReadBuffer, dataType ModbusDataType, numberO
 		// Array Field (value)
 		var value []api.PlcValue
 		for i := 0; i < int(numberOfValues); i++ {
-			_item, _itemErr := readBuffer.ReadUint8("value", 8)
+			_item, _itemErr := readBuffer.ReadString("value", uint32(8), "UTF-8")
 			if _itemErr != nil {
 				return nil, errors.Wrap(_itemErr, "Error parsing 'value' field")
 			}
-			value = append(value, values.NewPlcUSINT(_item))
+			value = append(value, values.NewPlcSTRING(_item))
 		}
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcList(value), nil
 	case dataType == ModbusDataType_WCHAR && numberOfValues == uint16(1): // WCHAR
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadUint16("value", 16)
+		value, _valueErr := readBuffer.ReadString("value", uint32(16), "UTF-16")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -363,11 +363,11 @@ func DataItemParse(readBuffer utils.ReadBuffer, dataType ModbusDataType, numberO
 		// Array Field (value)
 		var value []api.PlcValue
 		for i := 0; i < int(numberOfValues); i++ {
-			_item, _itemErr := readBuffer.ReadUint16("value", 16)
+			_item, _itemErr := readBuffer.ReadString("value", uint32(16), "UTF-16")
 			if _itemErr != nil {
 				return nil, errors.Wrap(_itemErr, "Error parsing 'value' field")
 			}
-			value = append(value, values.NewPlcUINT(_item))
+			value = append(value, values.NewPlcSTRING(_item))
 		}
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcList(value), nil
@@ -592,26 +592,26 @@ func DataItemSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, dataTy
 		}
 	case dataType == ModbusDataType_CHAR && numberOfValues == uint16(1): // CHAR
 		// Simple Field (value)
-		if _err := writeBuffer.WriteUint8("value", 8, value.GetUint8()); _err != nil {
+		if _err := writeBuffer.WriteString("value", uint32(8), "UTF-8", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case dataType == ModbusDataType_CHAR: // List
 		// Array Field (value)
 		for i := uint32(0); i < uint32(m.NumberOfValues); i++ {
-			_itemErr := writeBuffer.WriteUint8("", 8, value.GetIndex(i).GetUint8())
+			_itemErr := writeBuffer.WriteString("", uint32(8), "UTF-8", value.GetIndex(i).GetString())
 			if _itemErr != nil {
 				return errors.Wrap(_itemErr, "Error serializing 'value' field")
 			}
 		}
 	case dataType == ModbusDataType_WCHAR && numberOfValues == uint16(1): // WCHAR
 		// Simple Field (value)
-		if _err := writeBuffer.WriteUint16("value", 16, value.GetUint16()); _err != nil {
+		if _err := writeBuffer.WriteString("value", uint32(16), "UTF-16", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case dataType == ModbusDataType_WCHAR: // List
 		// Array Field (value)
 		for i := uint32(0); i < uint32(m.NumberOfValues); i++ {
-			_itemErr := writeBuffer.WriteUint16("", 16, value.GetIndex(i).GetUint16())
+			_itemErr := writeBuffer.WriteString("", uint32(16), "UTF-16", value.GetIndex(i).GetString())
 			if _itemErr != nil {
 				return errors.Wrap(_itemErr, "Error serializing 'value' field")
 			}
diff --git a/plc4go/protocols/s7/readwrite/model/DataItem.go b/plc4go/protocols/s7/readwrite/model/DataItem.go
index d0ad80537..b3ac2319f 100644
--- a/plc4go/protocols/s7/readwrite/model/DataItem.go
+++ b/plc4go/protocols/s7/readwrite/model/DataItem.go
@@ -174,16 +174,16 @@ func DataItemParse(readBuffer utils.ReadBuffer, dataProtocolId string, stringLen
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcLREAL(value), nil
 	case dataProtocolId == "IEC61131_CHAR": // CHAR
-		// Manual Field (value)
-		value, _valueErr := ParseS7Char(readBuffer, "UTF-8")
+		// Simple Field (value)
+		value, _valueErr := readBuffer.ReadString("value", uint32(8), "UTF-8")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcCHAR(value), nil
 	case dataProtocolId == "IEC61131_WCHAR": // CHAR
-		// Manual Field (value)
-		value, _valueErr := ParseS7Char(readBuffer, "UTF-16")
+		// Simple Field (value)
+		value, _valueErr := readBuffer.ReadString("value", uint32(16), "UTF-16")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -397,16 +397,14 @@ func DataItemSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, dataPr
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case dataProtocolId == "IEC61131_CHAR": // CHAR
-		// Manual Field (value)
-		_valueErr := SerializeS7Char(writeBuffer, value, "UTF-8")
-		if _valueErr != nil {
-			return errors.Wrap(_valueErr, "Error serializing 'value' field")
+		// Simple Field (value)
+		if _err := writeBuffer.WriteString("value", uint32(8), "UTF-8", value.GetString()); _err != nil {
+			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case dataProtocolId == "IEC61131_WCHAR": // CHAR
-		// Manual Field (value)
-		_valueErr := SerializeS7Char(writeBuffer, value, "UTF-16")
-		if _valueErr != nil {
-			return errors.Wrap(_valueErr, "Error serializing 'value' field")
+		// Simple Field (value)
+		if _err := writeBuffer.WriteString("value", uint32(16), "UTF-16", value.GetString()); _err != nil {
+			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case dataProtocolId == "IEC61131_STRING": // STRING
 		// Manual Field (value)
diff --git a/plc4go/protocols/s7/readwrite/model/StaticHelper.go b/plc4go/protocols/s7/readwrite/model/StaticHelper.go
index 82cc83846..0b588648e 100644
--- a/plc4go/protocols/s7/readwrite/model/StaticHelper.go
+++ b/plc4go/protocols/s7/readwrite/model/StaticHelper.go
@@ -130,7 +130,7 @@ func ParseS7String(io utils.ReadBuffer, stringLength int32, encoding string) (st
 	case "UTF-16":
 		multiplier = 16
 	}
-	return io.ReadString("", uint32(stringLength*multiplier))
+	return io.ReadString("", uint32(stringLength*multiplier), encoding)
 }
 
 func SerializeS7String(io utils.WriteBuffer, value values.PlcValue, stringLength int32, encoding string) error {
diff --git a/plc4go/protocols/simulated/readwrite/model/DataItem.go b/plc4go/protocols/simulated/readwrite/model/DataItem.go
index cbc655c91..5f86154d6 100644
--- a/plc4go/protocols/simulated/readwrite/model/DataItem.go
+++ b/plc4go/protocols/simulated/readwrite/model/DataItem.go
@@ -333,7 +333,7 @@ func DataItemParse(readBuffer utils.ReadBuffer, dataType string, numberOfValues
 		return values.NewPlcList(value), nil
 	case dataType == "CHAR" && numberOfValues == uint16(1): // CHAR
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadUint8("value", 8)
+		value, _valueErr := readBuffer.ReadString("value", uint32(8), "UTF-8")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -343,17 +343,17 @@ func DataItemParse(readBuffer utils.ReadBuffer, dataType string, numberOfValues
 		// Array Field (value)
 		var value []api.PlcValue
 		for i := 0; i < int(numberOfValues); i++ {
-			_item, _itemErr := readBuffer.ReadUint8("value", 8)
+			_item, _itemErr := readBuffer.ReadString("value", uint32(8), "UTF-8")
 			if _itemErr != nil {
 				return nil, errors.Wrap(_itemErr, "Error parsing 'value' field")
 			}
-			value = append(value, values.NewPlcUSINT(_item))
+			value = append(value, values.NewPlcSTRING(_item))
 		}
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcList(value), nil
 	case dataType == "WCHAR" && numberOfValues == uint16(1): // WCHAR
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadUint16("value", 16)
+		value, _valueErr := readBuffer.ReadString("value", uint32(16), "UTF-16")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -363,17 +363,17 @@ func DataItemParse(readBuffer utils.ReadBuffer, dataType string, numberOfValues
 		// Array Field (value)
 		var value []api.PlcValue
 		for i := 0; i < int(numberOfValues); i++ {
-			_item, _itemErr := readBuffer.ReadUint16("value", 16)
+			_item, _itemErr := readBuffer.ReadString("value", uint32(16), "UTF-16")
 			if _itemErr != nil {
 				return nil, errors.Wrap(_itemErr, "Error parsing 'value' field")
 			}
-			value = append(value, values.NewPlcUINT(_item))
+			value = append(value, values.NewPlcSTRING(_item))
 		}
 		readBuffer.CloseContext("DataItem")
 		return values.NewPlcList(value), nil
 	case dataType == "STRING": // STRING
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(255))
+		value, _valueErr := readBuffer.ReadString("value", uint32(255), "UTF-8")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -381,7 +381,7 @@ func DataItemParse(readBuffer utils.ReadBuffer, dataType string, numberOfValues
 		return values.NewPlcSTRING(value), nil
 	case dataType == "WSTRING": // STRING
 		// Simple Field (value)
-		value, _valueErr := readBuffer.ReadString("value", uint32(255))
+		value, _valueErr := readBuffer.ReadString("value", uint32(255), "UTF-16")
 		if _valueErr != nil {
 			return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
 		}
@@ -600,26 +600,26 @@ func DataItemSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, dataTy
 		}
 	case dataType == "CHAR" && numberOfValues == uint16(1): // CHAR
 		// Simple Field (value)
-		if _err := writeBuffer.WriteUint8("value", 8, value.GetUint8()); _err != nil {
+		if _err := writeBuffer.WriteString("value", uint32(8), "UTF-8", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case dataType == "CHAR": // List
 		// Array Field (value)
 		for i := uint32(0); i < uint32(m.NumberOfValues); i++ {
-			_itemErr := writeBuffer.WriteUint8("", 8, value.GetIndex(i).GetUint8())
+			_itemErr := writeBuffer.WriteString("", uint32(8), "UTF-8", value.GetIndex(i).GetString())
 			if _itemErr != nil {
 				return errors.Wrap(_itemErr, "Error serializing 'value' field")
 			}
 		}
 	case dataType == "WCHAR" && numberOfValues == uint16(1): // WCHAR
 		// Simple Field (value)
-		if _err := writeBuffer.WriteUint16("value", 16, value.GetUint16()); _err != nil {
+		if _err := writeBuffer.WriteString("value", uint32(16), "UTF-16", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	case dataType == "WCHAR": // List
 		// Array Field (value)
 		for i := uint32(0); i < uint32(m.NumberOfValues); i++ {
-			_itemErr := writeBuffer.WriteUint16("", 16, value.GetIndex(i).GetUint16())
+			_itemErr := writeBuffer.WriteString("", uint32(16), "UTF-16", value.GetIndex(i).GetString())
 			if _itemErr != nil {
 				return errors.Wrap(_itemErr, "Error serializing 'value' field")
 			}
@@ -631,7 +631,7 @@ func DataItemSerialize(writeBuffer utils.WriteBuffer, value api.PlcValue, dataTy
 		}
 	case dataType == "WSTRING": // STRING
 		// Simple Field (value)
-		if _err := writeBuffer.WriteString("value", uint32(255), "UTF-8", value.GetString()); _err != nil {
+		if _err := writeBuffer.WriteString("value", uint32(255), "UTF-16", value.GetString()); _err != nil {
 			return errors.Wrap(_err, "Error serializing 'value' field")
 		}
 	default:
diff --git a/plc4go/spi/utils/ReadBuffer.go b/plc4go/spi/utils/ReadBuffer.go
index 02e743a15..001a64950 100644
--- a/plc4go/spi/utils/ReadBuffer.go
+++ b/plc4go/spi/utils/ReadBuffer.go
@@ -47,7 +47,7 @@ type ReadBuffer interface {
 	ReadFloat32(logicalName string, bitLength uint8, readerArgs ...WithReaderArgs) (float32, error)
 	ReadFloat64(logicalName string, bitLength uint8, readerArgs ...WithReaderArgs) (float64, error)
 	ReadBigFloat(logicalName string, bitLength uint8, readerArgs ...WithReaderArgs) (*big.Float, error)
-	ReadString(logicalName string, bitLength uint32, readerArgs ...WithReaderArgs) (string, error)
+	ReadString(logicalName string, bitLength uint32, encoding string, readerArgs ...WithReaderArgs) (string, error)
 	// CloseContext signals that we expect the end of the context with the supplied logical name
 	CloseContext(logicalName string, readerArgs ...WithReaderArgs) error
 }
diff --git a/plc4go/spi/utils/ReadBufferByteBased.go b/plc4go/spi/utils/ReadBufferByteBased.go
index aae0c1e24..aea23d10f 100644
--- a/plc4go/spi/utils/ReadBufferByteBased.go
+++ b/plc4go/spi/utils/ReadBufferByteBased.go
@@ -377,7 +377,7 @@ func (rb *byteReadBuffer) ReadBigFloat(logicalName string, bitLength uint8, _ ..
 	return big.NewFloat(readFloat64), nil
 }
 
-func (rb *byteReadBuffer) ReadString(logicalName string, bitLength uint32, _ ...WithReaderArgs) (string, error) {
+func (rb *byteReadBuffer) ReadString(logicalName string, bitLength uint32, encoding string, _ ...WithReaderArgs) (string, error) {
 	stringBytes, err := rb.ReadByteArray(logicalName, int(bitLength/8))
 	if err != nil {
 		return "", errors.Wrap(err, "Error reading big int")
diff --git a/plc4go/spi/utils/ReadBufferByteBased_test.go b/plc4go/spi/utils/ReadBufferByteBased_test.go
index f1fa110bd..8c7e1a10e 100644
--- a/plc4go/spi/utils/ReadBufferByteBased_test.go
+++ b/plc4go/spi/utils/ReadBufferByteBased_test.go
@@ -1461,7 +1461,7 @@ func TestReadBuffer_ReadString(t *testing.T) {
 				pos:       tt.fields.pos,
 				byteOrder: tt.fields.byteOrder,
 			}
-			got, err := rb.ReadString("", tt.args.bitLength)
+			got, err := rb.ReadString("", tt.args.bitLength, "utf-8")
 			if (err != nil) != tt.wantErr {
 				t.Errorf("ReadString() error = %v, wantErr %v", err, tt.wantErr)
 				return
diff --git a/plc4go/spi/utils/ReadBufferJsonBased.go b/plc4go/spi/utils/ReadBufferJsonBased.go
index 5d4dad0a4..fb812ec95 100644
--- a/plc4go/spi/utils/ReadBufferJsonBased.go
+++ b/plc4go/spi/utils/ReadBufferJsonBased.go
@@ -406,7 +406,7 @@ func (j *jsonReadBuffer) ReadBigFloat(logicalName string, bitLength uint8, reade
 	}
 }
 
-func (j *jsonReadBuffer) ReadString(logicalName string, bitLength uint32, readerArgs ...WithReaderArgs) (string, error) {
+func (j *jsonReadBuffer) ReadString(logicalName string, bitLength uint32, encoding string, readerArgs ...WithReaderArgs) (string, error) {
 	if j.err != nil {
 		return "", j.err
 	}
diff --git a/plc4go/spi/utils/ReadBufferXmlBased.go b/plc4go/spi/utils/ReadBufferXmlBased.go
index 4933e768f..b0d7cab38 100644
--- a/plc4go/spi/utils/ReadBufferXmlBased.go
+++ b/plc4go/spi/utils/ReadBufferXmlBased.go
@@ -264,7 +264,7 @@ func (x *xmlReadBuffer) ReadBigFloat(logicalName string, bitLength uint8, reader
 	return &value, nil
 }
 
-func (x *xmlReadBuffer) ReadString(logicalName string, bitLength uint32, readerArgs ...WithReaderArgs) (string, error) {
+func (x *xmlReadBuffer) ReadString(logicalName string, bitLength uint32, encoding string, readerArgs ...WithReaderArgs) (string, error) {
 	var value string
 	// TODO: bitlength too short
 	err := x.decode(logicalName, rwStringKey, uint(bitLength), readerArgs, &value)
diff --git a/plc4go/spi/values/CHAR.go b/plc4go/spi/values/CHAR.go
index 5d2164eb1..b0f9f8f0d 100644
--- a/plc4go/spi/values/CHAR.go
+++ b/plc4go/spi/values/CHAR.go
@@ -28,17 +28,17 @@ import (
 type PlcCHAR struct {
 	PlcSimpleValueAdapter
 	// TODO: Why is this a byte-array?
-	value []byte
+	value string
 }
 
-func NewPlcCHAR(value uint8) PlcCHAR {
+func NewPlcCHAR(value string) PlcCHAR {
 	return PlcCHAR{
-		value: []byte{value},
+		value: value,
 	}
 }
 
 func (m PlcCHAR) GetRaw() []byte {
-	return m.value
+	return []byte(m.value)
 }
 
 func (m PlcCHAR) IsString() bool {
@@ -46,7 +46,7 @@ func (m PlcCHAR) IsString() bool {
 }
 
 func (m PlcCHAR) GetString() string {
-	return string(m.value)
+	return m.value
 }
 
 func (m PlcCHAR) GetPlcValueType() apiValues.PlcValueType {
@@ -54,9 +54,9 @@ func (m PlcCHAR) GetPlcValueType() apiValues.PlcValueType {
 }
 
 func (m PlcCHAR) Serialize(writeBuffer utils.WriteBuffer) error {
-	return writeBuffer.WriteString("PlcBYTE", 16, "UTF-8", string(m.value))
+	return writeBuffer.WriteString("PlcCHAR", 8, "UTF-8", m.value)
 }
 
 func (m PlcCHAR) String() string {
-	return fmt.Sprintf("%s(%dbit):%v", m.GetPlcValueType(), 16, m.value)
+	return fmt.Sprintf("%s(%dbit):%v", m.GetPlcValueType(), 8, m.value)
 }
diff --git a/plc4go/spi/values/IEC61131ValueHandler.go b/plc4go/spi/values/IEC61131ValueHandler.go
index 190c25287..c6da3aa47 100644
--- a/plc4go/spi/values/IEC61131ValueHandler.go
+++ b/plc4go/spi/values/IEC61131ValueHandler.go
@@ -380,44 +380,32 @@ func (m IEC61131ValueHandler) NewPlcValueFromType(typeName string, value interfa
 
 	// Chars and Strings
 	case IEC61131_CHAR:
-		if isString {
-			return nil, errors.New("string to IEC61131_CHAR conversion not implemented")
+		if !isString {
+			return nil, errors.New("non-string to IEC61131_CHAR conversion not implemented")
+		} else if len(stringValue) > 1 {
+			return nil, errors.New("IEC61131_CHAR can only contain one character")
 		} else {
-			casted, ok := value.(uint8)
-			if !ok {
-				return nil, errors.New("couldn't cast value of type " + reflect.TypeOf(value).Name() + " to uint8")
-			}
-			return NewPlcCHAR(casted), nil
+			return NewPlcCHAR(stringValue), nil
 		}
 	case IEC61131_WCHAR:
-		if isString {
-			return nil, errors.New("string to IEC61131_WCHAR conversion not implemented")
+		if !isString {
+			return nil, errors.New("non-string to IEC61131_WCHAR conversion not implemented")
+		} else if len(stringValue) > 1 {
+			return nil, errors.New("IEC61131_WCHAR can only contain one character")
 		} else {
-			casted, ok := value.(uint16)
-			if !ok {
-				return nil, errors.New("couldn't cast value of type " + reflect.TypeOf(value).Name() + " to uint16")
-			}
-			return NewPlcWCHAR(casted), nil
+			return NewPlcWCHAR(stringValue), nil
 		}
 	case IEC61131_STRING:
-		if isString {
-			return NewPlcSTRING(stringValue), nil
+		if !isString {
+			return nil, errors.New("non-string to IEC61131_STRING conversion not implemented")
 		} else {
-			/*casted, ok := value.([]uint8)
-			  if !ok {
-			  	return nil, errors.New("couldn't cast value of type " + reflect.TypeOf(value).Name() + " to []uint8")
-			  }
-			  return NewPlcSTRING(casted), nil*/
+			return NewPlcSTRING(stringValue), nil
 		}
 	case IEC61131_WSTRING:
-		if isString {
-			return NewPlcSTRING(stringValue), nil
+		if !isString {
+			return nil, errors.New("non-string to IEC61131_WSTRING conversion not implemented")
 		} else {
-			casted, ok := value.([]uint16)
-			if !ok {
-				return nil, errors.New("couldn't cast value of type " + reflect.TypeOf(value).Name() + " to []uint16")
-			}
-			return NewPlcWSTRING(casted), nil
+			return NewPlcSTRING(stringValue), nil
 		}
 	}
 
diff --git a/plc4go/spi/values/WCHAR.go b/plc4go/spi/values/WCHAR.go
index e67076ae3..35835ff4b 100644
--- a/plc4go/spi/values/WCHAR.go
+++ b/plc4go/spi/values/WCHAR.go
@@ -23,17 +23,16 @@ import (
 	"fmt"
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"unicode/utf16"
 )
 
 type PlcWCHAR struct {
 	PlcSimpleValueAdapter
-	value []rune
+	value string
 }
 
-func NewPlcWCHAR(value uint16) PlcWCHAR {
+func NewPlcWCHAR(value string) PlcWCHAR {
 	return PlcWCHAR{
-		value: utf16.Decode([]uint16{value}),
+		value: value,
 	}
 }
 
@@ -56,9 +55,9 @@ func (m PlcWCHAR) GetPlcValueType() apiValues.PlcValueType {
 }
 
 func (m PlcWCHAR) Serialize(writeBuffer utils.WriteBuffer) error {
-	return writeBuffer.WriteString("PlcSTRING", uint32(len(m.value)*8), "UTF-8", string(m.value))
+	return writeBuffer.WriteString("PlcWCHAR", uint32(16), "UTF-16", string(m.value))
 }
 
 func (m PlcWCHAR) String() string {
-	return fmt.Sprintf("%s(%dbit):%v", m.GetPlcValueType(), uint32(len(m.value)*8), m.value)
+	return fmt.Sprintf("%s(%dbit):%v", m.GetPlcValueType(), uint32(8), m.value)
 }
diff --git a/plc4go/spi/values/WSTRING.go b/plc4go/spi/values/WSTRING.go
index 8dd49267f..ba1f07136 100644
--- a/plc4go/spi/values/WSTRING.go
+++ b/plc4go/spi/values/WSTRING.go
@@ -23,17 +23,16 @@ import (
 	"fmt"
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"unicode/utf16"
 )
 
 type PlcWSTRING struct {
 	PlcSimpleValueAdapter
-	value []rune
+	value string
 }
 
-func NewPlcWSTRING(value []uint16) PlcWSTRING {
+func NewPlcWSTRING(value string) PlcWSTRING {
 	return PlcWSTRING{
-		value: utf16.Decode(value),
+		value: value,
 	}
 }
 
diff --git a/plc4go/spi/values/value_combination_test.go b/plc4go/spi/values/value_combination_test.go
index 13de19483..b913a1d3c 100644
--- a/plc4go/spi/values/value_combination_test.go
+++ b/plc4go/spi/values/value_combination_test.go
@@ -75,9 +75,7 @@ func TestCombinations(t *testing.T) {
 		{
 			name: apiValues.CHAR,
 			arguments: []apiValues.PlcValue{
-				NewPlcCHAR(0),
-				NewPlcCHAR(64),
-				NewPlcCHAR(255),
+				NewPlcCHAR(""),
 			},
 		},
 		{
@@ -280,10 +278,7 @@ func TestCombinations(t *testing.T) {
 		{
 			name: apiValues.WCHAR,
 			arguments: []apiValues.PlcValue{
-				NewPlcWCHAR(0),
-				NewPlcWCHAR(64),
-				NewPlcWCHAR(255),
-				NewPlcWCHAR(math.MaxUint16),
+				NewPlcWCHAR("a"),
 			},
 		},
 		{
@@ -298,7 +293,7 @@ func TestCombinations(t *testing.T) {
 		{
 			name: apiValues.WSTRING,
 			arguments: []apiValues.PlcValue{
-				NewPlcWSTRING([]uint16{0, 64, 255}),
+				NewPlcWSTRING("hurz"),
 			},
 		},
 	}
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
index 077787239..28bf8ac3e 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
@@ -808,7 +808,13 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                     String propertyName = child.getPropertyName();
                     AdsDataTypeTableEntry propertyDataTypeTableEntry = dataTypeTable.get(child.getDataTypeName());
                     PlcValueType propertyPlcValueType = getPlcValueTypeForAdsDataType(propertyDataTypeTableEntry);
-                    PlcValue propertyValue = parsePlcValue(propertyPlcValueType, propertyDataTypeTableEntry, stringLength, readBuffer);
+                    int strLen = 0;
+                    if ((propertyPlcValueType == PlcValueType.STRING) || (propertyPlcValueType == PlcValueType.WSTRING)) {
+                        String dataTypeName = propertyDataTypeTableEntry.getDataTypeName();
+                        // Extract the string length from the data type name.
+                        strLen = Integer.parseInt(dataTypeName.substring(dataTypeName.indexOf("(") + 1, dataTypeName.indexOf(")")));
+                    }
+                    PlcValue propertyValue = parsePlcValue(propertyPlcValueType, propertyDataTypeTableEntry, strLen, readBuffer);
                     properties.put(propertyName, propertyValue);
                     curPos = readBuffer.getPos() - startPos;
                 }
diff --git a/plc4net/drivers/knxnetip/src/drivers/knxnetip/readwrite/model/KnxDatapoint.cs b/plc4net/drivers/knxnetip/src/drivers/knxnetip/readwrite/model/KnxDatapoint.cs
index d8506f5bb..353d74aae 100644
--- a/plc4net/drivers/knxnetip/src/drivers/knxnetip/readwrite/model/KnxDatapoint.cs
+++ b/plc4net/drivers/knxnetip/src/drivers/knxnetip/readwrite/model/KnxDatapoint.cs
@@ -257,7 +257,7 @@ if( datapointType == KnxDatapointType.BOOL ) { // BOOL
                 }
 
                 // Simple Field (value)
-                var value = readBuffer.ReadByte("", 8);
+                var value = readBuffer.ReadString("", 8, System.Text.Encoding.GetEncoding("UTF-8"));
 
                 return new PlcCHAR(Convert.ToChar(value));
             } else if( datapointType == KnxDatapointType.WCHAR ) { // WCHAR
@@ -271,7 +271,7 @@ if( datapointType == KnxDatapointType.BOOL ) { // BOOL
                 }
 
                 // Simple Field (value)
-                var value = readBuffer.ReadUshort("", 16);
+                var value = readBuffer.ReadString("", 16, System.Text.Encoding.GetEncoding("UTF-16"));
 
                 return new PlcWCHAR(Convert.ToChar(value));
             } else if( datapointType == KnxDatapointType.TIME ) { // TIME
@@ -6673,8 +6673,8 @@ if( datapointType == KnxDatapointType.BOOL ) { // BOOL
                 // Reserved Field
                 writeBuffer.WriteByte("", 8, (byte) 0x00);
                 // Simple Field (value)
-                var value = (byte) _value.GetByte();
-                writeBuffer.WriteByte("", 8, (byte) (value));
+                var value = (string) _value.GetString();
+                writeBuffer.WriteString("", 8, "UTF-8", (string) (value));
             return writeBuffer;
         } else if( datapointType == KnxDatapointType.WCHAR ) { // WCHAR
                 var writeBuffer = new WriteBuffer();
@@ -6682,8 +6682,8 @@ if( datapointType == KnxDatapointType.BOOL ) { // BOOL
                 // Reserved Field
                 writeBuffer.WriteByte("", 8, (byte) 0x00);
                 // Simple Field (value)
-                var value = (ushort) _value.GetUshort();
-                writeBuffer.WriteUshort("", 16, (ushort) (value));
+                var value = (string) _value.GetString();
+                writeBuffer.WriteString("", 16, "UTF-16", (string) (value));
             return writeBuffer;
         } else if( datapointType == KnxDatapointType.TIME ) { // TIME
                 var writeBuffer = new WriteBuffer();
diff --git a/protocols/ads/src/main/resources/protocols/ads/ads.mspec b/protocols/ads/src/main/resources/protocols/ads/ads.mspec
index 284835ac0..e3f458cf6 100644
--- a/protocols/ads/src/main/resources/protocols/ads/ads.mspec
+++ b/protocols/ads/src/main/resources/protocols/ads/ads.mspec
@@ -408,6 +408,10 @@
         ['DWORD' BitString
             [simple uint 32 value]
         ]
+        // 8 byte (64 bit)
+        ['LWORD' BitString
+            [simple uint 64 value]
+        ]
 
         // -----------------------------------------
         // Integers
@@ -454,17 +458,17 @@
         // -----------------------------------------
         // Characters & Strings
         // -----------------------------------------
-        ['CHAR' STRING
-            [simple string 8 value]
+        ['CHAR' CHAR
+            [simple   string 8                       value    encoding='"UTF-8"'   ]
         ]
-        ['WCHAR' STRING
-            [simple string 16 value encoding='"UTF-16LE"']
+        ['WCHAR' WCHAR
+            [simple   string 16                      value    encoding='"UTF-16LE"']
         ]
         ['STRING' STRING
-            [simple   vstring 'stringLength * 8' value ]
-            [reserved uint 8                    '0x00']
+            [simple   vstring 'stringLength * 8'     value    encoding='"UTF-8"'   ]
+            [reserved uint 8                         '0x00'                        ]
         ]
-        ['WSTRING' STRING
+        ['WSTRING' WSTRING
             [simple   vstring 'stringLength * 8 * 2' value    encoding='"UTF-16LE"']
             [reserved uint 16                        '0x0000'                      ]
         ]
diff --git a/protocols/knxnetip/src/main/xslt/knx-types.xsl b/protocols/knxnetip/src/main/xslt/knx-types.xsl
index fee67cf21..6aa3a7007 100644
--- a/protocols/knxnetip/src/main/xslt/knx-types.xsl
+++ b/protocols/knxnetip/src/main/xslt/knx-types.xsl
@@ -177,11 +177,11 @@
         ]
         ['CHAR' CHAR
             [reserved uint 8    '0x00']
-            [simple   uint 8    value ]
+            [simple   string 8  value  encoding='"UTF-8"']
         ]
         ['WCHAR' WCHAR
             [reserved uint 8    '0x00']
-            [simple   uint 16   value ]
+            [simple   string 16 value  encoding='"UTF-16"']
         ]
         //['STRING' STRING
         //]
diff --git a/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec b/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec
index 1857a18e4..2ff7f748d 100644
--- a/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec
+++ b/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec
@@ -399,16 +399,16 @@
             [array float 64 value count 'numberOfValues']
         ]
         ['CHAR','1' CHAR
-            [simple uint 8 value]
+            [simple string 8 value encoding='"UTF-8"']
         ]
         ['CHAR' List
-            [array uint 8 value count 'numberOfValues']
+            [array string 8 value count 'numberOfValues' encoding='"UTF-8"']
         ]
         ['WCHAR','1' WCHAR
-            [simple uint 16 value]
+            [simple string 16 value encoding='"UTF-16"']
         ]
         ['WCHAR' List
-            [array uint 16 value count 'numberOfValues']
+            [array string 16 value count 'numberOfValues' encoding='"UTF-16"']
         ]
     ]
 ]
diff --git a/protocols/s7/src/main/resources/protocols/s7/s7.mspec b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
index cd54cf8b4..0a04787bd 100644
--- a/protocols/s7/src/main/resources/protocols/s7/s7.mspec
+++ b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
@@ -597,14 +597,14 @@
         // Characters & Strings
         // -----------------------------------------
         ['"IEC61131_CHAR"' CHAR
-            [manual string 8 value  'STATIC_CALL("parseS7Char", readBuffer, _type.encoding)' 'STATIC_CALL("serializeS7Char", writeBuffer, _value, _type.encoding)' '8']
+            [simple string 8 value encoding='"UTF-8"']
         ]
         ['"IEC61131_WCHAR"' CHAR
-            [manual string 16 value 'STATIC_CALL("parseS7Char", readBuffer, _type.encoding)' 'STATIC_CALL("serializeS7Char", writeBuffer, _value, _type.encoding)' '16' encoding='"UTF-16"']
+            [simple string 16 value encoding='"UTF-16"']
         ]
         ['"IEC61131_STRING"' STRING
             // TODO: Fix this length
-            [manual vstring value  'STATIC_CALL("parseS7String", readBuffer, stringLength, _type.encoding)' 'STATIC_CALL("serializeS7String", writeBuffer, _value, stringLength, _type.encoding)' 'STR_LEN(_value) + 2']
+            [manual vstring value  'STATIC_CALL("parseS7String", readBuffer, stringLength, _type.encoding)' 'STATIC_CALL("serializeS7String", writeBuffer, _value, stringLength, _type.encoding)' 'STR_LEN(_value) + 2' encoding='"UTF-8"']
         ]
         ['"IEC61131_WSTRING"' STRING
             // TODO: Fix this length
diff --git a/protocols/simulated/src/main/resources/protocols/simulated/simulated.mspec b/protocols/simulated/src/main/resources/protocols/simulated/simulated.mspec
index edaa137a8..b5e303e13 100644
--- a/protocols/simulated/src/main/resources/protocols/simulated/simulated.mspec
+++ b/protocols/simulated/src/main/resources/protocols/simulated/simulated.mspec
@@ -116,22 +116,22 @@
             [array float 64 value count 'numberOfValues']
         ]
         ['"CHAR"','1' CHAR
-            [simple uint 8 value]
+            [simple string 8 value encoding='"UTF-8"']
         ]
         ['"CHAR"' List
-            [array uint 8 value count 'numberOfValues']
+            [array string 8 value count 'numberOfValues' encoding='"UTF-8"']
         ]
         ['"WCHAR"','1' WCHAR
-            [simple uint 16 value]
+            [simple string 16 value encoding='"UTF-16"']
         ]
         ['"WCHAR"' List
-            [array uint 16 value count 'numberOfValues']
+            [array string 16 value count 'numberOfValues' encoding='"UTF-16"']
         ]
         ['"STRING"' STRING
-            [simple string 255 value]
+            [simple string 255 value encoding='"UTF-8"']
         ]
         ['"WSTRING"' STRING
-            [simple string 255 value]
+            [simple string 255 value encoding='"UTF-16"']
         ]
     ]
 ]