pCCU 锂电池页新增 BCU 断路器控制(0x10XX81FF 经 pCanBridge 下行 CAN 总线)

- CanBms: bcuCtrlCanId(0x10XX81FF) + buildBcuRelayCtrlData(02 00 总正 总负 FF*4)
- SystemData: BcuCtrlCmd 下行队列(Web线程入队->Iterate/MOOS线程出队Notify) + 下发统计
- CCU: /api/bcu_ctrl(addr/action 或 pos/neg, 校验地址01h~36h) + Iterate 经 MOOS CAN_TX_0x* 下发
- pCanBridge 变双向透传: 订阅 CAN_TX_0x*,CanEndpoint::sendFrame(13字节CANET帧,TCP写,互斥保护)
- 网页: 每BCU节点断路器闭合/断开按钮(confirm确认) + 下发统计卡片
- 测试: pccuTest 控制帧编码用例(183项);集成测试新增假CANET服务器验证完整下行链路(闭合/断开/非法地址)
This commit is contained in:
zjk
2026-09-01 15:23:30 +08:00
parent 0639b5904d
commit 90caacf9a2
15 changed files with 517 additions and 22 deletions
+52 -4
View File
@@ -90,25 +90,70 @@ bool CanBridge::OnConnectToServer() {
}
//---------------------------------------------------------
// registerVariables:纯发布应用,无需注册订阅变量
// registerVariables:订阅下行指令(CAN_TX_0x*,pCCU 发布的
// BCU 断路器控制帧等)。
void CanBridge::registerVariables() {
AppCastingMOOSApp::RegisterVariables();
// 通配订阅必须用三参数重载(变量模式 + 来源模式)
Register("CAN_TX_0x*", "*", 0);
}
//---------------------------------------------------------
// OnNewMail:当前无订阅指令,预留
// OnNewMail:下行指令 CAN_TX_0x%08X(二进制数据域)
bool CanBridge::OnNewMail(MOOSMSG_LIST &NewMail) {
AppCastingMOOSApp::OnNewMail(NewMail);
MOOSMSG_LIST::iterator p;
for (p = NewMail.begin(); p != NewMail.end(); p++) {
CMOOSMsg &msg = *p;
(void)msg;
if (msg.m_sKey.rfind("CAN_TX_0x", 0) == 0)
handleTxMessage(msg);
}
return true;
}
//---------------------------------------------------------
// handleTxMessage:MOOS 下行消息 -> CANET 13 字节帧 -> USBCAN
//
// m_sKey = "CAN_TX_0x%08X"(CAN ID)
// m_sVal = 二进制数据域(dlc<=8)
// 帧信息:id>0x7FF 视为扩展帧(bit7=1),DLC=数据字节数。
void CanBridge::handleTxMessage(CMOOSMsg& msg) {
if (!m_endpoint) return;
uint32_t id = 0;
// "CAN_TX_0x" 前缀长 9 字符(注意不是 8)
int sr = std::sscanf(msg.m_sKey.c_str() + 9, "%x", &id);
if (sr != 1) {
reportRunWarning("CAN_TX bad key: " + msg.m_sKey);
return;
}
if (!msg.IsBinary() || msg.GetBinaryDataSize() <= 0 ||
msg.GetBinaryDataSize() > 8) {
reportRunWarning("CAN_TX bad data size: " + msg.m_sKey);
return;
}
const unsigned char* d = msg.GetBinaryData();
if (!d) return;
int dlc = static_cast<int>(msg.GetBinaryDataSize());
uint8_t frameInfo = static_cast<uint8_t>(((id > 0x7FF) ? 0x80 : 0x00) | dlc);
if (m_endpoint->sendFrame(frameInfo, id, d, dlc)) {
++m_txCount;
char hex[32] = {0};
for (int i = 0; i < dlc && i < 8; ++i)
std::snprintf(hex + i * 2, 3, "%02X", d[i]);
std::cout << "[CAN-TX] 0x" << std::hex << id << std::dec
<< " dlc=" << dlc << " data=" << hex << std::endl;
} else {
reportRunWarning("CAN_TX send failed: " + msg.m_sKey +
(m_endpoint->isConnected() ? "" : " (未连接)"));
}
}
//---------------------------------------------------------
// Iterate:周期任务
@@ -146,7 +191,7 @@ void CanBridge::handleFrame(uint8_t frameInfo, uint32_t id,
bool CanBridge::buildReport() {
m_msgs << "============================================" << "\n";
m_msgs << "pCanBridge CAN->MOOSDB 透传" << "\n";
m_msgs << "pCanBridge CAN<->MOOSDB 双向透传" << "\n";
m_msgs << "============================================" << "\n";
if (m_endpoint) {
m_msgs << "目标: " << m_endpoint->host() << ":"
@@ -154,6 +199,9 @@ bool CanBridge::buildReport() {
m_msgs << "连接状态: " << (m_endpoint->isConnected() ? "已连接" : "断开") << "\n";
m_msgs << "收帧数: " << m_endpoint->frameCount() << "\n";
m_msgs << "发布数: " << m_notifyCount << "\n";
m_msgs << "下行帧数: " << m_endpoint->txCount() << " (错误 "
<< m_endpoint->txErrorCount() << ")" << "\n";
m_msgs << "MOOS下发数: " << m_txCount << "\n";
m_msgs << "错误数: " << m_endpoint->errorCount() << "\n";
m_msgs << "重连次数: " << m_endpoint->reconnectCount() << "\n";
m_msgs << "最近收帧: " << m_endpoint->lastFrameTime() << "\n";