libmodbus icon indicating copy to clipboard operation
libmodbus copied to clipboard

Reason for the Unaddressed Slave's "Waiting for Confirmation" in Modbus RTU

Open hadeszon opened this issue 9 months ago • 5 comments

I'm trying to understand the behavior of the Addressed Slave and Unaddressed Slave in Libmodbus.

When there's a request for the Slave (Addressed Slave), it respond appropriately.

Waiting for indication...
<00><00><00><00><00><00><00><00>
[00][00][00][00][00][00][00][00][00][00][00]

When there's a request but it is not for the Slave (Unaddressed Slave), it ignores the request.

Waiting for indication...
<01><00><00><00><00><00><00><00>
Request for slave 1 ignored (not 0)
Waiting for confirmation...
ERROR Connection timed out: select
Confirmation to ignore.
Waiting for indication...

But why after ignoring the request, does the Unaddressed Slave also needs to do the "Waiting for confirmation..."?

To give context, it is mentioned in the library the context for "Waiting for confirmation" (wait for response) and "Waiting for indication" (wait for request)

Further looking at the source of Libmodbus, this behavior seems to be intentional.

static int _modbus_rtu_receive(modbus_t *ctx, uint8_t *req)
{
    int rc;
    modbus_rtu_t *ctx_rtu = ctx->backend_data;

    if (ctx_rtu->confirmation_to_ignore) {
        _modbus_receive_msg(ctx, req, MSG_CONFIRMATION);
        /* Ignore errors and reset the flag */
        ctx_rtu->confirmation_to_ignore = FALSE;
        rc = 0;
        if (ctx->debug) {
            printf("Confirmation to ignore\n");
        }
    } else {
        rc = _modbus_receive_msg(ctx, req, MSG_INDICATION);
        if (rc == 0) {
            /* The next expected message is a confirmation to ignore */
            ctx_rtu->confirmation_to_ignore = TRUE;
        }
    }
    return rc;
}

But why does the Unaddressed Slave, waits for a response? What is the purpose or reason for "Waiting for confirmation" in this behavior? And is the behavior even necessary? Is it possible to completely change this to directly ignore without any further implications?

hadeszon avatar Mar 07 '25 23:03 hadeszon

Modbus is typically used with multiple slave devices on one bus, e.g. on a RS-485 bus. When the request is not for your device, then usually there is another one which responds - the addressed one. libmodbus - since on the same shared bus - sees this response too and thus needs to discard it.

mhei avatar Mar 08 '25 17:03 mhei

Thank you mhei, and to further provide explaination regarding your answer, here's a scenario

Master request 01 03 00 01 00 02 97 5B

Slave 1

Waiting for indication….   		(<--- Slave 1 waits for request)
01 03 00 01 00 02 97 5B 		(<--- Master request is received)
01 03 04 00 1D 00 30 6A 21 		(<--- Slave 1 respond)

Slave 0

Waiting for indication….  		  		(<--- Slave 0 waits for request)
01 03 00 01 00 02 97 5B  		  		(<--- Master request is received)
Request for slave 11 ignore (not 20)  		(<--- Slave 20 ignore the request)
Waiting for confirmation…  		  		(<--- To expect the response of another slave)
01 03 04 00 1D 00 30 6A 21  		  		(<--- Slave 1 response)
Confirmation to ignore.  		  		(<--- Ignore the response and discard it)

If Slave 0, does not do the “Waiting for confirmation” and directly listen to request again by doing the “Waiting for indication”, it will accept the response of other slaves in this case Slave 1

Slave 0

Waiting for indication….  		  		(<--- Slave 0 waits for request)
11 03 00 01 00 02 97 5B  		  		(<--- Master request is received)
Request for slave 11 ignore (not 20)  		(<--- Slave 20 ignore the request)
Ignore  		  		  		  		(<--- To not expect the response of another slave)
Waiting for indication….  		  		(<--- Slave 0 waits for request)
01 03 04 00 1D 00 30 6A 21  		  		(<--- Slave 1 response is received as a request)
ERROR CRC received  		  		  	(<--- The request frame is not valid)

In this case, it will process the frame but since the CRC of that frame is invalid, an error will occur then the remaining frame …21 is accepted, which results to error again.

Slave 0 must do the “Waiting for confirmation” to expect that the next receive is the response of another slave in this case Slave 1 and to discard or ignore it.

hadeszon avatar Mar 09 '25 02:03 hadeszon

I think we can close the issue here?

mhei avatar Mar 09 '25 18:03 mhei

I got a question. if there is two server device address 1 and 2, device 2 is offline, and client wants to request in a loop act like:

request address 2;     client -> server 2
timeout;                     client time out because device 2 is offline         
request address 1;     client -> server 1
timeout;                     client time out because device 1 is expecting a confirmation to ignore
request address 2;     client -> server 2
...and so on

in this case, the client request address 2, and the address 2 device is offline, at this moment the address 1 server will ignore the further one package. If client after request address 2 and timeout then directly request address 1 server, the address 1 server will ignore this request and needs client to retransmit, but if client just loop this will be a infinite fail loop.

Is this situation should be handled by the client? I feel like if the server just don't wait for confirmation which is not for the server address, there will not have this problem, and even the server get the response comes from other server, because the address is not for it, it will ignore the package anyway. Is there a recommended way to solve this kind of problem?

Zhaotianzheng avatar Jun 06 '25 15:06 Zhaotianzheng

I got a question. if there is two server device address 1 and 2, device 2 is offline, and client wants to request in a loop act like:

request address 2;     client -> server 2
timeout;                     client time out because device 2 is offline         
request address 1;     client -> server 1
timeout;                     client time out because device 1 is expecting a confirmation to ignore
request address 2;     client -> server 2
...and so on

in this case, the client request address 2, and the address 2 device is offline, at this moment the address 1 server will ignore the further one package. If client after request address 2 and timeout then directly request address 1 server, the address 1 server will ignore this request and needs client to retransmit, but if client just loop this will be a infinite fail loop.

Is this situation should be handled by the client? I feel like if the server just don't wait for confirmation which is not for the server address, there will not have this problem, and even the server get the response comes from other server, because the address is not for it, it will ignore the package anyway. Is there a recommended way to solve this kind of problem?

The answer is more difficult. Since the request/response sizes are different, the address 2 server will see the request for address 1 and go into the "waiting for a response" mode. When it sees its cmd code, it will wait for the size indicated by the command code, see the checksum mismatch and report an error.

See https://github.com/stephane/libmodbus/issues/723

From looking at the logs, I believe this is that exact problem.

robinmholt-daikin avatar Jul 03 '25 10:07 robinmholt-daikin