Warm tip: This article is reproduced from serverfault.com, please click

Modbus Pulse Coils with Spring Boot project

发布于 2021-02-16 18:21:40

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:

enter image description here

And more about Response and Errors:

enter image description here

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.

Questioner
catch23
Viewed
0
Kevin Herron 2021-03-05 08:56:37

This should be easy to accomplish using an existing library that supports the WriteMultipleRegisters function.

Try https://github.com/digitalpetri/modbus


An example of how to construct a WriteMultipleRegisters request based on that screenshot of documentation:

class Scratch {

  public static void main(String[] args) throws ExecutionException, InterruptedException {
    ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("ip_or_hostname").build();
    ModbusTcpMaster master = new ModbusTcpMaster(config);

    master.connect().get();

    ByteBuf buffer = Unpooled.buffer();
    buffer.writeInt(0x00003F00);
    buffer.writeInt(0x000040A0);

    WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(
        0x16,
        0x04,
        buffer
    );

    master.sendRequest(request, 0xFF).get();
  }

}