Commit 2b985f816374e79c9afb739944315cbb611fa762
1 parent
9ea54e09
Fix #591142 - Slave id check should be disabled in TCP connection
A new API will be committed to remove the slave in TCP communication.
Showing
10 changed files
with
62 additions
and
33 deletions
NEWS
| ... | ... | @@ -10,6 +10,8 @@ libmodbus 2.1.1 (2010-XX-XX) |
| 10 | 10 | Reported by David Olivari. |
| 11 | 11 | - Fix #463299 - New functions to define the timeouts of begin and end of trame |
| 12 | 12 | Original patch by Sisyph (eric-paul). |
| 13 | +- Fix #591142 - Slave id check should be disabled in TCP connection | |
| 14 | + Reported by aladdinwu. | |
| 13 | 15 | |
| 14 | 16 | libmodbus 2.1.0 (2010-03-24) |
| 15 | 17 | ============================ | ... | ... |
src/modbus.c
| ... | ... | @@ -363,7 +363,7 @@ static int build_response_basis_tcp(sft_t *sft, uint8_t *response) |
| 363 | 363 | |
| 364 | 364 | /* Length will be set later by modbus_send (4 and 5) */ |
| 365 | 365 | |
| 366 | - response[6] = sft->slave; | |
| 366 | + response[6] = 0xFF; | |
| 367 | 367 | response[7] = sft->function; |
| 368 | 368 | |
| 369 | 369 | return PRESET_RESPONSE_LENGTH_TCP; |
| ... | ... | @@ -887,8 +887,10 @@ int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, |
| 887 | 887 | int resp_length = 0; |
| 888 | 888 | sft_t sft; |
| 889 | 889 | |
| 890 | - if (slave != mb_param->slave && slave != MODBUS_BROADCAST_ADDRESS) { | |
| 891 | - // Ignores the query (not for me) | |
| 890 | + /* Filter on the Modbus unit identifier (slave) in RTU mode */ | |
| 891 | + if (mb_param->type_com == RTU && | |
| 892 | + slave != mb_param->slave && slave != MODBUS_BROADCAST_ADDRESS) { | |
| 893 | + /* Ignores the query (not for me) */ | |
| 892 | 894 | if (mb_param->debug) { |
| 893 | 895 | printf("Request for slave %d ignored (not %d)\n", |
| 894 | 896 | slave, mb_param->slave); |
| ... | ... | @@ -1483,7 +1485,7 @@ void init_common(modbus_param_t *mb_param) |
| 1483 | 1485 | - stop_bits: 1, 2 |
| 1484 | 1486 | - slave: slave number |
| 1485 | 1487 | */ |
| 1486 | -void modbus_init_rtu(modbus_param_t *mb_param, const char *device, | |
| 1488 | +int modbus_init_rtu(modbus_param_t *mb_param, const char *device, | |
| 1487 | 1489 | int baud, const char *parity, int data_bit, |
| 1488 | 1490 | int stop_bit, int slave) |
| 1489 | 1491 | { |
| ... | ... | @@ -1496,9 +1498,10 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device, |
| 1496 | 1498 | mb_param->stop_bit = stop_bit; |
| 1497 | 1499 | mb_param->type_com = RTU; |
| 1498 | 1500 | mb_param->error_recovery = FALSE; |
| 1499 | - mb_param->slave = slave; | |
| 1500 | 1501 | |
| 1501 | 1502 | init_common(mb_param); |
| 1503 | + | |
| 1504 | + return modbus_set_slave(mb_param, slave); | |
| 1502 | 1505 | } |
| 1503 | 1506 | |
| 1504 | 1507 | /* Initializes the modbus_param_t structure for TCP. |
| ... | ... | @@ -1510,35 +1513,48 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device, |
| 1510 | 1513 | to 1024 because it's not necessary to be root to use this port |
| 1511 | 1514 | number. |
| 1512 | 1515 | */ |
| 1513 | -void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port, int slave) | |
| 1516 | +int modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port) | |
| 1514 | 1517 | { |
| 1515 | 1518 | memset(mb_param, 0, sizeof(modbus_param_t)); |
| 1516 | 1519 | strncpy(mb_param->ip, ip, sizeof(char)*16); |
| 1517 | 1520 | mb_param->port = port; |
| 1518 | 1521 | mb_param->type_com = TCP; |
| 1519 | 1522 | mb_param->error_recovery = FALSE; |
| 1520 | - mb_param->slave = slave; | |
| 1523 | + /* Can be changed after to reach remote serial Modbus device */ | |
| 1524 | + mb_param->slave = 0xFF; | |
| 1521 | 1525 | |
| 1522 | 1526 | init_common(mb_param); |
| 1527 | + | |
| 1528 | + return 0; | |
| 1523 | 1529 | } |
| 1524 | 1530 | |
| 1525 | -/* Define the slave number */ | |
| 1526 | -void modbus_set_slave(modbus_param_t *mb_param, int slave) | |
| 1531 | +/* Define the slave number, the special value MODBUS_TCP_SLAVE (0xFF) can be | |
| 1532 | + * used in TCP mode to restore the default value. */ | |
| 1533 | +int modbus_set_slave(modbus_param_t *mb_param, int slave) | |
| 1527 | 1534 | { |
| 1528 | - mb_param->slave = slave; | |
| 1535 | + if (slave >= 1 && slave <= 247) { | |
| 1536 | + mb_param->slave = slave; | |
| 1537 | + } else if (mb_param->type_com == TCP && slave == MODBUS_TCP_SLAVE) { | |
| 1538 | + mb_param->slave = slave; | |
| 1539 | + } else { | |
| 1540 | + errno = EINVAL; | |
| 1541 | + return -1; | |
| 1542 | + } | |
| 1543 | + | |
| 1544 | + return 0; | |
| 1529 | 1545 | } |
| 1530 | 1546 | |
| 1531 | 1547 | /* |
| 1532 | - When disabled (default), it is expected that the application will check for error | |
| 1533 | - returns and deal with them as necessary. | |
| 1548 | + When disabled (default), it is expected that the application will check for | |
| 1549 | + error returns and deal with them as necessary. | |
| 1534 | 1550 | |
| 1535 | 1551 | It's not recommanded to enable error recovery for slave/server. |
| 1536 | 1552 | |
| 1537 | 1553 | When enabled, the library will attempt an immediate reconnection which may |
| 1538 | 1554 | hang for several seconds if the network to the remote target unit is down. |
| 1539 | 1555 | The write will try a infinite close/connect loop until to be successful and |
| 1540 | - the select/read calls will just try to retablish the connection one time | |
| 1541 | - then will return an error (if the connecton was down, the values to read are | |
| 1556 | + the select/read calls will just try to retablish the connection one time then | |
| 1557 | + will return an error (if the connecton was down, the values to read are | |
| 1542 | 1558 | certainly not available anymore after reconnection, except for slave/server). |
| 1543 | 1559 | */ |
| 1544 | 1560 | int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled) | ... | ... |
src/modbus.h.in
| ... | ... | @@ -39,6 +39,7 @@ extern "C" { |
| 39 | 39 | |
| 40 | 40 | #define MODBUS_TCP_DEFAULT_PORT 502 |
| 41 | 41 | #define MODBUS_BROADCAST_ADDRESS 0 |
| 42 | +#define MODBUS_TCP_SLAVE 0xFF | |
| 42 | 43 | |
| 43 | 44 | /* Slave index */ |
| 44 | 45 | #define HEADER_LENGTH_RTU 1 |
| ... | ... | @@ -249,12 +250,11 @@ typedef struct { |
| 249 | 250 | uint16_t *tab_holding_registers; |
| 250 | 251 | } modbus_mapping_t; |
| 251 | 252 | |
| 252 | -void modbus_init_rtu(modbus_param_t *mb_param, const char *device, | |
| 253 | - int baud, const char *parity, int data_bit, | |
| 254 | - int stop_bit, int slave); | |
| 255 | -void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port, | |
| 256 | - int slave); | |
| 257 | -void modbus_set_slave(modbus_param_t *mb_param, int slave); | |
| 253 | +int modbus_init_rtu(modbus_param_t *mb_param, const char *device, | |
| 254 | + int baud, const char *parity, int data_bit, | |
| 255 | + int stop_bit, int slave); | |
| 256 | +int modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port); | |
| 257 | +int modbus_set_slave(modbus_param_t *mb_param, int slave); | |
| 258 | 258 | int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled); |
| 259 | 259 | |
| 260 | 260 | void modbus_get_timeout_begin(modbus_param_t *mb_param, struct timeval *timeout); | ... | ... |
tests/bandwidth-master.c
| ... | ... | @@ -26,7 +26,6 @@ |
| 26 | 26 | #include <modbus.h> |
| 27 | 27 | |
| 28 | 28 | /* Tests based on PI-MBUS-300 documentation */ |
| 29 | -#define MY_ID 1 | |
| 30 | 29 | #define SERVER_ID 17 |
| 31 | 30 | #define NB_LOOPS 100000 |
| 32 | 31 | |
| ... | ... | @@ -55,7 +54,7 @@ int main(void) |
| 55 | 54 | int rc; |
| 56 | 55 | |
| 57 | 56 | /* TCP */ |
| 58 | - modbus_init_tcp(&mb_param, "127.0.0.1", 1502, MY_ID); | |
| 57 | + modbus_init_tcp(&mb_param, "127.0.0.1", 1502); | |
| 59 | 58 | rc = modbus_connect(&mb_param); |
| 60 | 59 | if (rc == -1) { |
| 61 | 60 | fprintf(stderr, "Connexion failed: %s\n", | ... | ... |
tests/bandwidth-slave-many-up.c
| ... | ... | @@ -48,7 +48,7 @@ int main(void) |
| 48 | 48 | /* Maximum file descriptor number */ |
| 49 | 49 | int fdmax; |
| 50 | 50 | |
| 51 | - modbus_init_tcp(&mb_param, "127.0.0.1", 1502, 17); | |
| 51 | + modbus_init_tcp(&mb_param, "127.0.0.1", 1502); | |
| 52 | 52 | |
| 53 | 53 | rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0); |
| 54 | 54 | if (rc == -1) { | ... | ... |
tests/bandwidth-slave-one.c
| ... | ... | @@ -30,7 +30,7 @@ int main(void) |
| 30 | 30 | modbus_mapping_t mb_mapping; |
| 31 | 31 | int rc; |
| 32 | 32 | |
| 33 | - modbus_init_tcp(&mb_param, "127.0.0.1", 1502, 17); | |
| 33 | + modbus_init_tcp(&mb_param, "127.0.0.1", 1502); | |
| 34 | 34 | |
| 35 | 35 | rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0); |
| 36 | 36 | if (rc == -1) { | ... | ... |
tests/random-test-master.c
| ... | ... | @@ -64,7 +64,7 @@ int main(void) |
| 64 | 64 | */ |
| 65 | 65 | |
| 66 | 66 | /* TCP */ |
| 67 | - modbus_init_tcp(&mb_param, "127.0.0.1", 1502, MY_ID); | |
| 67 | + modbus_init_tcp(&mb_param, "127.0.0.1", 1502); | |
| 68 | 68 | modbus_set_debug(&mb_param, TRUE); |
| 69 | 69 | if (modbus_connect(&mb_param) == -1) { |
| 70 | 70 | fprintf(stderr, "Connection failed: %s\n", | ... | ... |
tests/random-test-slave.c
| ... | ... | @@ -29,7 +29,7 @@ int main(void) |
| 29 | 29 | modbus_mapping_t mb_mapping; |
| 30 | 30 | int rc; |
| 31 | 31 | |
| 32 | - modbus_init_tcp(&mb_param, "127.0.0.1", 1502, 17); | |
| 32 | + modbus_init_tcp(&mb_param, "127.0.0.1", 1502); | |
| 33 | 33 | /* modbus_set_debug(&mb_param, TRUE); */ |
| 34 | 34 | |
| 35 | 35 | rc = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500); | ... | ... |
tests/unit-test-master.c
| ... | ... | @@ -46,7 +46,7 @@ int main(void) |
| 46 | 46 | */ |
| 47 | 47 | |
| 48 | 48 | /* TCP */ |
| 49 | - modbus_init_tcp(&mb_param, "127.0.0.1", 1502, CLIENT_ID); | |
| 49 | + modbus_init_tcp(&mb_param, "127.0.0.1", 1502); | |
| 50 | 50 | modbus_set_debug(&mb_param, TRUE); |
| 51 | 51 | |
| 52 | 52 | if (modbus_connect(&mb_param) == -1) { |
| ... | ... | @@ -450,16 +450,28 @@ int main(void) |
| 450 | 450 | |
| 451 | 451 | /** SLAVE REPLY **/ |
| 452 | 452 | printf("\nTEST SLAVE REPLY:\n"); |
| 453 | + | |
| 453 | 454 | rc = read_holding_registers(&mb_param, 18, |
| 454 | 455 | UT_HOLDING_REGISTERS_ADDRESS, |
| 455 | 456 | UT_HOLDING_REGISTERS_NB_POINTS, |
| 456 | 457 | tab_rp_registers); |
| 457 | - printf("1/3 No reply from slave %d: ", 18); | |
| 458 | - if (rc == -1 && errno == ETIMEDOUT) { | |
| 459 | - printf("OK\n"); | |
| 458 | + printf("1/3 No or response from slave %d: ", 18); | |
| 459 | + if (mb_param.type_com == RTU) { | |
| 460 | + /* No response in RTU mode */ | |
| 461 | + if (rc == -1 && errno == ETIMEDOUT) { | |
| 462 | + printf("OK\n"); | |
| 463 | + } else { | |
| 464 | + printf("FAILED\n"); | |
| 465 | + goto close; | |
| 466 | + } | |
| 460 | 467 | } else { |
| 461 | - printf("FAILED\n"); | |
| 462 | - goto close; | |
| 468 | + /* Response in TCP mode */ | |
| 469 | + if (rc == UT_HOLDING_REGISTERS_NB_POINTS) { | |
| 470 | + printf("OK\n"); | |
| 471 | + } else { | |
| 472 | + printf("FAILED\n"); | |
| 473 | + goto close; | |
| 474 | + } | |
| 463 | 475 | } |
| 464 | 476 | |
| 465 | 477 | rc = read_holding_registers(&mb_param, MODBUS_BROADCAST_ADDRESS, | ... | ... |
tests/unit-test-slave.c