<修改>1、将datacenter调整到public下;2、解耦应用模块,调整消息队列

This commit is contained in:
ypc 2026-06-18 17:53:22 +08:00
parent 8de2441a79
commit c6501da92f
17 changed files with 155 additions and 51 deletions

View File

@ -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 订阅编号硬编码

View File

@ -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);

View File

@ -15,6 +15,8 @@ SUBDIRS += ./libxml
SUBDIRS += ./libmy_xxhash
SUBDIRS += ./libdatacenter

View File

@ -4,7 +4,6 @@ SUBDIRS :=
SUBDIRS += ./libcom_decode
SUBDIRS += ./libdatacenter
SUBDIRS += ./libiec
SUBDIRS += ./libiec61850m
SUBDIRS += ./libiec61850s

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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)