You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by hu...@apache.org on 2020/10/29 11:14:12 UTC

[plc4x] branch backportvaluehandler created (now b85b67b)

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

hutcheb pushed a change to branch backportvaluehandler
in repository https://gitbox.apache.org/repos/asf/plc4x.git.


      at b85b67b  started to backport

This branch includes the following new commits:

     new b85b67b  started to backport

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[plc4x] 01/01: started to backport

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit b85b67b8d95aea25744407eaa5b3f2bbce52e68b
Author: hutcheb <be...@gmail.com>
AuthorDate: Thu Oct 29 07:02:04 2020 -0400

    started to backport
---
 .../resources/templates/java/data-io-template.ftlh |    2 +-
 .../plc4x/java/api/messages/PlcWriteRequest.java   |   43 +-
 .../org/apache/plc4x/java/api/model/PlcField.java  |    2 +-
 .../plc4x/java/api/value/IEC61131ValueHandler.java |  174 ++
 .../org/apache/plc4x/java/api/value/PlcBOOL.java   |   24 +
 .../org/apache/plc4x/java/api/value/PlcBYTE.java   |   24 +
 .../org/apache/plc4x/java/api/value/PlcCHAR.java   |   24 +
 .../org/apache/plc4x/java/api/value/PlcDINT.java   |   24 +
 .../org/apache/plc4x/java/api/value/PlcDWORD.java  |   24 +
 .../org/apache/plc4x/java/api/value/PlcINT.java    |   24 +
 .../org/apache/plc4x/java/api/value/PlcLINT.java   |   24 +
 .../org/apache/plc4x/java/api/value/PlcLREAL.java  |   24 +
 .../org/apache/plc4x/java/api/value/PlcLWORD.java  |   24 +
 .../org/apache/plc4x/java/api/value/PlcList.java   |   22 +-
 .../org/apache/plc4x/java/api/value/PlcREAL.java   |   24 +
 .../org/apache/plc4x/java/api/value/PlcSINT.java   |   24 +
 .../org/apache/plc4x/java/api/value/PlcSTRING.java |    8 +
 .../org/apache/plc4x/java/api/value/PlcUDINT.java  |   24 +
 .../org/apache/plc4x/java/api/value/PlcUINT.java   |   24 +
 .../org/apache/plc4x/java/api/value/PlcULINT.java  |   24 +
 .../org/apache/plc4x/java/api/value/PlcUSINT.java  |   24 +
 .../plc4x/java/api/value/PlcValueHandler.java      |   44 +
 .../org/apache/plc4x/java/api/value/PlcValues.java |  382 +---
 .../org/apache/plc4x/java/api/value/PlcWCHAR.java  |   24 +
 .../org/apache/plc4x/java/api/value/PlcWORD.java   |   24 +
 .../apache/plc4x/java/api/types/PlcValueTest.java  |   53 -
 .../apache/plc4x/java/api/value/PlcValuesTest.java |   51 -
 .../org/apache/plc4x/java/abeth/AbEthDriver.java   |    7 +
 .../java/abeth/protocol/AbEthProtocolLogic.java    |   14 +-
 .../java/abeth/protocol/Plc4xAbEthProtocol.java    |   14 +-
 .../org/apache/plc4x/java/ads/ADSPlcDriver.java    |    7 +
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  |    2 +-
 .../attic/protocol/util/LittleEndianDecoder.java   |   58 +-
 .../apache/plc4x/java/eip/readwrite/EIPDriver.java |    7 +
 .../java/firmata/readwrite/FirmataDriver.java      |    7 +
 .../apache/plc4x/java/knxnetip/KnxNetIpDriver.java |    7 +
 .../org/apache/plc4x/java/modbus/ModbusDriver.java |    7 +
 .../apache/plc4x/java/s7/readwrite/S7Driver.java   |    7 +
 .../s7/readwrite/protocol/S7ProtocolLogic.java     |    4 +-
 .../java/s7/readwrite/value/S7ValueHandler.java    |   51 +
 .../java/simulated/connection/SimulatedDevice.java |   18 +-
 .../java/spi/connection/AbstractPlcConnection.java |   12 +-
 .../spi/connection/DefaultNettyPlcConnection.java  |    5 +-
 .../spi/connection/DefaultPlcFieldHandler.java     | 2017 --------------------
 .../java/spi/connection/GeneratedDriverBase.java   |    4 +
 .../plc4x/java/spi/connection/PlcFieldHandler.java |   26 -
 .../java/spi/messages/DefaultPlcWriteRequest.java  |  177 +-
 .../java/opm/PlcEntityManagerComplexTest.java      |  113 +-
 .../apache/plc4x/java/bacnetip/BacNetIpDriver.java |    5 +
 .../bacnetip/protocol/BacNetIpProtocolLogic.java   |    8 +-
 .../org/apache/plc4x/java/df1/DF1PlcDriver.java    |    5 +
 .../plc4x/java/df1/field/Df1FieldHandler.java      |    6 -
 52 files changed, 879 insertions(+), 2898 deletions(-)

diff --git a/build-utils/language-java/src/main/resources/templates/java/data-io-template.ftlh b/build-utils/language-java/src/main/resources/templates/java/data-io-template.ftlh
index 1c63222..9291fdc 100644
--- a/build-utils/language-java/src/main/resources/templates/java/data-io-template.ftlh
+++ b/build-utils/language-java/src/main/resources/templates/java/data-io-template.ftlh
@@ -216,7 +216,7 @@ public class ${type.name}IO {
             <#if case.name == "Struct">
             Map<String, PlcValue> _map = new HashMap<>();
                 <#list case.fields as field>
-            _map.put("${field.name}", PlcValues.of(${field.name}));
+            _map.put("${field.name}", IEC61131ValueHandler.newPlcValue(${field.name}));
                 </#list>
             </#if>
             <#if !skipReturn>
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcWriteRequest.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcWriteRequest.java
index df0b833..ebd789b 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcWriteRequest.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcWriteRequest.java
@@ -39,47 +39,8 @@ public interface PlcWriteRequest extends PlcFieldRequest {
         @Override
         PlcWriteRequest build();
 
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, Boolean... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, Boolean... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, Byte... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, Byte... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, Short... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, Short... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, Integer... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, Integer... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, BigInteger... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, BigInteger... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, Long... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, Long... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, Float... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, Float... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, Double... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, Double... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, BigDecimal... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, BigDecimal... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, String... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, String... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, LocalTime... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, LocalTime... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, LocalDate... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, LocalDate... values);
-
-        PlcWriteRequest.Builder addItem(String name, String fieldQuery, LocalDateTime... values);
-        PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, LocalDateTime... values);
-
-        <T> PlcWriteRequest.Builder addItem(String name, String fieldQuery, T... values);
-        <T> PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, T... values);
+        <T> PlcWriteRequest.Builder addItem(String name, String fieldQuery, Object... values);
+        <T> PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, Object... values);
     }
 
 }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcField.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcField.java
