pCCU 新增真实CCU配电桥接(rcu链路原帧透传+网页显示)并适配板卡端口拓扑

- protocol/DisProtocol: 配电协议8条消息(指令0x0001~4/反馈0x0005~8, Sum8),复用pmSysvariable结构体+static_assert核对
- ChecksumPolicy 新增 Sum8;Frame 支持 1 字节校验和
- MessageRegistry 支持 (id+帧总长) 二维查找:配电指令与PM操控指令共用id按帧长区分(帧头length字段不可信)
- LinkManager: 按实际帧长分发 + sendRaw原帧透传 + 非本协议帧头落库节流告警;UdpEndpoint sendTo 加锁
- comm/RcuLinkManager: 真实CCU链路;core/DisBridge: 配电桥接器(反馈转pPowerManger+解码显示,指令转真实CCU,0x0004仅显示不转发)
- 网页新增"真实CCU"页签全字段展示;SnapshotBuilder realCcu 节 + rcu 链路描述
- h100.moos: 端口腾挪(真实CCU固定上报5001归pCCU,pPowerManger iport=5002),rcu_remote=192.168.0.140:7000
- 测试: pccuTest 新增配电/Sum8/长度分发/RCU注册表用例(176项);集成测试新增桥接字节一致+不误转发用例
This commit is contained in:
zjk
2026-09-01 15:06:11 +08:00
parent 5b8f0b1421
commit 0639b5904d
28 changed files with 1609 additions and 53 deletions
+76 -7
View File
@@ -17,8 +17,10 @@ CCU::CCU() {}
CCU::~CCU() {
if (m_web) { m_web->stop(); delete m_web; m_web = nullptr; }
if (m_coord) { delete m_coord; m_coord = nullptr; }
if (m_bridge) { delete m_bridge; m_bridge = nullptr; }
if (m_fcLink) { m_fcLink->stop(); delete m_fcLink; m_fcLink = nullptr; }
if (m_pmLink) { m_pmLink->stop(); delete m_pmLink; m_pmLink = nullptr; }
if (m_rcuLink) { m_rcuLink->stop(); delete m_rcuLink; m_rcuLink = nullptr; }
if (m_db) { m_db->close(); delete m_db; m_db = nullptr; }
if (m_snap) { delete m_snap; m_snap = nullptr; }
if (m_sysData) { delete m_sysData; m_sysData = nullptr; }
@@ -49,6 +51,10 @@ bool CCU::OnStartUp() {
else if (param == "pm_local_port") m_pmLocalPort = atol(value.c_str());
else if (param == "pm_remote_ip") m_pmHost = value;
else if (param == "pm_remote_port") m_pmPort = atol(value.c_str());
else if (param == "rcu_enable") m_rcuEnable = (tolower(value) == "true" || value == "1");
else if (param == "rcu_local_port") m_rcuLocalPort = atol(value.c_str());
else if (param == "rcu_remote_ip") m_rcuHost = value;
else if (param == "rcu_remote_port") m_rcuPort = atol(value.c_str());
else if (param == "dbpath") m_dbPath = value;
else if (param == "logpath") m_logPath = value;
else if (param == "web_port") m_webPort = atoi(value.c_str());
@@ -81,6 +87,9 @@ bool CCU::OnStartUp() {
// 系统数据快照
m_sysData = new SystemData();
// 配电桥接器(须在链路 start 前完成依赖注入,避免接收线程空指针)
m_bridge = new DisBridge();
// FC 链路
m_fcLink = new FcLinkManager(m_fcLocalPort, m_fcHost, m_fcPort);
m_fcLink->setLogSink(m_db);
@@ -90,19 +99,40 @@ bool CCU::OnStartUp() {
m_fcLink->setOnRawFrame([](int dir, const std::vector<uint8_t>&, bool) {
// 原始帧已通过 LogSink 落库;如需 Web 实时原始报文可在此扩展
});
if (!m_fcLink->start())
LOG_F(ERROR, "FC link start failed");
// PM 链路
m_pmLink = new PmLinkManager(m_pmLocalPort, m_pmHost, m_pmPort);
m_pmLink->setLogSink(m_db);
m_pmLink->setOnMessage([this](Message* msg, const std::vector<uint8_t>& frame) {
// 配电指令(0x0001~0x0004,Sum8 短帧)优先桥接转发真实CCU;
// 注册表按帧总长区分配电指令与 PM 操控/参数指令(共用 id)
if (m_bridge && m_bridge->onPmFrame(msg, frame)) return;
handlePmMessage(msg, frame);
});
m_pmLink->setOnRawFrame([](int, const std::vector<uint8_t>&, bool) {
});
// 真实 CCU 链路(配电桥接,rcu_enable 开启时创建)
if (m_rcuEnable) {
m_rcuLink = new RcuLinkManager(m_rcuLocalPort, m_rcuHost, m_rcuPort);
m_rcuLink->setLogSink(m_db);
m_rcuLink->setOnMessage([this](Message* msg, const std::vector<uint8_t>& frame) {
handleRcuMessage(msg, frame);
});
m_rcuLink->setOnRawFrame([](int, const std::vector<uint8_t>&, bool) {
});
}
// 注入桥接依赖(m_rcuLink 可为空:未启用桥接时相关入口自动失效)
m_bridge->setup(m_pmLink, m_rcuLink, m_sysData);
// 启动链路
if (!m_fcLink->start())
LOG_F(ERROR, "FC link start failed");
if (!m_pmLink->start())
LOG_F(ERROR, "PM link start failed");
if (m_rcuLink && !m_rcuLink->start())
LOG_F(ERROR, "RCU link start failed on port %ld", m_rcuLocalPort);
// 锂电池:CAN 总线(BMS 协议),数据经 pCanBridge 以 CAN_0x* 消息透传,
// 在 OnNewMail 中订阅解码(见 registerVariables/handleCanMessage)。
@@ -112,7 +142,7 @@ bool CCU::OnStartUp() {
m_coord->setup(m_sysData, m_fcLink, m_pmLink);
// 快照构建器(链路就绪后创建)
m_snap = new SnapshotBuilder(m_sysData, m_fcLink, m_pmLink, m_db);
m_snap = new SnapshotBuilder(m_sysData, m_fcLink, m_pmLink, m_rcuLink, m_db);
// 网页
if (m_webEnable) {
@@ -128,10 +158,20 @@ bool CCU::OnStartUp() {
}
}
LOG_F(INFO, "pCCU started: fc_link local=%ld -> %s:%ld, pm_link local=%ld -> %s:%ld, "
"battery=BMS/CAN via pCanBridge(CAN_0x*)",
m_fcLocalPort, m_fcHost.c_str(), m_fcPort,
m_pmLocalPort, m_pmHost.c_str(), m_pmPort);
if (m_rcuLink) {
LOG_F(INFO, "pCCU started: fc_link local=%ld -> %s:%ld, pm_link local=%ld -> %s:%ld, "
"rcu_link local=%ld -> %s:%ld (配电桥接), "
"battery=BMS/CAN via pCanBridge(CAN_0x*)",
m_fcLocalPort, m_fcHost.c_str(), m_fcPort,
m_pmLocalPort, m_pmHost.c_str(), m_pmPort,
m_rcuLocalPort, m_rcuHost.c_str(), m_rcuPort);
} else {
LOG_F(INFO, "pCCU started: fc_link local=%ld -> %s:%ld, pm_link local=%ld -> %s:%ld, "
"rcu_link disabled, "
"battery=BMS/CAN via pCanBridge(CAN_0x*)",
m_fcLocalPort, m_fcHost.c_str(), m_fcPort,
m_pmLocalPort, m_pmHost.c_str(), m_pmPort);
}
return true;
}
@@ -155,6 +195,7 @@ void CCU::registerVariables() {
// 运行状态变量
Register("CCU_FC_LINK_STATE", 0);
Register("CCU_PM_LINK_STATE", 0);
Register("CCU_RCU_LINK_STATE", 0);
}
//---------------------------------------------------------
@@ -281,6 +322,8 @@ void CCU::handleFcMessage(Message* msg, const std::vector<uint8_t>& frame) {
void CCU::handlePmMessage(Message* msg, const std::vector<uint8_t>& frame) {
if (!msg) return;
// 配电指令已在入口由 DisBridge 处理(见 OnStartUp 的 onMessage 接线),
// 到达此处的均为 PM 协议消息(Sum32 校验)
switch (msg->id()) {
case 0x0001: { // PM 操控指令 -> 转发给 FC
PmControlValue c;
@@ -340,6 +383,19 @@ void CCU::handlePmMessage(Message* msg, const std::vector<uint8_t>& frame) {
}
}
//---------------------------------------------------------
// handleRcuMessage:处理真实 CCU 链路收到的消息(配电桥接)
//
// 配电反馈(0x0005~0x0008)与真实CCU状态报文(0x0004)由 DisBridge
// 处理(原帧转发 pPowerManger / 仅解码显示);其余(如配电指令
// 回显)仅记录,不转发。
void CCU::handleRcuMessage(Message* msg, const std::vector<uint8_t>& frame) {
if (!msg) return;
if (m_bridge && m_bridge->onRcuFrame(msg, frame)) return;
LOG_F(WARNING, "[RCU] unhandled msg id 0x%04X, len=%zu", msg->id(), frame.size());
}
//---------------------------------------------------------
// sendPmStatus:整合最新 FC 状态,编码 PM 状态报文发送
@@ -476,6 +532,19 @@ bool CCU::buildReport() {
<< " tx:" << m_pmLink->txCount()
<< " err:" << m_pmLink->errorCount() << "\n";
}
if (m_rcuLink) {
m_msgs << "RCU 链路 local:" << m_rcuLink->localPort()
<< " -> " << m_rcuLink->rcuHost() << ":" << m_rcuLink->rcuPort()
<< " rx:" << m_rcuLink->rxCount()
<< " tx:" << m_rcuLink->txCount()
<< " err:" << m_rcuLink->errorCount() << "\n";
if (m_sysData) {
const RealCcuState& st = m_sysData->realCcu();
m_msgs << "配电桥接: 反馈转发 " << st.fwdFbOk << " 成功 / " << st.fwdFbErr
<< " 失败, 指令转发 " << st.fwdCmdOk << " 成功 / " << st.fwdCmdErr
<< " 失败\n";
}
}
if (m_sysData) {
m_msgs << "锂电池: BMS/CAN (经 pCanBridge CAN_0x* 订阅)\n";
m_msgs << "CAN 帧接收计数:" << m_sysData->canFrameCount() << "\n";