diff --git a/plugins/modbus/modbus_req.c b/plugins/modbus/modbus_req.c index 152b02fe..c26d8a63 100644 --- a/plugins/modbus/modbus_req.c +++ b/plugins/modbus/modbus_req.c @@ -120,7 +120,8 @@ int modbus_send_msg(void *ctx, uint16_t n_byte, uint8_t *bytes) } int modbus_stack_read_retry(neu_plugin_t *plugin, struct modbus_group_data *gd, - uint16_t i, uint16_t j, uint16_t *response_size) + uint16_t i, uint16_t j, uint16_t *response_size, + uint64_t *read_tms) { struct timespec t3 = { .tv_sec = plugin->retry_interval / 1000, .tv_nsec = @@ -128,21 +129,128 @@ int modbus_stack_read_retry(neu_plugin_t *plugin, struct modbus_group_data *gd, struct timespec t4 = { 0 }; nanosleep(&t3, &t4); plog_notice(plugin, "Resend read req. Times:%hu", j + 1); - int ret = modbus_stack_read( + *read_tms = neu_time_ms(); + return modbus_stack_read( plugin->stack, gd->cmd_sort->cmd[i].slave_id, gd->cmd_sort->cmd[i].area, gd->cmd_sort->cmd[i].start_address, gd->cmd_sort->cmd[i].n_register, response_size, false); - return ret; +} + +void handle_modbus_error(neu_plugin_t *plugin, struct modbus_group_data *gd, + uint16_t cmd_index, int error_code, + const char *error_message) +{ + modbus_value_handle(plugin, gd->cmd_sort->cmd[cmd_index].slave_id, 0, NULL, + error_code); + if (error_message) { + plog_error(plugin, "%s, skip, %hhu!%hu", error_message, + gd->cmd_sort->cmd[cmd_index].slave_id, + gd->cmd_sort->cmd[cmd_index].start_address); + } +} + +void finalize_modbus_read_result(neu_plugin_t * plugin, + struct modbus_group_data *gd, + uint16_t cmd_index, int ret_r, int ret_buf, + uint64_t read_tms, int64_t *rtt) +{ + if (ret_r <= 0) { + handle_modbus_error(plugin, gd, cmd_index, NEU_ERR_PLUGIN_DISCONNECTED, + "send message failed"); + *rtt = NEU_METRIC_LAST_RTT_MS_MAX; + neu_conn_disconnect(plugin->conn); + } else if (ret_buf <= 0) { + switch (ret_buf) { + case 0: + handle_modbus_error(plugin, gd, cmd_index, + NEU_ERR_PLUGIN_DEVICE_NOT_RESPONSE, + "no modbus response received"); + *rtt = neu_time_ms() - read_tms; + break; + case -1: + handle_modbus_error(plugin, gd, cmd_index, + NEU_ERR_PLUGIN_PROTOCOL_DECODE_FAILURE, + "modbus message error"); + *rtt = neu_time_ms() - read_tms; + break; + case -2: + handle_modbus_error(plugin, gd, cmd_index, + NEU_ERR_PLUGIN_READ_FAILURE, + "modbus device response error"); + *rtt = neu_time_ms() - read_tms; + break; + default: + break; + } + } else { + *rtt = neu_time_ms() - read_tms; + } +} + +void check_modbus_read_result(neu_plugin_t * plugin, + struct modbus_group_data *gd, uint16_t cmd_index, + int64_t *rtt) +{ + uint16_t response_size = 0; + uint64_t read_tms = neu_time_ms(); + + int ret_r = modbus_stack_read( + plugin->stack, gd->cmd_sort->cmd[cmd_index].slave_id, + gd->cmd_sort->cmd[cmd_index].area, + gd->cmd_sort->cmd[cmd_index].start_address, + gd->cmd_sort->cmd[cmd_index].n_register, &response_size, false); + + int ret_buf = 0; + if (ret_r > 0) { + ret_buf = process_protocol_buf( + plugin, gd->cmd_sort->cmd[cmd_index].slave_id, response_size); + } + + if (ret_r <= 0 || ret_buf == 0) { + for (uint16_t j = 0; j < plugin->max_retries; ++j) { + ret_r = modbus_stack_read_retry(plugin, gd, cmd_index, j, + &response_size, &read_tms); + if (ret_r > 0) { + ret_buf = process_protocol_buf( + plugin, gd->cmd_sort->cmd[cmd_index].slave_id, + response_size); + if (ret_buf == 0) { + continue; + } + } + break; + } + } + + finalize_modbus_read_result(plugin, gd, cmd_index, ret_r, ret_buf, read_tms, + rtt); +} + +void update_metrics_after_read(neu_plugin_t *plugin, int64_t rtt, + neu_plugin_group_t *group, + neu_conn_state_t * state) +{ + *state = neu_conn_state(plugin->conn); + neu_adapter_update_metric_cb_t update_metric = + plugin->common.adapter_callbacks->update_metric; + struct modbus_group_data *gd = + (struct modbus_group_data *) group->user_data; + + update_metric(plugin->common.adapter, NEU_METRIC_SEND_BYTES, + state->send_bytes, NULL); + update_metric(plugin->common.adapter, NEU_METRIC_RECV_BYTES, + state->recv_bytes, NULL); + update_metric(plugin->common.adapter, NEU_METRIC_LAST_RTT_MS, rtt, NULL); + update_metric(plugin->common.adapter, NEU_METRIC_GROUP_LAST_SEND_MSGS, + gd->cmd_sort->n_cmd, group->group_name); } int modbus_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group, uint16_t max_byte) { - neu_conn_state_t state = { 0 }; - neu_adapter_update_metric_cb_t update_metric = - plugin->common.adapter_callbacks->update_metric; - struct modbus_group_data *gd = NULL; - int64_t rtt = NEU_METRIC_LAST_RTT_MS_MAX; + neu_conn_state_t state = { 0 }; + struct modbus_group_data *gd = NULL; + int64_t rtt = NEU_METRIC_LAST_RTT_MS_MAX; if (group->user_data == NULL) { gd = calloc(1, sizeof(struct modbus_group_data)); @@ -171,142 +279,9 @@ int modbus_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group, plugin->plugin_group_data = gd; for (uint16_t i = 0; i < gd->cmd_sort->n_cmd; i++) { - plugin->cmd_idx = i; - uint16_t response_size = 0; - uint64_t read_tms = neu_time_ms(); - int ret_buf = 0; - int ret_r = modbus_stack_read( - plugin->stack, gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].area, gd->cmd_sort->cmd[i].start_address, - gd->cmd_sort->cmd[i].n_register, &response_size, false); - if (ret_r > 0) { - ret_buf = process_protocol_buf( - plugin, gd->cmd_sort->cmd[i].slave_id, response_size); - if (ret_buf > 0) { - rtt = neu_time_ms() - read_tms; - } else if (ret_buf == 0) { - for (uint16_t j = 0; j < plugin->max_retries; j++) { - ret_r = modbus_stack_read_retry(plugin, gd, i, j, - &response_size); - if (ret_r > 0) { - ret_buf = process_protocol_buf( - plugin, gd->cmd_sort->cmd[i].slave_id, - response_size); - if (ret_buf > 0) { - rtt = neu_time_ms() - read_tms; - break; - } else if (ret_buf < 0) { - if (ret_buf == -1) { - modbus_value_handle( - plugin, gd->cmd_sort->cmd[i].slave_id, 0, - NULL, - NEU_ERR_PLUGIN_PROTOCOL_DECODE_FAILURE); - plog_error( - plugin, - "modbus message error, skip, %hhu!%hu", - gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].start_address); - } else if (ret_buf == -2) { - modbus_value_handle( - plugin, gd->cmd_sort->cmd[i].slave_id, 0, - NULL, NEU_ERR_PLUGIN_READ_FAILURE); - plog_error( - plugin, - "modbus device response error, skip, " - "%hhu!%hu", - gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].start_address); - } - rtt = neu_time_ms() - read_tms; - break; - } - } else { - modbus_value_handle(plugin, - gd->cmd_sort->cmd[i].slave_id, 0, - NULL, NEU_ERR_PLUGIN_DISCONNECTED); - rtt = NEU_METRIC_LAST_RTT_MS_MAX; - neu_conn_disconnect(plugin->conn); - break; - } - } - if (ret_r > 0 && ret_buf == 0) { - modbus_value_handle(plugin, gd->cmd_sort->cmd[i].slave_id, - 0, NULL, - NEU_ERR_PLUGIN_DEVICE_NOT_RESPONSE); - plog_warn(plugin, - "no modbus response received, skip, %hhu!%hu", - gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].start_address); - } - } else if (ret_buf < 0) { - if (ret_buf == -1) { - modbus_value_handle(plugin, gd->cmd_sort->cmd[i].slave_id, - 0, NULL, - NEU_ERR_PLUGIN_PROTOCOL_DECODE_FAILURE); - plog_error(plugin, "modbus message error, skip, %hhu!%hu", - gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].start_address); - } else if (ret_buf == -2) { - modbus_value_handle(plugin, gd->cmd_sort->cmd[i].slave_id, - 0, NULL, NEU_ERR_PLUGIN_READ_FAILURE); - plog_error(plugin, - "modbus device response error, skip, %hhu!%hu", - gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].start_address); - } - rtt = neu_time_ms() - read_tms; - } - } else { - for (uint16_t j = 0; j < plugin->max_retries; j++) { - ret_r = - modbus_stack_read_retry(plugin, gd, i, j, &response_size); - if (ret_r > 0) { - ret_buf = process_protocol_buf( - plugin, gd->cmd_sort->cmd[i].slave_id, response_size); - if (ret_buf > 0) { - rtt = neu_time_ms() - read_tms; - break; - } else if (ret_buf < 0) { - if (ret_buf == -1) { - modbus_value_handle( - plugin, gd->cmd_sort->cmd[i].slave_id, 0, NULL, - NEU_ERR_PLUGIN_PROTOCOL_DECODE_FAILURE); - plog_error(plugin, - "modbus message error, skip, %hhu!%hu", - gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].start_address); - } else if (ret_buf == -2) { - modbus_value_handle( - plugin, gd->cmd_sort->cmd[i].slave_id, 0, NULL, - NEU_ERR_PLUGIN_READ_FAILURE); - plog_error(plugin, - "modbus device response error, skip, " - "%hhu!%hu", - gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].start_address); - } - rtt = neu_time_ms() - read_tms; - break; - } else if (ret_buf == 0) { - modbus_value_handle( - plugin, gd->cmd_sort->cmd[i].slave_id, 0, NULL, - NEU_ERR_PLUGIN_DEVICE_NOT_RESPONSE); - plog_warn(plugin, - "no modbus response received, skip, %hhu!%hu", - gd->cmd_sort->cmd[i].slave_id, - gd->cmd_sort->cmd[i].start_address); - continue; - } - } - } - if (ret_r <= 0) { - modbus_value_handle(plugin, gd->cmd_sort->cmd[i].slave_id, 0, - NULL, NEU_ERR_PLUGIN_DISCONNECTED); - rtt = NEU_METRIC_LAST_RTT_MS_MAX; - neu_conn_disconnect(plugin->conn); - break; - } - } + plugin->cmd_idx = i; + check_modbus_read_result(plugin, gd, i, &rtt); + if (plugin->interval > 0) { struct timespec t1 = { .tv_sec = plugin->interval / 1000, .tv_nsec = 1000 * 1000 * @@ -316,14 +291,7 @@ int modbus_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group, } } - state = neu_conn_state(plugin->conn); - update_metric(plugin->common.adapter, NEU_METRIC_SEND_BYTES, - state.send_bytes, NULL); - update_metric(plugin->common.adapter, NEU_METRIC_RECV_BYTES, - state.recv_bytes, NULL); - update_metric(plugin->common.adapter, NEU_METRIC_LAST_RTT_MS, rtt, NULL); - update_metric(plugin->common.adapter, NEU_METRIC_GROUP_LAST_SEND_MSGS, - gd->cmd_sort->n_cmd, group->group_name); + update_metrics_after_read(plugin, rtt, group, &state); return 0; } @@ -645,67 +613,84 @@ int modbus_test_read_tag(neu_plugin_t *plugin, void *req, neu_datatag_t tag) return 0; } -int modbus_write(neu_plugin_t *plugin, void *req, neu_datatag_t *tag, - neu_value_u value, bool response) +static uint8_t convert_value(neu_value_u *value, neu_datatag_t *tag, + modbus_point_t *point) { - modbus_point_t point = { 0 }; - int ret = modbus_tag_to_point(tag, &point); - assert(ret == 0); uint8_t n_byte = 0; - switch (tag->type) { case NEU_TYPE_UINT16: case NEU_TYPE_INT16: - value.u16 = htons(value.u16); - n_byte = sizeof(uint16_t); + value->u16 = htons(value->u16); + n_byte = sizeof(uint16_t); break; case NEU_TYPE_FLOAT: case NEU_TYPE_UINT32: case NEU_TYPE_INT32: - value.u32 = htonl(value.u32); - n_byte = sizeof(uint32_t); + value->u32 = htonl(value->u32); + n_byte = sizeof(uint32_t); break; - case NEU_TYPE_DOUBLE: case NEU_TYPE_INT64: case NEU_TYPE_UINT64: - value.u64 = neu_htonll(value.u64); - n_byte = sizeof(uint64_t); + value->u64 = neu_htonll(value->u64); + n_byte = sizeof(uint64_t); break; - case NEU_TYPE_BIT: { + case NEU_TYPE_BIT: n_byte = sizeof(uint8_t); break; - } case NEU_TYPE_STRING: { - switch (point.option.string.type) { + switch (point->option.string.type) { case NEU_DATATAG_STRING_TYPE_H: break; case NEU_DATATAG_STRING_TYPE_L: - neu_datatag_string_ltoh(value.str, point.option.string.length); + neu_datatag_string_ltoh(value->str, point->option.string.length); break; case NEU_DATATAG_STRING_TYPE_D: break; case NEU_DATATAG_STRING_TYPE_E: break; } - n_byte = point.option.string.length; + n_byte = point->option.string.length; break; } - case NEU_TYPE_BYTES: { - n_byte = point.option.bytes.length; + case NEU_TYPE_BYTES: + n_byte = point->option.bytes.length; break; - } default: - assert(1 == 0); + assert(false); break; } + return n_byte; +} + +static int write_modbus_point(neu_plugin_t *plugin, void *req, + modbus_point_t *point, neu_value_u value, + uint8_t n_byte) +{ + uint16_t response_size = 0; + int ret = modbus_stack_write( + plugin->stack, req, point->slave_id, point->area, point->start_address, + point->n_register, value.bytes.bytes, n_byte, &response_size, true); + + if (ret > 0) { + process_protocol_buf(plugin, point->slave_id, response_size); + } + return ret; +} + +static int write_modbus_points(neu_plugin_t * plugin, + modbus_write_cmd_t *write_cmd, void *req) +{ uint16_t response_size = 0; - ret = modbus_stack_write( - plugin->stack, req, point.slave_id, point.area, point.start_address, - point.n_register, value.bytes.bytes, n_byte, &response_size, response); + + int ret = modbus_stack_write(plugin->stack, req, write_cmd->slave_id, + write_cmd->area, write_cmd->start_address, + write_cmd->n_register, write_cmd->bytes, + write_cmd->n_byte, &response_size, false); + if (ret > 0) { - process_protocol_buf(plugin, point.slave_id, response_size); + process_protocol_buf(plugin, write_cmd->slave_id, response_size); } return ret; @@ -714,9 +699,12 @@ int modbus_write(neu_plugin_t *plugin, void *req, neu_datatag_t *tag, int modbus_write_tag(neu_plugin_t *plugin, void *req, neu_datatag_t *tag, neu_value_u value) { - int ret = 0; - ret = modbus_write(plugin, req, tag, value, true); - return ret; + modbus_point_t point = { 0 }; + int ret = modbus_tag_to_point(tag, &point); + assert(ret == 0); + + uint8_t n_byte = convert_value(&value, tag, &point); + return write_modbus_point(plugin, req, &point, value, n_byte); } int modbus_write_tags(neu_plugin_t *plugin, void *req, UT_array *tags) @@ -738,18 +726,7 @@ int modbus_write_tags(neu_plugin_t *plugin, void *req, UT_array *tags) } gtags->cmd_sort = modbus_write_tags_sort(gtags->tags); for (uint16_t i = 0; i < gtags->cmd_sort->n_cmd; i++) { - uint16_t response_size = 0; - - ret = modbus_stack_write( - plugin->stack, req, gtags->cmd_sort->cmd[i].slave_id, - gtags->cmd_sort->cmd[i].area, gtags->cmd_sort->cmd[i].start_address, - gtags->cmd_sort->cmd[i].n_register, gtags->cmd_sort->cmd[i].bytes, - gtags->cmd_sort->cmd[i].n_byte, &response_size, false); - if (ret > 0) { - process_protocol_buf(plugin, gtags->cmd_sort->cmd[i].slave_id, - response_size); - } - + ret = write_modbus_points(plugin, >ags->cmd_sort->cmd[i], req); if (ret <= 0) { rv = 1; } @@ -805,104 +782,123 @@ static void plugin_group_free(neu_plugin_group_t *pgp) free(gd); } +static ssize_t recv_data(neu_plugin_t *plugin, uint8_t *buffer, size_t size) +{ + if (plugin->is_server) { + return neu_conn_tcp_server_recv(plugin->conn, plugin->client_fd, buffer, + size); + } else { + return neu_conn_recv(plugin->conn, buffer, size); + } +} + +static int process_received_data(neu_plugin_t *plugin, uint8_t *recv_buf, + ssize_t recv_size, uint16_t expected_size, + uint8_t slave_id) +{ + if (recv_size < 512) { + plog_recv_protocol(plugin, recv_buf, recv_size); + } + neu_protocol_unpack_buf_t pbuf = { 0 }; + neu_protocol_unpack_buf_init(&pbuf, recv_buf, recv_size); + int ret = modbus_stack_recv(plugin->stack, slave_id, &pbuf); + if (ret == MODBUS_DEVICE_ERR) { + return -2; + } + return recv_size == expected_size ? ret : -1; +} + +static int process_received_data_test(neu_plugin_t *plugin, uint8_t *recv_buf, + ssize_t recv_size, uint16_t expected_size, + void *req, modbus_point_t *point) +{ + if (recv_size < 512) { + plog_recv_protocol(plugin, recv_buf, recv_size); + } + neu_protocol_unpack_buf_t pbuf = { 0 }; + neu_protocol_unpack_buf_init(&pbuf, recv_buf, recv_size); + int ret = modbus_stack_recv_test(plugin, req, point, &pbuf); + if (ret == MODBUS_DEVICE_ERR) { + return -2; + } + return recv_size == expected_size ? ret : -1; +} + +static int valid_modbus_tcp_response(neu_plugin_t *plugin, uint8_t *recv_buf, + uint16_t response_size) +{ + ssize_t ret = recv_data(plugin, recv_buf, sizeof(struct modbus_header)); + if (ret <= 0) { + return 0; + } + + if (ret != sizeof(struct modbus_header)) { + return -1; + } + + struct modbus_header *header = (struct modbus_header *) recv_buf; + + if (htons(header->len) > response_size - sizeof(struct modbus_header)) { + return -1; + } + + ret = recv_data(plugin, recv_buf + sizeof(struct modbus_header), + htons(header->len)); + + return ret == htons(header->len) + ? (ssize_t)(ret + sizeof(struct modbus_header)) + : (ssize_t) -1; +} + +static int process_modbus_tcp(neu_plugin_t *plugin, uint8_t *recv_buf, + uint16_t response_size, uint8_t slave_id) +{ + int total_recv = valid_modbus_tcp_response(plugin, recv_buf, response_size); + if (total_recv > 0) { + return process_received_data(plugin, recv_buf, total_recv, + response_size, slave_id); + } + return total_recv; +} + +static int process_modbus_tcp_test(neu_plugin_t *plugin, uint8_t *recv_buf, + uint16_t response_size, void *req, + modbus_point_t *point) +{ + int total_recv = valid_modbus_tcp_response(plugin, recv_buf, response_size); + if (total_recv > 0) { + return process_received_data_test(plugin, recv_buf, total_recv, + response_size, req, point); + } + return total_recv; +} + +static int process_modbus_rtu(neu_plugin_t *plugin, uint8_t *recv_buf, + uint16_t response_size, uint8_t slave_id) +{ + ssize_t ret = recv_data(plugin, recv_buf, response_size); + if (ret == 0 || ret == -1) { + return 0; + } + return process_received_data(plugin, recv_buf, ret, response_size, + slave_id); +} + static int process_protocol_buf(neu_plugin_t *plugin, uint8_t slave_id, uint16_t response_size) { - uint8_t * recv_buf = calloc(response_size, 1); - neu_protocol_unpack_buf_t pbuf = { 0 }; - ssize_t ret = 0; - if (plugin->protocol == MODBUS_PROTOCOL_TCP) { - if (plugin->is_server) { - ret = neu_conn_tcp_server_recv(plugin->conn, plugin->client_fd, - recv_buf, - sizeof(struct modbus_header)); - } else { - ret = neu_conn_recv(plugin->conn, recv_buf, - sizeof(struct modbus_header)); - } - - if (ret == 0 || ret == -1) { - free(recv_buf); - return 0; - } - - if (ret == sizeof(struct modbus_header)) { - struct modbus_header *header = (struct modbus_header *) recv_buf; - int ret1 = 0; - - if (htons(header->len) > - response_size - sizeof(struct modbus_header)) { - free(recv_buf); - return -1; - } - - plog_recv_protocol(plugin, recv_buf, ret); - if (plugin->is_server) { - ret1 = neu_conn_tcp_server_recv( - plugin->conn, plugin->client_fd, - recv_buf + sizeof(struct modbus_header), - htons(header->len)); - } else { - ret1 = neu_conn_recv(plugin->conn, - recv_buf + sizeof(struct modbus_header), - htons(header->len)); - } - if (ret1 != htons(header->len)) { - free(recv_buf); - return -1; - } - ret += ret1; - } else { - free(recv_buf); - return -1; - } - - if (ret > 0) { - if (ret < 512) { - plog_recv_protocol(plugin, recv_buf, ret); - } - neu_protocol_unpack_buf_init(&pbuf, recv_buf, ret); - int ret_s = modbus_stack_recv(plugin->stack, slave_id, &pbuf); - if (ret_s == MODBUS_DEVICE_ERR) { - ret = ret_s; - } else { - if (ret != response_size) { - ret = -1; - } else { - ret = ret_s; - } - } - } - } else if (plugin->protocol == MODBUS_PROTOCOL_RTU) { - if (plugin->is_server) { - ret = neu_conn_tcp_server_recv(plugin->conn, plugin->client_fd, - recv_buf, response_size); - } else { - ret = neu_conn_recv(plugin->conn, recv_buf, response_size); - } - - if (ret == 0 || ret == -1) { - free(recv_buf); - return 0; - } - - if (ret > 0) { - if (response_size < 512) { - plog_recv_protocol(plugin, recv_buf, ret); - } - neu_protocol_unpack_buf_init(&pbuf, recv_buf, ret); - int ret_s = modbus_stack_recv(plugin->stack, slave_id, &pbuf); - if (ret_s == MODBUS_DEVICE_ERR) { - ret = ret_s; - } else { - if (ret != response_size) { - ret = -1; - } else { - ret = ret_s; - } - } - } + uint8_t *recv_buf = (uint8_t *) calloc(response_size, 1); + if (!recv_buf) { + return -1; } + + int ret = 0; + if (plugin->protocol == MODBUS_PROTOCOL_TCP) { + ret = process_modbus_tcp(plugin, recv_buf, response_size, slave_id); + } else if (plugin->protocol == MODBUS_PROTOCOL_RTU) { + ret = process_modbus_rtu(plugin, recv_buf, response_size, slave_id); + } + free(recv_buf); return ret; } @@ -911,72 +907,17 @@ static int process_protocol_buf_test(neu_plugin_t *plugin, void *req, modbus_point_t *point, uint16_t response_size) { - uint8_t * recv_buf = calloc(response_size, 1); - neu_protocol_unpack_buf_t pbuf = { 0 }; - ssize_t ret = 0; - if (plugin->protocol == MODBUS_PROTOCOL_TCP) { - if (plugin->is_server) { - ret = neu_conn_tcp_server_recv(plugin->conn, plugin->client_fd, - recv_buf, - sizeof(struct modbus_header)); - } else { - ret = neu_conn_recv(plugin->conn, recv_buf, - sizeof(struct modbus_header)); - } - - if (ret == 0 || ret == -1) { - free(recv_buf); - return 0; - } - - if (ret == sizeof(struct modbus_header)) { - struct modbus_header *header = (struct modbus_header *) recv_buf; - int ret1 = 0; - - if (htons(header->len) > - response_size - sizeof(struct modbus_header)) { - free(recv_buf); - return -1; - } - - plog_recv_protocol(plugin, recv_buf, ret); - if (plugin->is_server) { - ret1 = neu_conn_tcp_server_recv( - plugin->conn, plugin->client_fd, - recv_buf + sizeof(struct modbus_header), - htons(header->len)); - } else { - ret1 = neu_conn_recv(plugin->conn, - recv_buf + sizeof(struct modbus_header), - htons(header->len)); - } - if (ret1 != htons(header->len)) { - free(recv_buf); - return -1; - } - ret += ret1; - } else { - free(recv_buf); - return -1; - } - - if (ret > 0) { - if (ret < 512) { - plog_recv_protocol(plugin, recv_buf, ret); - } - neu_protocol_unpack_buf_init(&pbuf, recv_buf, ret); - int ret_s = modbus_stack_recv_test(plugin, req, point, &pbuf); - if (ret_s == MODBUS_DEVICE_ERR) { - ret = ret_s; - } else { - if (ret != response_size) { - ret = -1; - } else { - ret = ret_s; - } - } - } + uint8_t *recv_buf = (uint8_t *) calloc(response_size, 1); + if (!recv_buf) { + return -1; } + + int ret = -1; + if (plugin->protocol == MODBUS_PROTOCOL_TCP) { + ret = process_modbus_tcp_test(plugin, recv_buf, response_size, req, + point); + } + free(recv_buf); return ret; } \ No newline at end of file diff --git a/plugins/modbus/modbus_rtu.c b/plugins/modbus/modbus_rtu.c index f61ce0ce..83f51ad8 100644 --- a/plugins/modbus/modbus_rtu.c +++ b/plugins/modbus/modbus_rtu.c @@ -199,8 +199,9 @@ static int driver_config(neu_plugin_t *plugin, const char *config) return -1; } - ret = neu_parse_param((char *) config, &err_param, 2, &port, &max_retries, + ret = neu_parse_param((char *) config, &err_param, 2, &max_retries, &retry_interval); + if (ret != 0) { free(err_param); max_retries.v.val_int = 0; diff --git a/plugins/modbus/modbus_tcp.c b/plugins/modbus/modbus_tcp.c index 17aa8e60..15d2ee19 100644 --- a/plugins/modbus/modbus_tcp.c +++ b/plugins/modbus/modbus_tcp.c @@ -182,7 +182,7 @@ static int driver_config(neu_plugin_t *plugin, const char *config) return -1; } - ret = neu_parse_param((char *) config, &err_param, 2, &port, &max_retries, + ret = neu_parse_param((char *) config, &err_param, 2, &max_retries, &retry_interval); if (ret != 0) { free(err_param); diff --git a/simulator/modbus_s.c b/simulator/modbus_s.c index cbb83841..6b51e97b 100644 --- a/simulator/modbus_s.c +++ b/simulator/modbus_s.c @@ -139,7 +139,7 @@ ssize_t modbus_s_rtu_req(uint8_t *req, uint16_t req_len, uint8_t *res, } } - if (simulate_error && ntohs(address->start_address) == 8000) { + if (simulate_error && ntohs(address->start_address) == 8004) { ++start_address_8001_counter; if (start_address_8001_counter % 3 != 0) { return -2; @@ -244,7 +244,7 @@ ssize_t modbus_s_tcp_req(uint8_t *req, uint16_t req_len, uint8_t *res, } } - if (simulate_error && ntohs(address->start_address) == 8000) { + if (simulate_error && ntohs(address->start_address) == 8004) { ++start_address_8001_counter; if (start_address_8001_counter % 3 != 0) { return -2; diff --git a/tests/ft/driver/test_modbus.py b/tests/ft/driver/test_modbus.py index 316aff7f..1730578a 100644 --- a/tests/ft/driver/test_modbus.py +++ b/tests/ft/driver/test_modbus.py @@ -285,7 +285,7 @@ coil_bit_m15 = [{"name": "coil_bit_m15", "address": "1!000125", hold_int16_retry_1 = [{"name": "hold_int16_retry_1", "address": "1!408000", "attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16}] -hold_int16_retry_2 = [{"name": "hold_int16_retry_2", "address": "1!408001", +hold_int16_retry_2 = [{"name": "hold_int16_retry_2", "address": "1!408005", "attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16}] hold_int16_B = [{"name": "hold_int16_B", "address": "1!400401#B", @@ -1492,16 +1492,10 @@ class TestModbus: def test_read_tag_retry(self, param): if param[0] == 'modbus-rtu-tty': pytest.skip("modbus rtu tty pass") - api.add_tags_check(node=param[0], group='group', tags=hold_int16_retry_1) api.add_tags_check(node=param[0], group='group', tags=hold_int16_retry_2) - - api.write_tag_check( - node=param[0], group='group', tag=hold_int16_retry_1[0]['name'], value=111) api.write_tag_check( node=param[0], group='group', tag=hold_int16_retry_2[0]['name'], value=222) time.sleep(0.5) - assert 111 == api.read_tag( - node=param[0], group='group', tag=hold_int16_retry_1[0]['name']) assert 222 == api.read_tag( node=param[0], group='group', tag=hold_int16_retry_2[0]['name']) diff --git a/tests/ft/neuron/api.py b/tests/ft/neuron/api.py index 2fd07de6..005947d6 100644 --- a/tests/ft/neuron/api.py +++ b/tests/ft/neuron/api.py @@ -329,37 +329,37 @@ def prgfile_process(driver): # plugin setting -def modbus_tcp_node_setting(node, port, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2): +def modbus_tcp_node_setting(node, port, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, retry_interval=1): return node_setting(node, json={"connection_mode": connection_mode, "transport_mode": transport_mode, "interval": interval, - "host": host, "port": port, "timeout": timeout, "max_retries": max_retries}) + "host": host, "port": port, "timeout": timeout, "max_retries": max_retries, "retry_interval": retry_interval}) -def modbus_rtu_node_setting(node, port=502, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, link=1, device="", stop=0, parity=0, baud=4, data=3): +def modbus_rtu_node_setting(node, port=502, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, retry_interval=1, link=1, device="", stop=0, parity=0, baud=4, data=3): return node_setting(node, json={"connection_mode": connection_mode, "transport_mode": transport_mode, "interval": interval, "host": host, "port": port, "timeout": timeout, - "max_retries": max_retries, "link": link, "device": device, "stop": stop, + "max_retries": max_retries, "retry_interval": retry_interval, "link": link, "device": device, "stop": stop, "parity": parity, "baud": baud, "data": data}) -def modbus_tcp_node_setting_endian(node, port, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, endianness=1): +def modbus_tcp_node_setting_endian(node, port, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, retry_interval=1, endianness=1): return node_setting(node, json={"connection_mode": connection_mode, "transport_mode": transport_mode, "interval": interval, - "host": host, "port": port, "timeout": timeout, "max_retries": max_retries, "endianess": endianness}) + "host": host, "port": port, "timeout": timeout, "max_retries": max_retries, "retry_interval": retry_interval, "endianess": endianness}) -def modbus_rtu_node_setting_endian(node, port=502, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, link=1, device="", stop=0, parity=0, baud=4, data=3, endianness=1): +def modbus_rtu_node_setting_endian(node, port=502, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, retry_interval=1, link=1, device="", stop=0, parity=0, baud=4, data=3, endianness=1): return node_setting(node, json={"connection_mode": connection_mode, "transport_mode": transport_mode, "interval": interval, "host": host, "port": port, "timeout": timeout, - "max_retries": max_retries, "link": link, "device": device, "stop": stop, + "max_retries": max_retries, "retry_interval": retry_interval, "link": link, "device": device, "stop": stop, "parity": parity, "baud": baud, "data": data, "endianess": endianness}) -def modbus_tcp_node_setting_base(node, port, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, base=1): +def modbus_tcp_node_setting_base(node, port, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, retry_interval=1, base=1): return node_setting(node, json={"connection_mode": connection_mode, "transport_mode": transport_mode, "interval": interval, - "host": host, "port": port, "timeout": timeout, "max_retries": max_retries, "address_base": base}) + "host": host, "port": port, "timeout": timeout, "max_retries": max_retries, "retry_interval": retry_interval, "address_base": base}) -def modbus_rtu_node_setting_base(node, port=502, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, link=1, device="", stop=0, parity=0, baud=4, data=3, base=1): +def modbus_rtu_node_setting_base(node, port=502, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000, max_retries=2, retry_interval=1, link=1, device="", stop=0, parity=0, baud=4, data=3, base=1): return node_setting(node, json={"connection_mode": connection_mode, "transport_mode": transport_mode, "interval": interval, "host": host, "port": port, "timeout": timeout, - "max_retries": max_retries, "link": link, "device": device, "stop": stop, + "max_retries": max_retries, "retry_interval": retry_interval, "link": link, "device": device, "stop": stop, "parity": parity, "baud": baud, "data": data, "address_base": base})