You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2024/06/21 14:31:56 UTC

(plc4x) branch develop updated: feat: Added support for modbus encodings of "LITTLE_ENDIAN_BYTE_SWAP" and "BIG_ENDIAN_BYTE_SWAP" as well as support for overriding the byte-order on a per-tag basis.

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new fecd23ece9 feat: Added support for modbus encodings of "LITTLE_ENDIAN_BYTE_SWAP" and "BIG_ENDIAN_BYTE_SWAP" as well as support for overriding the byte-order on a per-tag basis.
fecd23ece9 is described below

commit fecd23ece9008b4f32e88e88a0ee56aa32b2ab45
Author: Christofer Dutz <cd...@apache.org>
AuthorDate: Fri Jun 21 16:31:48 2024 +0200

    feat: Added support for modbus encodings of "LITTLE_ENDIAN_BYTE_SWAP" and "BIG_ENDIAN_BYTE_SWAP" as well as support for overriding the byte-order on a per-tag basis.
---
 .../all/src/site/generated/modbus-ascii.adoc       |   3 +
 .../drivers/all/src/site/generated/modbus-rtu.adoc |   3 +
 .../drivers/all/src/site/generated/modbus-tcp.adoc |   3 +
 .../ascii/config/ModbusAsciiConfiguration.java     |  12 +-
 .../ascii/protocol/ModbusAsciiProtocolLogic.java   |   7 +-
 .../modbus/base/protocol/ModbusProtocolLogic.java  | 132 +++++++++++++++++----
 .../plc4x/java/modbus/base/tag/ModbusTag.java      |  11 ++
 .../modbus/rtu/config/ModbusRtuConfiguration.java  |  12 +-
 .../rtu/protocol/ModbusRtuProtocolLogic.java       |   7 +-
 .../modbus/tcp/config/ModbusTcpConfiguration.java  |  12 +-
 .../tcp/protocol/ModbusTcpProtocolLogic.java       |   7 +-
 .../plc4x/java/modbus/types/ModbusByteOrder.java   |  17 +--
 .../plc4x/java/modbus/utils/ByteOrderUtils.java    | 101 ----------------
 .../apache/plc4x/java/modbus/ManualDriverTest.java |  67 +++++++++++
 .../java/modbus/ManualModbusTCPDriverTest.java     |   2 +-
 .../java/modbus/utils/ByteOrderUtilsTest.java      |  79 ------------
 src/site/asciidoc/users/protocols/modbus.adoc      |   8 +-
 17 files changed, 254 insertions(+), 229 deletions(-)

diff --git a/plc4j/drivers/all/src/site/generated/modbus-ascii.adoc b/plc4j/drivers/all/src/site/generated/modbus-ascii.adoc
index 99f531c3cd..7d3ec89ad2 100644
--- a/plc4j/drivers/all/src/site/generated/modbus-ascii.adoc
+++ b/plc4j/drivers/all/src/site/generated/modbus-ascii.adoc
@@ -43,6 +43,9 @@
 Allowed values are:  +
  - BIG_ENDIAN +
  - LITTLE_ENDIAN +
+ - BIG_ENDIAN_BYTE_SWAP +
+ - LITTLE_ENDIAN_BYTE_SWAP +
+ +
 *Since: 0.13.0*
 5+|Transport config options:
 5+|
diff --git a/plc4j/drivers/all/src/site/generated/modbus-rtu.adoc b/plc4j/drivers/all/src/site/generated/modbus-rtu.adoc
index a526d0e294..83f9811d0d 100644
--- a/plc4j/drivers/all/src/site/generated/modbus-rtu.adoc
+++ b/plc4j/drivers/all/src/site/generated/modbus-rtu.adoc
@@ -44,6 +44,9 @@
 Allowed values are:  +
  - BIG_ENDIAN +
  - LITTLE_ENDIAN +
+ - BIG_ENDIAN_BYTE_SWAP +
+ - LITTLE_ENDIAN_BYTE_SWAP +
+ +
 *Since: 0.13.0*
 5+|Transport config options:
 5+|
diff --git a/plc4j/drivers/all/src/site/generated/modbus-tcp.adoc b/plc4j/drivers/all/src/site/generated/modbus-tcp.adoc
index 6d1417db12..94abe6eb55 100644
--- a/plc4j/drivers/all/src/site/generated/modbus-tcp.adoc
+++ b/plc4j/drivers/all/src/site/generated/modbus-tcp.adoc
@@ -43,6 +43,9 @@
 Allowed values are:  +
  - BIG_ENDIAN +
  - LITTLE_ENDIAN +
+ - BIG_ENDIAN_BYTE_SWAP +
+ - LITTLE_ENDIAN_BYTE_SWAP +
+ +
 *Since: 0.13.0*
 5+|Transport config options:
 5+|
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/config/ModbusAsciiConfiguration.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/config/ModbusAsciiConfiguration.java
index 93a50ceb3b..60ddec578a 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/config/ModbusAsciiConfiguration.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/config/ModbusAsciiConfiguration.java
@@ -18,13 +18,13 @@
  */
 package org.apache.plc4x.java.modbus.ascii.config;
 
+import org.apache.plc4x.java.modbus.types.ModbusByteOrder;
 import org.apache.plc4x.java.spi.configuration.PlcConnectionConfiguration;
 import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.spi.configuration.annotations.Description;
 import org.apache.plc4x.java.spi.configuration.annotations.Since;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.StringDefaultValue;
