diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/optimizer/ModbusOptimizer.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/optimizer/ModbusOptimizer.java index 0bde206c48a..f09ff963e08 100644 --- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/optimizer/ModbusOptimizer.java +++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/optimizer/ModbusOptimizer.java @@ -51,6 +51,7 @@ import org.apache.plc4x.java.spi.messages.utils.PlcTagItem; import org.apache.plc4x.java.spi.optimizer.SingleTagOptimizer; import org.apache.plc4x.java.spi.values.PlcBOOL; +import org.apache.plc4x.java.spi.values.PlcList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -208,11 +209,25 @@ protected PlcReadResponse processReadResponses(PlcReadRequest readRequest, Map
(PlcResponseCode.OK, new PlcBOOL(isBitSet))); + + // Check if we're dealing with an array of Coils or Discrete Inputs + if (modbusTag.getNumberOfElements() > 1) { + PlcList bitValues = new PlcList(); + for (int i = 0; i < modbusTag.getNumberOfElements(); i++) { + int bitPosition = modbusTag.getAddress() - response.startingAddress + i; + int bytePosition = bitPosition / 8; + int bitPositionInByte = bitPosition % 8; + boolean isBitSet = (responseData[bytePosition] & (1 << bitPositionInByte)) != 0; + bitValues.add(new PlcBOOL(isBitSet)); + } + values.put(tagName, new DefaultPlcResponseItem<>(PlcResponseCode.OK, bitValues)); + } else { + int bitPosition = modbusTag.getAddress() - response.startingAddress; + int bytePosition = bitPosition / 8; + int bitPositionInByte = bitPosition % 8; + boolean isBitSet = (responseData[bytePosition] & (1 << bitPositionInByte)) != 0; + values.put(tagName, new DefaultPlcResponseItem<>(PlcResponseCode.OK, new PlcBOOL(isBitSet))); + } break; } } @@ -436,6 +451,32 @@ private ReadBuffer getReadBuffer(byte[] data, ModbusByteOrder byteOrder) { byte[] reordered = ModbusProtocolLogic.byteSwap(data); return new ReadBufferByteBased(reordered, ByteOrder.LITTLE_ENDIAN); } + case BIG_ENDIAN_WORD_SWAP: { + // [3, 4, 1, 2] + // [3, 4, 1, 2, 7, 8, 5, 6] + byte[] reordered = ModbusProtocolLogic.wordSwap(data); + return new ReadBufferByteBased(reordered, ByteOrder.BIG_ENDIAN); + } + case LITTLE_ENDIAN_WORD_SWAP: { + // [2, 1, 4, 3] + // [6, 5, 8, 7, 2, 1, 4, 3] + byte[] reordered = ModbusProtocolLogic.wordSwap(data); + return new ReadBufferByteBased(reordered, ByteOrder.LITTLE_ENDIAN); + } + case BIG_ENDIAN_WORD_SWAP_BYTE_SWAP: { + // [4, 3, 2, 1] + // [4, 3, 2, 1, 8, 7, 6, 5] + byte[] reordered = ModbusProtocolLogic.byteSwap(data); + reordered = ModbusProtocolLogic.wordSwap(reordered); + return new ReadBufferByteBased(reordered, ByteOrder.BIG_ENDIAN); + } + case LITTLE_ENDIAN_WORD_SWAP_BYTE_SWAP: { + // [1, 2, 3, 4] + // [5, 6, 7, 8, 1, 2, 3, 4] + byte[] reordered = ModbusProtocolLogic.byteSwap(data); + reordered = ModbusProtocolLogic.wordSwap(reordered); + return new ReadBufferByteBased(reordered, ByteOrder.LITTLE_ENDIAN); + } default: // 16909060 // [1, 2, 3, 4] 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 4e82e16b219..c454241de98 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 @@ -418,4 +418,18 @@ public static byte[] byteSwap(byte[] in) { return out; } + public static byte[] wordSwap(byte[] in) { + if (in.length % 2 != 0) { + throw new PlcRuntimeException("Input byte array length must be a multiple of 2 for word swapping."); + } + byte[] out = new byte[in.length]; + for (int i = 0; i < in.length; i += 4) { + out[i] = in[i + 2]; + out[i + 1] = in[i + 3]; + out[i + 2] = in[i]; + out[i + 3] = in[i + 1]; + } + return out; + } + } 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 98415071fc5..9f94321bcc6 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 @@ -30,5 +30,17 @@ public enum ModbusByteOrder { BIG_ENDIAN_BYTE_SWAP, // [3, 4, 1, 2] // [7, 8, 5, 6, 3, 4, 1, 2] - LITTLE_ENDIAN_BYTE_SWAP + LITTLE_ENDIAN_BYTE_SWAP, + // [3, 4, 1, 2] + // [3, 4, 1, 2, 7, 8, 5, 6] + BIG_ENDIAN_WORD_SWAP, + // [2, 1, 4, 3] + // [6, 5, 8, 7, 2, 1, 4, 3] + LITTLE_ENDIAN_WORD_SWAP, + // [4, 3, 2, 1] + // [4, 3, 2, 1, 8, 7, 6, 5] + BIG_ENDIAN_WORD_SWAP_BYTE_SWAP, + // [1, 2, 3, 4] + // [5, 6, 7, 8, 1, 2, 3, 4] + LITTLE_ENDIAN_WORD_SWAP_BYTE_SWAP, }