Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -208,11 +209,25 @@ protected PlcReadResponse processReadResponses(PlcReadRequest readRequest, Map<P

// Calculate the byte that contains the response for this Coil
byte[] responseData = response.getResponseData();
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)));

// 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;
}
}
Expand Down Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}