Skip to content

Commit 864791a

Browse files
authored
Customizable TransactionSequence in ModbusTcpClient (#74)
1 parent f8c889f commit 864791a

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

modbus/src/main/java/com/digitalpetri/modbus/client/ModbusTcpClient.java

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import java.util.concurrent.ExecutionException;
2020
import java.util.concurrent.TimeUnit;
2121
import java.util.concurrent.TimeoutException;
22-
import java.util.concurrent.atomic.AtomicInteger;
22+
import java.util.concurrent.atomic.AtomicReference;
2323
import java.util.function.Consumer;
2424
import org.slf4j.Logger;
2525
import org.slf4j.LoggerFactory;
@@ -33,17 +33,27 @@ public class ModbusTcpClient extends ModbusClient {
3333

3434
private final Logger logger = LoggerFactory.getLogger(getClass());
3535

36-
private final TransactionSequence transactionSequence = new TransactionSequence();
3736
private final Map<Integer, ResponsePromise> promises = new ConcurrentHashMap<>();
3837

39-
private final ModbusTcpClientTransport transport;
4038
private final ModbusClientConfig config;
39+
private final ModbusTcpClientTransport transport;
40+
private final TransactionSequence transactionSequence;
4141

4242
public ModbusTcpClient(ModbusClientConfig config, ModbusTcpClientTransport transport) {
43+
this(config, transport, new DefaultTransactionSequence());
44+
}
45+
46+
public ModbusTcpClient(
47+
ModbusClientConfig config,
48+
ModbusTcpClientTransport transport,
49+
TransactionSequence transactionSequence
50+
) {
51+
4352
super(transport);
4453

4554
this.config = config;
4655
this.transport = transport;
56+
this.transactionSequence = transactionSequence;
4757

4858
transport.receive(this::onFrameReceived);
4959
}
@@ -224,12 +234,44 @@ private record ResponsePromise(
224234
TimeoutHandle timeout
225235
) {}
226236

227-
static class TransactionSequence {
237+
public interface TransactionSequence {
238+
239+
/**
240+
* Return the next 2-byte transaction identifier. Range is [0, 65535] by default.
241+
*
242+
* @return the next 2-byte transaction identifier.
243+
*/
244+
int next();
245+
}
246+
247+
public static class DefaultTransactionSequence implements TransactionSequence {
228248

229-
private final AtomicInteger transactionId = new AtomicInteger(0);
249+
private final int low;
250+
private final int high;
230251

231-
int next() {
232-
return transactionId.getAndIncrement() & 0xFFFF;
252+
private final AtomicReference<Integer> transactionId = new AtomicReference<>(0);
253+
254+
public DefaultTransactionSequence() {
255+
this(0, 65535);
256+
}
257+
258+
public DefaultTransactionSequence(int low, int high) {
259+
this.low = low;
260+
this.high = high;
261+
262+
transactionId.set(low);
263+
}
264+
265+
@Override
266+
public int next() {
267+
while (true) {
268+
Integer id = transactionId.get();
269+
Integer nextId = id >= high ? low : id + 1;
270+
271+
if (transactionId.compareAndSet(id, nextId)) {
272+
return id;
273+
}
274+
}
233275
}
234276

235277
}

modbus/src/test/java/com/digitalpetri/modbus/client/TransactionSequenceTest.java renamed to modbus/src/test/java/com/digitalpetri/modbus/client/DefaultTransactionSequenceTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
44

5-
import com.digitalpetri.modbus.client.ModbusTcpClient.TransactionSequence;
5+
import com.digitalpetri.modbus.client.ModbusTcpClient.DefaultTransactionSequence;
66
import org.junit.jupiter.api.Test;
77

8-
class TransactionSequenceTest {
8+
class DefaultTransactionSequenceTest {
99

1010
@Test
1111
void rollover() {
12-
TransactionSequence sequence = new TransactionSequence();
12+
DefaultTransactionSequence sequence = new DefaultTransactionSequence();
1313

1414
// Assert that transactions are generated in the range [0, 65535]
1515
// and that they roll over back to 0.

0 commit comments

Comments
 (0)