Files
H100PowerManger/src/pCCU/comm/LinkManager.cpp
T
zjk 54c32a180a 新增复合管控器(pCCU) + 惯导数据解析 + 设备控制页增强 + 0824协议文档归档
- 新增 pCCU 复合管控器程序(src/pCCU):FC/PM 双链路(UDP)、协议编解码器
  (FcProtocol/PmProtocol/Frame/Message/MessageRegistry)、快照与落库(DbStore)、
  内置 WebServer;挂入 src/CMakeLists.txt 与板卡 mission(h100.moos)
- 惯导/深度数据:新增 uDevice_insData 消息解析,接入 UpperCommManager,
  pPowerMangerHost 注册监视,UpmsgTest 覆盖
- pPowerMangerHost 设备控制页增强(web/index.html)
- 部署/运维脚本改为 4 个 systemd 服务(moosdb/pPowerManger/pPowerMangerHost/pCCU):
  deploy/clean-data/fetch-data 同步适配
- 协议文档:归档 0824 控制主机与复合管控器通信协议 xlsx 及关联 docx,移除旧 md
- 测试:新增 pccu 单元/集成测试与 disSysTest Python 配电仿真
- 清理:移除未使用的 CCU 状态调试打印 coutMsg;.gitignore 补充编译产物/临时文件忽略
2026-08-26 22:43:10 +08:00

108 lines
3.2 KiB
C++

#include "LinkManager.h"
#include "../protocol/Frame.h"
#include "MOOS/libMOOS/Utils/MOOSUtilityFunctions.h"
#include "loguru.hpp"
namespace ccu {
LinkManager::LinkManager(const std::string& linkName, long localPort)
: m_linkName(linkName), m_localPort(localPort) {}
LinkManager::~LinkManager() {
stop();
}
bool LinkManager::start() {
if (m_running) return true;
if (!m_endpoint.init(m_localPort)) {
LOG_F(ERROR, "[%s] bind failed on port %ld", m_linkName.c_str(), m_localPort);
return false;
}
m_running = true;
m_rxThread = std::thread([this]() { rxThreadFunc(); });
LOG_F(INFO, "[%s] listening on local port %ld", m_linkName.c_str(), m_localPort);
return true;
}
void LinkManager::stop() {
if (!m_running) return;
m_running = false;
if (m_rxThread.joinable()) m_rxThread.join();
}
bool LinkManager::sendMessage(uint16_t id, const void* value) {
return sendMessageTo(id, value, defaultRemoteHost(), defaultRemotePort());
}
bool LinkManager::sendMessageTo(uint16_t id, const void* value,
const std::string& host, long port) {
if (host.empty() || port <= 0) return false;
Message* msg = m_registry.find(id);
if (!msg) {
LOG_F(ERROR, "[%s] unknown message id 0x%04X", m_linkName.c_str(), id);
return false;
}
std::vector<uint8_t> frame = msg->encode(value);
if (!m_endpoint.sendTo(host, port, frame)) {
LOG_F(ERROR, "[%s] send msg 0x%04X to %s:%ld failed",
m_linkName.c_str(), id, host.c_str(), port);
return false;
}
++m_txCount;
if (m_logSink) m_logSink->onRawFrame(1, id, m_linkName, frame, true);
if (m_onRawFrame) m_onRawFrame(1, frame, true);
return true;
}
bool LinkManager::handleIncoming(const std::vector<uint8_t>& frame) {
if (frame.size() < FRAME_HEADER_LEN) return false;
uint16_t id = 0;
if (!Frame::parseId(frame, id)) {
LOG_F(WARNING, "[%s] bad frame header", m_linkName.c_str());
++m_errorCount;
return false;
}
Message* msg = m_registry.find(id);
if (!msg) {
LOG_F(WARNING, "[%s] unknown msg id 0x%04X, len=%zu",
m_linkName.c_str(), id, frame.size());
++m_errorCount;
return false;
}
bool checksumOk = msg->checksum().verify(frame);
++m_rxCount;
m_lastRxTime = MOOSTime(false);
// 原始帧落库 + 回调
if (m_logSink) m_logSink->onRawFrame(0, id, m_linkName, frame, checksumOk);
if (m_onRawFrame) m_onRawFrame(0, frame, checksumOk);
if (!checksumOk) {
LOG_F(WARNING, "[%s] checksum error msg 0x%04X", m_linkName.c_str(), id);
++m_errorCount;
return false;
}
// 解码交给上层(CCU 层知道具体消息类型)
if (m_onMessage) m_onMessage(msg, frame);
return true;
}
void LinkManager::rxThreadFunc() {
uint8_t buf[2048];
while (m_running) {
int n = m_endpoint.receive(buf, sizeof(buf));
if (n > 0) {
std::vector<uint8_t> frame(buf, buf + n);
handleIncoming(frame);
} else {
// 无数据,短暂休眠避免忙等
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
}
} // namespace ccu