-import org.apache.plc4x.java.spi.generation.ByteOrder;
 
 public class ModbusAsciiConfiguration implements PlcConnectionConfiguration {
 
@@ -43,9 +43,11 @@ public class ModbusAsciiConfiguration implements PlcConnectionConfiguration {
     @Description("Default encoding used for transporting register values (Defaults to BIG_ENDIAN).\n" +
         "Allowed values are: \n" +
         " - BIG_ENDIAN\n" +
-        " - LITTLE_ENDIAN")
+        " - LITTLE_ENDIAN\n" +
+        " - BIG_ENDIAN_BYTE_SWAP\n" +
+        " - LITTLE_ENDIAN_BYTE_SWAP\n")
     @Since("0.13.0")
-    private ByteOrder defaultPayloadByteOrder;
+    private ModbusByteOrder defaultPayloadByteOrder;
 
     public int getRequestTimeout() {
         return requestTimeout;
@@ -63,11 +65,11 @@ public class ModbusAsciiConfiguration implements PlcConnectionConfiguration {
         this.defaultUnitIdentifier = defaultUnitIdentifier;
     }
 
-    public ByteOrder getDefaultPayloadByteOrder() {
+    public ModbusByteOrder getDefaultPayloadByteOrder() {
         return defaultPayloadByteOrder;
     }
 
-    public void setDefaultPayloadByteOrder(ByteOrder defaultPayloadByteOrder) {
+    public void setDefaultPayloadByteOrder(ModbusByteOrder defaultPayloadByteOrder) {
         this.defaultPayloadByteOrder = defaultPayloadByteOrder;
     }
 
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/protocol/ModbusAsciiProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/protocol/ModbusAsciiProtocolLogic.java
index 5245067c7e..47b5a86da6 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/protocol/ModbusAsciiProtocolLogic.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/protocol/ModbusAsciiProtocolLogic.java
@@ -27,6 +27,7 @@ import org.apache.plc4x.java.modbus.ascii.config.ModbusAsciiConfiguration;
 import org.apache.plc4x.java.modbus.base.tag.ModbusTag;
 import org.apache.plc4x.java.modbus.base.protocol.ModbusProtocolLogic;
 import org.apache.plc4x.java.modbus.readwrite.*;
+import org.apache.plc4x.java.modbus.types.ModbusByteOrder;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
 import org.apache.plc4x.java.spi.generation.ParseException;
@@ -120,7 +121,11 @@ public class ModbusAsciiProtocolLogic extends ModbusProtocolLogic<ModbusAsciiADU
                         responseCode = getErrorCode(errorResponse);
                     } else {
                         try {
-                            plcValue = toPlcValue(requestPdu, responsePdu, tag.getDataType());
+                            ModbusByteOrder byteOrder = defaultPayloadByteOrder;
+                            if(tag.getByteOrder() != null) {
+                                byteOrder = tag.getByteOrder();
+                            }
+                            plcValue = toPlcValue(requestPdu, responsePdu, tag.getDataType(), byteOrder);
                             responseCode = PlcResponseCode.OK;
                         } catch (ParseException e) {
                             // Add an error response code ...
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
index 0423c153f3..461b84014f 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
@@ -24,6 +24,7 @@ import org.apache.plc4x.java.api.value.*;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.modbus.base.tag.*;
 import org.apache.plc4x.java.modbus.readwrite.*;
+import org.apache.plc4x.java.modbus.types.ModbusByteOrder;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.generation.*;
@@ -45,7 +46,7 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
     protected Duration requestTimeout;
     protected short unitIdentifier;
     protected PlcTag pingAddress;
-    protected ByteOrder defaultPayloadByteOrder;
+    protected ModbusByteOrder defaultPayloadByteOrder;
 
     protected RequestTransactionManager tm;
     protected final AtomicInteger transactionIdentifierGenerator = new AtomicInteger(1);
@@ -151,9 +152,13 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
     protected ModbusPDU getWriteRequestPdu(PlcTag tag, PlcValue plcValue) {
         if (tag instanceof ModbusTagCoil) {
             ModbusTagCoil coil = (ModbusTagCoil) tag;
+            ModbusByteOrder byteOrder = defaultPayloadByteOrder;
+            if(coil.getByteOrder() != null) {
+                byteOrder = coil.getByteOrder();
+            }
             ModbusPDUWriteMultipleCoilsRequest request =
                 new ModbusPDUWriteMultipleCoilsRequest(coil.getAddress(), coil.getNumberOfElements(),
-                    fromPlcValue(tag, plcValue));
+                    fromPlcValue(tag, plcValue, byteOrder));
             if (request.getQuantity() == coil.getNumberOfElements()) {
                 return request;
             } else {
@@ -162,9 +167,13 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
             }
         } else if (tag instanceof ModbusTagHoldingRegister) {
             ModbusTagHoldingRegister holdingRegister = (ModbusTagHoldingRegister) tag;
+            ModbusByteOrder byteOrder = defaultPayloadByteOrder;
+            if(holdingRegister.getByteOrder() != null) {
+                byteOrder = holdingRegister.getByteOrder();
+            }
             ModbusPDUWriteMultipleHoldingRegistersRequest request =
                 new ModbusPDUWriteMultipleHoldingRegistersRequest(holdingRegister.getAddress(),
-                    holdingRegister.getLengthWords(), fromPlcValue(tag, plcValue));
+                    holdingRegister.getLengthWords(), fromPlcValue(tag, plcValue, byteOrder));
             if (request.getValue().length == holdingRegister.getLengthWords() * 2) {
                 return request;
             } else {
@@ -173,6 +182,10 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
             }
         } else if (tag instanceof ModbusTagExtendedRegister) {
             ModbusTagExtendedRegister extendedRegister = (ModbusTagExtendedRegister) tag;
+            ModbusByteOrder byteOrder = defaultPayloadByteOrder;
+            if(extendedRegister.getByteOrder() != null) {
+                byteOrder = extendedRegister.getByteOrder();
+            }
             int group1Address = extendedRegister.getAddress() % FC_EXTENDED_REGISTERS_FILE_RECORD_LENGTH;
             int group2Address = 0;
             int group1Quantity;
@@ -186,7 +199,7 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
                 //If request doesn't span file records, use a single group
                 group1Quantity = extendedRegister.getLengthWords();
                 ModbusPDUWriteFileRecordRequestItem group1 = new ModbusPDUWriteFileRecordRequestItem(
-                    (short) 6, group1FileNumber, group1Address, fromPlcValue(tag, plcValue));
+                    (short) 6, group1FileNumber, group1Address, fromPlcValue(tag, plcValue, byteOrder));
                 itemArray = Collections.singletonList(group1);
             } else {
                 //If it doesn't span a file record. e.g. 609998[10] request 2 words in first group and 8 in second.
@@ -194,9 +207,9 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
                 group2Quantity = extendedRegister.getLengthWords() - group1Quantity;
                 group2FileNumber = (short) (group1FileNumber + 1);
 
-                plcValue1 = ArrayUtils.subarray(fromPlcValue(tag, plcValue), 0, group1Quantity);
+                plcValue1 = ArrayUtils.subarray(fromPlcValue(tag, plcValue, byteOrder), 0, group1Quantity);
                 plcValue2 = ArrayUtils.subarray(
-                    fromPlcValue(tag, plcValue), group1Quantity, fromPlcValue(tag, plcValue).length);
+                    fromPlcValue(tag, plcValue, byteOrder), group1Quantity, fromPlcValue(tag, plcValue, byteOrder).length);
                 ModbusPDUWriteFileRecordRequestItem group1 = new ModbusPDUWriteFileRecordRequestItem(
                     (short) 6, group1FileNumber, group1Address, plcValue1);
                 ModbusPDUWriteFileRecordRequestItem group2 = new ModbusPDUWriteFileRecordRequestItem(
@@ -208,7 +221,7 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
         throw new PlcRuntimeException("Unsupported write tag type " + tag.getClass().getName());
     }
 
-    protected PlcValue toPlcValue(ModbusPDU request, ModbusPDU response, ModbusDataType dataType) throws ParseException {
+    protected PlcValue toPlcValue(ModbusPDU request, ModbusPDU response, ModbusDataType dataType, ModbusByteOrder byteOrder) throws ParseException {
         short tagDataTypeSize = dataType.getDataTypeSize();
 
         if (request instanceof ModbusPDUReadDiscreteInputsRequest) {
@@ -234,11 +247,11 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
             }
             ModbusPDUReadInputRegistersRequest req = (ModbusPDUReadInputRegistersRequest) request;
             ModbusPDUReadInputRegistersResponse resp = (ModbusPDUReadInputRegistersResponse) response;
-            ReadBuffer io = new ReadBufferByteBased(resp.getValue(), defaultPayloadByteOrder);
+            ReadBuffer io = getReadBuffer(resp.getValue(), byteOrder);
             if (tagDataTypeSize < 2) {
                 io.readByte();
             }
-            return DataItem.staticParse(io, dataType, Math.max(Math.round(req.getQuantity() / (tagDataTypeSize / 2.0f)), 1), defaultPayloadByteOrder == ByteOrder.BIG_ENDIAN);
+            return DataItem.staticParse(io, dataType, Math.max(Math.round(req.getQuantity() / (tagDataTypeSize / 2.0f)), 1), byteOrder == ModbusByteOrder.BIG_ENDIAN);
         } else if (request instanceof ModbusPDUReadHoldingRegistersRequest) {
             if (!(response instanceof ModbusPDUReadHoldingRegistersResponse)) {
                 throw new PlcRuntimeException("Unexpected response type. " +
@@ -246,11 +259,11 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
             }
             ModbusPDUReadHoldingRegistersRequest req = (ModbusPDUReadHoldingRegistersRequest) request;
             ModbusPDUReadHoldingRegistersResponse resp = (ModbusPDUReadHoldingRegistersResponse) response;
-            ReadBuffer io = new ReadBufferByteBased(resp.getValue(), defaultPayloadByteOrder);
+            ReadBuffer io = getReadBuffer(resp.getValue(), byteOrder);
             if ((dataType != ModbusDataType.STRING) && tagDataTypeSize < 2) {
                 io.readByte();
             }
-            return DataItem.staticParse(io, dataType, Math.max(Math.round(req.getQuantity() / (tagDataTypeSize / 2.0f)), 1), defaultPayloadByteOrder == ByteOrder.BIG_ENDIAN);
+            return DataItem.staticParse(io, dataType, Math.max(Math.round(req.getQuantity() / (tagDataTypeSize / 2.0f)), 1), byteOrder == ModbusByteOrder.BIG_ENDIAN);
         } else if (request instanceof ModbusPDUReadFileRecordRequest) {
             if (!(response instanceof ModbusPDUReadFileRecordResponse)) {
                 throw new PlcRuntimeException("Unexpected response type. " +
@@ -263,11 +276,11 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
 
             if (resp.getItems().size() == 2 && resp.getItems().size() == req.getItems().size()) {
                 //If request was split over file records, two groups in response should be received.
-                io = new ReadBufferByteBased(ArrayUtils.addAll(resp.getItems().get(0).getData(), resp.getItems().get(1).getData()), defaultPayloadByteOrder);
+                io = getReadBuffer(ArrayUtils.addAll(resp.getItems().get(0).getData(), resp.getItems().get(1).getData()), byteOrder);
                 dataLength = (short) (resp.getItems().get(0).getLengthInBytes() + resp.getItems().get(1).getLengthInBytes() - (2 * FC_EXTENDED_REGISTERS_GROUP_HEADER_LENGTH));
             } else if (resp.getItems().size() == 1 && resp.getItems().size() == req.getItems().size()) {
                 //If request was within a single file record, one group should be received.
-                io = new ReadBufferByteBased(resp.getItems().get(0).getData(), defaultPayloadByteOrder);
+                io = getReadBuffer(resp.getItems().get(0).getData(), byteOrder);
                 dataLength = (short) (resp.getItems().get(0).getLengthInBytes() - FC_EXTENDED_REGISTERS_GROUP_HEADER_LENGTH);
             } else {
                 throw new PlcRuntimeException("Unexpected number of groups in response. " +
@@ -276,12 +289,12 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
             if (tagDataTypeSize < 2) {
                 io.readByte();
             }
-            return DataItem.staticParse(io, dataType, Math.round(Math.max(dataLength / 2.0f, 1) / Math.max(tagDataTypeSize / 2.0f, 1)), defaultPayloadByteOrder == ByteOrder.BIG_ENDIAN);
+            return DataItem.staticParse(io, dataType, Math.round(Math.max(dataLength / 2.0f, 1) / Math.max(tagDataTypeSize / 2.0f, 1)), byteOrder == ModbusByteOrder.BIG_ENDIAN);
         }
         return null;
     }
 
-    protected byte[] fromPlcValue(PlcTag tag, PlcValue plcValue) {
+    protected byte[] fromPlcValue(PlcTag tag, PlcValue plcValue, ModbusByteOrder byteOrder) {
         ModbusDataType tagDataType = ((ModbusTag) tag).getDataType();
         try {
             if (tag instanceof ModbusTagCoil) {
@@ -293,7 +306,7 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
                 // If it's a List, convert the booleans in the list into an array of bytes.
                 else if(plcValue instanceof PlcList) {
                     PlcList valueList = (PlcList) plcValue;
-                    WriteBufferByteBased wb = new WriteBufferByteBased(((plcValue.getLength() - 1) / 8) + 1, defaultPayloadByteOrder);
+                    WriteBufferByteBased wb = getWriteBuffer(((plcValue.getLength() - 1) / 8) + 1, byteOrder);
                     int paddingBits = 8 - (plcValue.getLength() % 8);
                     if(paddingBits < 8) {
                         for(int i = 0; i < paddingBits; i++) {
@@ -309,8 +322,13 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
                         PlcBOOL boolValue = (PlcBOOL) value;
                         wb.writeBit(boolValue.getBoolean());
                     }
-                    // Reverse the bytes to have the "unfinished bytes" at the end.
+
+                    // Do the byte-swapping, if needed.
                     byte[] bytes = wb.getBytes();
+                    if(byteOrder == ModbusByteOrder.BIG_ENDIAN_BYTE_SWAP || byteOrder == ModbusByteOrder.LITTLE_ENDIAN_BYTE_SWAP) {
+                        bytes = byteSwap(bytes);
+                    }
+                    // Reverse the bytes to have the "unfinished bytes" at the end.
                     ArrayUtils.reverse(bytes);
                     return bytes;
                 }
@@ -319,9 +337,12 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
                }
             }
             else if (plcValue instanceof PlcList) {
-                WriteBufferByteBased writeBuffer = new WriteBufferByteBased(DataItem.getLengthInBytes(plcValue, tagDataType, plcValue.getLength(), defaultPayloadByteOrder == ByteOrder.BIG_ENDIAN), defaultPayloadByteOrder);
-                DataItem.staticSerialize(writeBuffer, plcValue, tagDataType, plcValue.getLength(), defaultPayloadByteOrder == ByteOrder.BIG_ENDIAN);
+                WriteBufferByteBased writeBuffer = getWriteBuffer(DataItem.getLengthInBytes(plcValue, tagDataType, plcValue.getLength(), byteOrder == ModbusByteOrder.BIG_ENDIAN), byteOrder);
+                DataItem.staticSerialize(writeBuffer, plcValue, tagDataType, plcValue.getLength(), byteOrder == ModbusByteOrder.BIG_ENDIAN);
                 byte[] data = writeBuffer.getBytes();
+                if(byteOrder == ModbusByteOrder.BIG_ENDIAN_BYTE_SWAP || byteOrder == ModbusByteOrder.LITTLE_ENDIAN_BYTE_SWAP) {
+                    data = byteSwap(data);
+                }
                 if (((ModbusTag) tag).getDataType() == ModbusDataType.BOOL) {
                     //Reverse Bits in each byte as
                     //they should be ordered like this: 8 7 6 5 4 3 2 1 | 0 0 0 0 0 0 0 9
@@ -333,9 +354,13 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
                 }
                 return data;
             } else {
-                WriteBufferByteBased writeBuffer = new WriteBufferByteBased(DataItem.getLengthInBytes(plcValue, tagDataType, plcValue.getLength(), defaultPayloadByteOrder == ByteOrder.BIG_ENDIAN), defaultPayloadByteOrder);
-                DataItem.staticSerialize(writeBuffer, plcValue, tagDataType, plcValue.getLength(), defaultPayloadByteOrder == ByteOrder.BIG_ENDIAN);
-                return writeBuffer.getBytes();
+                WriteBufferByteBased writeBuffer = getWriteBuffer(DataItem.getLengthInBytes(plcValue, tagDataType, plcValue.getLength(), byteOrder == ModbusByteOrder.BIG_ENDIAN), byteOrder);
+                DataItem.staticSerialize(writeBuffer, plcValue, tagDataType, plcValue.getLength(), byteOrder == ModbusByteOrder.BIG_ENDIAN);
+                byte[] bytes = writeBuffer.getBytes();
+                if(byteOrder == ModbusByteOrder.BIG_ENDIAN_BYTE_SWAP || byteOrder == ModbusByteOrder.LITTLE_ENDIAN_BYTE_SWAP) {
+                    bytes = byteSwap(bytes);
+                }
+                return bytes;
             }
         } catch (SerializationException e) {
             throw new PlcRuntimeException("Unable to parse PlcValue :- " + e);
@@ -383,4 +408,67 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
         return new PlcList(Arrays.asList(values));
     }
 
+    private ReadBuffer getReadBuffer(byte[] data, ModbusByteOrder byteOrder) {
+        switch (byteOrder) {
+            case LITTLE_ENDIAN: {
+                // [4, 3, 2, 1]
+                // [8, 7, 6, 5, 4, 3, 2, 1]
+                return new ReadBufferByteBased(data, ByteOrder.LITTLE_ENDIAN);
+            }
+            case BIG_ENDIAN_BYTE_SWAP: {
+                // [2, 1, 4, 3]
+                // [2, 1, 4, 3, 6, 5, 8, 7]
+                byte[] reordered = byteSwap(data);
+                return new ReadBufferByteBased(reordered, ByteOrder.BIG_ENDIAN);
+            }
+            case LITTLE_ENDIAN_BYTE_SWAP: {
+                // [3, 4, 1, 2]
+                // [7, 8, 5, 6, 3, 4, 1, 2]
+                byte[] reordered = byteSwap(data);
+                return new ReadBufferByteBased(reordered, ByteOrder.LITTLE_ENDIAN);
+            }
+            default:
+                // 16909060
+                // [1, 2, 3, 4]
+                // 72623859790382856
+                // [1, 2, 3, 4, 5, 6, 7, 8]
+                return new ReadBufferByteBased(data, ByteOrder.BIG_ENDIAN);
+        }
+    }
+
+    private WriteBufferByteBased getWriteBuffer(int size, ModbusByteOrder byteOrder) {
+        switch (byteOrder) {
+            case LITTLE_ENDIAN: {
+                // [4, 3, 2, 1]
+                // [8, 7, 6, 5, 4, 3, 2, 1]
+                return new WriteBufferByteBased(size, ByteOrder.LITTLE_ENDIAN);
+            }
+            case BIG_ENDIAN_BYTE_SWAP: {
+                // [2, 1, 4, 3]
+                // [2, 1, 4, 3, 6, 5, 8, 7]
+                return new WriteBufferByteBased(size, ByteOrder.BIG_ENDIAN);
+            }
+            case LITTLE_ENDIAN_BYTE_SWAP: {
+                // [3, 4, 1, 2]
+                // [7, 8, 5, 6, 3, 4, 1, 2]
+                return new WriteBufferByteBased(size, ByteOrder.LITTLE_ENDIAN);
+            }
+            default:
+                // 16909060
+                // [1, 2, 3, 4]
+                // 72623859790382856
+                // [1, 2, 3, 4, 5, 6, 7, 8]
+                return new WriteBufferByteBased(size, ByteOrder.BIG_ENDIAN);
+        }
+    }
+
+    public static byte[] byteSwap(byte[] in) {
+        byte[] out = new byte[in.length];
+        for(int i = 0; i < out.length; i += 2) {
+            out[i] = in[i + 1];
+            out[i + 1] = in[i];
+        }
+        return out;
+    }
+
 }
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/tag/ModbusTag.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/tag/ModbusTag.java
index 1b4cc0c29f..ba571f9ae1 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/tag/ModbusTag.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/tag/ModbusTag.java
@@ -23,6 +23,7 @@ import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcTag;
 import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.modbus.readwrite.*;
+import org.apache.plc4x.java.modbus.types.ModbusByteOrder;
 import org.apache.plc4x.java.spi.codegen.WithOption;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
@@ -46,6 +47,7 @@ public abstract class ModbusTag implements PlcTag, Serializable {
 
     private final ModbusDataType dataType;
     private final Short unitId;
+    private final ModbusByteOrder byteOrder;
 
     public static ModbusTag of(String addressString) {
         if (ModbusTagCoil.matches(addressString)) {
@@ -103,6 +105,11 @@ public abstract class ModbusTag implements PlcTag, Serializable {
         this.unitId = Optional.ofNullable(config.get("unit-id"))
             .map(Short::parseShort)
             .orElse(null);
+        if(config.containsKey("byte-order")) {
+            this.byteOrder = ModbusByteOrder.valueOf(config.get("byte-order"));
+        } else {
+            this.byteOrder = null;
+        }
     }
 
     /**
@@ -117,6 +124,10 @@ public abstract class ModbusTag implements PlcTag, Serializable {
         return unitId;
     }
 
+    public ModbusByteOrder getByteOrder() {
+        return byteOrder;
+    }
+
     /**
      * Get the logical (configured) address
      * @return The address which was configured and is different from what is used on the wire.
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/config/ModbusRtuConfiguration.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/config/ModbusRtuConfiguration.java
index 9525ef5f79..619e294244 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/config/ModbusRtuConfiguration.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/config/ModbusRtuConfiguration.java
@@ -18,13 +18,13 @@
  */
 package org.apache.plc4x.java.modbus.rtu.config;
 
+import org.apache.plc4x.java.modbus.types.ModbusByteOrder;
 import org.apache.plc4x.java.spi.configuration.PlcConnectionConfiguration;
 import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.spi.configuration.annotations.Description;
 import org.apache.plc4x.java.spi.configuration.annotations.Since;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.StringDefaultValue;
-import org.apache.plc4x.java.spi.generation.ByteOrder;
 
 public class ModbusRtuConfiguration implements PlcConnectionConfiguration {
 
@@ -44,9 +44,11 @@ public class ModbusRtuConfiguration implements PlcConnectionConfiguration {
     @Description("Default encoding used for transporting register values (Defaults to BIG_ENDIAN).\n" +
         "Allowed values are: \n" +
         " - BIG_ENDIAN\n" +
-        " - LITTLE_ENDIAN")
+        " - LITTLE_ENDIAN\n" +
+        " - BIG_ENDIAN_BYTE_SWAP\n" +
+        " - LITTLE_ENDIAN_BYTE_SWAP\n")
     @Since("0.13.0")
-    private ByteOrder defaultPayloadByteOrder;
+    private ModbusByteOrder defaultPayloadByteOrder;
 
     public int getRequestTimeout() {
         return requestTimeout;
@@ -64,11 +66,11 @@ public class ModbusRtuConfiguration implements PlcConnectionConfiguration {
         this.defaultUnitIdentifier = defaultUnitIdentifier;
     }
 
-    public ByteOrder getDefaultPayloadByteOrder() {
+    public ModbusByteOrder getDefaultPayloadByteOrder() {
         return defaultPayloadByteOrder;
     }
 
-    public void setDefaultPayloadByteOrder(ByteOrder defaultPayloadByteOrder) {
+    public void setDefaultPayloadByteOrder(ModbusByteOrder defaultPayloadByteOrder) {
         this.defaultPayloadByteOrder = defaultPayloadByteOrder;
     }
 
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/protocol/ModbusRtuProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/protocol/ModbusRtuProtocolLogic.java
index c28b1287c2..e3ad6e07b1 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/protocol/ModbusRtuProtocolLogic.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/protocol/ModbusRtuProtocolLogic.java
@@ -27,6 +27,7 @@ import org.apache.plc4x.java.modbus.base.tag.ModbusTag;
 import org.apache.plc4x.java.modbus.base.protocol.ModbusProtocolLogic;
 import org.apache.plc4x.java.modbus.readwrite.*;
 import org.apache.plc4x.java.modbus.rtu.config.ModbusRtuConfiguration;
+import org.apache.plc4x.java.modbus.types.ModbusByteOrder;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
 import org.apache.plc4x.java.spi.generation.ParseException;
@@ -120,7 +121,11 @@ public class ModbusRtuProtocolLogic extends ModbusProtocolLogic<ModbusRtuADU> im
                         responseCode = getErrorCode(errorResponse);
                     } else {
                         try {
-                            plcValue = toPlcValue(requestPdu, responsePdu, tag.getDataType());
+                            ModbusByteOrder byteOrder = defaultPayloadByteOrder;
+                            if(tag.getByteOrder() != null) {
+                                byteOrder = tag.getByteOrder();
+                            }
+                            plcValue = toPlcValue(requestPdu, responsePdu, tag.getDataType(), byteOrder);
                             responseCode = PlcResponseCode.OK;
                         } catch (ParseException e) {
                             // Add an error response code ...
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/config/ModbusTcpConfiguration.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/config/ModbusTcpConfiguration.java
index 4b8ec677a0..fe0214aadc 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/config/ModbusTcpConfiguration.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/config/ModbusTcpConfiguration.java
@@ -18,13 +18,13 @@
  */
 package org.apache.plc4x.java.modbus.tcp.config;
 
+import org.apache.plc4x.java.modbus.types.ModbusByteOrder;
 import org.apache.plc4x.java.spi.configuration.PlcConnectionConfiguration;
 import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.spi.configuration.annotations.Description;
 import org.apache.plc4x.java.spi.configuration.annotations.Since;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.StringDefaultValue;
-import org.apache.plc4x.java.spi.generation.ByteOrder;
 
 public class ModbusTcpConfiguration implements PlcConnectionConfiguration {
 
@@ -48,9 +48,11 @@ public class ModbusTcpConfiguration implements PlcConnectionConfiguration {
     @Description("Default encoding used for transporting register values (Defaults to BIG_ENDIAN).\n" +
         "Allowed values are: \n" +
         " - BIG_ENDIAN\n" +
-        " - LITTLE_ENDIAN")
+        " - LITTLE_ENDIAN\n" +
+        " - BIG_ENDIAN_BYTE_SWAP\n" +
+        " - LITTLE_ENDIAN_BYTE_SWAP\n")
     @Since("0.13.0")
-    private ByteOrder defaultPayloadByteOrder;
+    private ModbusByteOrder defaultPayloadByteOrder;
 
     public int getRequestTimeout() {
         return requestTimeout;
@@ -76,11 +78,11 @@ public class ModbusTcpConfiguration implements PlcConnectionConfiguration {
         this.pingAddress = pingAddress;
     }
 
-    public ByteOrder getDefaultPayloadByteOrder() {
+    public ModbusByteOrder getDefaultPayloadByteOrder() {
         return defaultPayloadByteOrder;
     }
 
-    public void setDefaultPayloadByteOrder(ByteOrder defaultPayloadByteOrder) {
+    public void setDefaultPayloadByteOrder(ModbusByteOrder defaultPayloadByteOrder) {
         this.defaultPayloadByteOrder = defaultPayloadByteOrder;
     }
 
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/protocol/ModbusTcpProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/protocol/ModbusTcpProtocolLogic.java
index 011127f6f7..ced1e1396d 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/protocol/ModbusTcpProtocolLogic.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/protocol/ModbusTcpProtocolLogic.java
@@ -28,6 +28,7 @@ import org.apache.plc4x.java.modbus.base.protocol.ModbusProtocolLogic;
 import org.apache.plc4x.java.modbus.base.tag.ModbusTagHandler;
 import org.apache.plc4x.java.modbus.readwrite.*;
 import org.apache.plc4x.java.modbus.tcp.config.ModbusTcpConfiguration;
+import org.apache.plc4x.java.modbus.types.ModbusByteOrder;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
 import org.apache.plc4x.java.spi.generation.ParseException;
@@ -136,7 +137,11 @@ public class ModbusTcpProtocolLogic extends ModbusProtocolLogic<ModbusTcpADU> im
                         responseCode = getErrorCode(errorResponse);
                     } else {
                         try {
-                            plcValue = toPlcValue(requestPdu, responsePdu, tag.getDataType());
+                            ModbusByteOrder byteOrder = defaultPayloadByteOrder;
+                            if(tag.getByteOrder() != null) {
+                                byteOrder = tag.getByteOrder();
+                            }
+                            plcValue = toPlcValue(requestPdu, responsePdu, tag.getDataType(), byteOrder);
                             responseCode = PlcResponseCode.OK;
                         } catch (ParseException e) {
                             // Add an error response code ...
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/types/ModbusByteOrder.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/types/ModbusByteOrder.java
index 5ed24e339e..98415071fc 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/types/ModbusByteOrder.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/types/ModbusByteOrder.java
@@ -19,13 +19,16 @@
 package org.apache.plc4x.java.modbus.types;
 
 public enum ModbusByteOrder {
-    //A B C D
+    // [1, 2, 3, 4]
+    // [1, 2, 3, 4, 5, 6, 7, 8]
     BIG_ENDIAN,
-    //D C B A
+    // [4, 3, 2, 1]
+    // [8, 7, 6, 5, 4, 3, 2, 1]
     LITTLE_ENDIAN,
-    //B A D C
-    BIG_ENDIAN_WORD_SWAP,
-    //C D A B
-    LITTLE_ENDIAN_WORD_SWAP
-
+    // [2, 1, 4, 3]
+    // [2, 1, 4, 3, 6, 5, 8, 7]
+    BIG_ENDIAN_BYTE_SWAP,
+    // [3, 4, 1, 2]
+    // [7, 8, 5, 6, 3, 4, 1, 2]
+    LITTLE_ENDIAN_BYTE_SWAP
 }
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtils.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtils.java
deleted file mode 100644
index ba98349ad0..0000000000
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtils.java
+++ /dev/null
@@ -1,101 +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
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.modbus.utils;
-
-public class ByteOrderUtils {
-
-    /**
-     * Byte order is 'A B C D'
-     * @param num int number
-     * @return int number in big endian format
-     */
-    public static int toBigEndian(int num){
-        return num;
-    }
-
-    /**
-     * Byte order is 'D C B A'
-     * @param num int number
-     * @return int number in little endian format
-     */
-    public static int toLittleEndian(int num){
-        return Integer.reverseBytes(num);
-    }
-
-    /**
-     * Byte order is 'B A D C'
-     * @param num int number
-     * @return int number in big endian swap format
-     */
-    public static int toBigEndianWordSwap(int num){
-        return (num << 16)|(num >>> 16);
-    }
-
-    /**
-     * Byte order is 'C D A B'
-     * @param num int number
-     * @return int number in little endian swap format
-     */
-    public static int toLittleEndianWordSwap(int num){
-        return ((num&0xff00)>>>8)|
-                ((num<<8)&0xff00)|
-                ((num<<8)&0xff000000)|
-                ((num &0xff000000)>>>8);
-    }
-
-    /**
-     * Byte order is 'A B C D E F G H'
-     * @param num long number
-     * @return long number in big endian format
-     */
-    public static long toBigEndian(long num){
-        return num;
-    }
-
-    /**
-     * Byte order is 'H G F E D C B A'
-     * @param num long number
-     * @return long number in little endian format
-     */
-    public static long toLittleEndian(long num){
-        return Long.reverseBytes(num);
-    }
-
-    /**
-     * Byte order is 'B A D C F E H G'
-     * @param num long number
-     * @return long number in big endian format
-     */
-    public static long toBigEndianWordSwap(long num){
-        return (num & 0x00ff00ff00ff00ffL) << 8 | (num >>> 8) & 0x00ff00ff00ff00ffL;
-    }
-
-    /**
-     * Byte order is 'G H E F C D A B'
-     * @param num long number
-     * @return long number in little endian format
-     */
-    public static long toLittleEndianWordSwap(long num){
-        return (num & 0xffff000000000000L) >>> 48 |
-               (num & 0x0000ffff00000000L) >>> 16 |
-               (num & 0x00000000ffff0000L) << 16 |
-               (num & 0x000000000000ffffL) << 48;
-    }
-
-}
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualDriverTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualDriverTest.java
new file mode 100644
index 0000000000..297adf5eb3
--- /dev/null
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualDriverTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.modbus;
+
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+
+public class ManualDriverTest {
+
+    /**
+     * Test programm made to work with the Modbus Simulator from https://www.modbustools.com/modbus_slave.html
+     * In contrast to others, this allows simulating the various types of modbus byte orders.
+     *
+     * @param args
+     * @throws Exception
+     */
+    public static void main(String[] args) throws Exception {
+        //final PlcConnection connection = new DefaultPlcDriverManager().getConnection("modbus-tcp://10.211.55.3?default-payload-byte-order=BIG_ENDIAN");
+        final PlcConnection connection = new DefaultPlcDriverManager().getConnection("modbus-tcp://10.211.55.3?default-payload-byte-order=LITTLE_ENDIAN");
+        //final PlcConnection connection = new DefaultPlcDriverManager().getConnection("modbus-tcp://10.211.55.3?default-payload-byte-order=BIG_ENDIAN_BYTE_SWAP");
+        //final PlcConnection connection = new DefaultPlcDriverManager().getConnection("modbus-tcp://10.211.55.3?default-payload-byte-order=LITTLE_ENDIAN_BYTE_SWAP");
+        final PlcReadRequest readRequest = connection.readRequestBuilder()
+            .addTagAddress("16 bit BigEndian", "holding-register:1:WORD{byte-order:'BIG_ENDIAN'}")
+            .addTagAddress("16 bit LittleEndian", "holding-register:2:WORD{byte-order:'LITTLE_ENDIAN'}")
+            .addTagAddress("32 bit BigEndian", "holding-register:3:DWORD{byte-order:'BIG_ENDIAN'}")
+            .addTagAddress("32 bit LittleEndian", "holding-register:5:DWORD{byte-order:'LITTLE_ENDIAN'}")
+            .addTagAddress("32 bit BigEndianByteSwap", "holding-register:7:DWORD{byte-order:'BIG_ENDIAN_BYTE_SWAP'}")
+            .addTagAddress("32 bit LittleEndianByteSwap", "holding-register:9:DWORD{byte-order:'LITTLE_ENDIAN_BYTE_SWAP'}")
+            .addTagAddress("64 bit BigEndian", "holding-register:11:LWORD{byte-order:'BIG_ENDIAN'}")
+            .addTagAddress("64 bit LittleEndian", "holding-register:15:LWORD{byte-order:'LITTLE_ENDIAN'}")
+            .addTagAddress("64 bit BigEndianByteSwap", "holding-register:19:LWORD{byte-order:'BIG_ENDIAN_BYTE_SWAP'}")
+            .addTagAddress("64 bit LittleEndianByteSwap", "holding-register:23:LWORD{byte-order:'LITTLE_ENDIAN_BYTE_SWAP'}")
+            .build();
+        final PlcReadResponse plcReadResponse = readRequest.execute().get();
+        connection.close();
+        System.out.println("16 bit BigEndian:            " + String.format("0x%04X", plcReadResponse.getInteger("16 bit BigEndian")));
+        System.out.println("16 bit LittleEndian:         " + String.format("0x%04X", plcReadResponse.getInteger("16 bit LittleEndian")));
+        System.out.println("32 bit BigEndian:            " + String.format("0x%08X", plcReadResponse.getInteger("32 bit BigEndian")));
+        System.out.println("32 bit LittleEndian:         " + String.format("0x%08X", plcReadResponse.getInteger("32 bit LittleEndian")));
+        System.out.println("32 bit BigEndianByteSwap:    " + String.format("0x%08X", plcReadResponse.getInteger("32 bit BigEndianByteSwap")));
+        System.out.println("32 bit LittleEndianByteSwap: " + String.format("0x%08X", plcReadResponse.getInteger("32 bit LittleEndianByteSwap")));
+        System.out.println("64 bit BigEndian:            " + String.format("0x%016X", plcReadResponse.getLong("64 bit BigEndian")));
+        System.out.println("64 bit LittleEndian:         " + String.format("0x%016X", plcReadResponse.getLong("64 bit LittleEndian")));
+        System.out.println("64 bit BigEndianByteSwap:    " + String.format("0x%016X", plcReadResponse.getLong("64 bit BigEndianByteSwap")));
+        System.out.println("64 bit LittleEndianByteSwap: " + String.format("0x%016X", plcReadResponse.getLong("64 bit LittleEndianByteSwap")));
+    }
+
+}
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusTCPDriverTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusTCPDriverTest.java
index 7f489b851f..39e3e0e656 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusTCPDriverTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusTCPDriverTest.java
@@ -72,7 +72,7 @@ public class ManualModbusTCPDriverTest extends ManualTest {
         ManualModbusTCPDriverTest test = new ManualModbusTCPDriverTest("modbus-tcp://192.168.23.30");
         test.addTestCase("holding-register:1:BOOL", new PlcBOOL(true)); // 0001
         test.addTestCase("holding-register:2:BYTE", new PlcBYTE(42)); // 2A
-        test.addTestCase("holding-register:3:WORD", new PlcWORD(42424)); // A5B8
+        //test.addTestCase("holding-register:3:WORD", new PlcWORD(42424)); // A5B8
         test.addTestCase("holding-register:4:DWORD", new PlcDWORD(4242442424L)); // FCDE 88B8
 //        test.addTestCase("holding-register:6:LWORD", new PlcLWORD(4242442424242424242L)); // FCDE 88B8 FCDE 88B8
         test.addTestCase("holding-register:10:SINT", new PlcSINT(-42)); // D6
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtilsTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtilsTest.java
deleted file mode 100644
index 6055fafb12..0000000000
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtilsTest.java
+++ /dev/null
@@ -1,79 +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.modbus.utils;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-class ByteOrderUtilsTest {
-
-    static final int INT_INPUT =   0x01020304;
-    static final long LONG_INPUT = 0x0102030405060708L;
-
-    @Test
-    void testIntToBigEndian() {
-        assertEquals(0x01020304, ByteOrderUtils.toBigEndian(INT_INPUT));
-        assertEquals(INT_INPUT, ByteOrderUtils.toBigEndian(ByteOrderUtils.toBigEndian(INT_INPUT)));
-    }
-
-    @Test
-    void testIntToLittleEndian() {
-        assertEquals(0x04030201, ByteOrderUtils.toLittleEndian(INT_INPUT));
-        assertEquals(INT_INPUT, ByteOrderUtils.toLittleEndian(ByteOrderUtils.toLittleEndian(INT_INPUT)));
-    }
-
-    @Test
-    void testIntToBigEndianWordSwap() {
-        assertEquals(0x03040102, ByteOrderUtils.toBigEndianWordSwap(INT_INPUT));
-        assertEquals(INT_INPUT, ByteOrderUtils.toBigEndianWordSwap(ByteOrderUtils.toBigEndianWordSwap(INT_INPUT)));
-    }
-
-    @Test
-    void testIntToLittleEndianWordSwap() {
-        assertEquals(0x02010403, ByteOrderUtils.toLittleEndianWordSwap(INT_INPUT));
-        assertEquals(INT_INPUT, ByteOrderUtils.toLittleEndianWordSwap(ByteOrderUtils.toLittleEndianWordSwap(INT_INPUT)));
-    }
-
-    @Test
-    void testLongToBigEndian() {
-        assertEquals(0x0102030405060708L, ByteOrderUtils.toBigEndian(LONG_INPUT));
-        assertEquals(LONG_INPUT, ByteOrderUtils.toBigEndian(ByteOrderUtils.toBigEndian(LONG_INPUT)));
-    }
-
-    @Test
-    void testLongToLittleEndian() {
-        assertEquals(0x0807060504030201L, ByteOrderUtils.toLittleEndian(LONG_INPUT));
-        assertEquals(LONG_INPUT, ByteOrderUtils.toLittleEndian(ByteOrderUtils.toLittleEndian(LONG_INPUT)));
-    }
-
-    @Test
-    void testLongToBigEndianWordSwap() {
-        assertEquals(0x0201040306050807L, ByteOrderUtils.toBigEndianWordSwap(LONG_INPUT));
-        assertEquals(LONG_INPUT, ByteOrderUtils.toBigEndianWordSwap(ByteOrderUtils.toBigEndianWordSwap(LONG_INPUT)));
-    }
-
-    @Test
-    void testLongToLittleEndianWordSwap() {
-        assertEquals(0x0708050603040102L, ByteOrderUtils.toLittleEndianWordSwap(LONG_INPUT));
-        assertEquals(LONG_INPUT, ByteOrderUtils.toLittleEndianWordSwap(ByteOrderUtils.toLittleEndianWordSwap(LONG_INPUT)));
-    }
-
-}
\ No newline at end of file
diff --git a/src/site/asciidoc/users/protocols/modbus.adoc b/src/site/asciidoc/users/protocols/modbus.adoc
index 688b02a99f..5f210f50c6 100644
--- a/src/site/asciidoc/users/protocols/modbus.adoc
+++ b/src/site/asciidoc/users/protocols/modbus.adoc
@@ -68,11 +68,12 @@ Note the transport, port and option fields are optional.
 In general all Modbus addresses have this format:
 
 ----
-{memory-Area}{start-address}:{data-type}[{array-size}]
+{memory-Area}{start-address}:{data-type}[{array-size}]:{name-value-tag-options}
 ----
 
 If the array-size part is omitted, the size-default of `1` is assumed.
 If the data-type part is omitted, it defaults to BOOL for Coils and Discrete Inputs and INT for input, holding and extended registers.
+If the name-value-tag-options part is omitted, simply no configuration fine-tuning is applied.
 
 Additionally address can contain tag configuration:
 ----
@@ -80,6 +81,11 @@ Additionally address can contain tag configuration:
 ----
 Specifying this value overrides value of `default-unit-id` parameter specified at the connection string.
 
+----
+{byte-order: 'LITTLE_ENDIAN'}
+----
+With this, can the default byte-order be overridden on a per-tag basis. If not provided the default-byte-order from the connection string is used, or BIG_ENDIAN, if this is also not provided.
+
 ==== Memory Areas
 
 There are a number of memory areas defined in the Modbus specification.