From c6501da92f7ff5cf1434a7328204d7e23e8a0fbb Mon Sep 17 00:00:00 2001 From: ypc <15051963820@163.com> Date: Thu, 18 Jun 2026 17:53:22 +0800 Subject: [PATCH] =?UTF-8?q?<=E4=BF=AE=E6=94=B9>1=E3=80=81=E5=B0=86datacent?= =?UTF-8?q?er=E8=B0=83=E6=95=B4=E5=88=B0public=E4=B8=8B=EF=BC=9B2=E3=80=81?= =?UTF-8?q?=E8=A7=A3=E8=80=A6=E5=BA=94=E7=94=A8=E6=A8=A1=E5=9D=97=EF=BC=8C?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B6=88=E6=81=AF=E9=98=9F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mimo/问题处理文档.md | 26 +++++++ release/inc/mySystem.h | 13 +++- .../{system => public}/libdatacenter/makefile | 0 release/src/public/makefile | 2 + release/src/system/makefile | 1 - .../libdatacenter/inc/dc_event.h | 0 .../libdatacenter/inc/dc_param.h | 0 .../libdatacenter/inc/dc_signal.h | 0 .../libdatacenter/src/datacenter.cpp | 0 .../libdatacenter/src/dc_event.cpp | 0 .../libdatacenter/src/dc_param.cpp | 0 .../libdatacenter/src/dc_signal.cpp | 0 src/system/RTU/src/app_sys.cpp | 22 ++++++ .../libcom_decode/src/decode_channel_mgr.cpp | 17 ++++- .../libcom_decode/src/decode_data_router.cpp | 24 +++---- src/system/libiec/src/iec.cpp | 32 +++++---- src/system/libself_ptl/src/self_ptl.cpp | 69 ++++++++++++++----- 17 files changed, 155 insertions(+), 51 deletions(-) rename release/src/{system => public}/libdatacenter/makefile (100%) rename src/{system => public}/libdatacenter/inc/dc_event.h (100%) rename src/{system => public}/libdatacenter/inc/dc_param.h (100%) rename src/{system => public}/libdatacenter/inc/dc_signal.h (100%) rename src/{system => public}/libdatacenter/src/datacenter.cpp (100%) rename src/{system => public}/libdatacenter/src/dc_event.cpp (100%) rename src/{system => public}/libdatacenter/src/dc_param.cpp (100%) rename src/{system => public}/libdatacenter/src/dc_signal.cpp (100%) diff --git a/mimo/问题处理文档.md b/mimo/问题处理文档.md index 32b04d9..11d8d87 100644 --- a/mimo/问题处理文档.md +++ b/mimo/问题处理文档.md @@ -189,6 +189,32 @@ --- +## 2026-06-18: 跨模块耦合解耦 — self_ptl_set_interface → dc_signal + app_get_ptr → app_get_mq_target + +**问题**:系统模块间存在两种硬编码耦合: +1. `decode_channel_mgr` 直接调用 `self_ptl_set_interface()` 传递 TCP 接口 → 强依赖 self_ptl 头文件 +2. `iec.cpp`/`self_ptl.cpp`/`decode_data_router.cpp` 中通过 `app_get_ptr(ENUM_APP_XXX)` + 硬编码事件号发送跨模块通知 → 模块间直接知晓对方身份 + +**根因**:早期快速迭代中,模块间交互未经过中间层抽象。协议处理模块(iec/self_ptl/comm)互相知道对方的应用 ID、事件号、接口函数。 + +**修复**: +### 问题一:self_ptl_set_interface 解耦 +- `decode_channel_mgr.cpp`:移除 `#include "self_ptl.h"` 和 `self_ptl_set_interface()` 调用,改为 `dc_signal_out("sys.tcp_c0_interface", ...)` 通过 datacenter 发布接口信息 +- `self_ptl.cpp`:移除 `self_ptl_set_interface()` 函数,`self_ptl_init()` 改为通过 `dc_get_out_signal_info("sys.tcp_c0_interface")` 从 datacenter 读取接口 + +### 问题二:app_get_ptr + 硬编码事件号解耦 +- `mySystem.h`:新增 `stru_mq_target {app_id, event}` 结构和 `app_get_mq_target(enum_mq_id)` 声明 +- `app_sys.cpp`:新增 `g_mq_target_map[ENUM_MQ_MAX]` 全局映射表和 `app_get_mq_target()` 实现 +- `iec.cpp`:`iec_data_tx()` 中 `app_get_ptr(ENUM_APP_COM_DECODE) + EV_COM_RX_IEC` → `app_get_mq_target(ENUM_MQ_IEC_TO_COM)` +- `self_ptl.cpp`:`self_ptl_data_tx()` 中硬编码事件号 → `app_get_mq_target(ENUM_MQ_SELF_PTL_TO_COM)` +- `decode_data_router.cpp`:`com_scan_send_data_to_app()` 中 if/else 判断目标 MQ → 通过 `app_get_mq_target(mq_id)` 统一处理 + +**状态**:✅ 已完成 +**涉及文件**:`decode_channel_mgr.cpp`, `self_ptl.cpp`, `iec.cpp`, `decode_data_router.cpp`, `mySystem.h`, `app_sys.cpp` +**验证**:`./release/build.sh` 编译通过,运行日志显示 `self_ptl_init got tcp_c0_if from dc: 20006` 确认 datacenter 信号通信正常。 + +--- + ## 2026-06-10 ### #1 libmms_m RCB 订阅编号硬编码 diff --git a/release/inc/mySystem.h b/release/inc/mySystem.h index 5b0b3ae..7c8bf87 100644 --- a/release/inc/mySystem.h +++ b/release/inc/mySystem.h @@ -176,6 +176,16 @@ stru_app_msg_queue *app_get_msg_queue_ptr(uint32_t mq_id); // 应用指针获取函数,根据应用ID获取应用指针 stru_app *app_get_ptr(uint32_t app_id); +// MQ 目标映射 — MQ 发送完成后要通知的目标 app_id 和 event +typedef struct +{ + uint32_t app_id; // 目标应用 ID + uint32_t event; // 通知事件 +}stru_mq_target; + +// 获取 MQ 对应的通知目标(app_id + event),解耦发送方对接收方 app_id 的硬编码 +stru_mq_target app_get_mq_target(uint32_t mq_id); + // 应用初始化与线程函数声明 — 由 app_modules.h X-macro 自动生成 #define APP_MODULE(name, cfg_name, init1, init2, func) \ extern int init1(void *arg); \ @@ -187,8 +197,7 @@ stru_app *app_get_ptr(uint32_t app_id); -// icp67线程设置通道类型 -void self_ptl_set_interface(uint32_t interface); + // 通讯通道获取接口类型,通过通道ID获取 uint32_t com_channel_interface_get(uint32_t comm_id); diff --git a/release/src/system/libdatacenter/makefile b/release/src/public/libdatacenter/makefile similarity index 100% rename from release/src/system/libdatacenter/makefile rename to release/src/public/libdatacenter/makefile diff --git a/release/src/public/makefile b/release/src/public/makefile index 1425986..4ca4e29 100644 --- a/release/src/public/makefile +++ b/release/src/public/makefile @@ -15,6 +15,8 @@ SUBDIRS += ./libxml SUBDIRS += ./libmy_xxhash +SUBDIRS += ./libdatacenter + diff --git a/release/src/system/makefile b/release/src/system/makefile index eb8b5d8..4624f6b 100644 --- a/release/src/system/makefile +++ b/release/src/system/makefile @@ -4,7 +4,6 @@ SUBDIRS := SUBDIRS += ./libcom_decode -SUBDIRS += ./libdatacenter SUBDIRS += ./libiec SUBDIRS += ./libiec61850m SUBDIRS += ./libiec61850s diff --git a/src/system/libdatacenter/inc/dc_event.h b/src/public/libdatacenter/inc/dc_event.h similarity index 100% rename from src/system/libdatacenter/inc/dc_event.h rename to src/public/libdatacenter/inc/dc_event.h diff --git a/src/system/libdatacenter/inc/dc_param.h b/src/public/libdatacenter/inc/dc_param.h similarity index 100% rename from src/system/libdatacenter/inc/dc_param.h rename to src/public/libdatacenter/inc/dc_param.h diff --git a/src/system/libdatacenter/inc/dc_signal.h b/src/public/libdatacenter/inc/dc_signal.h similarity index 100% rename from src/system/libdatacenter/inc/dc_signal.h rename to src/public/libdatacenter/inc/dc_signal.h diff --git a/src/system/libdatacenter/src/datacenter.cpp b/src/public/libdatacenter/src/datacenter.cpp similarity index 100% rename from src/system/libdatacenter/src/datacenter.cpp rename to src/public/libdatacenter/src/datacenter.cpp diff --git a/src/system/libdatacenter/src/dc_event.cpp b/src/public/libdatacenter/src/dc_event.cpp similarity index 100% rename from src/system/libdatacenter/src/dc_event.cpp rename to src/public/libdatacenter/src/dc_event.cpp diff --git a/src/system/libdatacenter/src/dc_param.cpp b/src/public/libdatacenter/src/dc_param.cpp similarity index 100% rename from src/system/libdatacenter/src/dc_param.cpp rename to src/public/libdatacenter/src/dc_param.cpp diff --git a/src/system/libdatacenter/src/dc_signal.cpp b/src/public/libdatacenter/src/dc_signal.cpp similarity index 100% rename from src/system/libdatacenter/src/dc_signal.cpp rename to src/public/libdatacenter/src/dc_signal.cpp diff --git a/src/system/RTU/src/app_sys.cpp b/src/system/RTU/src/app_sys.cpp index b90c2a2..8bf75ab 100644 --- a/src/system/RTU/src/app_sys.cpp +++ b/src/system/RTU/src/app_sys.cpp @@ -348,6 +348,28 @@ stru_app *app_get_ptr(uint32_t app_id) } +// MQ -> 目标(app_id, event) 映射表 +// 消息队列发送完成后,发送方通过此表查知应通知哪个模块的哪个事件 +LOCAL const stru_mq_target g_mq_target_map[ENUM_MQ_MAX] = +{ + {ENUM_APP_IEC, EV_IEC_RX_COM}, // ENUM_MQ_COM_TO_IEC + {ENUM_APP_COM_DECODE, EV_COM_RX_IEC}, // ENUM_MQ_IEC_TO_COM + {ENUM_APP_SELF_PTL, EV_SELF_PTL_RX_COM}, // ENUM_MQ_COM_TO_SELF_PTL + {ENUM_APP_COM_DECODE, EV_COM_RX_SELF_PTL}, // ENUM_MQ_SELF_PTL_TO_COM +}; + +stru_mq_target app_get_mq_target(uint32_t mq_id) +{ + if(mq_id >= ENUM_MQ_MAX) + { + LOG_E("mq_id over ENUM_MQ_MAX, mq_id %d, max %d", mq_id, ENUM_MQ_MAX); + return {ENUM_APP_MAX, 0}; + } + + return g_mq_target_map[mq_id]; +} + + int app_sys_init1(void *arg) diff --git a/src/system/libcom_decode/src/decode_channel_mgr.cpp b/src/system/libcom_decode/src/decode_channel_mgr.cpp index d9a2e47..50fae43 100644 --- a/src/system/libcom_decode/src/decode_channel_mgr.cpp +++ b/src/system/libcom_decode/src/decode_channel_mgr.cpp @@ -1,6 +1,7 @@ #include "mySystem.h" #include "myComm.h" #include "myLog.h" +#include "myDatacenter.h" #include "com_decode.h" @@ -86,6 +87,10 @@ LOCAL stru_channel_para g_channel_para[ENUM_COMM_MAX] = } }; +// 数据中心信号存储变量 — 供 self_ptl 等模块通过 dc_signal 读取 interface +LOCAL uint32_t g_sys_tcp_c0_if = 0; +LOCAL uint32_t g_sys_tcp_s0_if = 0; + uint32_t com_channel_interface_get(uint32_t comm_id) { @@ -122,8 +127,12 @@ LOCAL void com_channel_state_cb(int id, int socket_fd, CommState state) if(id == g_channel_para[ENUM_COMM_TCP_C_0].id) { - uint32_t itfs = com_channel_interface_get(ENUM_COMM_TCP_C_0); - self_ptl_set_interface(itfs); + g_sys_tcp_c0_if = com_channel_interface_get(ENUM_COMM_TCP_C_0); + } + + if(id == g_channel_para[ENUM_COMM_TCP_S_0].id) // TCP_S_0 用于 self_ptl 转发维护数据 + { + g_sys_tcp_s0_if = com_channel_interface_get(ENUM_COMM_TCP_S_0); } } @@ -187,6 +196,10 @@ int com_channel_create() } } + // 将 TCP 客户端/服务端的 interface 注册到数据中心,供 self_ptl 等模块读取 + dc_signal_out("sys.tcp_c0_interface", "TCP client 0 interface", DATA_TYPE_U32, &g_sys_tcp_c0_if); + dc_signal_out("sys.tcp_s0_interface", "TCP server 0 interface", DATA_TYPE_U32, &g_sys_tcp_s0_if); + return 0; } diff --git a/src/system/libcom_decode/src/decode_data_router.cpp b/src/system/libcom_decode/src/decode_data_router.cpp index 6f585ec..357c1f5 100644 --- a/src/system/libcom_decode/src/decode_data_router.cpp +++ b/src/system/libcom_decode/src/decode_data_router.cpp @@ -17,34 +17,30 @@ LOCAL int com_scan_send_data_to_app(stru_msg_head *p_head, uint16_t len, uint32_ stru_app_msg_queue *p_mq = NULL; stru_app *p_app = NULL; - uint32_t event = 0; - if(mq_id == ENUM_MQ_COM_TO_IEC && NULL != (p_mq = app_get_msg_queue_ptr(ENUM_MQ_COM_TO_IEC)) && len < p_mq->msg_size) - { - p_app = app_get_ptr(ENUM_APP_IEC); - event = EV_IEC_RX_COM; - } - else if(mq_id == ENUM_MQ_COM_TO_SELF_PTL && NULL != (p_mq = app_get_msg_queue_ptr(ENUM_MQ_COM_TO_SELF_PTL)) && len < p_mq->msg_size) - { - p_app = app_get_ptr(ENUM_APP_SELF_PTL); - event = EV_SELF_PTL_RX_COM; - } - else + if(NULL == (p_mq = app_get_msg_queue_ptr(mq_id)) || len >= p_mq->msg_size) { LOG_E("com_scan_send_data_to_app mq_id %d or len %d error", mq_id, len); return -1; } + stru_mq_target target = app_get_mq_target(mq_id); + if(ENUM_APP_MAX == target.app_id) + { + LOG_E("com_scan_send_data_to_app app_get_mq_target failed, mq_id %d", mq_id); + return -1; + } + if(0 != task_msg_queue_send(p_mq->p_msg_queue, p_head, p_mq->msg_size)) { LOG_E("com_scan_send_data_to_app send to queue failed"); return -1; } - if(0 != task_event_send(p_app->p_event, event)) + if(NULL == (p_app = app_get_ptr(target.app_id)) || 0 != task_event_send(p_app->p_event, target.event)) { LOG_E("com_scan_send_data_to_app send event failed"); - task_msg_queue_try_recv(p_mq->p_msg_queue, p_app->rtx.tx, p_mq->msg_size); + task_msg_queue_try_recv(p_mq->p_msg_queue, p_app ? p_app->rtx.tx : (uint8_t *)p_head, p_mq->msg_size); return -1; } diff --git a/src/system/libiec/src/iec.cpp b/src/system/libiec/src/iec.cpp index c36b391..0ddae1d 100644 --- a/src/system/libiec/src/iec.cpp +++ b/src/system/libiec/src/iec.cpp @@ -339,24 +339,27 @@ int iec_data_tx(uint8_t *p_tx, uint16_t tx_len, void *arg) return -1; } - if(NULL == (p_app = app_get_ptr(ENUM_APP_COM_DECODE)) || 0 != task_event_send(p_app->p_event, EV_COM_RX_IEC)) - { - LOG_E("iec_data_tx app_get_ptr or task_event_send failed"); - task_msg_queue_try_recv(p_mq->p_msg_queue, p_rtx->rx, p_mq->msg_size); - return -1; - } + { + stru_mq_target target = app_get_mq_target(ENUM_MQ_IEC_TO_COM); + if(ENUM_APP_MAX == target.app_id) + { + LOG_E("iec_data_tx app_get_mq_target failed"); + task_msg_queue_try_recv(p_mq->p_msg_queue, p_rtx->rx, p_mq->msg_size); + return -1; + } + if(NULL == (p_app = app_get_ptr(target.app_id)) || 0 != task_event_send(p_app->p_event, target.event)) + { + LOG_E("iec_data_tx app_get_ptr or task_event_send failed"); + task_msg_queue_try_recv(p_mq->p_msg_queue, p_rtx->rx, p_mq->msg_size); + return -1; + } + } - return 0; + return 0; } -void iec_data_rx(uint8_t *data) +int iec_data_rx(uint8_t *data) { - if(NULL == data) - { - LOG_E("iec_data_rx data null"); - return; - } - stru_msg_head *p_head = (stru_msg_head *)data; uint32_t interface = p_head->interface; uint16_t len = p_head->len; @@ -366,6 +369,7 @@ void iec_data_rx(uint8_t *data) { iec60870_decode(p_rx, len, interface); } + return 0; } void iec60870_task(uint16_t usGap) diff --git a/src/system/libself_ptl/src/self_ptl.cpp b/src/system/libself_ptl/src/self_ptl.cpp index 4c43101..6aa2b7f 100644 --- a/src/system/libself_ptl/src/self_ptl.cpp +++ b/src/system/libself_ptl/src/self_ptl.cpp @@ -79,6 +79,11 @@ stru_self_ptl g_self_ptl = }; +// 数据中心 interface 数据指针缓存 — 代替直接调用 com_channel_interface_get +LOCAL uint32_t *g_p_tcp_c0_if = NULL; // TCP 客户端 0 interface(自协议发送用) +LOCAL uint32_t *g_p_tcp_s0_if = NULL; // TCP 服务端 0 interface(维护数据转发用) + + stru_self_ptl_cfg_data g_self_ptl_cfg_data = {}; @@ -440,12 +445,20 @@ void self_ptl_data_tx(uint8_t *p_tx, uint16_t len, void *arg) return; } - if(NULL == (p_app = app_get_ptr(ENUM_APP_COM_DECODE)) || 0 != task_event_send(p_app->p_event, EV_COM_RX_SELF_PTL)) { - LOG_E("self_ptl_data_tx task_event_send failed"); - task_msg_queue_try_recv(p_mq->p_msg_queue, p_rtx->rx, p_mq->msg_size); - - return; + stru_mq_target target = app_get_mq_target(ENUM_MQ_SELF_PTL_TO_COM); + if(ENUM_APP_MAX == target.app_id) + { + LOG_E("self_ptl_data_tx app_get_mq_target failed"); + task_msg_queue_try_recv(p_mq->p_msg_queue, p_rtx->rx, p_mq->msg_size); + return; + } + if(NULL == (p_app = app_get_ptr(target.app_id)) || 0 != task_event_send(p_app->p_event, target.event)) + { + LOG_E("self_ptl_data_tx task_event_send failed"); + task_msg_queue_try_recv(p_mq->p_msg_queue, p_rtx->rx, p_mq->msg_size); + return; + } } } @@ -486,7 +499,7 @@ LOCAL void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp6 if(p_head->dev_addr == DEV_MAINTENANCE_ADDR) { - uint32_t interface = com_channel_interface_get(ENUM_COMM_TCP_S_0); + uint32_t interface = g_p_tcp_s0_if ? *g_p_tcp_s0_if : 0; self_ptl_data_tx(g_self_ptl.temp_buf + icp67_consumed - valid_len, valid_len, (void *)&interface); } else @@ -510,7 +523,7 @@ LOCAL void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp6 searched = true; iec_consumed += (pos + valid_len); - uint32_t interface = com_channel_interface_get(ENUM_COMM_TCP_S_0); + uint32_t interface = g_p_tcp_s0_if ? *g_p_tcp_s0_if : 0; self_ptl_data_tx(g_self_ptl.temp_buf + iec_consumed - valid_len, valid_len, (void *)&interface); } } while (ret == 0); @@ -591,14 +604,6 @@ void self_ptl_task() } } -void self_ptl_set_interface(uint32_t interface) -{ - g_self_ptl.interface = interface; - - LOG_I("self_ptl_init interface %d, %x", g_self_ptl.interface, g_self_ptl.interface); -} - - LOCAL int self_ptl_cfg_init() { stru_self_ptl_cfg *p_cfg = self_ptl_cfg_get(); @@ -748,11 +753,39 @@ LOCAL int self_ptl_cfg_init() void self_ptl_init() { - // g_self_ptl.interface = com_channel_interface_get(ENUM_COMM_TCP_C_0); - + // 从数据中心获取 TCP 通道 interface 数据指针,解耦 com_decode 直接调用 + { + uint8_t dc_type; + std::string desc; + void *p_data = NULL; + + if(0 == dc_get_out_signal_info("sys.tcp_c0_interface", desc, dc_type, &p_data) + && DATA_TYPE_U32 == dc_type && NULL != p_data) + { + g_p_tcp_c0_if = (uint32_t *)p_data; + g_self_ptl.interface = *g_p_tcp_c0_if; + MY_LOG_I("self_ptl_init got tcp_c0_if from dc: %x", g_self_ptl.interface); + } + else + { + MY_LOG_E("self_ptl_init dc_get tcp_c0_interface failed, use local"); + g_p_tcp_c0_if = &g_self_ptl.interface; + } + + p_data = NULL; + if(0 == dc_get_out_signal_info("sys.tcp_s0_interface", desc, dc_type, &p_data) + && DATA_TYPE_U32 == dc_type && NULL != p_data) + { + g_p_tcp_s0_if = (uint32_t *)p_data; + } + else + { + g_p_tcp_s0_if = &g_self_ptl.interface; // fallback + } + } stru_icp67 *p_icp67 = &g_self_ptl.icp67; - icp67_init(p_icp67, self_ptl_data_tx, (void *)&g_self_ptl.interface); + icp67_init(p_icp67, self_ptl_data_tx, (void *)g_p_tcp_c0_if); stru_self_ptl_cfg *p_self_cfg = self_ptl_cfg_get(); if(nullptr == p_self_cfg)