[Feature Request]: Modbus: Support for Word Swap
- Dominant language
- Java
- Stars
- 1.7k
- Forks
- 504
- Avg merge
- 10h 55m
- Merged PRs (30d)
- 43
Description
### What would you like to happen?
The 0.13.0 version of the Modbus driver introduced the endianness and byte swapping features, but there is still one feature that should be added - word swapping. Word swapping swaps sequential word pairs (or registers), which is relevant with 64-bit values. For example, with 4 registers totalling 8 bytes:
Big Endian :
`[1, 2] [3, 4] [5, 6] [7, 8]`
Big Endian with Word Swap:
`[3, 4] [1, 2] [7, 8] [5, 6]`
Big Endian with Word Swap and Byte Swap:
`[4, 3] [2, 1] [8, 7] [6, 5]`
I'm not sure if the LittleEndian was thought to be for this use originally, but as it reverses the entire sequence, it is conceptually different from Modbus word swapping for large data types.
I have created an implementation by extending the `ModbusByteOrder` with additional members:
```
// [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
```
And in addition, to complement `byteSwap()`, I've added `wordSwap()`:
```
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;
}
```
So, depending on the `ModbusByteOrder`, a combination of these methods are applied. My implementation currently is built on top of the previous PR #2055, I could either expand that PR to be more generic for Modbus improvements, or if it can be handled first, I can make a separate PR with the implementation.
### Programming Languages
- [x] plc4j
- [ ] plc4go
- [ ] plc4c
- [ ] plc4net
### Protocols
- [ ] AB-Ethernet
- [ ] ADS /AMS
- [ ] BACnet/IP
- [ ] CANopen
- [ ] DeltaV
- [ ] DF1
- [ ] EtherNet/IP
- [ ] Firmata
- [ ] KNXnet/IP
- [x] Modbus
- [ ] OPC-UA
- [ ] S7
Contributor guide
Research direction
Locate the plc4j ModbusByteOrder enum and existing byteSwap() path, then compare the proposed behavior with PR #2055. Done means plc4j Modbus supports the four word-swap and byte-swap combinations shown, including word-swap input validation; the payload names no tests, so identify the relevant test entry point before changing code.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- embedded-iot
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100