Commit a4f7996eafbf701371db7c9fa826987fed119188
1 parent
311137cf
New function to reply to an indication with an exception message
Contributed by Dominic Storey. - new function modbus_reply_exception - unit test
Showing
5 changed files
with
55 additions
and
0 deletions
src/modbus.c
| ... | ... | @@ -818,6 +818,37 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 818 | 818 | return send_msg(ctx, rsp, rsp_length); |
| 819 | 819 | } |
| 820 | 820 | |
| 821 | +int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, | |
| 822 | + unsigned int exception_code) | |
| 823 | +{ | |
| 824 | + int offset = ctx->backend->header_length; | |
| 825 | + int slave = req[offset - 1]; | |
| 826 | + int function = req[offset]; | |
| 827 | + uint8_t rsp[MAX_MESSAGE_LENGTH]; | |
| 828 | + int rsp_length; | |
| 829 | + int dummy_length = 99; | |
| 830 | + sft_t sft; | |
| 831 | + | |
| 832 | + if (ctx->backend->filter_request(ctx, slave) == 1) { | |
| 833 | + /* Filtered */ | |
| 834 | + return 0; | |
| 835 | + } | |
| 836 | + | |
| 837 | + sft.slave = slave; | |
| 838 | + sft.function = function + 0x80;; | |
| 839 | + sft.t_id = ctx->backend->prepare_response_tid(req, &dummy_length); | |
| 840 | + rsp_length = ctx->backend->build_response_basis(&sft, rsp); | |
| 841 | + | |
| 842 | + /* Positive exception code */ | |
| 843 | + if (exception_code < MODBUS_EXCEPTION_MAX) { | |
| 844 | + rsp[rsp_length++] = exception_code; | |
| 845 | + return send_msg(ctx, rsp, rsp_length); | |
| 846 | + } else { | |
| 847 | + errno = EINVAL; | |
| 848 | + return -1; | |
| 849 | + } | |
| 850 | +} | |
| 851 | + | |
| 821 | 852 | /* Reads IO status */ |
| 822 | 853 | static int read_io_status(modbus_t *ctx, int function, |
| 823 | 854 | int addr, int nb, uint8_t *data_dest) | ... | ... |
src/modbus.h
| ... | ... | @@ -171,6 +171,8 @@ void modbus_mapping_free(modbus_mapping_t *mb_mapping); |
| 171 | 171 | int modbus_receive(modbus_t *ctx, int sockfd, uint8_t *req); |
| 172 | 172 | int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 173 | 173 | int req_length, modbus_mapping_t *mb_mapping); |
| 174 | +int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, | |
| 175 | + unsigned int exception_code); | |
| 174 | 176 | |
| 175 | 177 | /** |
| 176 | 178 | * UTILS FUNCTIONS | ... | ... |
tests/unit-test-client.c
| ... | ... | @@ -618,8 +618,23 @@ int main(int argc, char *argv[]) |
| 618 | 618 | printf("FAILED\n"); |
| 619 | 619 | goto close; |
| 620 | 620 | } |
| 621 | + | |
| 621 | 622 | free(tab_rp_registers_bad); |
| 622 | 623 | |
| 624 | + /** MANUAL EXCEPTION **/ | |
| 625 | + printf("\nTEST MANUAL EXCEPTION:\n"); | |
| 626 | + | |
| 627 | + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SPECIAL, | |
| 628 | + UT_REGISTERS_NB_POINTS, | |
| 629 | + tab_rp_registers); | |
| 630 | + printf("* modbus_read_registers at special address: "); | |
| 631 | + if (rc == -1 && errno == EMBXSBUSY) { | |
| 632 | + printf("OK\n"); | |
| 633 | + } else { | |
| 634 | + printf("FAILED\n"); | |
| 635 | + goto close; | |
| 636 | + } | |
| 637 | + | |
| 623 | 638 | printf("\nALL TESTS PASS WITH SUCCESS.\n"); |
| 624 | 639 | |
| 625 | 640 | close: | ... | ... |
tests/unit-test-server.c
| ... | ... | @@ -119,6 +119,11 @@ int main(int argc, char*argv[]) |
| 119 | 119 | printf("Set an incorrect number of values\n"); |
| 120 | 120 | MODBUS_SET_INT16_TO_INT8(query, header_length + 3, |
| 121 | 121 | UT_REGISTERS_NB_POINTS); |
| 122 | + } else if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1) | |
| 123 | + == UT_REGISTERS_ADDRESS_SPECIAL) { | |
| 124 | + modbus_reply_exception(ctx, query, | |
| 125 | + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY); | |
| 126 | + continue; | |
| 122 | 127 | } |
| 123 | 128 | } |
| 124 | 129 | ... | ... |
tests/unit-test.h
| ... | ... | @@ -38,6 +38,8 @@ const uint16_t UT_INPUT_BITS_NB_POINTS = 0x16; |
| 38 | 38 | const uint8_t UT_INPUT_BITS_TAB[] = { 0xAC, 0xDB, 0x35 }; |
| 39 | 39 | |
| 40 | 40 | const uint16_t UT_REGISTERS_ADDRESS = 0x6B; |
| 41 | +/* Raise a manual exception when this adress is used for the first byte */ | |
| 42 | +const uint16_t UT_REGISTERS_ADDRESS_SPECIAL = 0x6C; | |
| 41 | 43 | const uint16_t UT_REGISTERS_NB_POINTS = 0x3; |
| 42 | 44 | const uint16_t UT_REGISTERS_TAB[] = { 0x022B, 0x0000, 0x0064 }; |
| 43 | 45 | /* If the following value is used, a bad response is sent. | ... | ... |