Commit c1e2e0b319b1f1fbbd663b2322162278bd48e4f5
1 parent
81a52093
New RTU receive() to ignore confirmation from other slaves (closes #18)
- export new symbols to create specific behavior (RTU) - the flag can't only be set by slaves - new tests
Showing
6 changed files
with
96 additions
and
28 deletions
src/modbus-private.h
| @@ -68,6 +68,18 @@ typedef enum { | @@ -68,6 +68,18 @@ typedef enum { | ||
| 68 | _MODBUS_BACKEND_TYPE_TCP | 68 | _MODBUS_BACKEND_TYPE_TCP |
| 69 | } modbus_bakend_type_t; | 69 | } modbus_bakend_type_t; |
| 70 | 70 | ||
| 71 | +/* | ||
| 72 | + * ---------- Request Indication ---------- | ||
| 73 | + * | Client | ---------------------->| Server | | ||
| 74 | + * ---------- Confirmation Response ---------- | ||
| 75 | + */ | ||
| 76 | +typedef enum { | ||
| 77 | + /* Request message on the server side */ | ||
| 78 | + MSG_INDICATION, | ||
| 79 | + /* Request message on the client side */ | ||
| 80 | + MSG_CONFIRMATION | ||
| 81 | +} msg_type_t; | ||
| 82 | + | ||
| 71 | /* This structure reduces the number of params in functions and so | 83 | /* This structure reduces the number of params in functions and so |
| 72 | * optimizes the speed of execution (~ 37%). */ | 84 | * optimizes the speed of execution (~ 37%). */ |
| 73 | typedef struct _sft { | 85 | typedef struct _sft { |
| @@ -88,6 +100,7 @@ typedef struct _modbus_backend { | @@ -88,6 +100,7 @@ typedef struct _modbus_backend { | ||
| 88 | int (*prepare_response_tid) (const uint8_t *req, int *req_length); | 100 | int (*prepare_response_tid) (const uint8_t *req, int *req_length); |
| 89 | int (*send_msg_pre) (uint8_t *req, int req_length); | 101 | int (*send_msg_pre) (uint8_t *req, int req_length); |
| 90 | ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length); | 102 | ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length); |
| 103 | + int (*receive) (modbus_t *ctx, uint8_t *req); | ||
| 91 | ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length); | 104 | ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length); |
| 92 | int (*check_integrity) (modbus_t *ctx, uint8_t *msg, | 105 | int (*check_integrity) (modbus_t *ctx, uint8_t *msg, |
| 93 | const int msg_length); | 106 | const int msg_length); |
| @@ -114,6 +127,7 @@ struct _modbus { | @@ -114,6 +127,7 @@ struct _modbus { | ||
| 114 | 127 | ||
| 115 | void _modbus_init_common(modbus_t *ctx); | 128 | void _modbus_init_common(modbus_t *ctx); |
| 116 | void _error_print(modbus_t *ctx, const char *context); | 129 | void _error_print(modbus_t *ctx, const char *context); |
| 130 | +int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type); | ||
| 117 | 131 | ||
| 118 | #ifndef HAVE_STRLCPY | 132 | #ifndef HAVE_STRLCPY |
| 119 | size_t strlcpy(char *dest, const char *src, size_t dest_size); | 133 | size_t strlcpy(char *dest, const char *src, size_t dest_size); |
src/modbus-rtu-private.h
| @@ -88,6 +88,8 @@ typedef struct _modbus_rtu { | @@ -88,6 +88,8 @@ typedef struct _modbus_rtu { | ||
| 88 | #if HAVE_DECL_TIOCM_RTS | 88 | #if HAVE_DECL_TIOCM_RTS |
| 89 | int rts; | 89 | int rts; |
| 90 | #endif | 90 | #endif |
| 91 | + /* To handle many slaves on the same link */ | ||
| 92 | + int confirmation_to_ignore; | ||
| 91 | } modbus_rtu_t; | 93 | } modbus_rtu_t; |
| 92 | 94 | ||
| 93 | #endif /* _MODBUS_RTU_PRIVATE_H_ */ | 95 | #endif /* _MODBUS_RTU_PRIVATE_H_ */ |
src/modbus-rtu.c
| @@ -309,6 +309,29 @@ ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) | @@ -309,6 +309,29 @@ ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) | ||
| 309 | #endif | 309 | #endif |
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | +int _modbus_rtu_receive(modbus_t *ctx, uint8_t *req) | ||
| 313 | +{ | ||
| 314 | + int rc; | ||
| 315 | + modbus_rtu_t *ctx_rtu = ctx->backend_data; | ||
| 316 | + | ||
| 317 | + if (ctx_rtu->confirmation_to_ignore) { | ||
| 318 | + _modbus_receive_msg(ctx, req, MSG_CONFIRMATION); | ||
| 319 | + /* Ignore errors and reset the flag */ | ||
| 320 | + ctx_rtu->confirmation_to_ignore = FALSE; | ||
| 321 | + rc = 0; | ||
| 322 | + if (ctx->debug) { | ||
| 323 | + printf("Confirmation to ignore\n"); | ||
| 324 | + } | ||
| 325 | + } else { | ||
| 326 | + rc = _modbus_receive_msg(ctx, req, MSG_INDICATION); | ||
| 327 | + if (rc == 0) { | ||
| 328 | + /* The next expected message is a confirmation to ignore */ | ||
| 329 | + ctx_rtu->confirmation_to_ignore = TRUE; | ||
| 330 | + } | ||
| 331 | + } | ||
| 332 | + return rc; | ||
| 333 | +} | ||
| 334 | + | ||
| 312 | ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) | 335 | ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) |
| 313 | { | 336 | { |
| 314 | #if defined(_WIN32) | 337 | #if defined(_WIN32) |
| @@ -354,6 +377,7 @@ int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, | @@ -354,6 +377,7 @@ int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, | ||
| 354 | if (ctx->debug) { | 377 | if (ctx->debug) { |
| 355 | printf("Request for slave %d ignored (not %d)\n", slave, ctx->slave); | 378 | printf("Request for slave %d ignored (not %d)\n", slave, ctx->slave); |
| 356 | } | 379 | } |
| 380 | + | ||
| 357 | return 0; | 381 | return 0; |
| 358 | } | 382 | } |
| 359 | 383 | ||
| @@ -368,6 +392,7 @@ int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, | @@ -368,6 +392,7 @@ int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, | ||
| 368 | fprintf(stderr, "ERROR CRC received %0X != CRC calculated %0X\n", | 392 | fprintf(stderr, "ERROR CRC received %0X != CRC calculated %0X\n", |
| 369 | crc_received, crc_calculated); | 393 | crc_received, crc_calculated); |
| 370 | } | 394 | } |
| 395 | + | ||
| 371 | if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { | 396 | if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { |
| 372 | _modbus_rtu_flush(ctx); | 397 | _modbus_rtu_flush(ctx); |
| 373 | } | 398 | } |
| @@ -970,6 +995,7 @@ const modbus_backend_t _modbus_rtu_backend = { | @@ -970,6 +995,7 @@ const modbus_backend_t _modbus_rtu_backend = { | ||
| 970 | _modbus_rtu_prepare_response_tid, | 995 | _modbus_rtu_prepare_response_tid, |
| 971 | _modbus_rtu_send_msg_pre, | 996 | _modbus_rtu_send_msg_pre, |
| 972 | _modbus_rtu_send, | 997 | _modbus_rtu_send, |
| 998 | + _modbus_rtu_receive, | ||
| 973 | _modbus_rtu_recv, | 999 | _modbus_rtu_recv, |
| 974 | _modbus_rtu_check_integrity, | 1000 | _modbus_rtu_check_integrity, |
| 975 | _modbus_rtu_pre_check_confirmation, | 1001 | _modbus_rtu_pre_check_confirmation, |
| @@ -1032,5 +1058,7 @@ modbus_t* modbus_new_rtu(const char *device, | @@ -1032,5 +1058,7 @@ modbus_t* modbus_new_rtu(const char *device, | ||
| 1032 | ctx_rtu->rts = MODBUS_RTU_RTS_NONE; | 1058 | ctx_rtu->rts = MODBUS_RTU_RTS_NONE; |
| 1033 | #endif | 1059 | #endif |
| 1034 | 1060 | ||
| 1061 | + ctx_rtu->confirmation_to_ignore = FALSE; | ||
| 1062 | + | ||
| 1035 | return ctx; | 1063 | return ctx; |
| 1036 | } | 1064 | } |
src/modbus-tcp.c
| @@ -178,6 +178,10 @@ ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length) | @@ -178,6 +178,10 @@ ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length) | ||
| 178 | return send(ctx->s, (const char*)req, req_length, MSG_NOSIGNAL); | 178 | return send(ctx->s, (const char*)req, req_length, MSG_NOSIGNAL); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | +int _modbus_tcp_receive(modbus_t *ctx, uint8_t *req) { | ||
| 182 | + return _modbus_receive_msg(ctx, req, MSG_INDICATION); | ||
| 183 | +} | ||
| 184 | + | ||
| 181 | ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) { | 185 | ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) { |
| 182 | return recv(ctx->s, (char *)rsp, rsp_length, 0); | 186 | return recv(ctx->s, (char *)rsp, rsp_length, 0); |
| 183 | } | 187 | } |
| @@ -597,6 +601,7 @@ const modbus_backend_t _modbus_tcp_backend = { | @@ -597,6 +601,7 @@ const modbus_backend_t _modbus_tcp_backend = { | ||
| 597 | _modbus_tcp_prepare_response_tid, | 601 | _modbus_tcp_prepare_response_tid, |
| 598 | _modbus_tcp_send_msg_pre, | 602 | _modbus_tcp_send_msg_pre, |
| 599 | _modbus_tcp_send, | 603 | _modbus_tcp_send, |
| 604 | + _modbus_tcp_receive, | ||
| 600 | _modbus_tcp_recv, | 605 | _modbus_tcp_recv, |
| 601 | _modbus_tcp_check_integrity, | 606 | _modbus_tcp_check_integrity, |
| 602 | _modbus_tcp_pre_check_confirmation, | 607 | _modbus_tcp_pre_check_confirmation, |
| @@ -618,6 +623,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = { | @@ -618,6 +623,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = { | ||
| 618 | _modbus_tcp_prepare_response_tid, | 623 | _modbus_tcp_prepare_response_tid, |
| 619 | _modbus_tcp_send_msg_pre, | 624 | _modbus_tcp_send_msg_pre, |
| 620 | _modbus_tcp_send, | 625 | _modbus_tcp_send, |
| 626 | + _modbus_tcp_receive, | ||
| 621 | _modbus_tcp_recv, | 627 | _modbus_tcp_recv, |
| 622 | _modbus_tcp_check_integrity, | 628 | _modbus_tcp_check_integrity, |
| 623 | _modbus_tcp_pre_check_confirmation, | 629 | _modbus_tcp_pre_check_confirmation, |
src/modbus.c
| @@ -26,6 +26,7 @@ | @@ -26,6 +26,7 @@ | ||
| 26 | #include <errno.h> | 26 | #include <errno.h> |
| 27 | #include <limits.h> | 27 | #include <limits.h> |
| 28 | #include <time.h> | 28 | #include <time.h> |
| 29 | +#include <unistd.h> | ||
| 29 | 30 | ||
| 30 | #include <config.h> | 31 | #include <config.h> |
| 31 | 32 | ||
| @@ -233,17 +234,10 @@ int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length) | @@ -233,17 +234,10 @@ int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length) | ||
| 233 | } | 234 | } |
| 234 | 235 | ||
| 235 | /* | 236 | /* |
| 236 | - ---------- Request Indication ---------- | ||
| 237 | - | Client | ---------------------->| Server | | ||
| 238 | - ---------- Confirmation Response ---------- | ||
| 239 | -*/ | ||
| 240 | - | ||
| 241 | -typedef enum { | ||
| 242 | - /* Request message on the server side */ | ||
| 243 | - MSG_INDICATION, | ||
| 244 | - /* Request message on the client side */ | ||
| 245 | - MSG_CONFIRMATION | ||
| 246 | -} msg_type_t; | 237 | + * ---------- Request Indication ---------- |
| 238 | + * | Client | ---------------------->| Server | | ||
| 239 | + * ---------- Confirmation Response ---------- | ||
| 240 | + */ | ||
| 247 | 241 | ||
| 248 | /* Computes the length to read after the function received */ | 242 | /* Computes the length to read after the function received */ |
| 249 | static uint8_t compute_meta_length_after_function(int function, | 243 | static uint8_t compute_meta_length_after_function(int function, |
| @@ -329,7 +323,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, | @@ -329,7 +323,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, | ||
| 329 | - read() or recv() error codes | 323 | - read() or recv() error codes |
| 330 | */ | 324 | */ |
| 331 | 325 | ||
| 332 | -static int receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) | 326 | +int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) |
| 333 | { | 327 | { |
| 334 | int rc; | 328 | int rc; |
| 335 | fd_set rfds; | 329 | fd_set rfds; |
| @@ -462,7 +456,7 @@ static int receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) | @@ -462,7 +456,7 @@ static int receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) | ||
| 462 | /* Receive the request from a modbus master */ | 456 | /* Receive the request from a modbus master */ |
| 463 | int modbus_receive(modbus_t *ctx, uint8_t *req) | 457 | int modbus_receive(modbus_t *ctx, uint8_t *req) |
| 464 | { | 458 | { |
| 465 | - return receive_msg(ctx, req, MSG_INDICATION); | 459 | + return ctx->backend->receive(ctx, req); |
| 466 | } | 460 | } |
| 467 | 461 | ||
| 468 | /* Receives the confirmation. | 462 | /* Receives the confirmation. |
| @@ -475,7 +469,7 @@ int modbus_receive(modbus_t *ctx, uint8_t *req) | @@ -475,7 +469,7 @@ int modbus_receive(modbus_t *ctx, uint8_t *req) | ||
| 475 | */ | 469 | */ |
| 476 | int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp) | 470 | int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp) |
| 477 | { | 471 | { |
| 478 | - return receive_msg(ctx, rsp, MSG_CONFIRMATION); | 472 | + return _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); |
| 479 | } | 473 | } |
| 480 | 474 | ||
| 481 | static int check_confirmation(modbus_t *ctx, uint8_t *req, | 475 | static int check_confirmation(modbus_t *ctx, uint8_t *req, |
| @@ -965,7 +959,7 @@ static int read_io_status(modbus_t *ctx, int function, | @@ -965,7 +959,7 @@ static int read_io_status(modbus_t *ctx, int function, | ||
| 965 | int offset; | 959 | int offset; |
| 966 | int offset_end; | 960 | int offset_end; |
| 967 | 961 | ||
| 968 | - rc = receive_msg(ctx, rsp, MSG_CONFIRMATION); | 962 | + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); |
| 969 | if (rc == -1) | 963 | if (rc == -1) |
| 970 | return -1; | 964 | return -1; |
| 971 | 965 | ||
| @@ -1064,7 +1058,7 @@ static int read_registers(modbus_t *ctx, int function, int addr, int nb, | @@ -1064,7 +1058,7 @@ static int read_registers(modbus_t *ctx, int function, int addr, int nb, | ||
| 1064 | int offset; | 1058 | int offset; |
| 1065 | int i; | 1059 | int i; |
| 1066 | 1060 | ||
| 1067 | - rc = receive_msg(ctx, rsp, MSG_CONFIRMATION); | 1061 | + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); |
| 1068 | if (rc == -1) | 1062 | if (rc == -1) |
| 1069 | return -1; | 1063 | return -1; |
| 1070 | 1064 | ||
| @@ -1140,7 +1134,7 @@ static int write_single(modbus_t *ctx, int function, int addr, int value) | @@ -1140,7 +1134,7 @@ static int write_single(modbus_t *ctx, int function, int addr, int value) | ||
| 1140 | /* Used by write_bit and write_register */ | 1134 | /* Used by write_bit and write_register */ |
| 1141 | uint8_t rsp[_MIN_REQ_LENGTH]; | 1135 | uint8_t rsp[_MIN_REQ_LENGTH]; |
| 1142 | 1136 | ||
| 1143 | - rc = receive_msg(ctx, rsp, MSG_CONFIRMATION); | 1137 | + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); |
| 1144 | if (rc == -1) | 1138 | if (rc == -1) |
| 1145 | return -1; | 1139 | return -1; |
| 1146 | 1140 | ||
| @@ -1211,7 +1205,7 @@ int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src) | @@ -1211,7 +1205,7 @@ int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src) | ||
| 1211 | if (rc > 0) { | 1205 | if (rc > 0) { |
| 1212 | uint8_t rsp[MAX_MESSAGE_LENGTH]; | 1206 | uint8_t rsp[MAX_MESSAGE_LENGTH]; |
| 1213 | 1207 | ||
| 1214 | - rc = receive_msg(ctx, rsp, MSG_CONFIRMATION); | 1208 | + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); |
| 1215 | if (rc == -1) | 1209 | if (rc == -1) |
| 1216 | return -1; | 1210 | return -1; |
| 1217 | 1211 | ||
| @@ -1257,7 +1251,7 @@ int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src) | @@ -1257,7 +1251,7 @@ int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src) | ||
| 1257 | if (rc > 0) { | 1251 | if (rc > 0) { |
| 1258 | uint8_t rsp[MAX_MESSAGE_LENGTH]; | 1252 | uint8_t rsp[MAX_MESSAGE_LENGTH]; |
| 1259 | 1253 | ||
| 1260 | - rc = receive_msg(ctx, rsp, MSG_CONFIRMATION); | 1254 | + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); |
| 1261 | if (rc == -1) | 1255 | if (rc == -1) |
| 1262 | return -1; | 1256 | return -1; |
| 1263 | 1257 | ||
| @@ -1320,7 +1314,7 @@ int modbus_write_and_read_registers(modbus_t *ctx, | @@ -1320,7 +1314,7 @@ int modbus_write_and_read_registers(modbus_t *ctx, | ||
| 1320 | if (rc > 0) { | 1314 | if (rc > 0) { |
| 1321 | int offset; | 1315 | int offset; |
| 1322 | 1316 | ||
| 1323 | - rc = receive_msg(ctx, rsp, MSG_CONFIRMATION); | 1317 | + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); |
| 1324 | if (rc == -1) | 1318 | if (rc == -1) |
| 1325 | return -1; | 1319 | return -1; |
| 1326 | 1320 | ||
| @@ -1361,7 +1355,7 @@ int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest) | @@ -1361,7 +1355,7 @@ int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest) | ||
| 1361 | int offset; | 1355 | int offset; |
| 1362 | uint8_t rsp[MAX_MESSAGE_LENGTH]; | 1356 | uint8_t rsp[MAX_MESSAGE_LENGTH]; |
| 1363 | 1357 | ||
| 1364 | - rc = receive_msg(ctx, rsp, MSG_CONFIRMATION); | 1358 | + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); |
| 1365 | if (rc == -1) | 1359 | if (rc == -1) |
| 1366 | return -1; | 1360 | return -1; |
| 1367 | 1361 |
tests/unit-test-client.c
| @@ -491,8 +491,12 @@ int main(int argc, char *argv[]) | @@ -491,8 +491,12 @@ int main(int argc, char *argv[]) | ||
| 491 | UT_REGISTERS_NB, tab_rp_registers); | 491 | UT_REGISTERS_NB, tab_rp_registers); |
| 492 | if (use_backend == RTU) { | 492 | if (use_backend == RTU) { |
| 493 | const int RAW_REQ_LENGTH = 6; | 493 | const int RAW_REQ_LENGTH = 6; |
| 494 | - uint8_t raw_req[] = { INVALID_SERVER_ID, 0x03, 0x00, 0x01, 0xFF, 0xFF }; | ||
| 495 | - uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH]; | 494 | + uint8_t raw_req[] = { INVALID_SERVER_ID, 0x03, 0x00, 0x01, 0x01, 0x01 }; |
| 495 | + /* Too many points */ | ||
| 496 | + uint8_t raw_invalid_req[] = { INVALID_SERVER_ID, 0x03, 0x00, 0x01, 0xFF, 0xFF }; | ||
| 497 | + const int RAW_REP_LENGTH = 7; | ||
| 498 | + uint8_t raw_rep[] = { INVALID_SERVER_ID, 0x03, 0x04, 0, 0, 0, 0 }; | ||
| 499 | + uint8_t rsp[MODBUS_RTU_MAX_ADU_LENGTH]; | ||
| 496 | 500 | ||
| 497 | /* No response in RTU mode */ | 501 | /* No response in RTU mode */ |
| 498 | printf("1/5-A No response from slave %d: ", INVALID_SERVER_ID); | 502 | printf("1/5-A No response from slave %d: ", INVALID_SERVER_ID); |
| @@ -504,12 +508,19 @@ int main(int argc, char *argv[]) | @@ -504,12 +508,19 @@ int main(int argc, char *argv[]) | ||
| 504 | goto close; | 508 | goto close; |
| 505 | } | 509 | } |
| 506 | 510 | ||
| 507 | - /* Send an invalid query with a wrong slave ID */ | ||
| 508 | - modbus_send_raw_request(ctx, raw_req, | ||
| 509 | - RAW_REQ_LENGTH * sizeof(uint8_t)); | 511 | + /* The slave raises a timeout on a confirmation to ignore because if an |
| 512 | + * indication for another slave is received, a confirmation must follow */ | ||
| 513 | + | ||
| 514 | + | ||
| 515 | + /* Send a pair of indication/confimration to the slave with a different | ||
| 516 | + * slave ID to simulate a communication on a RS485 bus. At first, the | ||
| 517 | + * slave will see the indication message then the confirmation, and it must | ||
| 518 | + * ignore both. */ | ||
| 519 | + modbus_send_raw_request(ctx, raw_req, RAW_REQ_LENGTH * sizeof(uint8_t)); | ||
| 520 | + modbus_send_raw_request(ctx, raw_rep, RAW_REP_LENGTH * sizeof(uint8_t)); | ||
| 510 | rc = modbus_receive_confirmation(ctx, rsp); | 521 | rc = modbus_receive_confirmation(ctx, rsp); |
| 511 | 522 | ||
| 512 | - printf("1/5-B No response from slave %d with invalid request: ", | 523 | + printf("1/5-B No response from slave %d on indication/confirmation messages: ", |
| 513 | INVALID_SERVER_ID); | 524 | INVALID_SERVER_ID); |
| 514 | 525 | ||
| 515 | if (rc == -1 && errno == ETIMEDOUT) { | 526 | if (rc == -1 && errno == ETIMEDOUT) { |
| @@ -519,9 +530,22 @@ int main(int argc, char *argv[]) | @@ -519,9 +530,22 @@ int main(int argc, char *argv[]) | ||
| 519 | goto close; | 530 | goto close; |
| 520 | } | 531 | } |
| 521 | 532 | ||
| 533 | + /* Send an INVALID request for another slave */ | ||
| 534 | + modbus_send_raw_request(ctx, raw_invalid_req, RAW_REQ_LENGTH * sizeof(uint8_t)); | ||
| 535 | + rc = modbus_receive_confirmation(ctx, rsp); | ||
| 536 | + | ||
| 537 | + printf("1/5-C No response from slave %d with invalid request: ", | ||
| 538 | + INVALID_SERVER_ID); | ||
| 539 | + | ||
| 540 | + if (rc == -1 && errno == ETIMEDOUT) { | ||
| 541 | + printf("OK\n"); | ||
| 542 | + } else { | ||
| 543 | + printf("FAILED (%d)\n", rc); | ||
| 544 | + goto close; | ||
| 545 | + } | ||
| 522 | } else { | 546 | } else { |
| 523 | /* Response in TCP mode */ | 547 | /* Response in TCP mode */ |
| 524 | - printf("1/4 Response from slave %d: ", 18); | 548 | + printf("1/4 Response from slave %d: ", INVALID_SERVER_ID); |
| 525 | 549 | ||
| 526 | if (rc == UT_REGISTERS_NB) { | 550 | if (rc == UT_REGISTERS_NB) { |
| 527 | printf("OK\n"); | 551 | printf("OK\n"); |