fix nodes reconnection issues

This commit is contained in:
aleks
2025-07-25 10:08:24 +02:00
parent 32c670b71c
commit d04ff303dd
8 changed files with 184 additions and 82 deletions

10
Kconfig
View File

@@ -72,12 +72,12 @@ menu "Modbus configuration"
then master can send next frame.
config FMB_QUEUE_LENGTH
int "Modbus serial task queue length"
range 0 200
default 20
int "Modbus event task queue length"
range 10 500
default 50
help
Modbus serial driver queue length. It is used by event queue task.
See the serial driver API for more information.
Modbus event queue length. It is used by event queue tasks
for corresponding communication mode.
config FMB_PORT_TASK_STACK_SIZE
int "Modbus port task stack size"

View File

@@ -201,6 +201,14 @@ esp_err_t transaction_item_set_state(transaction_item_handle_t item, pending_sta
return ESP_FAIL;
}
transaction_tick_t transaction_item_get_tick(transaction_item_handle_t item)
{
if (item) {
return atomic_load(&(item->tick));
}
return 0;
}
esp_err_t transaction_set_tick(transaction_handle_t transaction, int msg_id, transaction_tick_t tick)
{
transaction_item_handle_t item = transaction_get(transaction, msg_id);
@@ -232,6 +240,24 @@ int transaction_delete_single_expired(transaction_handle_t transaction, transact
return msg_id;
}
int transaction_delete_by_node_id(transaction_handle_t transaction, int node_id)
{
int deleted_items = 0;
transaction_item_handle_t item, tmp;
CRITICAL_SECTION_LOCK(transaction->lock);
STAILQ_FOREACH_SAFE(item, transaction->list, next, tmp) {
if (item->node_id == node_id) {
STAILQ_REMOVE(transaction->list, item, transaction_item, next);
free(item->buffer);
transaction->size -= item->len;
free(item);
deleted_items ++;
}
}
CRITICAL_SECTION_UNLOCK(transaction->lock);
return deleted_items;
}
int transaction_delete_expired(transaction_handle_t transaction, transaction_tick_t current_tick, transaction_tick_t timeout)
{
int deleted_items = 0;

View File

@@ -54,6 +54,7 @@ transaction_item_handle_t transaction_get_first(transaction_handle_t transaction
uint8_t *transaction_item_get_data(transaction_item_handle_t item, size_t *len, uint16_t *msg_id, int *node_id);
esp_err_t transaction_delete(transaction_handle_t transaction, int msg_id);
esp_err_t transaction_delete_item(transaction_handle_t transaction, transaction_item_handle_t item);
int transaction_delete_by_node_id(transaction_handle_t transaction, int node_id);
int transaction_delete_expired(transaction_handle_t transaction, transaction_tick_t current_tick, transaction_tick_t timeout);
/**
@@ -66,6 +67,7 @@ esp_err_t transaction_set_state(transaction_handle_t transaction, int msg_id, pe
pending_state_t transaction_item_get_state(transaction_item_handle_t item);
esp_err_t transaction_item_set_state(transaction_item_handle_t item, pending_state_t state);
esp_err_t transaction_set_tick(transaction_handle_t transaction, int msg_id, transaction_tick_t tick);
transaction_tick_t transaction_item_get_tick(transaction_item_handle_t item);
uint64_t transaction_get_size(transaction_handle_t transaction);
void transaction_destroy(transaction_handle_t transaction);
void transaction_delete_all_items(transaction_handle_t transaction);

View File

@@ -63,7 +63,11 @@ esp_err_t queue_push(QueueHandle_t queue, void *pbuf, size_t len, frame_entry_t
frame_entry_t frame_info = {0};
if (!queue) { // || !pbuf || (len <= 0)
return -1;
return ESP_ERR_INVALID_ARG;
}
if (!uxQueueSpacesAvailable(queue)) {
return ESP_ERR_NO_MEM;
}
if (pframe) {
@@ -114,7 +118,7 @@ ssize_t queue_pop(QueueHandle_t queue, void *pbuf, size_t len, frame_entry_t *pf
}
return len;
err:
return -1;
return ESP_ERR_INVALID_STATE;
}
bool queue_is_empty(QueueHandle_t queue)

View File

@@ -302,7 +302,7 @@ int mb_drv_open(void *ctx, mb_uid_info_t addr_info, int flags)
goto err;
}
if (pdrv_ctx->mb_node_open_count > MB_MAX_FDS) {
ESP_LOGD(TAG, "Exceeded maximum node count: %d", pdrv_ctx->mb_node_open_count);
ESP_LOGE(TAG, "Exceeded maximum node count: %d", pdrv_ctx->mb_node_open_count);
goto err;
}
pdrv_ctx->mb_node_open_count++;
@@ -461,7 +461,6 @@ mb_node_info_t *mb_drv_get_next_node_from_set(void *ctx, int *pfd, fd_set *pfdse
&& (MB_GET_NODE_STATE(pnode_info) >= MB_SOCK_STATE_CONNECTED)
&& (FD_ISSET(pnode_info->index, pfdset) || (FD_ISSET(pnode_info->sock_id, pfdset)))) {
*pfd = fd;
//FD_CLR(pnode_info->sock_id, pfdset);
return pnode_info;
}
}
@@ -576,7 +575,7 @@ err_t mb_drv_check_node_state(void *ctx, int *pfd, uint32_t timeout_ms)
pnode = mb_drv_get_next_node_from_set(ctx, pfd, &pdrv_ctx->conn_set);
if (pnode && FD_ISSET(pnode->sock_id, &pdrv_ctx->conn_set)) {
uint64_t last_read_div_us = (esp_timer_get_time() - pnode->recv_time);
ESP_LOGD(TAG, "%p, node: %d, sock: %d, IP:%s, check connection timeout = %" PRId64 ", rcv_time: %" PRId64 " %" PRId32,
ESP_LOGD(TAG, "%p, node: %d, sock: %d, IP:%s, check connection timeout = %" PRId64 ", rcv_time: %" PRId64 " %" PRIu32,
ctx, (int)pnode->index, (int)pnode->sock_id, pnode->addr_info.ip_addr_str,
(esp_timer_get_time() / 1000), pnode->recv_time / 1000, timeout_ms);
if (last_read_div_us >= (uint64_t)(timeout_ms * 1000)) {
@@ -631,11 +630,20 @@ void mb_drv_tcp_task(void *ctx)
mb_uid_info_t node_info;
int sock_id = port_accept_connection(pdrv_ctx->listen_sock_fd, &node_info);
if (sock_id) {
int fd = mb_drv_open(pdrv_ctx, node_info, 0);
if (fd < 0) {
ESP_LOGE(TAG, "%p, unable to open node: %s", pdrv_ctx, node_info.ip_addr_str);
if (pdrv_ctx->mb_node_open_count >= MB_MAX_FDS) {
ESP_LOGE(TAG, "%p, unable to accept node, maximum is %u connections.", pdrv_ctx, MB_MAX_FDS);
struct linger sl;
sl.l_onoff = 1; // non-zero value enables linger option in kernel
sl.l_linger = 0; // timeout interval in seconds
setsockopt(sock_id, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
close(sock_id);
} else {
DRIVER_SEND_EVENT(ctx, MB_EVENT_CONNECT, fd);
int fd = mb_drv_open(pdrv_ctx, node_info, 0);
if (fd < 0) {
ESP_LOGE(TAG, "%p, unable to open node: #%d, %s", pdrv_ctx, fd, node_info.ip_addr_str);
} else {
DRIVER_SEND_EVENT(ctx, MB_EVENT_CONNECT, fd);
}
}
}
} else {

View File

@@ -198,6 +198,7 @@ typedef enum _mb_sync_event {
MB_SYNC_EVENT_RECV_OK = 0x0001,
MB_SYNC_EVENT_RECV_FAIL = 0x0002,
MB_SYNC_EVENT_SEND_OK = 0x0003,
MB_SYNC_EVENT_SEND_ERR = 0x0004,
MB_SYNC_EVENT_TOUT
} mb_sync_event_t;

View File

@@ -230,7 +230,7 @@ bool mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *p
//*ppframe = pbuf;
*plength = (uint16_t)len;
status = true;
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", get packet TID: 0x%04" PRIx16 ", %p."),
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", read packet TID: 0x%04" PRIx16 ", %p."),
port_obj, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (unsigned)pnode->tid_counter, *ppframe);
if (ESP_OK != transaction_item_set_state(item, CONFIRMED)) {
@@ -263,8 +263,9 @@ bool mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t leng
transaction_item_handle_t item;
mb_drv_lock(pdrv_ctx);
item = transaction_dequeue(port_obj->transaction, CONFIRMED, NULL);
if (item) {
//item = transaction_dequeue(port_obj->transaction, CONFIRMED, NULL);
item = transaction_get(port_obj->transaction, tid);
if (item && transaction_item_get_state(item) == CONFIRMED) {
uint16_t msg_id = 0;
int node_id = 0;
uint8_t *pbuf = transaction_item_get_data(item, NULL, &msg_id, &node_id);
@@ -277,16 +278,16 @@ bool mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t leng
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.node_name_str, (unsigned)tid, (unsigned)msg_id, pframe, length);
} else {
ESP_LOGE(TAG, "%p, node: #%d, socket(#%d)[%s], mbs_write fail, TID: 0x%04" PRIx16 ":0x%04" PRIx16 ", %p, len: %d, ",
ESP_LOGE(TAG, "%p, node: #%d, socket(#%d)[%s], modbus write fail, TID: 0x%04" PRIx16 ":0x%04" PRIx16 ", %p, len: %d, ",
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.node_name_str, (unsigned)tid, (unsigned)msg_id, pframe, length);
}
if (ESP_OK != transaction_item_set_state(item, REPLIED)) {
ESP_LOGE(TAG, "transaction queue set state fail.");
ESP_LOGE(TAG, "transaction queue set reply state fail.");
}
}
} else {
ESP_LOGE(TAG, "queue can not find the item to send.");
ESP_LOGE(TAG, "queue can not find transaction TID: 0x%04" PRIx16 ", drop frame", tid);
}
mb_drv_unlock(pdrv_ctx);
@@ -316,6 +317,13 @@ static uint64_t mbs_port_tcp_sync_event(void *inst, mb_sync_event_t sync_event)
case MB_SYNC_EVENT_SEND_OK:
mb_port_event_post(inst, EVENT(EV_FRAME_SENT));
break;
case MB_SYNC_EVENT_SEND_ERR:
mb_port_timer_disable(inst);
mb_port_event_set_err_type(inst, EV_ERROR_RESPOND_TIMEOUT);
mb_port_event_post(inst, EVENT(EV_ERROR_PROCESS));
break;
default:
break;
}
@@ -404,16 +412,16 @@ MB_EVENT_HANDLER(mbs_on_recv_data)
{
if (!queue_is_empty(pnode->rx_queue))
{
ESP_LOGD(TAG, "%p, node #%d(%d) [%s], receive data ready.", ctx, (int)pevent_info->opt_fd,
ESP_LOGD(TAG, "%p, node #%d, socket(#%d) [%s], receive data ready.", ctx, (int)pevent_info->opt_fd,
(int)pnode->sock_id, pnode->addr_info.ip_addr_str);
frame_entry_t frame_entry;
size_t sz = queue_pop(pnode->rx_queue, NULL, MB_BUFFER_SIZE, &frame_entry);
if (sz > MB_TCP_FUNC)
{
uint16_t tid_counter = MB_TCP_MBAP_GET_FIELD(frame_entry.pbuf, MB_TCP_TID);
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", received packet TID: 0x%04" PRIx16 ", %p."),
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", received packet TID: 0x%04" PRIx16),
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (unsigned)tid_counter, frame_entry.pbuf);
pnode->addr_info.ip_addr_str, (unsigned)tid_counter);
mb_drv_lock(pdrv_ctx);
transaction_message_t msg;
msg.buffer = frame_entry.pbuf;
@@ -421,6 +429,7 @@ MB_EVENT_HANDLER(mbs_on_recv_data)
msg.msg_id = frame_entry.tid;
msg.node_id = pnode->index;
msg.pnode = pnode;
// Enqueue the transaction, keep time of receiving.
item = transaction_enqueue(port_obj->transaction, &msg, port_get_timestamp());
pnode->tid_counter = tid_counter; // assign the TID from frame to use it on send
mb_drv_unlock(pdrv_ctx);
@@ -442,11 +451,11 @@ MB_EVENT_HANDLER(mbs_on_recv_data)
// send receive event to modbus object to get the new data
mb_drv_lock(pdrv_ctx);
uint16_t msg_id = 0;
uint64_t tick = 0;
(void)transaction_item_get_data(item, NULL, &msg_id, NULL);
tick = port_get_timestamp();
int node_id = 0;
(void)transaction_item_get_data(item, NULL, &msg_id, &node_id);
pnode = mb_drv_get_node(pdrv_ctx, node_id);
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_RECV_OK);
transaction_set_tick(port_obj->transaction, msg_id, (transaction_tick_t)tick);
// transaction_set_tick(port_obj->transaction, msg_id, (transaction_tick_t)port_get_timestamp());
if (ESP_OK == transaction_item_set_state(item, ACKNOWLEDGED)) {
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", acknoledged packet TID: 0x%04" PRIx16 "."),
pdrv_ctx, pnode->index, pnode->sock_id,
@@ -473,67 +482,97 @@ MB_EVENT_HANDLER(mbs_on_send_data)
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
mbs_tcp_port_t *port_obj = (mbs_tcp_port_t *)pdrv_ctx->parent;
transaction_item_handle_t item = NULL;
frame_entry_t frame_entry = {0};
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
if (pnode && !queue_is_empty(pnode->tx_queue))
{
frame_entry_t frame_entry;
// pop the frame entry, keep the buffer
if (pnode && !queue_is_empty(pnode->tx_queue)) {
// Pop the frame entry, keep the buffer
size_t sz = queue_pop(pnode->tx_queue, NULL, MB_BUFFER_SIZE, &frame_entry);
if (!sz || (MB_GET_NODE_STATE(pnode) < MB_SOCK_STATE_CONNECTED)) {
ESP_LOGE(TAG, "%p, "MB_NODE_FMT(", is invalid, drop data."),
ctx, (int)pnode->index, (int)pnode->sock_id, pnode->addr_info.ip_addr_str);
return;
}
uint16_t tid = MB_TCP_MBAP_GET_FIELD(frame_entry.pbuf, MB_TCP_TID);
pnode->error = 0;
int ret = port_write_poll(pnode, frame_entry.pbuf, sz, MB_TCP_SEND_TIMEOUT_MS);
if (ret < 0)
{
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", send data failure, err(errno) = %d(%u)."),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode->index);
pnode->error = ret;
}
else
{
pnode->error = 0;
if (tid != pnode->tid_counter)
{
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", send incorrect frame TID:0x%04" PRIx16 "!= 0x%04" PRIx16 ", %d (bytes), errno %d"),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid, (int)ret, (unsigned)errno);
pnode->tid_counter = tid; // update the TID to the current one
if (sz) {
uint16_t tid = MB_TCP_MBAP_GET_FIELD(frame_entry.pbuf, MB_TCP_TID);
// Try to find actual transaction for current TID,
// if not found just ignore the frame as expired
item = transaction_get(port_obj->transaction, tid);
if (item && pnode) {
// Check if the TID is equal to the current received TID for this node.
// If not, means the slave was not able to process the previous transaction on time.
if ((tid != pnode->tid_counter) || (MB_GET_NODE_STATE(pnode) < MB_SOCK_STATE_CONNECTED)) {
mb_drv_lock(pdrv_ctx);
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_SEND_ERR);
if (transaction_delete(port_obj->transaction, tid) != ESP_OK) {
ESP_LOGE(TAG, "Failed to remove queued TID:0x%04" PRIx16, (int)tid);
} else {
ESP_LOGD(TAG, "Remove the message TID:0x%04" PRIx16, (int)tid);
}
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
mb_drv_unlock(pdrv_ctx);
uint64_t tick = (transaction_tick_t)transaction_item_get_tick(item);
uint64_t time_div_us = (esp_timer_get_time() - tick);
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", frame TID:0x%04" PRIx16 "!=0x%04" PRIx16 ", slave is busy."),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid);
ESP_LOGW(TAG, "%p, " MB_NODE_FMT(", handling time [ms]: %" PRIu64 ", exceeds master response time."),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, (time_div_us / 1000));
} else {
mb_drv_lock(pdrv_ctx);
int ret = port_write_poll(pnode, frame_entry.pbuf, sz, MB_TCP_SEND_TIMEOUT_MS);
if (ret < 0) {
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", send data failure, err(errno) = %d(%u)."),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode->index);
pnode->error = ret;
} else {
pnode->error = 0;
ESP_LOG_BUFFER_HEX_LEVEL("SENT", frame_entry.pbuf, ret, ESP_LOG_DEBUG);
}
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_SEND_OK);
esp_err_t err = transaction_set_state(port_obj->transaction, tid, TRANSMITTED);
if (err == ESP_OK) {
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", sent packet TID: 0x%04" PRIx16 ", %p."),
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, tid, frame_entry.pbuf);
} else {
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", transaction set state fail for TID: 0x%04" PRIx16 ", %p."),
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, tid, frame_entry.pbuf);
}
if (transaction_delete_item(port_obj->transaction, item) != ESP_OK) {
ESP_LOGE(TAG, "Failed to remove queued TID:0x%04" PRIx16, tid);
} else {
ESP_LOGD(TAG, "Remove the message TID:0x%04" PRIx16, tid);
}
pnode->send_time = esp_timer_get_time();
pnode->send_counter = (pnode->send_counter < (USHRT_MAX - 1)) ? (pnode->send_counter + 1) : 0;
mb_drv_unlock(pdrv_ctx);
}
} else {
// Note: the transaction processing time is increase proportional to number of connected Masters.
// If it is still needed to connect several number of Masters simultaneously,
// then the slave response time option needs to be increased in Masters.
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", transaction not found for TID: 0x%04" PRIx16 ", drop data %p."),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, tid, pnode);
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_SEND_ERR);
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
}
else
{
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", send data successful: TID:0x%04" PRIx16 ":0x%04" PRIx16 ", %d (bytes), errno %d"),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid, (int)ret, (unsigned)errno);
}
ESP_LOG_BUFFER_HEX_LEVEL("SENT", frame_entry.pbuf, ret, ESP_LOG_DEBUG);
}
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_SEND_OK);
mb_drv_lock(pdrv_ctx);
transaction_set_state(port_obj->transaction, tid, TRANSMITTED);
if (transaction_delete(port_obj->transaction, tid) != ESP_OK) {
ESP_LOGE(TAG, "Failed to remove queued TID:0x%04" PRIx16, tid);
} else {
ESP_LOGD(TAG, "Remove the message TID:0x%04" PRIx16, tid);
ESP_LOGE(TAG, "%p, "MB_NODE_FMT(", frame is invalid, drop data."),
ctx, (int)pnode->index, (int)pnode->sock_id, pnode->addr_info.ip_addr_str);
}
free(frame_entry.pbuf);
pnode->send_time = esp_timer_get_time();
pnode->send_counter = (pnode->send_counter < (USHRT_MAX - 1)) ? (pnode->send_counter + 1) : 0;
mb_drv_unlock(pdrv_ctx);
}
mb_drv_check_suspend_shutdown(ctx);
}
MB_EVENT_HANDLER(mbs_on_error)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
mbs_tcp_port_t *port_obj = __containerof(pdrv_ctx->parent, mbs_tcp_port_t, base);
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
if (!pnode) {
@@ -541,11 +580,26 @@ MB_EVENT_HANDLER(mbs_on_error)
return;
}
// Check if the node is not alive for timeout
int ret = mb_drv_check_node_state(pdrv_ctx, (int *)&pevent_info->opt_fd, MB_TCP_EVENT_LOOP_TICK_MS);
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
ESP_LOGE(TAG, "Node: #%d is not alive, err= %d", (int)pevent_info->opt_fd, ret);
// int ret = mb_drv_check_node_state(pdrv_ctx, (int *)&pevent_info->opt_fd, MB_EVENT_SEND_RCV_TOUT_MS);
// if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
mb_status_flags_t flags = mb_drv_wait_status_flag(port_obj->pdriver, MB_FLAG_TRANSACTION_READY, TRANSACTION_TICKS);
if (MB_FLAG_TRANSACTION_READY == flags) {
(void)mb_drv_clear_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
mb_drv_lock(pdrv_ctx);
int ret = pnode->error;
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", communication fail, err= %d"),
port_obj, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (int)ret);
(void)transaction_delete_by_node_id(port_obj->transaction, pevent_info->opt_fd);
mb_drv_unlock(pdrv_ctx);
mb_drv_close(pdrv_ctx, pevent_info->opt_fd);
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_READY);
} else {
// postpone the packet processing
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode->index);
return;
}
mb_drv_check_suspend_shutdown(ctx);
}
MB_EVENT_HANDLER(mbs_on_close)
@@ -553,6 +607,7 @@ MB_EVENT_HANDLER(mbs_on_close)
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s, fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mbs_tcp_port_t *port_obj = __containerof(pdrv_ctx->parent, mbs_tcp_port_t, base);
mb_node_info_t *pnode =NULL;
// if close all sockets event is received
if (pevent_info->opt_fd < 0)
@@ -573,6 +628,7 @@ MB_EVENT_HANDLER(mbs_on_close)
pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
if (pnode && (MB_GET_NODE_STATE(pnode) >= MB_SOCK_STATE_OPENED)) {
if ((pnode->sock_id < 0) && FD_ISSET(pnode->sock_id, &pdrv_ctx->open_set)) {
(void)transaction_delete_by_node_id(port_obj->transaction, pevent_info->opt_fd);
mb_drv_close(ctx, pevent_info->opt_fd);
}
}
@@ -585,12 +641,17 @@ MB_EVENT_HANDLER(mbs_on_timeout)
// Slave timeout triggered
//mb_event_info_t *pevent_info = (mb_event_info_t *)data;
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mbs_tcp_port_t *port_obj = __containerof(pdrv_ctx->parent, mbs_tcp_port_t, base);
static int curr_fd = 0;
ESP_LOGD(TAG, "%s %s: fd: %d, %d", (char *)base, __func__, (int)curr_fd, pdrv_ctx->node_conn_count);
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, curr_fd);
ESP_LOGD(TAG, "%s %s: fd: %d, count: %d", (char *)base, __func__, (int)curr_fd, pdrv_ctx->node_conn_count);
mb_drv_check_suspend_shutdown(ctx);
int ret = mb_drv_check_node_state(pdrv_ctx, &curr_fd, MB_RECONNECT_TIME_MS);
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
ESP_LOGE(TAG, "Node: %d, connection lost, err= %d", curr_fd, ret);
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", connection lost, err=%d, drop connection."),
port_obj, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (int)ret);
(void)transaction_delete_by_node_id(port_obj->transaction, curr_fd);
mb_drv_close(pdrv_ctx, curr_fd);
}
if ((curr_fd + 1) >= (pdrv_ctx->node_conn_count)) {

View File

@@ -201,8 +201,8 @@ int port_read_packet(mb_node_info_t *pinfo)
pinfo->recv_err = ret;
return ret;
} else if (ret != MB_TCP_UID) {
ESP_LOGD(TAG, "Socket (#%d)(%s), fail to read modbus header. ret=%d",
pinfo->sock_id, pinfo->addr_info.ip_addr_str, ret);
ESP_LOGD(TAG, "node #%d, Socket (#%d)(%s), fail to read modbus header, err=%d",
pinfo->fd, pinfo->sock_id, pinfo->addr_info.ip_addr_str, ret);
pinfo->recv_err = ERR_VAL;
return ERR_VAL;
}
@@ -914,7 +914,7 @@ int port_accept_connection(int listen_sock_id, mb_uid_info_t *pinfo)
// Make sure ss_family is valid
abort();
}
ESP_LOGI(TAG, "Socket (#%d), accept client connection from address[port]: %s[%d]", (int)sock_id, addr_str, pinfo->port);
ESP_LOGI(TAG, "Socket (#%d), accept client connection from address[port]: %s[%u]", (int)sock_id, addr_str, pinfo->port);
paddr = strdup(addr_str);
if (paddr) {
pinfo->fd = sock_id;