Have to implement call to Digital IO with Modbus protocol on Spring Boot project build by Maven.
It should be a pulsed call with some duration at the body (like 5 seconds, etc.)
Here is a snippet from the specification:
And more about Response and Errors:
Seems at this call application should behave like a master. And Web Relay should be like a slave in this case.
I suppose that taking some library for integrating with Modbus will be much more preferable than writing it from zero.
Which approach will be preferable to adopt this functionality with Spring Boot?
Here are Web Relay manuals.
UPDATE:
Tried answer by KevinHerron
Here is the code part:
@Override
public void callDigitalIO(String ipAddress, String relay) {
log.debug("call Digital IO by MODBUS");
checkNotEmpty(ipAddress, relay);
ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder(ipAddress).build();
ModbusTcpMaster master = new ModbusTcpMaster(config);
master.connect();
ByteBuf buffer = Unpooled.buffer();
buffer.writeInt(0x00003F00);
buffer.writeInt(0x000040A0);
int relayNum = Integer.parseInt(relay);
WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(
relayNum,
0x02 * relayNum,
buffer
);
log.debug("MODBUS_REQUEST: {}", request);
master.sendRequest(request, 0xFF)
.whenCompleteAsync((response, ex) -> {
if (response != null) {
log.info("MODBUS_RESPONSE: {}", response);
} else {
log.error("EXECUTION_FAILED: {}", ex.getMessage(), ex);
}
});
master.disconnect();
}
Tried below snippet with a real device, the output is following:
2021-02-25 22-07-03.955 [carpark-ex-4] DEBUG c.s.s.dio.ModbusDigitalIoServiceImpl - MODBUS_REQUEST: WriteMultipleRegistersRequest(UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 0, widx: 8, cap: 256))
2021-02-25 22-07-03.970 [ForkJoinPool.commonPool-worker-5] ERROR c.s.s.dio.ModbusDigitalIoServiceImpl - EXECUTION_FAILED: not connected
java.lang.Exception: not connected
at com.digitalpetri.netty.fsm.ChannelFsmFactory.lambda$null$2(ChannelFsmFactory.java:115)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:832)
Only when I did:
master.sendRequest(request, 0xFF).get()
it started to work.