From 4d3bf7beeaa8c196957c8daa76fa7dc51941b859 Mon Sep 17 00:00:00 2001 From: Stéphane Raimbault Date: Wed, 21 Jul 2010 22:39:51 +0200 Subject: [PATCH] Implement report slave ID on server side --- NEWS | 2 ++ src/modbus.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ tests/unit-test-client.c | 22 +++++++++++++++++++--- tests/unit-test-server.c | 12 +++++++----- 4 files changed, 97 insertions(+), 38 deletions(-) diff --git a/NEWS b/NEWS index ec5f78b..75e0bd7 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ libmodbus 2.1.1 (2010-XX-XX) ============================ +- New API - Remove the internal function set_message_length_tcp - Restore slave ID (server ID) argument in functions - Error conventions of POSIX systems and error recover @@ -13,6 +14,7 @@ libmodbus 2.1.1 (2010-XX-XX) - Fix #591142 - Slave id check should be disabled in TCP connection Reported by aladdinwu. - Parity setting is now a single char ('N', 'E' or 'O') +- Report slave ID server side libmodbus 2.1.0 (2010-03-24) ============================ diff --git a/src/modbus.c b/src/modbus.c index c741790..4bdb03f 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -479,7 +479,7 @@ static int send_msg(modbus_t *ctx, uint8_t *req, int req_length) } /* Computes the length of the header following the function code */ -static uint8_t compute_request_length_header(int function) +static uint8_t compute_indication_length_header(int function) { int length; @@ -492,6 +492,28 @@ static uint8_t compute_request_length_header(int function) /* Multiple write */ length = 5; else if (function == FC_REPORT_SLAVE_ID) + length = 0; + else + length = 0; + + return length; +} + +/* Computes the length of the header following the function code */ +static uint8_t compute_confirmation_length_header(int function) +{ + int length; + + if (function <= FC_WRITE_SINGLE_COIL || + function == FC_WRITE_SINGLE_REGISTER) + /* Read and single write */ + length = 4; + else if (function == FC_WRITE_MULTIPLE_COILS || + function == FC_WRITE_MULTIPLE_REGISTERS) + /* Multiple write */ + length = 5; + else if (function == FC_REPORT_SLAVE_ID) + /* Report slave_ID */ length = 1; else length = 0; @@ -500,17 +522,17 @@ static uint8_t compute_request_length_header(int function) } /* Computes the length of the data to write in the request */ -static int compute_request_length_data(modbus_t *ctx, uint8_t *msg) +static int compute_msg_length_data(modbus_t *ctx, uint8_t *msg) { int function = msg[TAB_HEADER_LENGTH[ctx->type_com]]; int length; if (function == FC_WRITE_MULTIPLE_COILS || - function == FC_WRITE_MULTIPLE_REGISTERS) + function == FC_WRITE_MULTIPLE_REGISTERS) { length = msg[TAB_HEADER_LENGTH[ctx->type_com] + 5]; - else if (function == FC_REPORT_SLAVE_ID) + } else if (function == FC_REPORT_SLAVE_ID) { length = msg[TAB_HEADER_LENGTH[ctx->type_com] + 1]; - else + } else length = 0; length += TAB_CHECKSUM_LENGTH[ctx->type_com]; @@ -573,7 +595,14 @@ static int compute_request_length_data(modbus_t *ctx, uint8_t *msg) - ETIMEDOUT - read() or recv() error codes */ -static int receive_msg(modbus_t *ctx, int msg_length_computed, uint8_t *msg) +enum { + /* Request message on the server side */ + MSG_INDICATION, + /* Request message on the client side */ + MSG_CONFIRMATION +}; + +static int receive_msg(modbus_t *ctx, int msg_length_computed, uint8_t *msg, int type) { int s_rc; int read_rc; @@ -586,11 +615,16 @@ static int receive_msg(modbus_t *ctx, int msg_length_computed, uint8_t *msg) int msg_length = 0; if (ctx->debug) { + if (type == MSG_INDICATION) { + printf("Waiting for a indication"); + } else { + printf("Waiting for a confirmation"); + } + if (msg_length_computed == MSG_LENGTH_UNDEFINED) - printf("Waiting for a message...\n"); + printf("...\n"); else - printf("Waiting for a message (%d bytes)...\n", - msg_length_computed); + printf("(%d bytes)...\n", msg_length_computed); } /* Add a file descriptor to the set */ @@ -661,8 +695,13 @@ static int receive_msg(modbus_t *ctx, int msg_length_computed, uint8_t *msg) switch (state) { case FUNCTION: /* Function code position */ - length_to_read = compute_request_length_header( - msg[TAB_HEADER_LENGTH[ctx->type_com]]); + if (type == MSG_INDICATION) { + length_to_read = compute_indication_length_header( + msg[TAB_HEADER_LENGTH[ctx->type_com]]); + } else { + length_to_read = compute_confirmation_length_header( + msg[TAB_HEADER_LENGTH[ctx->type_com]]); + } msg_length_computed += length_to_read; /* It's useless to check the value of msg_length_computed in this case (only @@ -670,7 +709,7 @@ static int receive_msg(modbus_t *ctx, int msg_length_computed, uint8_t *msg) state = DATA; break; case DATA: - length_to_read = compute_request_length_data(ctx, msg); + length_to_read = compute_msg_length_data(ctx, msg); msg_length_computed += length_to_read; if (msg_length_computed > TAB_MAX_ADU_LENGTH[ctx->type_com]) { errno = EMBBADDATA; @@ -727,7 +766,7 @@ int modbus_receive(modbus_t *ctx, int sockfd, uint8_t *req) } /* The length of the request to receive isn't known. */ - return receive_msg(ctx, MSG_LENGTH_UNDEFINED, req); + return receive_msg(ctx, MSG_LENGTH_UNDEFINED, req, MSG_INDICATION); } /* Receives the response and checks values (and checksum in RTU). @@ -744,7 +783,7 @@ static int receive_msg_req(modbus_t *ctx, uint8_t *req, uint8_t *rsp) int offset = TAB_HEADER_LENGTH[ctx->type_com]; rsp_length_computed = compute_response_length(ctx, req); - rc = receive_msg(ctx, rsp_length_computed, rsp); + rc = receive_msg(ctx, rsp_length_computed, rsp, MSG_CONFIRMATION); if (rc != -1) { /* GOOD RESPONSE */ int req_nb_value; @@ -776,7 +815,7 @@ static int receive_msg_req(modbus_t *ctx, uint8_t *req, uint8_t *rsp) break; case FC_REPORT_SLAVE_ID: /* Report slave ID (bytes received) */ - req_nb_value = rsp_nb_value = rc; + req_nb_value = rsp_nb_value = rsp[offset + 1]; break; default: /* 1 Write functions & others */ @@ -1088,8 +1127,15 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } break; - case FC_READ_EXCEPTION_STATUS: case FC_REPORT_SLAVE_ID: + resp_length = build_response_basis(ctx, &sft, rsp); + /* 2 bytes */ + rsp[resp_length++] = 2; + rsp[resp_length++] = ctx->slave; + /* Slave is ON */ + rsp[resp_length++] = 0xFF; + break; + case FC_READ_EXCEPTION_STATUS: if (ctx->debug) { fprintf(stderr, "FIXME Not implemented\n"); } @@ -1127,11 +1173,11 @@ static int read_io_status(modbus_t *ctx, int function, if (rc == -1) return -1; - offset = TAB_HEADER_LENGTH[ctx->type_com]; + offset = TAB_HEADER_LENGTH[ctx->type_com] + 2; offset_end = offset + rc; for (i = offset; i < offset_end; i++) { /* Shift reg hi_byte to temp */ - temp = rsp[i + 2]; + temp = rsp[i]; for (bit = 0x01; (bit & 0xff) && (pos < nb);) { data_dest[pos++] = (temp & bit) ? TRUE : FALSE; @@ -1410,19 +1456,13 @@ int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data } /* Send a request to get the slave ID of the device (only available in serial - * communication) */ + * communication). */ int modbus_report_slave_id(modbus_t *ctx, uint8_t *data_dest) { int rc; int req_length; uint8_t req[MIN_REQ_LENGTH]; - if (ctx->type_com != RTU) { - /* Only for serial communications */ - errno = EINVAL; - return -1; - } - req_length = build_request_basis(ctx, FC_REPORT_SLAVE_ID, 0, 0, req); /* HACKISH, addr and count are not used */ @@ -1432,7 +1472,6 @@ int modbus_report_slave_id(modbus_t *ctx, uint8_t *data_dest) if (rc > 0) { int i; int offset; - int offset_end; uint8_t rsp[MAX_MESSAGE_LENGTH]; /* Byte count, slave id, run indicator status, @@ -1441,11 +1480,11 @@ int modbus_report_slave_id(modbus_t *ctx, uint8_t *data_dest) if (rc == -1) return -1; - offset = TAB_HEADER_LENGTH[ctx->type_com] - 1; - offset_end = offset + rc; + offset = TAB_HEADER_LENGTH[ctx->type_com] + 2; - for (i = offset; i < offset_end; i++) - data_dest[i] = rsp[i]; + for (i=0; i < rc; i++) { + data_dest[i] = rsp[offset + i]; + } } return rc; diff --git a/tests/unit-test-client.c b/tests/unit-test-client.c index 5c3afca..4dd0ea0 100644 --- a/tests/unit-test-client.c +++ b/tests/unit-test-client.c @@ -443,7 +443,7 @@ int main(void) rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_POINTS, tab_rp_registers); - printf("1/3 No or response from slave %d: ", 18); + printf("1/4 No or response from slave %d: ", 18); if (is_mode_rtu) { /* No response in RTU mode */ if (rc == -1 && errno == ETIMEDOUT) { @@ -466,7 +466,7 @@ int main(void) rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_POINTS, tab_rp_registers); - printf("2/3 Reply after a broadcast query: "); + printf("2/4 Reply after a broadcast query: "); if (rc == UT_REGISTERS_NB_POINTS) { printf("OK\n"); } else { @@ -481,6 +481,22 @@ int main(void) modbus_set_slave(ctx, MODBUS_TCP_SLAVE); } + printf("3/4 Report slave ID: \n"); + /* tab_rp_bits is used to store bytes */ + rc = modbus_report_slave_id(ctx, tab_rp_bits); + if (rc == -1) { + printf("FAILED\n"); + goto close; + } + + if ((is_mode_rtu && tab_rp_bits[0] == SERVER_ID) + || tab_rp_bits[0] == 0xFF) { + printf("OK\n"); + } else { + printf("FAILED\n"); + goto close; + } + /* Save original timeout */ modbus_get_timeout_begin(ctx, &timeout_begin_old); @@ -492,7 +508,7 @@ int main(void) rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_POINTS, tab_rp_registers); - printf("3/3 Too short timeout: "); + printf("4/4 Too short timeout: "); if (rc == -1 && errno == ETIMEDOUT) { printf("OK\n"); } else { diff --git a/tests/unit-test-server.c b/tests/unit-test-server.c index e46a45b..6207496 100644 --- a/tests/unit-test-server.c +++ b/tests/unit-test-server.c @@ -39,10 +39,11 @@ int main(void) modbus_set_debug(ctx, TRUE); modbus_set_error_recovery(ctx, TRUE); - mb_mapping = modbus_mapping_new(UT_BITS_ADDRESS + UT_BITS_NB_POINTS, - UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB_POINTS, - UT_REGISTERS_ADDRESS + UT_REGISTERS_NB_POINTS, - UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS); + mb_mapping = modbus_mapping_new( + UT_BITS_ADDRESS + UT_BITS_NB_POINTS, + UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB_POINTS, + UT_REGISTERS_ADDRESS + UT_REGISTERS_NB_POINTS, + UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS); if (mb_mapping == NULL) { fprintf(stderr, "Failed to allocate the mapping: %s\n", modbus_strerror(errno)); @@ -72,7 +73,8 @@ int main(void) rc = modbus_receive(ctx, -1, query); if (rc > 0) { - if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4]) + if (((query[HEADER_LENGTH_TCP + 3] << 8) + + query[HEADER_LENGTH_TCP + 4]) == UT_REGISTERS_NB_POINTS_SPECIAL) { /* Change the number of values (offset TCP = 6) */ -- libgit2 0.21.4