Commit 14f42c1896f6d8fdce152e1f9bea82ae67939594
1 parent
efbbc3f7
Error handling improvements
- new function modbus_flush - new names and values for error defines - finer recovery on error - merge TOO_MANY_DATA and INVALID_DATA - stop unit-test-master at the first error - FLUSH_OR_RECONNECT_ON_ERROR -> FLUSH_OR_CONNECT_ON_ERROR - more precise tests in unit-test-master
Showing
3 changed files
with
116 additions
and
72 deletions
src/modbus.c
| @@ -151,24 +151,44 @@ static const int TAB_MAX_ADU_LENGTH[2] = { | @@ -151,24 +151,44 @@ static const int TAB_MAX_ADU_LENGTH[2] = { | ||
| 151 | MAX_ADU_LENGTH_TCP, | 151 | MAX_ADU_LENGTH_TCP, |
| 152 | }; | 152 | }; |
| 153 | 153 | ||
| 154 | +void modbus_flush(modbus_param_t *mb_param) | ||
| 155 | +{ | ||
| 156 | + if (mb_param->type_com == RTU) { | ||
| 157 | + tcflush(mb_param->fd, TCIOFLUSH); | ||
| 158 | + } else { | ||
| 159 | + int ret; | ||
| 160 | + do { | ||
| 161 | + /* Extract the garbage from the socket */ | ||
| 162 | + char devnull[MAX_ADU_LENGTH_TCP]; | ||
| 163 | + ret = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, MSG_DONTWAIT); | ||
| 164 | + if (mb_param->debug && ret > 0) { | ||
| 165 | + printf("%d bytes flushed\n", ret); | ||
| 166 | + } | ||
| 167 | + } while (ret > 0); | ||
| 168 | + } | ||
| 169 | +} | ||
| 170 | + | ||
| 154 | /* Treats errors and flush or close connection if necessary */ | 171 | /* Treats errors and flush or close connection if necessary */ |
| 155 | static void error_treat(modbus_param_t *mb_param, int code, const char *string) | 172 | static void error_treat(modbus_param_t *mb_param, int code, const char *string) |
| 156 | { | 173 | { |
| 157 | - printf("\nERROR %s (%d)\n", string, code); | 174 | + printf("\nERROR %s (%0X)\n", string, -code); |
| 158 | 175 | ||
| 159 | - if (mb_param->error_handling == FLUSH_OR_RECONNECT_ON_ERROR) { | 176 | + if (mb_param->error_handling == FLUSH_OR_CONNECT_ON_ERROR) { |
| 160 | switch (code) { | 177 | switch (code) { |
| 161 | - case ILLEGAL_DATA_VALUE: | ||
| 162 | - case ILLEGAL_DATA_ADDRESS: | ||
| 163 | - case ILLEGAL_FUNCTION: | 178 | + case INVALID_DATA: |
| 179 | + case INVALID_CRC: | ||
| 180 | + case INVALID_EXCEPTION_CODE: | ||
| 181 | + modbus_flush(mb_param); | ||
| 182 | + break; | ||
| 183 | + case SELECT_FAILURE: | ||
| 184 | + case SOCKET_FAILURE: | ||
| 185 | + case CONNECTION_CLOSED: | ||
| 186 | + modbus_close(mb_param); | ||
| 187 | + modbus_connect(mb_param); | ||
| 164 | break; | 188 | break; |
| 165 | default: | 189 | default: |
| 166 | - if (mb_param->type_com == RTU) { | ||
| 167 | - tcflush(mb_param->fd, TCIOFLUSH); | ||
| 168 | - } else { | ||
| 169 | - modbus_close(mb_param); | ||
| 170 | - modbus_connect(mb_param); | ||
| 171 | - } | 190 | + /* NOP */ |
| 191 | + break; | ||
| 172 | } | 192 | } |
| 173 | } | 193 | } |
| 174 | } | 194 | } |
| @@ -394,10 +414,10 @@ static int modbus_send(modbus_param_t *mb_param, uint8_t *query, | @@ -394,10 +414,10 @@ static int modbus_send(modbus_param_t *mb_param, uint8_t *query, | ||
| 394 | ret = send(mb_param->fd, query, query_length, 0); | 414 | ret = send(mb_param->fd, query, query_length, 0); |
| 395 | 415 | ||
| 396 | /* Return the number of bytes written (0 to n) | 416 | /* Return the number of bytes written (0 to n) |
| 397 | - or PORT_SOCKET_FAILURE on error */ | 417 | + or SOCKET_FAILURE on error */ |
| 398 | if ((ret == -1) || (ret != query_length)) { | 418 | if ((ret == -1) || (ret != query_length)) { |
| 399 | - ret = PORT_SOCKET_FAILURE; | ||
| 400 | - error_treat(mb_param, ret, "Write port/socket failure"); | 419 | + ret = SOCKET_FAILURE; |
| 420 | + error_treat(mb_param, ret, "Write socket failure"); | ||
| 401 | } | 421 | } |
| 402 | 422 | ||
| 403 | return ret; | 423 | return ret; |
| @@ -455,7 +475,7 @@ static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg) | @@ -455,7 +475,7 @@ static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg) | ||
| 455 | \ | 475 | \ |
| 456 | if (select_ret == 0) { \ | 476 | if (select_ret == 0) { \ |
| 457 | /* Call to error_treat is done later to manage exceptions */ \ | 477 | /* Call to error_treat is done later to manage exceptions */ \ |
| 458 | - return COMM_TIME_OUT; \ | 478 | + return SELECT_TIMEOUT; \ |
| 459 | } \ | 479 | } \ |
| 460 | } | 480 | } |
| 461 | 481 | ||
| @@ -534,9 +554,9 @@ static int receive_msg(modbus_param_t *mb_param, | @@ -534,9 +554,9 @@ static int receive_msg(modbus_param_t *mb_param, | ||
| 534 | return CONNECTION_CLOSED; | 554 | return CONNECTION_CLOSED; |
| 535 | } else if (read_ret < 0) { | 555 | } else if (read_ret < 0) { |
| 536 | /* The only negative possible value is -1 */ | 556 | /* The only negative possible value is -1 */ |
| 537 | - error_treat(mb_param, PORT_SOCKET_FAILURE, | ||
| 538 | - "Read port/socket failure"); | ||
| 539 | - return PORT_SOCKET_FAILURE; | 557 | + error_treat(mb_param, SOCKET_FAILURE, |
| 558 | + "Read socket failure"); | ||
| 559 | + return SOCKET_FAILURE; | ||
| 540 | } | 560 | } |
| 541 | 561 | ||
| 542 | /* Sums bytes received */ | 562 | /* Sums bytes received */ |
| @@ -568,8 +588,8 @@ static int receive_msg(modbus_param_t *mb_param, | @@ -568,8 +588,8 @@ static int receive_msg(modbus_param_t *mb_param, | ||
| 568 | length_to_read = compute_query_length_data(mb_param, msg); | 588 | length_to_read = compute_query_length_data(mb_param, msg); |
| 569 | msg_length_computed += length_to_read; | 589 | msg_length_computed += length_to_read; |
| 570 | if (msg_length_computed > TAB_MAX_ADU_LENGTH[mb_param->type_com]) { | 590 | if (msg_length_computed > TAB_MAX_ADU_LENGTH[mb_param->type_com]) { |
| 571 | - error_treat(mb_param, TOO_MANY_DATA, "Too many data"); | ||
| 572 | - return TOO_MANY_DATA; | 591 | + error_treat(mb_param, INVALID_DATA, "Too many data"); |
| 592 | + return INVALID_DATA; | ||
| 573 | } | 593 | } |
| 574 | state = COMPLETE; | 594 | state = COMPLETE; |
| 575 | break; | 595 | break; |
| @@ -692,13 +712,13 @@ static int modbus_receive(modbus_param_t *mb_param, | @@ -692,13 +712,13 @@ static int modbus_receive(modbus_param_t *mb_param, | ||
| 692 | ret = response_nb_value; | 712 | ret = response_nb_value; |
| 693 | } else { | 713 | } else { |
| 694 | char *s_error = malloc(64 * sizeof(char)); | 714 | char *s_error = malloc(64 * sizeof(char)); |
| 695 | - sprintf(s_error, "Quantity (%d) not corresponding to the query (%d)", | 715 | + sprintf(s_error, "Quantity not corresponding to the query (%d != %d)", |
| 696 | response_nb_value, query_nb_value); | 716 | response_nb_value, query_nb_value); |
| 697 | - ret = ILLEGAL_DATA_VALUE; | ||
| 698 | - error_treat(mb_param, ILLEGAL_DATA_VALUE, s_error); | 717 | + ret = INVALID_DATA; |
| 718 | + error_treat(mb_param, ret, s_error); | ||
| 699 | free(s_error); | 719 | free(s_error); |
| 700 | } | 720 | } |
| 701 | - } else if (ret == COMM_TIME_OUT) { | 721 | + } else if (ret == SELECT_TIMEOUT) { |
| 702 | 722 | ||
| 703 | if (response_length == (offset + 2 + TAB_CHECKSUM_LENGTH[mb_param->type_com])) { | 723 | if (response_length == (offset + 2 + TAB_CHECKSUM_LENGTH[mb_param->type_com])) { |
| 704 | /* EXCEPTION CODE RECEIVED */ | 724 | /* EXCEPTION CODE RECEIVED */ |
| @@ -745,8 +765,7 @@ static int modbus_receive(modbus_param_t *mb_param, | @@ -745,8 +765,7 @@ static int modbus_receive(modbus_param_t *mb_param, | ||
| 745 | TIME OUT here */ | 765 | TIME OUT here */ |
| 746 | } | 766 | } |
| 747 | 767 | ||
| 748 | - /* COMMUNICATION TIME OUT */ | ||
| 749 | - error_treat(mb_param, ret, "Communication time out"); | 768 | + error_treat(mb_param, ret, "Select timeout"); |
| 750 | return ret; | 769 | return ret; |
| 751 | } | 770 | } |
| 752 | 771 | ||
| @@ -1046,7 +1065,7 @@ int read_coil_status(modbus_param_t *mb_param, int start_addr, | @@ -1046,7 +1065,7 @@ int read_coil_status(modbus_param_t *mb_param, int start_addr, | ||
| 1046 | if (nb > MAX_STATUS) { | 1065 | if (nb > MAX_STATUS) { |
| 1047 | printf("ERROR Too many coils status requested (%d > %d)\n", | 1066 | printf("ERROR Too many coils status requested (%d > %d)\n", |
| 1048 | nb, MAX_STATUS); | 1067 | nb, MAX_STATUS); |
| 1049 | - return TOO_MANY_DATA; | 1068 | + return INVALID_DATA; |
| 1050 | } | 1069 | } |
| 1051 | 1070 | ||
| 1052 | status = read_io_status(mb_param, FC_READ_COIL_STATUS, | 1071 | status = read_io_status(mb_param, FC_READ_COIL_STATUS, |
| @@ -1068,7 +1087,7 @@ int read_input_status(modbus_param_t *mb_param, int start_addr, | @@ -1068,7 +1087,7 @@ int read_input_status(modbus_param_t *mb_param, int start_addr, | ||
| 1068 | if (nb > MAX_STATUS) { | 1087 | if (nb > MAX_STATUS) { |
| 1069 | printf("ERROR Too many input status requested (%d > %d)\n", | 1088 | printf("ERROR Too many input status requested (%d > %d)\n", |
| 1070 | nb, MAX_STATUS); | 1089 | nb, MAX_STATUS); |
| 1071 | - return TOO_MANY_DATA; | 1090 | + return INVALID_DATA; |
| 1072 | } | 1091 | } |
| 1073 | 1092 | ||
| 1074 | status = read_io_status(mb_param, FC_READ_INPUT_STATUS, | 1093 | status = read_io_status(mb_param, FC_READ_INPUT_STATUS, |
| @@ -1092,7 +1111,7 @@ static int read_registers(modbus_param_t *mb_param, int function, | @@ -1092,7 +1111,7 @@ static int read_registers(modbus_param_t *mb_param, int function, | ||
| 1092 | if (nb > MAX_REGISTERS) { | 1111 | if (nb > MAX_REGISTERS) { |
| 1093 | printf("EROOR Too many holding registers requested (%d > %d)\n", | 1112 | printf("EROOR Too many holding registers requested (%d > %d)\n", |
| 1094 | nb, MAX_REGISTERS); | 1113 | nb, MAX_REGISTERS); |
| 1095 | - return TOO_MANY_DATA; | 1114 | + return INVALID_DATA; |
| 1096 | } | 1115 | } |
| 1097 | 1116 | ||
| 1098 | query_length = build_query_basis(mb_param, function, | 1117 | query_length = build_query_basis(mb_param, function, |
| @@ -1128,7 +1147,7 @@ int read_holding_registers(modbus_param_t *mb_param, | @@ -1128,7 +1147,7 @@ int read_holding_registers(modbus_param_t *mb_param, | ||
| 1128 | if (nb > MAX_REGISTERS) { | 1147 | if (nb > MAX_REGISTERS) { |
| 1129 | printf("ERROR Too many holding registers requested (%d > %d)\n", | 1148 | printf("ERROR Too many holding registers requested (%d > %d)\n", |
| 1130 | nb, MAX_REGISTERS); | 1149 | nb, MAX_REGISTERS); |
| 1131 | - return TOO_MANY_DATA; | 1150 | + return INVALID_DATA; |
| 1132 | } | 1151 | } |
| 1133 | 1152 | ||
| 1134 | status = read_registers(mb_param, FC_READ_HOLDING_REGISTERS, | 1153 | status = read_registers(mb_param, FC_READ_HOLDING_REGISTERS, |
| @@ -1146,7 +1165,7 @@ int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb, | @@ -1146,7 +1165,7 @@ int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb, | ||
| 1146 | if (nb > MAX_REGISTERS) { | 1165 | if (nb > MAX_REGISTERS) { |
| 1147 | printf("ERROR Too many input registers requested (%d > %d)\n", | 1166 | printf("ERROR Too many input registers requested (%d > %d)\n", |
| 1148 | nb, MAX_REGISTERS); | 1167 | nb, MAX_REGISTERS); |
| 1149 | - return TOO_MANY_DATA; | 1168 | + return INVALID_DATA; |
| 1150 | } | 1169 | } |
| 1151 | 1170 | ||
| 1152 | status = read_registers(mb_param, FC_READ_INPUT_REGISTERS, | 1171 | status = read_registers(mb_param, FC_READ_INPUT_REGISTERS, |
| @@ -1219,7 +1238,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb, | @@ -1219,7 +1238,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb, | ||
| 1219 | if (nb > MAX_STATUS) { | 1238 | if (nb > MAX_STATUS) { |
| 1220 | printf("ERROR Writing to too many coils (%d > %d)\n", | 1239 | printf("ERROR Writing to too many coils (%d > %d)\n", |
| 1221 | nb, MAX_STATUS); | 1240 | nb, MAX_STATUS); |
| 1222 | - return TOO_MANY_DATA; | 1241 | + return INVALID_DATA; |
| 1223 | } | 1242 | } |
| 1224 | 1243 | ||
| 1225 | query_length = build_query_basis(mb_param, FC_FORCE_MULTIPLE_COILS, | 1244 | query_length = build_query_basis(mb_param, FC_FORCE_MULTIPLE_COILS, |
| @@ -1268,7 +1287,7 @@ int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb, | @@ -1268,7 +1287,7 @@ int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb, | ||
| 1268 | if (nb > MAX_REGISTERS) { | 1287 | if (nb > MAX_REGISTERS) { |
| 1269 | printf("ERROR Trying to write to too many registers (%d > %d)\n", | 1288 | printf("ERROR Trying to write to too many registers (%d > %d)\n", |
| 1270 | nb, MAX_REGISTERS); | 1289 | nb, MAX_REGISTERS); |
| 1271 | - return TOO_MANY_DATA; | 1290 | + return INVALID_DATA; |
| 1272 | } | 1291 | } |
| 1273 | 1292 | ||
| 1274 | query_length = build_query_basis(mb_param, FC_PRESET_MULTIPLE_REGISTERS, | 1293 | query_length = build_query_basis(mb_param, FC_PRESET_MULTIPLE_REGISTERS, |
| @@ -1344,7 +1363,7 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device, | @@ -1344,7 +1363,7 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device, | ||
| 1344 | mb_param->data_bit = data_bit; | 1363 | mb_param->data_bit = data_bit; |
| 1345 | mb_param->stop_bit = stop_bit; | 1364 | mb_param->stop_bit = stop_bit; |
| 1346 | mb_param->type_com = RTU; | 1365 | mb_param->type_com = RTU; |
| 1347 | - mb_param->error_handling = FLUSH_OR_RECONNECT_ON_ERROR; | 1366 | + mb_param->error_handling = FLUSH_OR_CONNECT_ON_ERROR; |
| 1348 | mb_param->slave = slave; | 1367 | mb_param->slave = slave; |
| 1349 | } | 1368 | } |
| 1350 | 1369 | ||
| @@ -1363,16 +1382,15 @@ void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port, int sla | @@ -1363,16 +1382,15 @@ void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port, int sla | ||
| 1363 | strncpy(mb_param->ip, ip, sizeof(char)*16); | 1382 | strncpy(mb_param->ip, ip, sizeof(char)*16); |
| 1364 | mb_param->port = port; | 1383 | mb_param->port = port; |
| 1365 | mb_param->type_com = TCP; | 1384 | mb_param->type_com = TCP; |
| 1366 | - mb_param->error_handling = FLUSH_OR_RECONNECT_ON_ERROR; | 1385 | + mb_param->error_handling = FLUSH_OR_CONNECT_ON_ERROR; |
| 1367 | mb_param->slave = slave; | 1386 | mb_param->slave = slave; |
| 1368 | } | 1387 | } |
| 1369 | 1388 | ||
| 1370 | -/* By default, the error handling mode used is FLUSH_OR_RECONNECT_ON_ERROR. | 1389 | +/* By default, the error handling mode used is FLUSH_OR_CONNECT_ON_ERROR. |
| 1371 | 1390 | ||
| 1372 | - With FLUSH_OR_RECONNECT_ON_ERROR, the library will flush to I/O | ||
| 1373 | - port in RTU mode or attempt an immediate reconnection which may | ||
| 1374 | - hang for several seconds if the network to the remote target unit | ||
| 1375 | - is down in TCP mode. | 1391 | + With FLUSH_OR_CONNECT_ON_ERROR, the library will attempt an immediate |
| 1392 | + reconnection which may hang for several seconds if the network to | ||
| 1393 | + the remote target unit is down. | ||
| 1376 | 1394 | ||
| 1377 | With NOP_ON_ERROR, it is expected that the application will | 1395 | With NOP_ON_ERROR, it is expected that the application will |
| 1378 | check for error returns and deal with them as necessary. | 1396 | check for error returns and deal with them as necessary. |
| @@ -1380,7 +1398,7 @@ void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port, int sla | @@ -1380,7 +1398,7 @@ void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port, int sla | ||
| 1380 | void modbus_set_error_handling(modbus_param_t *mb_param, | 1398 | void modbus_set_error_handling(modbus_param_t *mb_param, |
| 1381 | error_handling_t error_handling) | 1399 | error_handling_t error_handling) |
| 1382 | { | 1400 | { |
| 1383 | - if (error_handling == FLUSH_OR_RECONNECT_ON_ERROR || | 1401 | + if (error_handling == FLUSH_OR_CONNECT_ON_ERROR || |
| 1384 | error_handling == NOP_ON_ERROR) { | 1402 | error_handling == NOP_ON_ERROR) { |
| 1385 | mb_param->error_handling = error_handling; | 1403 | mb_param->error_handling = error_handling; |
| 1386 | } else { | 1404 | } else { |
src/modbus.h
| @@ -120,19 +120,20 @@ extern "C" { | @@ -120,19 +120,20 @@ extern "C" { | ||
| 120 | #define GATEWAY_PROBLEM_TARGET -0x0B | 120 | #define GATEWAY_PROBLEM_TARGET -0x0B |
| 121 | 121 | ||
| 122 | /* Local */ | 122 | /* Local */ |
| 123 | -#define COMM_TIME_OUT -0x0C | ||
| 124 | -#define PORT_SOCKET_FAILURE -0x0D | ||
| 125 | -#define SELECT_FAILURE -0x0E | ||
| 126 | -#define TOO_MANY_DATA -0x0F | ||
| 127 | -#define INVALID_CRC -0x10 | ||
| 128 | -#define INVALID_EXCEPTION_CODE -0x11 | ||
| 129 | -#define CONNECTION_CLOSED -0x12 | 123 | +#define INVALID_DATA -0x10 |
| 124 | +#define INVALID_CRC -0x11 | ||
| 125 | +#define INVALID_EXCEPTION_CODE -0x12 | ||
| 126 | + | ||
| 127 | +#define SELECT_TIMEOUT -0x13 | ||
| 128 | +#define SELECT_FAILURE -0x14 | ||
| 129 | +#define SOCKET_FAILURE -0x15 | ||
| 130 | +#define CONNECTION_CLOSED -0x16 | ||
| 130 | 131 | ||
| 131 | /* Internal using */ | 132 | /* Internal using */ |
| 132 | #define MSG_LENGTH_UNDEFINED -1 | 133 | #define MSG_LENGTH_UNDEFINED -1 |
| 133 | 134 | ||
| 134 | typedef enum { RTU=0, TCP } type_com_t; | 135 | typedef enum { RTU=0, TCP } type_com_t; |
| 135 | -typedef enum { FLUSH_OR_RECONNECT_ON_ERROR, NOP_ON_ERROR } error_handling_t; | 136 | +typedef enum { FLUSH_OR_CONNECT_ON_ERROR, NOP_ON_ERROR } error_handling_t; |
| 136 | 137 | ||
| 137 | /* This structure is byte-aligned */ | 138 | /* This structure is byte-aligned */ |
| 138 | typedef struct { | 139 | typedef struct { |
| @@ -250,9 +251,9 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device, | @@ -250,9 +251,9 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device, | ||
| 250 | void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port, | 251 | void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port, |
| 251 | int slave); | 252 | int slave); |
| 252 | 253 | ||
| 253 | -/* By default, the error handling mode used is RECONNECT_ON_ERROR. | 254 | +/* By default, the error handling mode used is CONNECT_ON_ERROR. |
| 254 | 255 | ||
| 255 | - With RECONNECT_ON_ERROR, the library will attempt an immediate | 256 | + With FLUSH_OR_CONNECT_ON_ERROR, the library will attempt an immediate |
| 256 | reconnection which may hang for several seconds if the network to | 257 | reconnection which may hang for several seconds if the network to |
| 257 | the remote target unit is down. | 258 | the remote target unit is down. |
| 258 | 259 | ||
| @@ -270,6 +271,9 @@ int modbus_connect(modbus_param_t *mb_param); | @@ -270,6 +271,9 @@ int modbus_connect(modbus_param_t *mb_param); | ||
| 270 | /* Closes a modbus connection */ | 271 | /* Closes a modbus connection */ |
| 271 | void modbus_close(modbus_param_t *mb_param); | 272 | void modbus_close(modbus_param_t *mb_param); |
| 272 | 273 | ||
| 274 | +/* Flush the pending request */ | ||
| 275 | +void modbus_flush(modbus_param_t *mb_param); | ||
| 276 | + | ||
| 273 | /* Activates the debug messages */ | 277 | /* Activates the debug messages */ |
| 274 | void modbus_set_debug(modbus_param_t *mb_param, int boolean); | 278 | void modbus_set_debug(modbus_param_t *mb_param, int boolean); |
| 275 | 279 |
tests/unit-test-master.c
| @@ -42,8 +42,7 @@ int main(void) | @@ -42,8 +42,7 @@ int main(void) | ||
| 42 | 42 | ||
| 43 | /* TCP */ | 43 | /* TCP */ |
| 44 | modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); | 44 | modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); |
| 45 | -/* modbus_set_debug(&mb_param, TRUE);*/ | ||
| 46 | - modbus_set_error_handling(&mb_param, NOP_ON_ERROR); | 45 | +/* modbus_set_debug(&mb_param, TRUE); */ |
| 47 | 46 | ||
| 48 | if (modbus_connect(&mb_param) == -1) { | 47 | if (modbus_connect(&mb_param) == -1) { |
| 49 | printf("ERROR Connection failed\n"); | 48 | printf("ERROR Connection failed\n"); |
| @@ -267,8 +266,10 @@ int main(void) | @@ -267,8 +266,10 @@ int main(void) | ||
| 267 | printf("* read_coil_status: "); | 266 | printf("* read_coil_status: "); |
| 268 | if (ret == ILLEGAL_DATA_ADDRESS) | 267 | if (ret == ILLEGAL_DATA_ADDRESS) |
| 269 | printf("OK\n"); | 268 | printf("OK\n"); |
| 270 | - else | 269 | + else { |
| 271 | printf("FAILED\n"); | 270 | printf("FAILED\n"); |
| 271 | + goto close; | ||
| 272 | + } | ||
| 272 | 273 | ||
| 273 | ret = read_input_status(&mb_param, | 274 | ret = read_input_status(&mb_param, |
| 274 | UT_INPUT_STATUS_ADDRESS, | 275 | UT_INPUT_STATUS_ADDRESS, |
| @@ -277,8 +278,10 @@ int main(void) | @@ -277,8 +278,10 @@ int main(void) | ||
| 277 | printf("* read_input_status: "); | 278 | printf("* read_input_status: "); |
| 278 | if (ret == ILLEGAL_DATA_ADDRESS) | 279 | if (ret == ILLEGAL_DATA_ADDRESS) |
| 279 | printf("OK\n"); | 280 | printf("OK\n"); |
| 280 | - else | 281 | + else { |
| 281 | printf("FAILED\n"); | 282 | printf("FAILED\n"); |
| 283 | + goto close; | ||
| 284 | + } | ||
| 282 | 285 | ||
| 283 | ret = read_holding_registers(&mb_param, | 286 | ret = read_holding_registers(&mb_param, |
| 284 | UT_HOLDING_REGISTERS_ADDRESS, | 287 | UT_HOLDING_REGISTERS_ADDRESS, |
| @@ -287,8 +290,10 @@ int main(void) | @@ -287,8 +290,10 @@ int main(void) | ||
| 287 | printf("* read_holding_registers: "); | 290 | printf("* read_holding_registers: "); |
| 288 | if (ret == ILLEGAL_DATA_ADDRESS) | 291 | if (ret == ILLEGAL_DATA_ADDRESS) |
| 289 | printf("OK\n"); | 292 | printf("OK\n"); |
| 290 | - else | 293 | + else { |
| 291 | printf("FAILED\n"); | 294 | printf("FAILED\n"); |
| 295 | + goto close; | ||
| 296 | + } | ||
| 292 | 297 | ||
| 293 | ret = read_input_registers(&mb_param, | 298 | ret = read_input_registers(&mb_param, |
| 294 | UT_INPUT_REGISTERS_ADDRESS, | 299 | UT_INPUT_REGISTERS_ADDRESS, |
| @@ -297,8 +302,10 @@ int main(void) | @@ -297,8 +302,10 @@ int main(void) | ||
| 297 | printf("* read_input_registers: "); | 302 | printf("* read_input_registers: "); |
| 298 | if (ret == ILLEGAL_DATA_ADDRESS) | 303 | if (ret == ILLEGAL_DATA_ADDRESS) |
| 299 | printf("OK\n"); | 304 | printf("OK\n"); |
| 300 | - else | 305 | + else { |
| 301 | printf("FAILED\n"); | 306 | printf("FAILED\n"); |
| 307 | + goto close; | ||
| 308 | + } | ||
| 302 | 309 | ||
| 303 | ret = force_single_coil(&mb_param, | 310 | ret = force_single_coil(&mb_param, |
| 304 | UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS, | 311 | UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS, |
| @@ -308,6 +315,7 @@ int main(void) | @@ -308,6 +315,7 @@ int main(void) | ||
| 308 | printf("OK\n"); | 315 | printf("OK\n"); |
| 309 | } else { | 316 | } else { |
| 310 | printf("FAILED\n"); | 317 | printf("FAILED\n"); |
| 318 | + goto close; | ||
| 311 | } | 319 | } |
| 312 | 320 | ||
| 313 | ret = force_multiple_coils(&mb_param, | 321 | ret = force_multiple_coils(&mb_param, |
| @@ -319,6 +327,7 @@ int main(void) | @@ -319,6 +327,7 @@ int main(void) | ||
| 319 | printf("OK\n"); | 327 | printf("OK\n"); |
| 320 | } else { | 328 | } else { |
| 321 | printf("FAILED\n"); | 329 | printf("FAILED\n"); |
| 330 | + goto close; | ||
| 322 | } | 331 | } |
| 323 | 332 | ||
| 324 | ret = preset_multiple_registers(&mb_param, | 333 | ret = preset_multiple_registers(&mb_param, |
| @@ -330,6 +339,7 @@ int main(void) | @@ -330,6 +339,7 @@ int main(void) | ||
| 330 | printf("OK\n"); | 339 | printf("OK\n"); |
| 331 | } else { | 340 | } else { |
| 332 | printf("FAILED\n"); | 341 | printf("FAILED\n"); |
| 342 | + goto close; | ||
| 333 | } | 343 | } |
| 334 | 344 | ||
| 335 | 345 | ||
| @@ -341,49 +351,58 @@ int main(void) | @@ -341,49 +351,58 @@ int main(void) | ||
| 341 | MAX_STATUS + 1, | 351 | MAX_STATUS + 1, |
| 342 | tab_rp_status); | 352 | tab_rp_status); |
| 343 | printf("* read_coil_status: "); | 353 | printf("* read_coil_status: "); |
| 344 | - if (ret == TOO_MANY_DATA) | 354 | + if (ret == INVALID_DATA) { |
| 345 | printf("OK\n"); | 355 | printf("OK\n"); |
| 346 | - else | 356 | + } else { |
| 347 | printf("FAILED\n"); | 357 | printf("FAILED\n"); |
| 358 | + goto close; | ||
| 359 | + } | ||
| 348 | 360 | ||
| 349 | ret = read_input_status(&mb_param, | 361 | ret = read_input_status(&mb_param, |
| 350 | UT_INPUT_STATUS_ADDRESS, | 362 | UT_INPUT_STATUS_ADDRESS, |
| 351 | MAX_STATUS + 1, | 363 | MAX_STATUS + 1, |
| 352 | tab_rp_status); | 364 | tab_rp_status); |
| 353 | printf("* read_input_status: "); | 365 | printf("* read_input_status: "); |
| 354 | - if (ret == TOO_MANY_DATA) | 366 | + if (ret == INVALID_DATA) { |
| 355 | printf("OK\n"); | 367 | printf("OK\n"); |
| 356 | - else | 368 | + } else { |
| 357 | printf("FAILED\n"); | 369 | printf("FAILED\n"); |
| 370 | + goto close; | ||
| 371 | + } | ||
| 358 | 372 | ||
| 359 | ret = read_holding_registers(&mb_param, | 373 | ret = read_holding_registers(&mb_param, |
| 360 | UT_HOLDING_REGISTERS_ADDRESS, | 374 | UT_HOLDING_REGISTERS_ADDRESS, |
| 361 | MAX_REGISTERS + 1, | 375 | MAX_REGISTERS + 1, |
| 362 | tab_rp_registers); | 376 | tab_rp_registers); |
| 363 | printf("* read_holding_registers: "); | 377 | printf("* read_holding_registers: "); |
| 364 | - if (ret == TOO_MANY_DATA) | 378 | + if (ret == INVALID_DATA) { |
| 365 | printf("OK\n"); | 379 | printf("OK\n"); |
| 366 | - else | 380 | + } else { |
| 367 | printf("FAILED\n"); | 381 | printf("FAILED\n"); |
| 382 | + goto close; | ||
| 383 | + } | ||
| 368 | 384 | ||
| 369 | ret = read_input_registers(&mb_param, | 385 | ret = read_input_registers(&mb_param, |
| 370 | UT_INPUT_REGISTERS_ADDRESS, | 386 | UT_INPUT_REGISTERS_ADDRESS, |
| 371 | MAX_REGISTERS + 1, | 387 | MAX_REGISTERS + 1, |
| 372 | tab_rp_registers); | 388 | tab_rp_registers); |
| 373 | printf("* read_input_registers: "); | 389 | printf("* read_input_registers: "); |
| 374 | - if (ret == TOO_MANY_DATA) | 390 | + if (ret == INVALID_DATA) { |
| 375 | printf("OK\n"); | 391 | printf("OK\n"); |
| 376 | - else | 392 | + } else { |
| 377 | printf("FAILED\n"); | 393 | printf("FAILED\n"); |
| 394 | + goto close; | ||
| 395 | + } | ||
| 378 | 396 | ||
| 379 | ret = force_multiple_coils(&mb_param, | 397 | ret = force_multiple_coils(&mb_param, |
| 380 | UT_COIL_STATUS_ADDRESS, | 398 | UT_COIL_STATUS_ADDRESS, |
| 381 | MAX_STATUS + 1, | 399 | MAX_STATUS + 1, |
| 382 | tab_rp_status); | 400 | tab_rp_status); |
| 383 | printf("* force_multiple_coils: "); | 401 | printf("* force_multiple_coils: "); |
| 384 | - if (ret == TOO_MANY_DATA) { | 402 | + if (ret == INVALID_DATA) { |
| 385 | printf("OK\n"); | 403 | printf("OK\n"); |
| 386 | } else { | 404 | } else { |
| 405 | + goto close; | ||
| 387 | printf("FAILED\n"); | 406 | printf("FAILED\n"); |
| 388 | } | 407 | } |
| 389 | 408 | ||
| @@ -392,10 +411,11 @@ int main(void) | @@ -392,10 +411,11 @@ int main(void) | ||
| 392 | MAX_REGISTERS + 1, | 411 | MAX_REGISTERS + 1, |
| 393 | tab_rp_registers); | 412 | tab_rp_registers); |
| 394 | printf("* preset_multiple_registers: "); | 413 | printf("* preset_multiple_registers: "); |
| 395 | - if (ret == TOO_MANY_DATA) { | 414 | + if (ret == INVALID_DATA) { |
| 396 | printf("OK\n"); | 415 | printf("OK\n"); |
| 397 | } else { | 416 | } else { |
| 398 | printf("FAILED\n"); | 417 | printf("FAILED\n"); |
| 418 | + goto close; | ||
| 399 | } | 419 | } |
| 400 | 420 | ||
| 401 | /** SLAVE REPLY **/ | 421 | /** SLAVE REPLY **/ |
| @@ -407,10 +427,11 @@ int main(void) | @@ -407,10 +427,11 @@ int main(void) | ||
| 407 | UT_HOLDING_REGISTERS_NB_POINTS, | 427 | UT_HOLDING_REGISTERS_NB_POINTS, |
| 408 | tab_rp_registers); | 428 | tab_rp_registers); |
| 409 | printf("1/2 No reply from slave %d: ", mb_param.slave); | 429 | printf("1/2 No reply from slave %d: ", mb_param.slave); |
| 410 | - if (ret != UT_HOLDING_REGISTERS_NB_POINTS) { | 430 | + if (ret == SELECT_TIMEOUT) { |
| 411 | printf("OK\n", ret); | 431 | printf("OK\n", ret); |
| 412 | } else { | 432 | } else { |
| 413 | printf("FAILED\n"); | 433 | printf("FAILED\n"); |
| 434 | + goto close; | ||
| 414 | } | 435 | } |
| 415 | 436 | ||
| 416 | mb_param.slave = MODBUS_BROADCAST_ADDRESS; | 437 | mb_param.slave = MODBUS_BROADCAST_ADDRESS; |
| @@ -422,6 +443,7 @@ int main(void) | @@ -422,6 +443,7 @@ int main(void) | ||
| 422 | if (ret == UT_HOLDING_REGISTERS_NB_POINTS) { | 443 | if (ret == UT_HOLDING_REGISTERS_NB_POINTS) { |
| 423 | printf("OK\n", ret); | 444 | printf("OK\n", ret); |
| 424 | } else { | 445 | } else { |
| 446 | + goto close; | ||
| 425 | printf("FAILED\n"); | 447 | printf("FAILED\n"); |
| 426 | } | 448 | } |
| 427 | 449 | ||
| @@ -436,11 +458,11 @@ int main(void) | @@ -436,11 +458,11 @@ int main(void) | ||
| 436 | UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL, | 458 | UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL, |
| 437 | tab_rp_registers_bad); | 459 | tab_rp_registers_bad); |
| 438 | printf("* read_holding_registers: "); | 460 | printf("* read_holding_registers: "); |
| 439 | - if (ret > 0) { | ||
| 440 | - /* Error not detected */ | ||
| 441 | - printf("FAILED\n"); | ||
| 442 | - } else { | 461 | + if (ret == INVALID_DATA) { |
| 443 | printf("OK\n"); | 462 | printf("OK\n"); |
| 463 | + } else { | ||
| 464 | + printf("FAILED\n"); | ||
| 465 | + goto close; | ||
| 444 | } | 466 | } |
| 445 | free(tab_rp_registers_bad); | 467 | free(tab_rp_registers_bad); |
| 446 | 468 |