mirror of
https://github.com/emqx/neuron.git
synced 2026-10-17 04:40:42 +08:00
Merge pull request #1306 from hxy7yx/main
Support retry when modbus read fails.
This commit is contained in:
@@ -76,6 +76,32 @@
|
||||
"max": 30000
|
||||
}
|
||||
},
|
||||
"max_retries": {
|
||||
"name": "Maximum Retry Times",
|
||||
"name_zh": "最大重试次数",
|
||||
"description": "The maximum number of retries after a failed attempt to send a read command",
|
||||
"description_zh": "发送读取指令失败后最大重试次数",
|
||||
"attribute": "required",
|
||||
"type": "int",
|
||||
"default": 0,
|
||||
"valid": {
|
||||
"min": 0,
|
||||
"max": 3
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
"name": "Retry Interval",
|
||||
"name_zh": "指令重新发送间隔",
|
||||
"description": "Resend reading instruction interval(ms) after a failed attempt to send a read command",
|
||||
"description_zh": "发送读取指令失败后重新发送读指令时间间隔,单位为毫秒",
|
||||
"attribute": "required",
|
||||
"type": "int",
|
||||
"default": 0,
|
||||
"valid": {
|
||||
"min": 20,
|
||||
"max": 10000
|
||||
}
|
||||
},
|
||||
"interval": {
|
||||
"name": "Send Interval",
|
||||
"name_zh": "指令发送间隔",
|
||||
@@ -304,7 +330,7 @@
|
||||
"transport_mode": {
|
||||
"name": "Transport Mode",
|
||||
"name_zh": "传输模式",
|
||||
"description": "Neuron as the client, or as the server",
|
||||
"description": "TCP transfer or UDP transfer",
|
||||
"description_zh": "TCP 传输或 UDP 传输",
|
||||
"attribute": "required",
|
||||
"type": "map",
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"transport_mode": {
|
||||
"name": "Transport Mode",
|
||||
"name_zh": "传输模式",
|
||||
"description": "Neuron as the client, or as the server",
|
||||
"description": "TCP transfer or UDP transfer",
|
||||
"description_zh": "TCP 传输或 UDP 传输",
|
||||
"attribute": "required",
|
||||
"type": "map",
|
||||
@@ -88,6 +88,32 @@
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"max_retries": {
|
||||
"name": "Maximum Retry Times",
|
||||
"name_zh": "最大重试次数",
|
||||
"description": "The maximum number of retries after a failed attempt to send a read command",
|
||||
"description_zh": "发送读取指令失败后最大重试次数",
|
||||
"attribute": "required",
|
||||
"type": "int",
|
||||
"default": 0,
|
||||
"valid": {
|
||||
"min": 0,
|
||||
"max": 3
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
"name": "Retry Interval",
|
||||
"name_zh": "指令重新发送间隔",
|
||||
"description": "Resend reading instruction interval(ms) after a failed attempt to send a read command",
|
||||
"description_zh": "发送读取指令失败后重新发送读指令时间间隔,单位为毫秒",
|
||||
"attribute": "required",
|
||||
"type": "int",
|
||||
"default": 0,
|
||||
"valid": {
|
||||
"min": 20,
|
||||
"max": 10000
|
||||
}
|
||||
},
|
||||
"interval": {
|
||||
"name": "Send Interval",
|
||||
"name_zh": "指令发送间隔",
|
||||
|
||||
@@ -110,6 +110,22 @@ int modbus_send_msg(void *ctx, uint16_t n_byte, uint8_t *bytes)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int modbus_stack_read_retry(neu_plugin_t *plugin, struct modbus_group_data *gd,
|
||||
uint16_t i, uint16_t j, uint16_t *response_size)
|
||||
{
|
||||
struct timespec t3 = { .tv_sec = plugin->retry_interval / 1000,
|
||||
.tv_nsec =
|
||||
1000 * 1000 * (plugin->retry_interval % 1000) };
|
||||
struct timespec t4 = { 0 };
|
||||
nanosleep(&t3, &t4);
|
||||
plog_notice(plugin, "Resend read req. Times:%hu", j + 1);
|
||||
int ret = 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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int modbus_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group,
|
||||
uint16_t max_byte)
|
||||
{
|
||||
@@ -156,10 +172,20 @@ int modbus_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group,
|
||||
rtt = neu_time_ms() - read_tms;
|
||||
}
|
||||
if (ret <= 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);
|
||||
for (uint16_t j = 0; j < plugin->max_retries; j++) {
|
||||
ret = modbus_stack_read_retry(plugin, gd, i, j, &response_size);
|
||||
if (ret > 0) {
|
||||
ret = process_protocol_buf(plugin, response_size);
|
||||
rtt = neu_time_ms() - read_tms;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret <= 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);
|
||||
}
|
||||
}
|
||||
if (plugin->interval > 0) {
|
||||
struct timespec t1 = { .tv_sec = plugin->interval / 1000,
|
||||
|
||||
@@ -41,6 +41,8 @@ struct neu_plugin {
|
||||
modbus_protocol_e protocol;
|
||||
|
||||
uint16_t interval;
|
||||
uint16_t retry_interval;
|
||||
uint16_t max_retries;
|
||||
};
|
||||
|
||||
void modbus_conn_connected(void *data, int fd);
|
||||
|
||||
@@ -158,6 +158,10 @@ static int driver_config(neu_plugin_t *plugin, const char *config)
|
||||
neu_json_elem_t baud = { .name = "baud", .t = NEU_JSON_INT };
|
||||
neu_json_elem_t data = { .name = "data", .t = NEU_JSON_INT };
|
||||
|
||||
neu_json_elem_t max_retries = { .name = "max_retries", .t = NEU_JSON_INT };
|
||||
neu_json_elem_t retry_interval = { .name = "retry_interval",
|
||||
.t = NEU_JSON_INT };
|
||||
|
||||
ret = neu_parse_param((char *) config, &err_param, 3, &link, &timeout,
|
||||
&interval);
|
||||
if (ret != 0) {
|
||||
@@ -189,7 +193,18 @@ static int driver_config(neu_plugin_t *plugin, const char *config)
|
||||
return -1;
|
||||
}
|
||||
|
||||
param.log = plugin->common.log;
|
||||
ret = neu_parse_param((char *) config, &err_param, 2, &port, &max_retries,
|
||||
&retry_interval);
|
||||
if (ret != 0) {
|
||||
free(err_param);
|
||||
max_retries.v.val_int = 0;
|
||||
retry_interval.v.val_int = 0;
|
||||
}
|
||||
|
||||
param.log = plugin->common.log;
|
||||
plugin->max_retries = max_retries.v.val_int;
|
||||
plugin->retry_interval = retry_interval.v.val_int;
|
||||
|
||||
if (link.v.val_int == 0) {
|
||||
param.type = NEU_CONN_TTY_CLIENT;
|
||||
|
||||
|
||||
@@ -148,6 +148,9 @@ static int driver_config(neu_plugin_t *plugin, const char *config)
|
||||
neu_json_elem_t mode = { .name = "connection_mode", .t = NEU_JSON_INT };
|
||||
neu_json_elem_t tmode = { .name = "transport_mode", .t = NEU_JSON_INT };
|
||||
neu_conn_param_t param = { 0 };
|
||||
neu_json_elem_t max_retries = { .name = "max_retries", .t = NEU_JSON_INT };
|
||||
neu_json_elem_t retry_interval = { .name = "retry_interval",
|
||||
.t = NEU_JSON_INT };
|
||||
|
||||
ret = neu_parse_param((char *) config, &err_param, 6, &port, &host, &mode,
|
||||
&timeout, &interval, &tmode);
|
||||
@@ -166,8 +169,18 @@ static int driver_config(neu_plugin_t *plugin, const char *config)
|
||||
return -1;
|
||||
}
|
||||
|
||||
param.log = plugin->common.log;
|
||||
plugin->interval = interval.v.val_int;
|
||||
ret = neu_parse_param((char *) config, &err_param, 2, &port, &max_retries,
|
||||
&retry_interval);
|
||||
if (ret != 0) {
|
||||
free(err_param);
|
||||
max_retries.v.val_int = 0;
|
||||
retry_interval.v.val_int = 0;
|
||||
}
|
||||
|
||||
param.log = plugin->common.log;
|
||||
plugin->interval = interval.v.val_int;
|
||||
plugin->max_retries = max_retries.v.val_int;
|
||||
plugin->retry_interval = retry_interval.v.val_int;
|
||||
|
||||
if (tmode.v.val_int == 1) {
|
||||
param.type = NEU_CONN_UDP;
|
||||
|
||||
Reference in New Issue
Block a user