From 8cf00ad14d40dc3610a524b54eeadc905ad6103d Mon Sep 17 00:00:00 2001 From: ypc <15051963820@163.com> Date: Fri, 10 Jul 2026 10:40:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(com=5Frouter):=20bind=5Fapp=20=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E7=BB=91=E5=AE=9A=E8=B7=AF=E7=94=B1=20=E2=80=94=20?= =?UTF-8?q?=E7=AB=AF=E5=8F=A3=E2=86=92=E8=A7=84=E7=BA=A6=E7=9B=B4=E6=8A=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 设计 通道配置新增 bind_app 字段: - bind_app="" (空) → 现有帧内容分路 (FTU串口) - bind_app="iec" → 整帧直投 libiec (TCP :2404 主站) - bind_app="self_ptl" → 整帧直投 self_ptl (备用) 新增 com_router_register_dispatch(bind_app, cb): - 协议模块在 app_wiring() 注册回调 - recv_cb 发现通道 bind_app 匹配, 直接调用 dispatch - 不需要帧解析 — 协议模块自行解码 ## 路由优先级 1. forward_rule → 维护透传 2. bind_app 非空 → dispatch 投递 3. bind_app 空 → 帧内容分路 (ICP67 dev=0/IEC/ICP67 dev≠0) ## 配置示例 channel_cfg.json: tcp_master(:2404) bind_app="iec" → 外部主站连接 :2404 → com_router → libiec 回调 --- config/CHANNEL/channel_cfg.json | 3 +- src/system/libcom_router/inc/com_router.h | 24 +++++++++ src/system/libcom_router/src/com_router.cpp | 50 +++++++++++++++++++ .../libcom_router/src/com_router_dispatch.cpp | 31 +++++++++++- 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/config/CHANNEL/channel_cfg.json b/config/CHANNEL/channel_cfg.json index 34f698c..7fa8001 100644 --- a/config/CHANNEL/channel_cfg.json +++ b/config/CHANNEL/channel_cfg.json @@ -15,7 +15,8 @@ "type": "tcp_server", "local_ip": "0.0.0.0", "local_port": 2404, - "desc": "主站通道 (libiec直管, 不走com_router路由)" + "bind_app": "iec", + "desc": "IEC-104主站通道 (:2404) — com_router直接投递给libiec" } ], "forward_rules": [ diff --git a/src/system/libcom_router/inc/com_router.h b/src/system/libcom_router/inc/com_router.h index 63f42a6..ccecc13 100644 --- a/src/system/libcom_router/inc/com_router.h +++ b/src/system/libcom_router/inc/com_router.h @@ -21,6 +21,18 @@ extern "C" { #endif +/* =========================== 协议分发回调 =========================== */ + +#define MAX_DISPATCH_APPS 8 + +/** + * @brief 协议模块数据接收回调 — 通道绑定 bind_app 后, 整帧投递 + * @param interface 通道标识 (ch_id<<16)|fd + * @param data 原始数据 (整帧, 不解包) + * @param len 数据长度 + */ +typedef void (*com_router_dispatch_cb)(uint32_t interface, const unsigned char *data, int len); + /* =========================== 通道配置结构 =========================== */ /** @@ -76,6 +88,18 @@ uint32_t com_router_interface_get(const char *key); int com_router_fd_get(const char *key); int com_router_id_get_by_bind(const char *bind_app); +/** + * @brief 协议模块注册分发回调 — 通道 bind_app 匹配时直接投递 + * @param bind_app 协议标识 (如 "iec", "self_ptl", "iec61850") + * @param cb 数据接收回调, 通道收到数据时调用 + * @return 0 成功, -1 失败 (表满) + * + * @note 调用时机: app_wiring() 中, 在 app_com_router_init1 之后 + * 若通道配置中 bind_app 非空, 该通道的原始数据直接投递给注册的回调 + * 不再经过帧内容分路逻辑 (帧解析由协议模块自行完成) + */ +int com_router_register_dispatch(const char *bind_app, com_router_dispatch_cb cb); + /* =========================== 应用线程入口 =========================== */ int app_com_router_init1(void *arg); diff --git a/src/system/libcom_router/src/com_router.cpp b/src/system/libcom_router/src/com_router.cpp index f061b69..f85fb7c 100644 --- a/src/system/libcom_router/src/com_router.cpp +++ b/src/system/libcom_router/src/com_router.cpp @@ -29,6 +29,53 @@ int g_forward_count = 0; static int g_config_loaded = 0; +/* =========================== 协议分发注册表 =========================== */ + +typedef struct +{ + char bind_app[16]; + com_router_dispatch_cb cb; +} dispatch_entry_t; + +static dispatch_entry_t g_dispatch_table[MAX_DISPATCH_APPS]; +static int g_dispatch_count = 0; + +int com_router_register_dispatch(const char *bind_app, com_router_dispatch_cb cb) +{ + if(NULL == bind_app || NULL == cb || g_dispatch_count >= MAX_DISPATCH_APPS) + { + return -1; + } + + strncpy(g_dispatch_table[g_dispatch_count].bind_app, bind_app, 15); + g_dispatch_table[g_dispatch_count].cb = cb; + g_dispatch_count++; + + LOG_I("com_router: registered dispatch for [%s]", bind_app); + return 0; +} + +/* 内部查找: 按 bind_app 取回调, 未找到返回 NULL */ +com_router_dispatch_cb com_router_dispatch_find(const char *bind_app) +{ + int i; + + if(NULL == bind_app || '\0' == bind_app[0]) + { + return NULL; + } + + for(i = 0; i < g_dispatch_count; i++) + { + if(0 == strcmp(g_dispatch_table[i].bind_app, bind_app)) + { + return g_dispatch_table[i].cb; + } + } + + return NULL; +} + /* =========================== 前向声明 =========================== */ extern void com_router_recv_cb(int id, int fd, const unsigned char *data, int len); @@ -59,11 +106,14 @@ static int com_router_parse_channels(cJSON *arr) cJSON *key = cJSON_GetObjectItem(item, "key"); cJSON *type = cJSON_GetObjectItem(item, "type"); + cJSON *bind = cJSON_GetObjectItem(item, "bind_app"); cJSON *desc = cJSON_GetObjectItem(item, "desc"); if(NULL == key || NULL == type) continue; strncpy(ch->key, key->valuestring, 31); + if(NULL != bind) { strncpy(ch->bind_app, bind->valuestring, 15); } + else { ch->bind_app[0] = '\0'; } if(0 == strcmp(type->valuestring, "uart")) { diff --git a/src/system/libcom_router/src/com_router_dispatch.cpp b/src/system/libcom_router/src/com_router_dispatch.cpp index 05c5c40..7205601 100644 --- a/src/system/libcom_router/src/com_router_dispatch.cpp +++ b/src/system/libcom_router/src/com_router_dispatch.cpp @@ -11,6 +11,11 @@ #include +/* =========================== 前向声明 =========================== */ + +/* 来自 com_router.cpp 的内部函数 */ +extern com_router_dispatch_cb com_router_dispatch_find(const char *bind_app); + /* =========================== 全局变量引用 =========================== */ extern com_channel_t g_channels[]; @@ -119,6 +124,13 @@ static int com_router_fwd_send_back(int serial_ch_id, /* =========================== 核心: 数据接收回调 =========================== */ +/* + * 路由优先级: + * 1. 匹配 forward_rule.sock_fd → 透传到目标通道 (维护透传) + * 2. 通道 bind_app 非空 → 整帧投递给注册的协议模块回调 + * 3. bind_app 为空 (FTU 串口) → 按帧内容分路 (ICP67/IEC 帧识别) + */ + void com_router_recv_cb(int id, int fd, const unsigned char *p_rx, int rx_len) { com_channel_t *ch = NULL; @@ -155,7 +167,24 @@ void com_router_recv_cb(int id, int fd, const unsigned char *p_rx, int rx_len) return; } - /* Step 2: FTU 串口接收 → 按帧分路 */ + /* Step 2: bind_app 协议绑定 → 直接投递给注册的协议模块 */ + if('\0' != ch->bind_app[0]) + { + com_router_dispatch_cb dispatch = com_router_dispatch_find(ch->bind_app); + + if(NULL != dispatch) + { + uint32_t interface = ((uint32_t)id << 16) | (uint32_t)fd; + + dispatch(interface, p_rx, rx_len); + return; + } + + LOG_E("com_router: bind_app [%s] has no dispatch registered", ch->bind_app); + return; + } + + /* Step 3: bind_app 为空 → FTU 串口按帧内容分路 */ /* a) ICP67 维护软件回复 (dev_addr=0) */ if(rx_len >= (int)sizeof(stru_head)