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:
+76
-7
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user