mirror of
https://github.com/espressif/esp-modbus.git
synced 2025-08-01 03:14:29 +02:00
fix nodes reconnection issues
This commit is contained in:
10
Kconfig
10
Kconfig
@@ -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"
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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)) {
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user