apache / apache/plc4x

[Feature Request]: Modbus: Support for Word Swap

Open
#2,059 6 comments 0 reactions 0 assignees View on GitHub
java Modbus
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.