index 74a1527..bc2e73d 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcField.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcField.java
@@ -55,7 +55,7 @@ public interface PlcField {
 
     /**
      * Returns the "datatype" of the response one can expect from this field.
-     * I.e. The mapping between this string and the PlcValue datatype is handled in the FieldHandler class.
+     * I.e. The mapping between this string and the PlcValue datatype is handled in the Valuehandler class.
      *
      * The contract is to return a String description of the datatype. This doesn't necessarily
      * define the PlcValue type but should be related.
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/IEC61131ValueHandler.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/IEC61131ValueHandler.java
new file mode 100644
index 0000000..5f1b013
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/IEC61131ValueHandler.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.api.value;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException;
+import org.apache.plc4x.java.api.model.PlcField;
+
+import java.math.BigInteger;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.nio.charset.StandardCharsets;
+import java.util.BitSet;
+import java.util.LinkedList;
+import java.util.List;
+
+
+public class IEC61131ValueHandler implements PlcValueHandler {
+
+
+    public PlcValue of(Object value) {
+        return newPlcValue(new Object[] {value});
+    }
+
+    public PlcValue of(Object[] values) {
+        return newPlcValue(values);
+    }
+
+    public static PlcValue newPlcValue(Object value) {
+        return newPlcValue(new Object[] {value});
+    }
+
+
+    public static PlcValue newPlcValue(Object[] values) {
+        if (values.length == 1) {
+            Object value = values[0];
+            if (value instanceof Boolean) {
+                return PlcBOOL.of(value);
+            } else if (value instanceof Byte) {
+                return PlcSINT.of(value);
+            } else if (value instanceof Short) {
+                return PlcINT.of(value);
+            } else if (value instanceof Integer) {
+                return PlcDINT.of(value);
+            } else if (value instanceof Long) {
+                return PlcLINT.of(value);
+            } else if (value instanceof BigInteger) {
+                return new PlcBigInteger((BigInteger) value);
+            } else if (value instanceof Float) {
+                return PlcREAL.of(value);
+            } else if (value instanceof Double) {
+                return PlcLREAL.of(value);
+            } else if (value instanceof BigDecimal) {
+                return new PlcBigDecimal((BigDecimal) value);
+            } else if (value instanceof LocalTime) {
+                return new PlcTime((LocalTime) value);
+            } else if (value instanceof LocalDate) {
+                return new PlcDate((LocalDate) value);
+            } else if (value instanceof LocalDateTime) {
+                return new PlcDateTime((LocalDateTime) value);
+            } else {
+                throw new PlcUnsupportedDataTypeException("Data Type " + value.getClass()
+                    + "Is not supported");
+            }
+        } else {
+            PlcList list = new PlcList();
+            for (Object value : values) {
+                list.add(newPlcValue(new Object[] {value}));
+            }
+            return list;
+        }
+    }
+
+
+    public static PlcValue newPlcValue(PlcField field, Object value) {
+        return newPlcValue(field, new Object[] {value});
+    }
+
+
+    public static PlcValue newPlcValue(PlcField field, Object[] values) {
+        if(values.length == 1) {
+            Object value = values[0];
+            switch (field.getPlcDataType().toUpperCase()) {
+                case "IEC61131_BOOL":
+                case "IEC61131_BIT":
+                    return PlcBOOL.of(value);
+                case "IEC61131_BYTE":
+                case "IEC61131_BITARR8":
+                    return PlcBYTE.of(value);
+                case "IEC61131_SINT":
+                case "IEC61131_INT8":
+                    return PlcSINT.of(value);
+                case "IEC61131_USINT":
+                case "IEC61131_UINT8":
+                case "IEC61131_BIT8":
+                    return PlcUSINT.of(value);
+                case "IEC61131_INT":
+                case "IEC61131_INT16":
+                    return PlcINT.of(value);
+                case "IEC61131_UINT":
+                case "IEC61131_UINT16":
+                    return PlcUINT.of(value);
+                case "IEC61131_WORD":
+                case "IEC61131_BITARR16":
+                    return PlcWORD.of(value);
+                case "IEC61131_DINT":
+                case "IEC61131_INT32":
+                    return PlcDINT.of(value);
+                case "IEC61131_UDINT":
+                case "IEC61131_UINT32":
+                    return PlcUDINT.of(value);
+                case "IEC61131_DWORD":
+                case "IEC61131_BITARR32":
+                    return PlcDWORD.of(value);
+                case "IEC61131_LINT":
+                case "IEC61131_INT64":
+                    return PlcLINT.of(value);
+                case "IEC61131_ULINT":
+                case "IEC61131_UINT64":
+                    return PlcULINT.of(value);
+                case "IEC61131_LWORD":
+                case "IEC61131_BITARR64":
+                    return PlcLWORD.of(value);
+                case "IEC61131_REAL":
+                case "IEC61131_FLOAT":
+                    return PlcREAL.of(value);
+                case "IEC61131_LREAL":
+                case "IEC61131_DOUBLE":
+                    return PlcLREAL.of(value);
+                case "IEC61131_CHAR":
+                    return PlcCHAR.of(value);
+                case "IEC61131_WCHAR":
+                    return PlcWCHAR.of(value);
+                case "IEC61131_STRING":
+                    return PlcSTRING.of(value);
+                case "IEC61131_WSTRING":
+                case "IEC61131_STRING16":
+                    return PlcSTRING.of(value);
+                default:
+                    return customDataType(field, new Object[] {value});
+            }
+        } else {
+            PlcList list = new PlcList();
+            for (Object value : values) {
+                list.add(newPlcValue(field, new Object[] {value}));
+            }
+            return list;
+        }
+    }
+
+    public static PlcValue customDataType(PlcField field, Object[] values) {
+        throw new PlcUnsupportedDataTypeException("Data Type " + field.getPlcDataType()
+            + "Is not supported");
+    }
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBOOL.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBOOL.java
index e197c3d..022087f 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBOOL.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBOOL.java
@@ -34,6 +34,30 @@ public class PlcBOOL extends PlcIECValue<Boolean> {
     static int minValue = 0;
     static int maxValue = 1;
 
+    public static PlcBOOL of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcBOOL((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcBOOL((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcBOOL((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcBOOL((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcBOOL((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcBOOL((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcBOOL((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcBOOL((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcBOOL((BigDecimal) value);
+        } else {
+            return new PlcBOOL((String) value);
+        }
+    }
+
     public PlcBOOL(Boolean value) {
         super();
         this.value = value;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBYTE.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBYTE.java
index 47c801e..d3298e3 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBYTE.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBYTE.java
@@ -35,6 +35,30 @@ public class PlcBYTE extends PlcIECValue<Short> {
     static Short minValue = 0;
     static Short maxValue = (short) Byte.MAX_VALUE * 2 + 1;
 
+    public static PlcBYTE of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcBYTE((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcBYTE((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcBYTE((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcBYTE((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcBYTE((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcBYTE((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcBYTE((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcBYTE((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcBYTE((BigDecimal) value);
+        } else {
+            return new PlcBYTE((String) value);
+        }
+    }
+
     public PlcBYTE(Boolean value) {
         super();
         this.value = value ? Short.valueOf((short) 1) : Short.valueOf((short) 0);
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcCHAR.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcCHAR.java
index 2f62f00..fa1fd74 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcCHAR.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcCHAR.java
@@ -38,6 +38,30 @@ public class PlcCHAR extends PlcIECValue<Short> {
     static Short minValue = 0;
     static Short maxValue = (short) Byte.MAX_VALUE * 2 + 1;
 
+    public static PlcCHAR of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcCHAR((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcCHAR((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcCHAR((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcCHAR((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcCHAR((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcCHAR((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcCHAR((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcCHAR((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcCHAR((BigDecimal) value);
+        } else {
+            return new PlcCHAR((String) value);
+        }
+    }
+
     public PlcCHAR(Boolean value) {
         super();
         this.value = value ? Short.valueOf((short) 1) : Short.valueOf((short) 0);
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDINT.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDINT.java
index 2858162..62b85aa 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDINT.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDINT.java
@@ -34,6 +34,30 @@ public class PlcDINT extends PlcIECValue<Integer> {
     static Integer minValue = Integer.MIN_VALUE;
     static Integer maxValue = Integer.MAX_VALUE;
 
+    public static PlcDINT of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcDINT((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcDINT((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcDINT((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcDINT((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcDINT((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcDINT((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcDINT((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcDINT((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcDINT((BigDecimal) value);
+        } else {
+            return new PlcDINT((String) value);
+        }
+    }
+
     public PlcDINT(Boolean value) {
         super();
         this.value = value ? 1 : 0;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDWORD.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDWORD.java
index 67bf9d3..a3cbc4b 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDWORD.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDWORD.java
@@ -35,6 +35,30 @@ public class PlcDWORD extends PlcIECValue<Long> {
     static Long minValue = (long) 0;
     static Long maxValue = (long) Integer.MAX_VALUE * 2 + 1;
 
+    public static PlcDWORD of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcDWORD((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcDWORD((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcDWORD((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcDWORD((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcDWORD((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcDWORD((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcDWORD((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcDWORD((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcDWORD((BigDecimal) value);
+        } else {
+            return new PlcDWORD((String) value);
+        }
+    }
+
     public PlcDWORD(Boolean value) {
         super();
         this.value = value ? (long) 1 : (long) 0;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcINT.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcINT.java
index 89b3064..1e6e722 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcINT.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcINT.java
@@ -34,6 +34,30 @@ public class PlcINT extends PlcIECValue<Short> {
     static Short minValue = Short.MIN_VALUE;
     static Short maxValue = Short.MAX_VALUE;
 
+    public static PlcINT of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcINT((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcINT((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcINT((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcINT((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcINT((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcINT((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcINT((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcINT((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcINT((BigDecimal) value);
+        } else {
+            return new PlcINT((String) value);
+        }
+    }
+
     public PlcINT(Boolean value) {
         super();
         this.value = value ? Short.valueOf((short) 1) : Short.valueOf((short) 0);
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLINT.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLINT.java
index 4afbb1d..f188e4c 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLINT.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLINT.java
@@ -34,6 +34,30 @@ public class PlcLINT extends PlcIECValue<Long> {
     static Long minValue = (long) 0;
     static Long maxValue = Long.MAX_VALUE;
 
+    public static PlcLINT of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcLINT((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcLINT((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcLINT((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcLINT((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcLINT((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcLINT((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcLINT((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcLINT((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcLINT((BigDecimal) value);
+        } else {
+            return new PlcLINT((String) value);
+        }
+    }
+
     public PlcLINT(Boolean value) {
         super();
         this.value = value ? (long) 1 : (long) 0;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLREAL.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLREAL.java
index 097704d..31fd6c1 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLREAL.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLREAL.java
@@ -34,6 +34,30 @@ public class PlcLREAL extends PlcIECValue<Double> {
     static Double minValue = -Double.MAX_VALUE;
     static Double maxValue = Double.MAX_VALUE;
 
+    public static PlcLREAL of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcLREAL((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcLREAL((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcLREAL((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcLREAL((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcLREAL((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcLREAL((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcLREAL((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcLREAL((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcLREAL((BigDecimal) value);
+        } else {
+            return new PlcLREAL((String) value);
+        }
+    }
+
     public PlcLREAL(Boolean value) {
         super();
         this.value = value ? (Double) 1.0 : (Double) 0.0;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLWORD.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLWORD.java
index da502ae..0c0a7a4 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLWORD.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLWORD.java
@@ -33,6 +33,30 @@ public class PlcLWORD extends PlcIECValue<BigInteger> {
     static BigInteger minValue = BigInteger.valueOf(0);
     static BigInteger maxValue = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(2)).add(BigInteger.valueOf(1));
 
+    public static PlcLWORD of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcLWORD((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcLWORD((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcLWORD((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcLWORD((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcLWORD((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcLWORD((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcLWORD((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcLWORD((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcLWORD((BigDecimal) value);
+        } else {
+            return new PlcLWORD((String) value);
+        }
+    }
+
     public PlcLWORD(Boolean value) {
         super();
         this.value = value ? BigInteger.valueOf(1) : BigInteger.valueOf(0);
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcList.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcList.java
index 6a25d2e..8e912ec 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcList.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcList.java
@@ -26,26 +26,32 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.ArrayList;
 import java.util.stream.Collectors;
 
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
 public class PlcList extends PlcValueAdapter {
 
-    private final List<PlcValue> listItems;
+    private List<PlcValue> listItems;
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
-    public PlcList(@JsonProperty("listItems") List<?> listItems) {
+    public PlcList() {
+        listItems = new ArrayList<>();
+    }
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public PlcList(@JsonProperty("listItems") List<PlcValue> listItems) {
         List<PlcValue> safelist = listItems.stream().map(plcValue -> {
             // to avoid unwrapped list cause of type erasure
-            if (plcValue instanceof PlcValue) {
-                return (PlcValue) plcValue;
-            } else {
-                return PlcValues.of(plcValue);
-            }
+            return plcValue;
         }).collect(Collectors.toList());
         this.listItems = Collections.unmodifiableList(safelist);
     }
 
+    public void add(PlcValue value) {
+        listItems.add(value);        
+    }
+
     @Override
     public Object getObject() {
         return listItems;
@@ -71,7 +77,7 @@ public class PlcList extends PlcValueAdapter {
 
     @Override
     @JsonIgnore
-    public List<? extends PlcValue> getList() {
+    public List<PlcValue> getList() {
         return listItems;
     }
 
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcREAL.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcREAL.java
index 14cc345..945a3d8 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcREAL.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcREAL.java
@@ -34,6 +34,30 @@ public class PlcREAL extends PlcIECValue<Float> {
     static Float minValue = -Float.MAX_VALUE;
     static Float maxValue = Float.MAX_VALUE;
 
+    public static PlcREAL of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcREAL((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcREAL((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcREAL((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcREAL((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcREAL((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcREAL((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcREAL((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcREAL((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcREAL((BigDecimal) value);
+        } else {
+            return new PlcREAL((String) value);
+        }
+    }
+
     public PlcREAL(Boolean value) {
         super();
         this.value = value ? (Float) 1.0f : (Float) 0.0f;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSINT.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSINT.java
index 0e1bbe6..8288f30 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSINT.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSINT.java
@@ -34,6 +34,30 @@ public class PlcSINT extends PlcIECValue<Byte> {
     static Byte minValue = Byte.MIN_VALUE;
     static Byte maxValue = Byte.MAX_VALUE;
 
+    public static PlcSINT of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcSINT((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcSINT((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcSINT((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcSINT((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcSINT((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcSINT((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcSINT((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcSINT((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcSINT((BigDecimal) value);
+        } else {
+            return new PlcSINT((String) value);
+        }
+    }
+
     public PlcSINT(Boolean value) {
         super();
         this.value = value ? Byte.valueOf((byte) 1) : Byte.valueOf((byte) 0);
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSTRING.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSTRING.java
index 615825d..7ee4efc 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSTRING.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSTRING.java
@@ -32,6 +32,14 @@ public class PlcSTRING extends PlcSimpleValue<String> {
 
     static int maxLength = 254;
 
+    public static PlcSTRING of(Object value) {
+        if (value instanceof String) {
+            return new PlcSTRING((String) value);
+        } else {
+            return new PlcSTRING((String) value);
+        }
+    }
+
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
     public PlcSTRING(@JsonProperty("value") String value) {
         super(value, true);
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUDINT.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUDINT.java
index fba7c71..5f71bac 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUDINT.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUDINT.java
@@ -34,6 +34,30 @@ public class PlcUDINT extends PlcIECValue<Long> {
     static Long minValue = (long) 0;
     static Long maxValue = (long) Integer.MAX_VALUE * 2 + 1;
 
+    public static PlcUDINT of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcUDINT((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcUDINT((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcUDINT((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcUDINT((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcUDINT((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcUDINT((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcUDINT((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcUDINT((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcUDINT((BigDecimal) value);
+        } else {
+            return new PlcUDINT((String) value);
+        }
+    }
+
     public PlcUDINT(Boolean value) {
         super();
         this.value = value ? (long) 1 : (long) 0;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUINT.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUINT.java
index 3d68938..c86ccdf 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUINT.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUINT.java
@@ -34,6 +34,30 @@ public class PlcUINT extends PlcIECValue<Integer> {
     static Integer minValue = 0;
     static Integer maxValue = Short.MAX_VALUE * 2 + 1;
 
+    public static PlcUINT of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcUINT((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcUINT((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcUINT((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcUINT((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcUINT((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcUINT((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcUINT((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcUINT((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcUINT((BigDecimal) value);
+        } else {
+            return new PlcUINT((String) value);
+        }
+    }
+
     public PlcUINT(Boolean value) {
         super();
         this.value = value ? (Integer) 1 : (Integer) 0;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcULINT.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcULINT.java
index af4a158..1273bb4 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcULINT.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcULINT.java
@@ -32,6 +32,30 @@ public class PlcULINT extends PlcIECValue<BigInteger> {
     static BigInteger minValue = BigInteger.valueOf(0);
     static BigInteger maxValue = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(2)).add(BigInteger.valueOf(1));
 
+    public static PlcULINT of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcULINT((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcULINT((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcULINT((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcULINT((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcULINT((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcULINT((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcULINT((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcULINT((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcULINT((BigDecimal) value);
+        } else {
+            return new PlcULINT((String) value);
+        }
+    }
+
     public PlcULINT(Boolean value) {
         super();
         this.value = value ? BigInteger.valueOf(1) : BigInteger.valueOf(0);
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUSINT.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUSINT.java
index 7927414..3316c97 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUSINT.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUSINT.java
@@ -34,6 +34,30 @@ public class PlcUSINT extends PlcIECValue<Short> {
     static Short minValue = 0;
     static Short maxValue = (short) Byte.MAX_VALUE * 2 + 1;
 
+    public static PlcUSINT of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcUSINT((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcUSINT((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcUSINT((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcUSINT((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcUSINT((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcUSINT((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcUSINT((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcUSINT((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcUSINT((BigDecimal) value);
+        } else {
+            return new PlcUSINT((String) value);
+        }
+    }
+
     public PlcUSINT(Boolean value) {
         super();
         this.value = value ? Short.valueOf((short) 1) : Short.valueOf((short) 0);
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValueHandler.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValueHandler.java
new file mode 100644
index 0000000..a5f5893
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValueHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.api.value;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Base Valuehandler
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
+public interface PlcValueHandler {
+
+    public PlcValue of(Object value);
+    public PlcValue of(Object[] values);
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java
index f01027a..39e2eed 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java
@@ -39,387 +39,7 @@ import java.util.Map;
 public class PlcValues {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(PlcValues.class);
-
-    public static PlcValue of(Boolean b) {
-        return new PlcBOOL(b);
-    }
-
-    public static PlcValue of(boolean b) {
-        return new PlcBOOL(b);
-    }
-
-    public static PlcValue of(Boolean[] b) {
-        if(b != null) {
-            if(b.length == 1) {
-                return new PlcBOOL(b[0]);
-            } else if(b.length > 1) {
-                List<PlcBOOL> plcValues = new LinkedList<>();
-                for (int i = 0; i < b.length; i++) {
-                    plcValues.add(new PlcBOOL(b[i]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(boolean[] b) {
-        if(b != null) {
-            if(b.length == 1) {
-                return new PlcBOOL(b[0]);
-            } else if(b.length > 1) {
-                List<PlcBOOL> plcValues = new LinkedList<>();
-                for (int i = 0; i < b.length; i++) {
-                    plcValues.add(new PlcBOOL(b[i]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(Byte i) {
-        return new PlcSINT(i);
-    }
-
-    public static PlcValue of(byte i) {
-        return new PlcSINT(i);
-    }
-
-    public static PlcValue of(Byte[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcSINT(i[0]);
-            } else if(i.length > 1) {
-                List<PlcBYTE> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcBYTE(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(byte[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcSINT(i[0]);
-            } else if(i.length > 1) {
-                List<PlcBYTE> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcBYTE(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(Short i) {
-        return new PlcINT(i);
-    }
-
-    public static PlcValue of(short i) {
-        return new PlcINT(i);
-    }
-
-    public static PlcValue of(Short[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcINT(i[0]);
-            } else if(i.length > 1) {
-                List<PlcINT> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcINT(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(short[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcINT(i[0]);
-            } else if(i.length > 1) {
-                List<PlcINT> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcINT(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(Integer i) {
-        return new PlcDINT(i);
-    }
-
-    public static PlcValue of(int i) {
-        return new PlcDINT(i);
-    }
-
-    public static PlcValue of(Integer[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcDINT(i[0]);
-            } else if(i.length > 1) {
-                List<PlcDINT> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcDINT(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(int[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcDINT(i[0]);
-            } else if(i.length > 1) {
-                List<PlcDINT> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcDINT(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(Long i) {
-        return new PlcLINT(i);
-    }
-
-    public static PlcValue of(long i) {
-        return new PlcLINT(i);
-    }
-
-    public static PlcValue of(Long[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcLINT(i[0]);
-            } else if(i.length > 1) {
-                List<PlcLINT> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcLINT(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(long[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcLINT(i[0]);
-            } else if(i.length > 1) {
-                List<PlcLINT> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcLINT(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(BigInteger i) {
-        return new PlcBigInteger(i);
-    }
-
-    public static PlcValue of(BigInteger[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcBigInteger(i[0]);
-            } else if(i.length > 1) {
-                List<PlcBigInteger> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcBigInteger(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(Float i) {
-        return new PlcREAL(i);
-    }
-
-    public static PlcValue of(float i) {
-        return new PlcREAL(i);
-    }
-
-    public static PlcValue of(Float[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcREAL(i[0]);
-            } else if(i.length > 1) {
-                List<PlcREAL> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcREAL(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(float[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcREAL(i[0]);
-            } else if(i.length > 1) {
-                List<PlcREAL> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcREAL(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(Double i) {
-        return new PlcLREAL(i);
-    }
-
-    public static PlcValue of(double i) {
-        return new PlcLREAL(i);
-    }
-
-    public static PlcValue of(Double[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcLREAL(i[0]);
-            } else if(i.length > 1) {
-                List<PlcLREAL> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcLREAL(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(double[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcLREAL(i[0]);
-            } else if(i.length > 1) {
-                List<PlcLREAL> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcLREAL(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(BigDecimal i) {
-        return new PlcBigDecimal(i);
-    }
-
-    public static PlcValue of(BigDecimal[] i) {
-        if(i != null) {
-            if(i.length == 1) {
-                return new PlcBigDecimal(i[0]);
-            } else if(i.length > 1) {
-                List<PlcBigDecimal> plcValues = new LinkedList<>();
-                for (int j = 0; j < i.length; j++) {
-                    plcValues.add(new PlcBigDecimal(i[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(String s) {
-        return new PlcSTRING(s);
-    }
-
-    public static PlcValue of(String[] s) {
-        if(s != null) {
-            if(s.length == 1) {
-                return new PlcSTRING(s[0]);
-            } else if(s.length > 1) {
-                List<PlcSTRING> plcValues = new LinkedList<>();
-                for (int j = 0; j < s.length; j++) {
-                    plcValues.add(new PlcSTRING(s[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(LocalTime s) {
-        return new PlcTime(s);
-    }
-
-    public static PlcValue of(LocalTime[] s) {
-        if(s != null) {
-            if(s.length == 1) {
-                return new PlcTime(s[0]);
-            } else if(s.length > 1) {
-                List<PlcTime> plcValues = new LinkedList<>();
-                for (int j = 0; j < s.length; j++) {
-                    plcValues.add(new PlcTime(s[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(LocalDate s) {
-        return new PlcDate(s);
-    }
-
-    public static PlcValue of(LocalDate[] s) {
-        if(s != null) {
-            if(s.length == 1) {
-                return new PlcDate(s[0]);
-            } else if(s.length > 1) {
-                List<PlcDate> plcValues = new LinkedList<>();
-                for (int j = 0; j < s.length; j++) {
-                    plcValues.add(new PlcDate(s[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
-    public static PlcValue of(LocalDateTime s) {
-        return new PlcDateTime(s);
-    }
-
-    public static PlcValue of(LocalDateTime[] s) {
-        if(s != null) {
-            if(s.length == 1) {
-                return new PlcDateTime(s[0]);
-            } else if(s.length > 1) {
-                List<PlcDateTime> plcValues = new LinkedList<>();
-                for (int j = 0; j < s.length; j++) {
-                    plcValues.add(new PlcDateTime(s[j]));
-                }
-                return new PlcList(plcValues);
-            }
-        }
-        return null;
-    }
-
+    
     public static PlcValue of(List<PlcValue> list) {
         return new PlcList(list);
     }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWCHAR.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWCHAR.java
index a1c368e..ec7028e 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWCHAR.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWCHAR.java
@@ -34,6 +34,30 @@ public class PlcWCHAR extends PlcIECValue<Integer> {
     static Integer minValue = 0;
     static Integer maxValue = Short.MAX_VALUE * 2 + 1;
 
+    public static PlcWCHAR of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcWCHAR((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcWCHAR((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcWCHAR((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcWCHAR((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcWCHAR((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcWCHAR((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcWCHAR((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcWCHAR((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcWCHAR((BigDecimal) value);
+        } else {
+            return new PlcWCHAR((String) value);
+        }
+    }
+
     public PlcWCHAR(Boolean value) {
         super();
         this.value = value ? (Integer) 1 : (Integer) 0;
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWORD.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWORD.java
index 3aeeb34..eb87609 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWORD.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWORD.java
@@ -35,6 +35,30 @@ public class PlcWORD extends PlcIECValue<Integer> {
     static Integer minValue = 0;
     static Integer maxValue = Short.MAX_VALUE * 2 + 1;
 
+    public static PlcWORD of(Object value) {
+        if (value instanceof Boolean) {
+            return new PlcWORD((Boolean) value);
+        } else if (value instanceof Byte) {
+            return new PlcWORD((Byte) value);
+        } else if (value instanceof Short) {
+            return new PlcWORD((Short) value);
+        } else if (value instanceof Integer) {
+            return new PlcWORD((Integer) value);
+        } else if (value instanceof Long) {
+            return new PlcWORD((Long) value);
+        } else if (value instanceof Float) {
+            return new PlcWORD((Float) value);
+        } else if (value instanceof Double) {
+            return new PlcWORD((Double) value);
+        } else if (value instanceof BigInteger) {
+            return new PlcWORD((BigInteger) value);
+        } else if (value instanceof BigDecimal) {
+            return new PlcWORD((BigDecimal) value);
+        } else {
+            return new PlcWORD((String) value);
+        }
+    }
+
     public PlcWORD(Boolean value) {
         super();
         this.value = value ? (Integer) 1 : (Integer) 0;
diff --git a/plc4j/api/src/test/java/org/apache/plc4x/java/api/types/PlcValueTest.java b/plc4j/api/src/test/java/org/apache/plc4x/java/api/types/PlcValueTest.java
deleted file mode 100644
index d3d8ba3..0000000
--- a/plc4j/api/src/test/java/org/apache/plc4x/java/api/types/PlcValueTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.plc4x.java.api.types;
-
-import org.apache.plc4x.java.api.exceptions.PlcIncompatibleDatatypeException;
-import org.apache.plc4x.java.api.value.PlcValue;
-import org.apache.plc4x.java.api.value.PlcValues;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class PlcValueTest {
-
-    @Nested
-    class Complex {
-
-        @Test
-        void complexTestCase_isComplex() {
-            PlcValue value = PlcValues.of("Entry 1", PlcValues.of(
-                PlcValues.of(true),
-                PlcValues.of("Pimmel"),
-                PlcValues.of(false),
-                PlcValues.of("Arsch"),
-                PlcValues.of(1278391)
-            ));
-
-            System.out.println(value);
-
-            assertThrows(PlcIncompatibleDatatypeException.class, value::getBoolean);
-            assertTrue(value.getValue("Entry 1").getIndex(0).getBoolean());
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/plc4j/api/src/test/java/org/apache/plc4x/java/api/value/PlcValuesTest.java b/plc4j/api/src/test/java/org/apache/plc4x/java/api/value/PlcValuesTest.java
deleted file mode 100644
index 1d202e9..0000000
--- a/plc4j/api/src/test/java/org/apache/plc4x/java/api/value/PlcValuesTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.plc4x.java.api.value;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.MethodSource;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-
-class PlcValuesTest {
-
-    @ParameterizedTest
-    @MethodSource("values")
-    void builders(Class<?> clazz, List<Object> values) throws Exception {
-        Method declaredMethod = PlcValues.class.getDeclaredMethod("of", clazz);
-        for (Object value : values) {
-            Object invoke = declaredMethod.invoke(null, value);
-            Assertions.assertNotNull(invoke);
-        }
-    }
-
-    private static Object[][] values() {
-        return new Object[][]{
-            {String.class, Arrays.asList("test", "test2")},
-            {Integer.class, Arrays.asList(1, 2, 3, 4)},
-            {int.class, Arrays.asList(1, 1)},
-            {Boolean.class, Arrays.asList(true, false)},
-            {boolean.class, Arrays.asList(true, false)},
-        };
-    }
-}
\ No newline at end of file
diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/AbEthDriver.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/AbEthDriver.java
index f242812..7841b2d 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/AbEthDriver.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/AbEthDriver.java
@@ -26,6 +26,8 @@ import org.apache.plc4x.java.abeth.protocol.AbEthProtocolLogic;
 import org.apache.plc4x.java.abeth.readwrite.CIPEncapsulationPacket;
 import org.apache.plc4x.java.abeth.readwrite.io.CIPEncapsulationPacketIO;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
@@ -64,6 +66,11 @@ public class AbEthDriver extends GeneratedDriverBase<CIPEncapsulationPacket> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new IEC61131ValueHandler();
+    }
+
+    @Override
     protected ProtocolStackConfigurer<CIPEncapsulationPacket> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(CIPEncapsulationPacket.class, CIPEncapsulationPacketIO.class)
             .withProtocol(AbEthProtocolLogic.class)
diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/AbEthProtocolLogic.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/AbEthProtocolLogic.java
index 0583e96..1c5b191 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/AbEthProtocolLogic.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/AbEthProtocolLogic.java
@@ -157,7 +157,7 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
                                 if(data.length == 1) {
                                     plcValue = new PlcINT(data[0]);
                                 } else {
-                                    plcValue = new PlcList(Arrays.asList(data));
+                                    plcValue = IEC61131ValueHandler.newPlcValue(data);
                                 }
                             }
                             break;
@@ -166,9 +166,9 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 short[] data = df1PTLR.getData();
                                 if (((data[1]>> 7) & 1) == 0)  {
-                                    plcValue = PlcValues.of((data[1] << 8) + data[0]);  // positive number
+                                    plcValue = IEC61131ValueHandler.newPlcValue((data[1] << 8) + data[0]);  // positive number
                                 } else {
-                                    plcValue = PlcValues.of((((~data[1] & 0b01111111) << 8) + (~(data[0]-1) & 0b11111111))  * -1);  // negative number
+                                    plcValue = IEC61131ValueHandler.newPlcValue((((~data[1] & 0b01111111) << 8) + (~(data[0]-1) & 0b11111111))  * -1);  // negative number
                                 }
                             }
                             break;
@@ -177,9 +177,9 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 short[] data = df1PTLR.getData();
                                 if (((data[3]>> 7) & 1) == 0)  {
-                                    plcValue = PlcValues.of((data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]);  // positive number
+                                    plcValue = IEC61131ValueHandler.newPlcValue((data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]);  // positive number
                                 } else {
-                                    plcValue = PlcValues.of((((~data[3] & 0b01111111) << 24) + ((~(data[2]-1) & 0b11111111) << 16)+ ((~(data[1]-1) & 0b11111111) << 8) + (~(data[0]-1) & 0b11111111))  * -1);  // negative number
+                                    plcValue = IEC61131ValueHandler.newPlcValue((((~data[3] & 0b01111111) << 24) + ((~(data[2]-1) & 0b11111111) << 16)+ ((~(data[1]-1) & 0b11111111) << 8) + (~(data[0]-1) & 0b11111111))  * -1);  // negative number
                                 }
                             }
                             break;
@@ -188,9 +188,9 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 short[] data = df1PTLR.getData();
                                 if (field.getBitNumber() < 8) {
-                                    plcValue = PlcValues.of((data[0] & (1 <<  field.getBitNumber())) != 0);         // read from first byte
+                                    plcValue = IEC61131ValueHandler.newPlcValue((data[0] & (1 <<  field.getBitNumber())) != 0);         // read from first byte
                                 } else {
-                                    plcValue = PlcValues.of((data[1] & (1 << (field.getBitNumber() - 8) )) != 0);   // read from second byte
+                                    plcValue = IEC61131ValueHandler.newPlcValue((data[1] & (1 << (field.getBitNumber() - 8) )) != 0);   // read from second byte
                                 }
                             }
                             break;
diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/Plc4xAbEthProtocol.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/Plc4xAbEthProtocol.java
index 3658ec8..9002420 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/Plc4xAbEthProtocol.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/Plc4xAbEthProtocol.java
@@ -181,7 +181,7 @@ public class Plc4xAbEthProtocol extends PlcMessageToMessageCodec<CIPEncapsulatio
                                 if(data.length == 1) {
                                     plcValue = new PlcINT(data[0]);
                                 } else {
-                                    plcValue = new PlcList(Arrays.asList(data));
+                                    plcValue = IEC61131ValueHandler.newPlcValue(data);
                                 }
                             }
                             break;
@@ -190,9 +190,9 @@ public class Plc4xAbEthProtocol extends PlcMessageToMessageCodec<CIPEncapsulatio
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 short[] data = df1PTLR.getData();
                                 if (((data[1]>> 7) & 1) == 0)  {
-                                    plcValue = PlcValues.of((data[1] << 8) + data[0]);  // positive number
+                                    plcValue = IEC61131ValueHandler.newPlcValue((data[1] << 8) + data[0]);  // positive number
                                 } else {
-                                    plcValue = PlcValues.of((((~data[1] & 0b01111111) << 8) + (~(data[0]-1) & 0b11111111))  * -1);  // negative number
+                                    plcValue = IEC61131ValueHandler.newPlcValue((((~data[1] & 0b01111111) << 8) + (~(data[0]-1) & 0b11111111))  * -1);  // negative number
                                 }
                             }
                             break;
@@ -201,9 +201,9 @@ public class Plc4xAbEthProtocol extends PlcMessageToMessageCodec<CIPEncapsulatio
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 short[] data = df1PTLR.getData();
                                 if (((data[3]>> 7) & 1) == 0)  {
-                                    plcValue = PlcValues.of((data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]);  // positive number
+                                    plcValue = IEC61131ValueHandler.newPlcValue((data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]);  // positive number
                                 } else {
-                                    plcValue = PlcValues.of((((~data[3] & 0b01111111) << 24) + ((~(data[2]-1) & 0b11111111) << 16)+ ((~(data[1]-1) & 0b11111111) << 8) + (~(data[0]-1) & 0b11111111))  * -1);  // negative number
+                                    plcValue = IEC61131ValueHandler.newPlcValue((((~data[3] & 0b01111111) << 24) + ((~(data[2]-1) & 0b11111111) << 16)+ ((~(data[1]-1) & 0b11111111) << 8) + (~(data[0]-1) & 0b11111111))  * -1);  // negative number
                                 }
                             }
                             break;
@@ -212,9 +212,9 @@ public class Plc4xAbEthProtocol extends PlcMessageToMessageCodec<CIPEncapsulatio
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 short[] data = df1PTLR.getData();
                                 if (field.getBitNumber() < 8) {
-                                    plcValue = PlcValues.of((data[0] & (1 <<  field.getBitNumber())) != 0);         // read from first byte
+                                    plcValue = IEC61131ValueHandler.newPlcValue((data[0] & (1 <<  field.getBitNumber())) != 0);         // read from first byte
                                 } else {
-                                    plcValue = PlcValues.of((data[1] & (1 << (field.getBitNumber() - 8) )) != 0);   // read from second byte
+                                    plcValue = IEC61131ValueHandler.newPlcValue((data[1] & (1 << (field.getBitNumber() - 8) )) != 0);   // read from second byte
                                 }
                             }
                             break;
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/ADSPlcDriver.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/ADSPlcDriver.java
index 5eec572..8d51021 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/ADSPlcDriver.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/ADSPlcDriver.java
@@ -23,6 +23,8 @@ import org.apache.plc4x.java.ads.field.AdsFieldHandler;
 import org.apache.plc4x.java.ads.protocol.AdsProtocolLogic;
 import org.apache.plc4x.java.ads.readwrite.AmsTCPPacket;
 import org.apache.plc4x.java.ads.readwrite.io.AmsTCPPacketIO;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
@@ -74,6 +76,11 @@ public class ADSPlcDriver extends GeneratedDriverBase<AmsTCPPacket> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new IEC61131ValueHandler();
+    }
+
+    @Override
     protected ProtocolStackConfigurer<AmsTCPPacket> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(AmsTCPPacket.class, AmsTCPPacketIO.class)
             .withProtocol(AdsProtocolLogic.class)
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 a9a1d8c..7f33247 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
@@ -314,7 +314,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                     }
                     return null;
                 }).toArray(PlcValue[]::new);
-                return new ResponseItem<>(PlcResponseCode.OK, PlcValues.of(resultItems));
+                return new ResponseItem<>(PlcResponseCode.OK, IEC61131ValueHandler.newPlcValue(resultItems));
             }
         } catch (Exception e) {
             LOGGER.warn(String.format("Error parsing field item of type: '%s'", field.getAdsDataType()), e);
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/util/LittleEndianDecoder.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/util/LittleEndianDecoder.java
index 6b53d39..6491c97 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/util/LittleEndianDecoder.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/util/LittleEndianDecoder.java
@@ -49,7 +49,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Boolean[values.size()]));
                 }
             }
             case BIT8: {
@@ -61,7 +61,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Boolean[values.size()]));
                 }
             }
             case BITARR8: {
@@ -74,7 +74,7 @@ public class LittleEndianDecoder {
                     // TODO: Double-Check this ...
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Short[values.size()]));
                 }
             }
             case BITARR16: {
@@ -87,7 +87,7 @@ public class LittleEndianDecoder {
                     // TODO: Double-Check this ...
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Integer[values.size()]));
                 }
             }
             case BITARR32: {
@@ -100,7 +100,7 @@ public class LittleEndianDecoder {
                     // TODO: Double-Check this ...
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Long[values.size()]));
                 }
             }
             case INT8: {
@@ -112,7 +112,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcSINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Byte[values.size()]));
                 }
             }
             case INT16: {
@@ -124,7 +124,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Short[values.size()]));
                 }
             }
             case INT32: {
@@ -136,7 +136,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcDINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Integer[values.size()]));
                 }
             }
             case INT64: {
@@ -148,7 +148,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcLINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Long[values.size()]));
                 }
             }
             case UINT8: {
@@ -160,7 +160,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcUSINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Short[values.size()]));
                 }
             }
             case UINT16: {
@@ -172,7 +172,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcUINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Integer[values.size()]));
                 }
             }
             case UINT32: {
@@ -184,7 +184,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcUDINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Long[values.size()]));
                 }
             }
             case ULINT:
@@ -200,7 +200,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcULINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new BigInteger[values.size()]));
                 }
             }
             case FLOAT: {
@@ -214,7 +214,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcREAL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Float[values.size()]));
                 }
             }
             case DOUBLE: {
@@ -228,7 +228,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcLREAL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Double[values.size()]));
                 }
             }
             case BOOL: {
@@ -240,7 +240,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Boolean[values.size()]));
                 }
             }
             case BYTE: {
@@ -253,7 +253,7 @@ public class LittleEndianDecoder {
                     // TODO: Double-Check this ...
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Short[values.size()]));
                 }
             }
             case WORD: {
@@ -266,7 +266,7 @@ public class LittleEndianDecoder {
                     // TODO: Double-Check this ...
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Integer[values.size()]));
                 }
             }
             case DWORD: {
@@ -279,7 +279,7 @@ public class LittleEndianDecoder {
                     // TODO: Double-Check this ...
                     return new PlcBOOL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Long[values.size()]));
                 }
             }
             case SINT: {
@@ -291,7 +291,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcSINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Byte[values.size()]));
                 }
             }
             case USINT: {
@@ -303,7 +303,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcUSINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Short[values.size()]));
                 }
             }
             case INT: {
@@ -315,7 +315,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Short[values.size()]));
                 }
             }
             case UINT: {
@@ -327,7 +327,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcUINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Integer[values.size()]));
                 }
             }
             case DINT: {
@@ -339,7 +339,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcDINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Integer[values.size()]));
                 }
             }
             case UDINT: {
@@ -351,7 +351,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcUDINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Long[values.size()]));
                 }
             }
             case LINT: {
@@ -363,7 +363,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcLINT(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Long[values.size()]));
                 }
             }
             case REAL: {
@@ -377,7 +377,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcREAL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Float[values.size()]));
                 }
             }
             case LREAL: {
@@ -391,7 +391,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcLREAL(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new Double[values.size()]));
                 }
             }
             case STRING: {
@@ -407,7 +407,7 @@ public class LittleEndianDecoder {
                 if(values.size() == 1) {
                     return new PlcSTRING(values.get(0));
                 } else {
-                    return new PlcList(values);
+                    return IEC61131ValueHandler.newPlcValue(values.toArray(new String[values.size()]));
                 }
             }
 /*            case TIME: {
diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/EIPDriver.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/EIPDriver.java
index 727b489..8a147f1 100644
--- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/EIPDriver.java
+++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/EIPDriver.java
@@ -24,6 +24,8 @@ import org.apache.plc4x.java.eip.readwrite.field.EipField;
 import org.apache.plc4x.java.eip.readwrite.field.EipFieldHandler;
 import org.apache.plc4x.java.eip.readwrite.io.EipPacketIO;
 import org.apache.plc4x.java.eip.readwrite.protocol.EipProtocolLogic;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
@@ -56,6 +58,11 @@ public class EIPDriver extends GeneratedDriverBase<EipPacket> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new IEC61131ValueHandler();
+    }
+
+    @Override
     protected String getDefaultTransport() {
         return "tcp";
     }
diff --git a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java
index a6fb805..6174a74 100644
--- a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java
+++ b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java
@@ -26,6 +26,8 @@ import org.apache.plc4x.java.firmata.readwrite.field.FirmataField;
 import org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldHandler;
 import org.apache.plc4x.java.firmata.readwrite.io.FirmataMessageIO;
 import org.apache.plc4x.java.firmata.readwrite.protocol.FirmataProtocolLogic;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
@@ -73,6 +75,11 @@ public class FirmataDriver extends GeneratedDriverBase<FirmataMessage> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new IEC61131ValueHandler();
+    }
+
+    @Override
     protected ProtocolStackConfigurer<FirmataMessage> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(FirmataMessage.class, FirmataMessageIO.class)
             .withProtocol(FirmataProtocolLogic.class)
diff --git a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
index 6a5242f..630d839 100644
--- a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
+++ b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
@@ -27,6 +27,8 @@ import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.knxnetip.field.KnxNetIpFieldHandler;
 import org.apache.plc4x.java.knxnetip.protocol.KnxNetIpProtocolLogic;
 import org.apache.plc4x.java.knxnetip.readwrite.KNXNetIPMessage;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
@@ -86,6 +88,11 @@ public class KnxNetIpDriver extends GeneratedDriverBase<KNXNetIPMessage> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new IEC61131ValueHandler();
+    }
+
+    @Override
     protected ProtocolStackConfigurer<KNXNetIPMessage> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(KNXNetIPMessage.class, KNXNetIPMessageIO.class)
             .withProtocol(KnxNetIpProtocolLogic.class)
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
index 306e8f2..f1b04d5 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ModbusDriver.java
@@ -25,6 +25,8 @@ import org.apache.plc4x.java.modbus.field.ModbusFieldHandler;
 import org.apache.plc4x.java.modbus.protocol.ModbusProtocolLogic;
 import org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU;
 import org.apache.plc4x.java.modbus.readwrite.io.ModbusTcpADUIO;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
@@ -86,6 +88,11 @@ public class ModbusDriver extends GeneratedDriverBase<ModbusTcpADU> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new IEC61131ValueHandler();
+    }
+
+    @Override
     protected ProtocolStackConfigurer<ModbusTcpADU> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class, ModbusTcpADUIO.class)
             .withProtocol(ModbusProtocolLogic.class)
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
index ff75659..b9e486a 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
@@ -26,6 +26,8 @@ import org.apache.plc4x.java.s7.readwrite.io.TPKTPacketIO;
 import org.apache.plc4x.java.s7.readwrite.optimizer.S7Optimizer;
 import org.apache.plc4x.java.s7.readwrite.protocol.S7ProtocolLogic;
 import org.apache.plc4x.java.s7.readwrite.field.S7PlcFieldHandler;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
@@ -80,6 +82,11 @@ public class S7Driver extends GeneratedDriverBase<TPKTPacket> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new S7ValueHandler();
+    }
+
+    @Override
     protected ProtocolStackConfigurer<TPKTPacket> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(TPKTPacket.class, TPKTPacketIO.class)
             .withProtocol(S7ProtocolLogic.class)
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
index dbc3745..6d9d16d 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
@@ -32,6 +32,8 @@ import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.value.PlcNull;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.api.value.PlcValues;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.s7.readwrite.*;
 import org.apache.plc4x.java.s7.readwrite.context.S7DriverContext;
 import org.apache.plc4x.java.s7.readwrite.field.S7StringField;
@@ -523,7 +525,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
                     }
                     return null;
                 }).toArray(PlcValue[]::new);
-                return PlcValues.of(resultItems);
+                return IEC61131ValueHandler.newPlcValue(resultItems);
             }
         } catch (ParseException e) {
             LOGGER.warn(String.format("Error parsing field item of type: '%s'", field.getDataType().name()), e);
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/value/S7ValueHandler.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/value/S7ValueHandler.java
new file mode 100644
index 0000000..8193912
--- /dev/null
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/value/S7ValueHandler.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.api.value;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
+
+import java.math.BigInteger;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.util.BitSet;
+import java.util.LinkedList;
+import java.util.List;
+
+
+public abstract class S7ValueHandler extends IEC61131ValueHandler {
+
+    @Override
+    public PlcValue customDataType(PlcField field, Object value) {
+        switch (field.getPlcDataType().toUpperCase()) {
+            case "TIME":
+                return PlcBOOL.of(value);
+            case "DATE":
+                return PlcBYTE.of(value);
+            case "DATE_AND_TIME":
+                return PlcSINT.of(value);
+            default:
+                throw PlcUnsuppportedDataTypeException("Data Type " + field.getPlcDataType())
+                    + "Is not supported");
+        }
+    }
+}
diff --git a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
index fb91433..ec507f1 100644
--- a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
+++ b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
@@ -22,6 +22,8 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.api.value.PlcValues;
+import org.apache.plc4x.java.api.value.IEC61131ValueHandler;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.simulated.field.SimulatedField;
 import org.apache.plc4x.java.spi.model.InternalPlcSubscriptionHandle;
 
@@ -94,31 +96,31 @@ public class SimulatedDevice {
         Object result = null;
 
         if (type.equals(Byte.class)) {
-            return PlcValues.of((byte) random.nextInt(1 << 8));
+            return IEC61131ValueHandler.newPlcValue((byte) random.nextInt(1 << 8));
         }
 
         if (type.equals(Short.class)) {
-            return PlcValues.of((short) random.nextInt(1 << 16));
+            return IEC61131ValueHandler.newPlcValue((short) random.nextInt(1 << 16));
         }
 
         if (type.equals(Integer.class)) {
-            return PlcValues.of(random.nextInt());
+            return IEC61131ValueHandler.newPlcValue(random.nextInt());
         }
 
         if (type.equals(Long.class)) {
-            return PlcValues.of(random.nextLong());
+            return IEC61131ValueHandler.newPlcValue(random.nextLong());
         }
 
         if (type.equals(Float.class)) {
-            return PlcValues.of(random.nextFloat());
+            return IEC61131ValueHandler.newPlcValue(random.nextFloat());
         }
 
         if (type.equals(Double.class)) {
-            return PlcValues.of(random.nextDouble());
+            return IEC61131ValueHandler.newPlcValue(random.nextDouble());
         }
 
         if (type.equals(Boolean.class)) {
-            return PlcValues.of(random.nextBoolean());
+            return IEC61131ValueHandler.newPlcValue(random.nextBoolean());
         }
 
         if (type.equals(String.class)) {
@@ -128,7 +130,7 @@ public class SimulatedDevice {
                 char c = (char) ('a' + random.nextInt(26));
                 sb.append(c);
             }
-            return PlcValues.of(sb.toString());
+            return IEC61131ValueHandler.newPlcValue(sb.toString());
         }
 
         return null;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
index 2457495..09cb882 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
@@ -43,6 +43,8 @@ import org.apache.plc4x.java.spi.messages.PlcReader;
 import org.apache.plc4x.java.spi.messages.PlcSubscriber;
 import org.apache.plc4x.java.spi.messages.PlcWriter;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
+
 
 import java.util.Collection;
 import java.util.Objects;
@@ -61,6 +63,7 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
     private boolean canWrite = false;
     private boolean canSubscribe = false;
     private PlcFieldHandler fieldHandler;
+    private PlcValueHandler valueHandler;
     private Plc4xProtocolBase<?> protocol;
     private BaseOptimizer optimizer;
 
@@ -71,12 +74,13 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
     public AbstractPlcConnection() {
     }
 
-    public AbstractPlcConnection(boolean canRead, boolean canWrite, boolean canSubscribe, PlcFieldHandler fieldHandler,
+    public AbstractPlcConnection(boolean canRead, boolean canWrite, boolean canSubscribe, PlcFieldHandler fieldHandler, PlcValueHandler valueHandler,
                                  BaseOptimizer optimizer) {
         this.canRead = canRead;
         this.canWrite = canWrite;
         this.canSubscribe = canSubscribe;
         this.fieldHandler = fieldHandler;
+        this.valueHandler = valueHandler;
         this.optimizer = optimizer;
     }
 
@@ -115,6 +119,10 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
         return this.fieldHandler;
     }
 
+    public PlcValueHandler getPlcValueHandler() {
+        return this.valueHandler;
+    }
+
     @Override
     public PlcReadRequest.Builder readRequestBuilder() {
         if (!canRead()) {
@@ -128,7 +136,7 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
         if (!canWrite()) {
             throw new PlcUnsupportedOperationException("The connection does not support writing");
         }
-        return new DefaultPlcWriteRequest.Builder(this, getPlcFieldHandler());
+        return new DefaultPlcWriteRequest.Builder(this, getPlcFieldHandler(), getPlcValueHandler());
     }
 
     @Override
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
index ce43c73..292c458 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
@@ -36,6 +36,7 @@ import org.apache.plc4x.java.spi.events.ConnectedEvent;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -58,10 +59,10 @@ public class DefaultNettyPlcConnection extends AbstractPlcConnection implements
     protected boolean connected;
 
     public DefaultNettyPlcConnection(boolean canRead, boolean canWrite, boolean canSubscribe,
-                                     PlcFieldHandler fieldHandler, Configuration configuration,
+                                     PlcFieldHandler fieldHandler, PlcValueHandler valueHandler, Configuration configuration,
                                      ChannelFactory channelFactory, boolean awaitSessionSetupComplete,
                                      ProtocolStackConfigurer stackConfigurer, BaseOptimizer optimizer) {
-        super(canRead, canWrite, canSubscribe, fieldHandler, optimizer);
+        super(canRead, canWrite, canSubscribe, fieldHandler, valueHandler, optimizer);
         this.configuration = configuration;
         this.channelFactory = channelFactory;
         this.awaitSessionSetupComplete = awaitSessionSetupComplete;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultPlcFieldHandler.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultPlcFieldHandler.java
index 8beae1f..03deb74 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultPlcFieldHandler.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultPlcFieldHandler.java
@@ -36,2022 +36,5 @@ import java.util.List;
  */
 public abstract class DefaultPlcFieldHandler implements PlcFieldHandler {
 
-    @Override
-    public PlcValue encodeBoolean(PlcField field, Object[] values) {
-
-        List<PlcBOOL> booleanValues = new LinkedList<>();
-        for (Object value : values) {
-            if (value instanceof Boolean) {
-                booleanValues.add(new PlcBOOL((Boolean) value));
-            } else if (value instanceof Byte) {
-                Byte byteValue = (Byte) value;
-                BitSet bitSet = BitSet.valueOf(new byte[]{byteValue});
-                for (int i = 0; i < 8; i++) {
-                    booleanValues.add(new PlcBOOL(bitSet.get(i)));
-                }
-            } else if (value instanceof Short) {
-                Short shortValue = (Short) value;
-                BitSet bitSet = BitSet.valueOf(new long[]{shortValue});
-                for (int i = 0; i < 16; i++) {
-                    booleanValues.add(new PlcBOOL(bitSet.get(i)));
-                }
-            } else if (value instanceof Integer) {
-                Integer integerValue = (Integer) value;
-                BitSet bitSet = BitSet.valueOf(new long[]{integerValue});
-                for (int i = 0; i < 32; i++) {
-                    booleanValues.add(new PlcBOOL(bitSet.get(i)));
-                }
-            } else if (value instanceof Long) {
-                long longValue = (Long) value;
-                BitSet bitSet = BitSet.valueOf(new long[]{longValue});
-                for (int i = 0; i < 64; i++) {
-                    booleanValues.add(new PlcBOOL(bitSet.get(i)));
-                }
-            } else {
-                throw new IllegalArgumentException(
-                    "Value of type " + value.getClass().getName() +
-                        " is not assignable to " + field + " fields.");
-            }
-        }
-        if(booleanValues.size() == 1) {
-            return booleanValues.get(0);
-        } else {
-            return new PlcList(booleanValues);
-        }
-    }
-
-    @Override
-    public PlcValue encodeByte(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((Byte) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((Byte) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((Byte) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((Byte) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((Byte) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((Byte) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((Byte) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((Byte) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((Byte) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((Byte) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((Byte) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((Byte) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((Byte) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((Byte) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((Byte) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((Byte) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((Byte) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((Byte) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((Byte) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((Byte) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((Byte) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((Byte) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((Byte) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((Byte) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((Byte) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((Byte) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                stringBytes = new byte[values.length];
-
-                for (int i = 0; i < values.length; i++) {
-                    Byte byteValue = (Byte) values[i];
-                    stringBytes[(2*i)+0] = (byte) (byteValue & 0xFF);
-                }
-                return new PlcSTRING(new String(stringBytes, StandardCharsets.UTF_8));
-            case "WSTRING":
-            case "STRING16":
-                stringBytes = new byte[values.length];
-
-                for (int i = 0; i < values.length; i++) {
-                    Byte byteValue = (Byte) values[i];
-                    stringBytes[(2*i)+0] = (byte) (byteValue & 0xFF);
-                }
-                return new PlcSTRING(new String(stringBytes, StandardCharsets.UTF_8));
-            default:
-                if(values.length == 1) {
-                    return new PlcSINT((Byte) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((Byte) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-        }
-    }
-
-    @Override
-    public PlcValue encodeShort(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((Short) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((Short) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((Short) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((Short) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((Short) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((Short) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((Short) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((Short) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((Short) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((Short) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((Short) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((Short) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((Short) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((Short) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((Short) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((Short) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((Short) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((Short) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((Short) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((Short) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((Short) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((Short) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((Short) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((Short) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((Short) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((Short) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((Short) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((Short) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((Short) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((Short) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((Short) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((Short) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((Short) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((Short) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                stringBytes = new byte[2 * values.length];
-
-                for (int i = 0; i < values.length; i++) {
-                    Short shortValue = (Short) values[i];
-                    stringBytes[(2*i)+0] = (byte) (shortValue >> 8);
-                    stringBytes[(2*i)+1] = (byte) (shortValue & 0xFF);
-                }
-                return new PlcSTRING(new String(stringBytes, StandardCharsets.UTF_8));
-            case "WSTRING":
-            case "STRING16":
-                stringBytes = new byte[2 * values.length];
-
-                for (int i = 0; i < values.length; i++) {
-                    Short shortValue = (Short) values[i];
-                    stringBytes[(2*i)+0] = (byte) (shortValue >> 8);
-                    stringBytes[(2*i)+1] = (byte) (shortValue & 0xFF);
-                }
-                return new PlcSTRING(new String(stringBytes, StandardCharsets.UTF_16));
-            default:
-                if(values.length == 1) {
-                    return new PlcINT((Short) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((Short) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-        }
-    }
-
-
-    @Override
-    public PlcValue encodeInteger(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((Integer) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((Integer) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((Integer) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((Integer) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((Integer) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((Integer) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((Integer) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((Integer) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((Integer) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((Integer) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((Integer) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((Integer) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((Integer) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((Integer) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((Integer) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((Integer) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((Integer) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((Integer) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((Integer) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((Integer) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((Integer) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((Integer) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((Integer) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((Integer) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((Integer) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((Integer) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                stringBytes = new byte[4 * values.length];
-
-                for (int i = 0; i < values.length; i++) {
-                    Integer integerValue = (Integer) values[i];
-                    stringBytes[(4*i)+0] = (byte) ((integerValue >> 24) & 0xFF);
-                    stringBytes[(4*i)+1] = (byte) ((integerValue >> 16) & 0xFF);
-                    stringBytes[(4*i)+2] = (byte) ((integerValue >> 8) & 0xFF);
-                    stringBytes[(4*i)+3] = (byte) (integerValue & 0xFF);
-                }
-                return new PlcSTRING(new String(stringBytes, StandardCharsets.UTF_8));
-            case "WSTRING":
-            case "STRING16":
-                    stringBytes = new byte[4 * values.length];
-
-                    for (int i = 0; i < values.length; i++) {
-                        Integer integerValue = (Integer) values[i];
-                        stringBytes[(4*i)+0] = (byte) ((integerValue >> 24) & 0xFF);
-                        stringBytes[(4*i)+1] = (byte) ((integerValue >> 16) & 0xFF);
-                        stringBytes[(4*i)+2] = (byte) ((integerValue >> 8) & 0xFF);
-                        stringBytes[(4*i)+3] = (byte) (integerValue & 0xFF);
-                    }
-                    return new PlcSTRING(new String(stringBytes, StandardCharsets.UTF_16));
-            default:
-                if(values.length == 1) {
-                    return new PlcDINT((Integer) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((Integer) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-        }
-    }
-
-    @Override
-    public PlcValue encodeLong(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((Long) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((Long) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((Long) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((Long) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((Long) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((Long) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((Long) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((Long) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((Long) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((Long) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((Long) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((Long) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((Long) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((Long) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((Long) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((Long) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((Long) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((Long) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((Long) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((Long) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((Long) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((Long) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((Long) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((Long) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((Long) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((Long) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((Long) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((Long) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((Long) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((Long) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((Long) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((Long) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((Long) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((Long) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                stringBytes = new byte[8 * values.length];
-
-                for (int i = 0; i < values.length; i++) {
-                    Long longValue = (Long) values[i];
-                    stringBytes[(4*i)+0] = (byte) ((longValue >> 56) & 0xFF);
-                    stringBytes[(4*i)+1] = (byte) ((longValue >> 48) & 0xFF);
-                    stringBytes[(4*i)+2] = (byte) ((longValue >> 40) & 0xFF);
-                    stringBytes[(4*i)+3] = (byte) ((longValue >> 32) & 0xFF);
-                    stringBytes[(4*i)+4] = (byte) ((longValue >> 24) & 0xFF);
-                    stringBytes[(4*i)+5] = (byte) ((longValue >> 16) & 0xFF);
-                    stringBytes[(4*i)+6] = (byte) ((longValue >> 8) & 0xFF);
-                    stringBytes[(4*i)+7] = (byte) (longValue & 0xFF);
-                }
-                return new PlcSTRING(new String(stringBytes, StandardCharsets.UTF_8));
-            case "WSTRING":
-            case "STRING16":
-                stringBytes = new byte[8 * values.length];
-
-                for (int i = 0; i < values.length; i++) {
-                    Long longValue = (Long) values[i];
-                    stringBytes[(4*i)+0] = (byte) ((longValue >> 56) & 0xFF);
-                    stringBytes[(4*i)+1] = (byte) ((longValue >> 48) & 0xFF);
-                    stringBytes[(4*i)+2] = (byte) ((longValue >> 40) & 0xFF);
-                    stringBytes[(4*i)+3] = (byte) ((longValue >> 32) & 0xFF);
-                    stringBytes[(4*i)+4] = (byte) ((longValue >> 24) & 0xFF);
-                    stringBytes[(4*i)+5] = (byte) ((longValue >> 16) & 0xFF);
-                    stringBytes[(4*i)+6] = (byte) ((longValue >> 8) & 0xFF);
-                    stringBytes[(4*i)+7] = (byte) (longValue & 0xFF);
-                }
-                return new PlcSTRING(new String(stringBytes, StandardCharsets.UTF_16));
-            default:
-                if(values.length == 1) {
-                    return new PlcLINT((Long) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((Long) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-        }
-    }
-
-    @Override
-    public PlcValue encodeBigInteger(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((BigInteger) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((BigInteger) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((BigInteger) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((BigInteger) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((BigInteger) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((BigInteger) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((BigInteger) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((BigInteger) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((BigInteger) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((BigInteger) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((BigInteger) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((BigInteger) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((BigInteger) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((BigInteger) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((BigInteger) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((BigInteger) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((BigInteger) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                throw new PlcRuntimeException("Invalid STRING encoder for type " + values.getClass().getName());
-            case "WSTRING":
-            case "STRING16":
-                throw new PlcRuntimeException("Invalid WSTRING encoder for type " + values.getClass().getName());
-            default:
-                if(values.length == 1) {
-                    return new PlcBigInteger((BigInteger) values[0]);
-                } else {
-                    List<PlcBigInteger> plcBigIntegerValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBigIntegerValues.add(new PlcBigInteger((BigInteger) values[i]));
-                    }
-                    return new PlcList(plcBigIntegerValues);
-                }
-        }
-    }
-
-    @Override
-    public PlcValue encodeFloat(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((Float) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((Float) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((Float) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((Float) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((Float) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((Float) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((Float) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((Float) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((Float) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((Float) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((Float) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((Float) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((Float) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((Float) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((Float) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((Float) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((Float) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((Float) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((Float) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((Float) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((Float) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((Float) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((Float) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((Float) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((Float) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((Float) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((Float) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((Float) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((Float) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((Float) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((Float) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((Float) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((Float) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((Float) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                throw new PlcRuntimeException("Invalid STRING encoder for type " + values.getClass().getName());
-            case "WSTRING":
-            case "STRING16":
-                throw new PlcRuntimeException("Invalid WSTRING encoder for type " + values.getClass().getName());
-            default:
-                if(values.length == 1) {
-                    return new PlcREAL((Float) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((Float) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-        }
-    }
-
-    @Override
-    public PlcValue encodeDouble(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((Double) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((Double) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((Double) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((Double) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((Double) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((Double) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((Double) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((Double) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((Double) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((Double) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((Double) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((Double) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((Double) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((Double) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((Double) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((Double) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((Double) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((Double) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((Double) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((Double) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((Double) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((Double) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((Double) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((Double) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((Double) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((Double) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((Double) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((Double) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((Double) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((Double) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((Double) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((Double) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((Double) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((Double) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                throw new PlcRuntimeException("Invalid STRING encoder for type " + values.getClass().getName());
-            case "WSTRING":
-            case "STRING16":
-                throw new PlcRuntimeException("Invalid WSTRING encoder for type " + values.getClass().getName());
-            default:
-                if(values.length == 1) {
-                    return new PlcLREAL((Double) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((Double) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-        }
-    }
-
-    @Override
-    public PlcValue encodeBigDecimal(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((BigDecimal) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((BigDecimal) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((BigDecimal) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((BigDecimal) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((BigDecimal) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((BigDecimal) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((BigDecimal) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((BigDecimal) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((BigDecimal) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((BigDecimal) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((BigDecimal) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((BigDecimal) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((BigDecimal) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((BigDecimal) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((BigDecimal) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((BigDecimal) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((BigDecimal) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                throw new PlcRuntimeException("Invalid STRING encoder for type " + values.getClass().getName());
-            case "WSTRING":
-            case "STRING16":
-                throw new PlcRuntimeException("Invalid WSTRING encoder for type " + values.getClass().getName());
-            default:
-                if(values.length == 1) {
-                    return new PlcBigDecimal((BigDecimal) values[0]);
-                } else {
-                    List<PlcBigDecimal> plcBigDecimalValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBigDecimalValues.add(new PlcBigDecimal((BigDecimal) values[i]));
-                    }
-                    return new PlcList(plcBigDecimalValues);
-                }
-        }
-    }
-
-    @Override
-    public PlcValue encodeString(PlcField field, Object[] values) {
-        byte[] stringBytes;
-        switch (field.getPlcDataType().toUpperCase()) {
-            case "BOOL":
-            case "BIT":
-                if(values.length == 1) {
-                    return new PlcBOOL((String) values[0]);
-                } else {
-                    List<PlcBOOL> plcBOOLValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBOOLValues.add(new PlcBOOL((String) values[i]));
-                    }
-                    return new PlcList(plcBOOLValues);
-                }
-            case "BYTE":
-            case "BITARR8":
-                if(values.length == 1) {
-                    return new PlcBYTE((String) values[0]);
-                } else {
-                    List<PlcBYTE> plcBYTEValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcBYTEValues.add(new PlcBYTE((String) values[i]));
-                    }
-                    return new PlcList(plcBYTEValues);
-                }
-            case "SINT":
-            case "INT8":
-                if(values.length == 1) {
-                    return new PlcSINT((String) values[0]);
-                } else {
-                    List<PlcSINT> plcSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcSINTValues.add(new PlcSINT((String) values[i]));
-                    }
-                    return new PlcList(plcSINTValues);
-                }
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                if(values.length == 1) {
-                    return new PlcUSINT((String) values[0]);
-                } else {
-                    List<PlcUSINT> plcUSINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUSINTValues.add(new PlcUSINT((String) values[i]));
-                    }
-                    return new PlcList(plcUSINTValues);
-                }
-            case "INT":
-            case "INT16":
-                if(values.length == 1) {
-                    return new PlcINT((String) values[0]);
-                } else {
-                    List<PlcINT> plcINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcINTValues.add(new PlcINT((String) values[i]));
-                    }
-                    return new PlcList(plcINTValues);
-                }
-            case "UINT":
-            case "UINT16":
-                if(values.length == 1) {
-                    return new PlcUINT((String) values[0]);
-                } else {
-                    List<PlcUINT> plcUINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUINTValues.add(new PlcUINT((String) values[i]));
-                    }
-                    return new PlcList(plcUINTValues);
-                }
-            case "WORD":
-            case "BITARR16":
-                if(values.length == 1) {
-                    return new PlcWORD((String) values[0]);
-                } else {
-                    List<PlcWORD> plcWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWORDValues.add(new PlcWORD((String) values[i]));
-                    }
-                    return new PlcList(plcWORDValues);
-                }
-            case "DINT":
-            case "INT32":
-                if(values.length == 1) {
-                    return new PlcDINT((String) values[0]);
-                } else {
-                    List<PlcDINT> plcDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDINTValues.add(new PlcDINT((String) values[i]));
-                    }
-                    return new PlcList(plcDINTValues);
-                }
-            case "UDINT":
-            case "UINT32":
-                if(values.length == 1) {
-                    return new PlcUDINT((String) values[0]);
-                } else {
-                    List<PlcUDINT> plcUDINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcUDINTValues.add(new PlcUDINT((String) values[i]));
-                    }
-                    return new PlcList(plcUDINTValues);
-                }
-            case "DWORD":
-            case "BITARR32":
-                if(values.length == 1) {
-                    return new PlcDWORD((String) values[0]);
-                } else {
-                    List<PlcDWORD> plcDWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcDWORDValues.add(new PlcDWORD((String) values[i]));
-                    }
-                    return new PlcList(plcDWORDValues);
-                }
-            case "LINT":
-            case "INT64":
-                if(values.length == 1) {
-                    return new PlcLINT((String) values[0]);
-                } else {
-                    List<PlcLINT> plcLINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLINTValues.add(new PlcLINT((String) values[i]));
-                    }
-                    return new PlcList(plcLINTValues);
-                }
-            case "ULINT":
-            case "UINT64":
-                if(values.length == 1) {
-                    return new PlcULINT((String) values[0]);
-                } else {
-                    List<PlcULINT> plcULINTValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcULINTValues.add(new PlcULINT((String) values[i]));
-                    }
-                    return new PlcList(plcULINTValues);
-                }
-            case "LWORD":
-            case "BITARR64":
-                if(values.length == 1) {
-                    return new PlcLWORD((String) values[0]);
-                } else {
-                    List<PlcLWORD> plcLWORDValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLWORDValues.add(new PlcLWORD((String) values[i]));
-                    }
-                    return new PlcList(plcLWORDValues);
-                }
-            case "REAL":
-            case "FLOAT":
-                if(values.length == 1) {
-                    return new PlcREAL((String) values[0]);
-                } else {
-                    List<PlcREAL> plcREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcREALValues.add(new PlcREAL((String) values[i]));
-                    }
-                    return new PlcList(plcREALValues);
-                }
-            case "LREAL":
-            case "DOUBLE":
-                if(values.length == 1) {
-                    return new PlcLREAL((String) values[0]);
-                } else {
-                    List<PlcLREAL> plcLREALValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcLREALValues.add(new PlcLREAL((String) values[i]));
-                    }
-                    return new PlcList(plcLREALValues);
-                }
-            case "CHAR":
-                if(values.length == 1) {
-                    return new PlcCHAR((String) values[0]);
-                } else {
-                    List<PlcCHAR> plcCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcCHARValues.add(new PlcCHAR((String) values[i]));
-                    }
-                    return new PlcList(plcCHARValues);
-                }
-            case "WCHAR":
-                if(values.length == 1) {
-                    return new PlcWCHAR((String) values[0]);
-                } else {
-                    List<PlcWCHAR> plcWCHARValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcWCHARValues.add(new PlcWCHAR((String) values[i]));
-                    }
-                    return new PlcList(plcWCHARValues);
-                }
-            case "STRING":
-                if(values.length == 1) {
-                    return new PlcSTRING((String) values[0]);
-                } else {
-                    List<PlcSTRING> plcStringValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcStringValues.add(new PlcSTRING((String) values[i]));
-                    }
-                    return new PlcList(plcStringValues);
-                }
-            case "WSTRING":
-            case "STRING16":
-                if(values.length == 1) {
-                    return new PlcSTRING((String) values[0]);
-                } else {
-                    List<PlcSTRING> plcStringValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcStringValues.add(new PlcSTRING((String) values[i]));
-                    }
-                    return new PlcList(plcStringValues);
-                }
-            default:
-                if(values.length == 1) {
-                    return new PlcSTRING((String) values[0]);
-                } else {
-                    List<PlcSTRING> plcStringValues = new LinkedList<>();
-                    for (int i = 0; i < values.length; i++) {
-                        plcStringValues.add(new PlcSTRING((String) values[i]));
-                    }
-                    return new PlcList(plcStringValues);
-                }
-        }
-    }
-
-    @Override
-    public PlcValue encodeTime(PlcField field, Object[] values) {
-        throw new PlcRuntimeException("Invalid encoder for type " + field);
-    }
-
-    @Override
-    public PlcValue encodeDate(PlcField field, Object[] values) {
-        throw new PlcRuntimeException("Invalid encoder for type " + field);
-    }
-
-    @Override
-    public PlcValue encodeDateTime(PlcField field, Object[] values) {
-        throw new PlcRuntimeException("Invalid encoder for type " + field);
-    }
 
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
index e855b4a..fe43179 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
@@ -30,6 +30,7 @@ import org.apache.plc4x.java.spi.generation.Message;
 import org.apache.plc4x.java.spi.configuration.ConfigurationFactory;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.apache.plc4x.java.spi.transport.Transport;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 
 import java.util.ServiceLoader;
 import java.util.regex.Matcher;
@@ -66,6 +67,8 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
 
     protected abstract PlcFieldHandler getFieldHandler();
 
+    protected abstract PlcValueHandler getValueHandler();
+
     protected abstract String getDefaultTransport();
 
     protected abstract ProtocolStackConfigurer<BASE_PACKET> getStackConfigurer();
@@ -138,6 +141,7 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
         return new DefaultNettyPlcConnection(
             canRead(), canWrite(), canSubscribe(),
             getFieldHandler(),
+            getValueHandler(),
             configuration,
             channelFactory,
             awaitSetupComplete,
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/PlcFieldHandler.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/PlcFieldHandler.java
index 4da1bd8..551692e 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/PlcFieldHandler.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/PlcFieldHandler.java
@@ -29,30 +29,4 @@ public interface PlcFieldHandler {
 
     PlcField createField(String fieldQuery) throws PlcInvalidFieldException;
 
-    PlcValue encodeBoolean(PlcField field, Object[] values);
-
-    PlcValue encodeByte(PlcField field, Object[] values);
-
-    PlcValue encodeShort(PlcField field, Object[] values);
-
-    PlcValue encodeInteger(PlcField field, Object[] values);
-
-    PlcValue encodeBigInteger(PlcField field, Object[] values);
-
-    PlcValue encodeLong(PlcField field, Object[] values);
-
-    PlcValue encodeFloat(PlcField field, Object[] values);
-
-    PlcValue encodeBigDecimal(PlcField field, Object[] values);
-
-    PlcValue encodeDouble(PlcField field, Object[] values);
-
-    PlcValue encodeString(PlcField field, Object[] values);
-
-    PlcValue encodeTime(PlcField field, Object[] values);
-
-    PlcValue encodeDate(PlcField field, Object[] values);
-
-    PlcValue encodeDateTime(PlcField field, Object[] values);
-
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteRequest.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteRequest.java
index fbac6aa..211fdaa 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteRequest.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteRequest.java
@@ -30,6 +30,7 @@ import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.api.value.PlcList;
 import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 import org.apache.plc4x.java.spi.messages.utils.FieldValueItem;
 
@@ -153,186 +154,24 @@ public class DefaultPlcWriteRequest implements InternalPlcWriteRequest, Internal
 
         private final PlcWriter writer;
         private final PlcFieldHandler fieldHandler;
+        private final PlcValueHandler valueHandler;
         private final Map<String, BuilderItem<Object>> fields;
-        private final Map<Class<?>, BiFunction<PlcField, Object[], PlcValue>> handlerMap;
 
-        public Builder(PlcWriter writer, PlcFieldHandler fieldHandler) {
+        public Builder(PlcWriter writer, PlcFieldHandler fieldHandler, PlcValueHandler valueHandler) {
             this.writer = writer;
             this.fieldHandler = fieldHandler;
+            this.valueHandler = valueHandler;
             fields = new TreeMap<>();
-            handlerMap = new HashMap<>();
-            handlerMap.put(Boolean.class, fieldHandler::encodeBoolean);
-            handlerMap.put(Byte.class, fieldHandler::encodeByte);
-            handlerMap.put(Short.class, fieldHandler::encodeShort);
-            handlerMap.put(Integer.class, fieldHandler::encodeInteger);
-            handlerMap.put(BigInteger.class, fieldHandler::encodeBigInteger);
-            handlerMap.put(Long.class, fieldHandler::encodeLong);
-            handlerMap.put(Float.class, fieldHandler::encodeFloat);
-            handlerMap.put(Double.class, fieldHandler::encodeDouble);
-            handlerMap.put(BigDecimal.class, fieldHandler::encodeBigDecimal);
-            handlerMap.put(String.class, fieldHandler::encodeString);
-            handlerMap.put(LocalTime.class, fieldHandler::encodeTime);
-            handlerMap.put(LocalDate.class, fieldHandler::encodeDate);
-            handlerMap.put(LocalDateTime.class, fieldHandler::encodeDateTime);
         }
 
         @Override
-        public Builder addItem(String name, String fieldQuery, Boolean... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeBoolean);
+        public <T> Builder addItem(String name, String fieldQuery, Object... values) {
+            return addItem(name, fieldQuery, values, valueHandler.of(values));
         }
 
         @Override
-        public Builder addItem(String name, PlcField fieldQuery, Boolean... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeBoolean);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, Byte... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeByte);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, Byte... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeByte);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, Short... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeShort);
-        }
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, Short... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeShort);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, Integer... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeInteger);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, Integer... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeInteger);
-        }
-
-        @Override
-        public PlcWriteRequest.Builder addItem(String name, String fieldQuery, BigInteger... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeBigInteger);
-        }
-
-        @Override
-        public PlcWriteRequest.Builder addItem(String name, PlcField fieldQuery, BigInteger... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeBigInteger);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, Long... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeLong);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, Long... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeLong);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, Float... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeFloat);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, Float... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeFloat);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, Double... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeDouble);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, Double... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeDouble);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, BigDecimal... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeBigDecimal);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, BigDecimal... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeBigDecimal);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, String... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeString);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, String... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeString);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, LocalTime... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeTime);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, LocalTime... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeTime);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, LocalDate... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeDate);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, LocalDate... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeDate);
-        }
-
-        @Override
-        public Builder addItem(String name, String fieldQuery, LocalDateTime... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeDateTime);
-        }
-
-        @Override
-        public Builder addItem(String name, PlcField fieldQuery, LocalDateTime... values) {
-            return addItem(name, fieldQuery, values, fieldHandler::encodeDateTime);
-        }
-
-        @Override
-        public <T> Builder addItem(String name, String fieldQuery, T... values) {
-            BiFunction<PlcField, Object[], PlcValue> plcFieldPlcValueBiFunction = validateArray(values);
-            return addItem(name, fieldQuery, values, plcFieldPlcValueBiFunction);
-        }
-
-        @Override
-        public <T> Builder addItem(String name, PlcField fieldQuery, T... values) {
-            BiFunction<PlcField, Object[], PlcValue> plcFieldPlcValueBiFunction = validateArray(values);
-            return addItem(name, fieldQuery, values, plcFieldPlcValueBiFunction);
-        }
-
-        private <T> BiFunction<PlcField, Object[], PlcValue> validateArray(T[] values) {
-            Objects.requireNonNull(values);
-            Class<?> checkedClazz = null;
-            for (T value : values) {
-                if (checkedClazz == null) {
-                    checkedClazz = value.getClass();
-                }
-                if (value.getClass() != checkedClazz) {
-                    throw new IllegalArgumentException("Invalid class found " + value.getClass() + ". should all be " + checkedClazz);
-                }
-            }
-            BiFunction<PlcField, Object[], PlcValue> plcFieldPlcValueBiFunction = handlerMap.get(checkedClazz);
-            if (plcFieldPlcValueBiFunction == null) {
-                throw new IllegalArgumentException("no field handler for " + checkedClazz + " found");
-            }
-            return plcFieldPlcValueBiFunction;
+        public <T> Builder addItem(String name, PlcField fieldQuery, Object... values) {
+            return addItem(name, fieldQuery, values, valueHandler.of(values));
         }
 
         @Override
diff --git a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
index 70a4bef..f4d41a2 100644
--- a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
+++ b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
@@ -128,26 +128,26 @@ public class PlcEntityManagerComplexTest implements WithAssertions {
     private PlcEntityManager getInitializedEntityManager() throws PlcConnectionException {
         Map<String, PlcValue> map = new HashMap<>();
         String prefix = ConnectedEntity.class.getName() + ".";
-        map.put(prefix + "boolVar", PlcValues.of(true));
-        map.put(prefix + "byteVar", PlcValues.of((byte) 1));
-        map.put(prefix + "shortVar", PlcValues.of((short) 1));
-        map.put(prefix + "intVar", PlcValues.of(1));
-        map.put(prefix + "longVar", PlcValues.of(1L));
-        map.put(prefix + "boxedBoolVar", PlcValues.of(1L));
-        map.put(prefix + "boxedByteVar", PlcValues.of((byte) 1));
-        map.put(prefix + "boxedShortVar", PlcValues.of((short) 1));
-        map.put(prefix + "boxedIntegerVar", PlcValues.of(1));
-        map.put(prefix + "boxedLongVar", PlcValues.of(1L));
-        map.put(prefix + "bigIntegerVar", PlcValues.of(BigInteger.ONE));
-        map.put(prefix + "floatVar", PlcValues.of(1f));
-        map.put(prefix + "doubleVar", PlcValues.of(1d));
-        map.put(prefix + "bigDecimalVar", PlcValues.of(BigDecimal.ONE));
-        map.put(prefix + "localTimeVar", PlcValues.of(LocalTime.of(1, 1)));
-        map.put(prefix + "localDateVar", PlcValues.of(LocalDate.of(1, 1, 1)));
-        map.put(prefix + "localDateTimeVar", PlcValues.of(LocalDateTime.of(1, 1, 1, 1, 1)));
-        map.put(prefix + "byteArrayVar", PlcValues.of(new Byte[]{0x0, 0x1}));
-        map.put(prefix + "bigByteArrayVar", PlcValues.of(new Byte[]{0x0, 0x1}));
-        map.put(prefix + "stringVar", PlcValues.of("Hallo"));
+        map.put(prefix + "boolVar", IEC61131ValueHandler.newPlcValue(true));
+        map.put(prefix + "byteVar", IEC61131ValueHandler.newPlcValue((byte) 1));
+        map.put(prefix + "shortVar", IEC61131ValueHandler.newPlcValue((short) 1));
+        map.put(prefix + "intVar", IEC61131ValueHandler.newPlcValue(1));
+        map.put(prefix + "longVar", IEC61131ValueHandler.newPlcValue(1L));
+        map.put(prefix + "boxedBoolVar", IEC61131ValueHandler.newPlcValue(1L));
+        map.put(prefix + "boxedByteVar", IEC61131ValueHandler.newPlcValue((byte) 1));
+        map.put(prefix + "boxedShortVar", IEC61131ValueHandler.newPlcValue((short) 1));
+        map.put(prefix + "boxedIntegerVar", IEC61131ValueHandler.newPlcValue(1));
+        map.put(prefix + "boxedLongVar", IEC61131ValueHandler.newPlcValue(1L));
+        map.put(prefix + "bigIntegerVar", IEC61131ValueHandler.newPlcValue(BigInteger.ONE));
+        map.put(prefix + "floatVar", IEC61131ValueHandler.newPlcValue(1f));
+        map.put(prefix + "doubleVar", IEC61131ValueHandler.newPlcValue(1d));
+        map.put(prefix + "bigDecimalVar", IEC61131ValueHandler.newPlcValue(BigDecimal.ONE));
+        map.put(prefix + "localTimeVar", IEC61131ValueHandler.newPlcValue(LocalTime.of(1, 1)));
+        map.put(prefix + "localDateVar", IEC61131ValueHandler.newPlcValue(LocalDate.of(1, 1, 1)));
+        map.put(prefix + "localDateTimeVar", IEC61131ValueHandler.newPlcValue(LocalDateTime.of(1, 1, 1, 1, 1)));
+        map.put(prefix + "byteArrayVar", IEC61131ValueHandler.newPlcValue(new Byte[]{0x0, 0x1}));
+        map.put(prefix + "bigByteArrayVar", IEC61131ValueHandler.newPlcValue(new Byte[]{0x0, 0x1}));
+        map.put(prefix + "stringVar", IEC61131ValueHandler.newPlcValue("Hallo"));
         return getPlcEntityManager(map);
     }
 
@@ -237,7 +237,7 @@ public class PlcEntityManagerComplexTest implements WithAssertions {
                 ));
             return CompletableFuture.completedFuture(new DefaultPlcWriteResponse((InternalPlcWriteRequest) writeRequest, map));
         };
-        when(connection.writeRequestBuilder()).then(invocation -> new DefaultPlcWriteRequest.Builder(writer, getFieldHandler()));
+        when(connection.writeRequestBuilder()).then(invocation -> new DefaultPlcWriteRequest.Builder(writer, getFieldHandler(), getValueHandler()));
 
         return new PlcEntityManager(mock);
     }
@@ -246,76 +246,23 @@ public class PlcEntityManagerComplexTest implements WithAssertions {
         return new NoOpPlcFieldHandler();
     }
 
+    private PlcFieldHandler getValueHandler() {
+        return new NoOpPlcFieldHandler();
+    }
+
     private static class NoOpPlcFieldHandler extends DefaultPlcFieldHandler {
         @Override
         public org.apache.plc4x.java.api.model.PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
             return new org.apache.plc4x.java.api.model.PlcField() {
             };
         }
+    }
 
+    private static class NoOpPlcValueHandler extends IEC61131Valuehandler {
         @Override
-        public PlcValue encodeBoolean(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeByte(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeShort(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeInteger(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeBigInteger(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeLong(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeFloat(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeBigDecimal(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeDouble(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeString(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeTime(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeDate(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
-        }
-
-        @Override
-        public PlcValue encodeDateTime(org.apache.plc4x.java.api.model.PlcField field, Object[] values) {
-            return null;
+        public org.apache.plc4x.java.api.model.PlcValue newPlcValue(PlcField field, Object value) throws PlcUnsuppportedDataTypeException {
+            throw PlcUnsuppportedDataTypeException("Data Type " + field.getPlcDataType())
+                + "Is not supported");
         }
     }
 
diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/BacNetIpDriver.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/BacNetIpDriver.java
index e3e0cf4..b282391 100644
--- a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/BacNetIpDriver.java
+++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/BacNetIpDriver.java
@@ -80,6 +80,11 @@ public class BacNetIpDriver extends GeneratedDriverBase<BVLC> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new IEC61131ValueHandler();
+    }
+
+    @Override
     protected ProtocolStackConfigurer<BVLC> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(BVLC.class, BVLCIO.class)
             .withProtocol(BacNetIpProtocolLogic.class)
diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
index 37e7586b..039bc23 100644
--- a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
+++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
@@ -145,15 +145,15 @@ public class BacNetIpProtocolLogic extends Plc4xProtocolBase<BVLC> implements Ha
                             enrichedPlcValue.put("address", new PlcSTRING(toString(curField)));
 
                             // From the original BACNet tag
-                            enrichedPlcValue.put("typeOrTagNumber", PlcValues.of(baCnetTag.getTypeOrTagNumber()));
-                            enrichedPlcValue.put("lengthValueType", PlcValues.of(baCnetTag.getLengthValueType()));
+                            enrichedPlcValue.put("typeOrTagNumber", IEC61131ValueHandler.newPlcValue(baCnetTag.getTypeOrTagNumber()));
+                            enrichedPlcValue.put("lengthValueType", IEC61131ValueHandler.newPlcValue(baCnetTag.getLengthValueType()));
                             if(baCnetTag.getExtTagNumber() != null) {
-                                enrichedPlcValue.put("extTagNumber", PlcValues.of(baCnetTag.getExtTagNumber()));
+                                enrichedPlcValue.put("extTagNumber", IEC61131ValueHandler.newPlcValue(baCnetTag.getExtTagNumber()));
                             } else {
                                 enrichedPlcValue.put("extTagNumber", new PlcNull());
                             }
                             if(baCnetTag.getExtLength() != null) {
-                                enrichedPlcValue.put("extLength", PlcValues.of(baCnetTag.getExtLength()));
+                                enrichedPlcValue.put("extLength", IEC61131ValueHandler.newPlcValue(baCnetTag.getExtLength()));
                             } else {
                                 enrichedPlcValue.put("extLength", new PlcNull());
                             }
diff --git a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
index b89dcc1..d1c6f2c 100644
--- a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
+++ b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
@@ -59,6 +59,11 @@ public class DF1PlcDriver extends GeneratedDriverBase<DF1Command> {
     }
 
     @Override
+    protected PlcValueHandler getValueHandler() {
+        return new IEC61131ValueHandler();
+    }
+
+    @Override
     protected ProtocolStackConfigurer<DF1Command> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(DF1Command.class, DF1CommandIO.class)
             .withProtocol(Df1ProtocolLogic.class)
diff --git a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1FieldHandler.java b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1FieldHandler.java
index cba7d15..daa75ec 100644
--- a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1FieldHandler.java
+++ b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1FieldHandler.java
@@ -30,10 +30,4 @@ public class Df1FieldHandler extends DefaultPlcFieldHandler {
     public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
         return Df1Field.of(fieldQuery);
     }
-
-    @Override
-    public PlcValue encodeByte(PlcField field, Object[] values) {
-        return super.encodeByte(field, values);
-    }
-
 }