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:13 UTC

[plc4x] 01/01: started to backport

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);
-    }
-
 }