libmodbus icon indicating copy to clipboard operation
libmodbus copied to clipboard

RTU slave responds to requests with different slave address

Open philippludwig opened this issue 1 year ago • 1 comments

I am using libmodbus 3.1.6 and have the situation, that my modbus RTU slave application answers to requests for address 1, even though it has address 10.

Debug output:

Waiting for an indication...
<01><04><75><4A><00><01><0A><10>
Request for slave 1 ignored (not 10)
[01][04][02][36][FD][6F][11]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><04><75><4B><00><01><5B><D0>Confirmation to ignore
[01][04][02][4B][FC][8F][81]
Waiting for an indication...
<01><04><75><44><00><02><2B><D2>
Request for slave 1 ignored (not 10)
[01][04][04][00][00][E2][B2][33][51]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><04><75><46><00><01><CA><13>Confirmation to ignore
[01][04][02][69][98][96][CA]
Waiting for an indication...
<01><04><75><47><00><01><9B><D3>
Request for slave 1 ignored (not 10)
[01][04][02][79][D8][9A][FA]
Waiting for a confirmation...

So we can see that the request for slave 1 is ignored. However, the device on the other end of the line still receives data. I tried it with a proprietary device and with modpoll: Receiving data is possible, without regard for the modbus address.

Here is the relevant part of the code (error checking omitted for brevity):

ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
modbus_connect(ctx);
modbus_set_slave(ctx, 10);

I have seen that this was also asked on the mailing list, but no responses.


From reading the libmodbus source, I believe this happens because _modbus_rtu_check_integrity returns 0 which gets propagated up in _modbus_receive_msg, which’s return code is unused in the remaining part of the RTU code – but that is just my limited understanding of the code base.


Suggested fix: I changed this code in modbus-rtu.c:

/* Following call to check_confirmation handles this error */
        return 0;

to:

/* Following call to check_confirmation handles this error */
        return -1;

And now my application only answers to requests for slave address 1. However, I did not opened a PR because I am not sure if I misunderstood either how to use libmodbus correctly or how slave addresses are supposed to work. Furthermore, I am not sure if this introduces any side-effects.

philippludwig avatar Aug 02 '23 09:08 philippludwig

I had a similar issue. modbus_receive returns message length. So if slave ID doesn't match, then you just get 0 (empty message), so you could detect this case, I guess.

The solution is just check returned message length. If it's positive (>0) you can process the message.

int rc = 0;
ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
modbus_set_slave(ctx, 0xF0);
modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS232);
modbus_connect(ctx);
mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0, MODBUS_MAX_READ_REGISTERS, 0);

while(1) {
    rc = modbus_receive(ctx, query);
    if (rc > 0) {
        print_query(query, MODBUS_RTU_MAX_ADU_LENGTH);
    }
}

akmubi avatar Sep 21 '23 10:09 akmubi