Files
H100PowerManger/src/pCCU/comm/LinkManager.h
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

112 lines
3.9 KiB
C++

#ifndef PCCU_LINK_MANAGER_H
#define PCCU_LINK_MANAGER_H
#include <cstdint>
#include <string>
#include <atomic>
#include <thread>
#include <functional>
#include "UdpEndpoint.h"
#include "../protocol/MessageRegistry.h"
#include "../protocol/Message.h"
namespace ccu {
// 落库接口:由 DbStore 实现,供链路层记录原始帧(实现收发数据入库)
class ILinkLogSink {
public:
virtual ~ILinkLogSink() = default;
// direction: 0=收 1=发;data 为原始完整帧;checksumOk 为校验结果
virtual void onRawFrame(int direction, uint16_t msgId, const std::string& link,
const std::vector<uint8_t>& data, bool checksumOk) = 0;
};
//============================================================================
// LinkManager:单条 UDP 链路的管理者。
//
// 职责:
// - 绑定本地端口并维护独立接收线程
// - 持有该链路的 MessageRegistry(收发共用,id 按链路隔离)
// - 收帧:解析 id -> 查注册表 -> 校验 -> 回调 onMessage(携带消息对象与原始帧)
// - 发帧:编码 -> 发送 -> 落库
//
// 派生类(FcLinkManager / PmLinkManager)仅需提供链路名与默认收发地址。
//============================================================================
class LinkManager {
public:
LinkManager(const std::string& linkName, long localPort);
virtual ~LinkManager();
// 启动:绑定端口 + 启动接收线程。返回是否成功。
bool start();
void stop();
bool isRunning() const { return m_running; }
// 注册表(收发共用)
MessageRegistry& registry() { return m_registry; }
const MessageRegistry& registry() const { return m_registry; }
// 收帧回调:msg 为注册表中命中的消息对象(可调用 decode 解码),frame 为原始完整帧
void setOnMessage(std::function<void(Message* msg, const std::vector<uint8_t>& frame)> cb) {
m_onMessage = std::move(cb);
}
// 原始帧回调(用于 Web/调试展示原始报文)
void setOnRawFrame(std::function<void(int direction, const std::vector<uint8_t>& frame, bool checksumOk)> cb) {
m_onRawFrame = std::move(cb);
}
// 落库接口(可空)
void setLogSink(ILinkLogSink* sink) { m_logSink = sink; }
// 编码并发送一条已注册消息;返回是否成功
bool sendMessage(uint16_t id, const void* value);
// 编码并发送一条已注册消息,同时指定目标地址(覆盖默认)
bool sendMessageTo(uint16_t id, const void* value,
const std::string& host, long port);
// 处理一帧收到的原始数据(供接收线程调用,也可测试时手动喂入)
bool handleIncoming(const std::vector<uint8_t>& frame);
// 链路状态:最近一次收到消息的时间(MOOSTime),0 表示从未收到
double lastRxTime() const { return m_lastRxTime; }
long localPort() const { return m_localPort; }
const std::string& linkName() const { return m_linkName; }
// 收发统计
unsigned long rxCount() const { return m_rxCount; }
unsigned long txCount() const { return m_txCount; }
unsigned long errorCount() const { return m_errorCount; }
protected:
// 派生类提供发送默认目标
virtual std::string defaultRemoteHost() const { return ""; }
virtual long defaultRemotePort() const { return 0; }
private:
void rxThreadFunc();
std::string m_linkName;
long m_localPort;
UdpEndpoint m_endpoint;
MessageRegistry m_registry;
std::atomic<bool> m_running{false};
std::thread m_rxThread;
std::function<void(Message*, const std::vector<uint8_t>&)> m_onMessage;
std::function<void(int, const std::vector<uint8_t>&, bool)> m_onRawFrame;
ILinkLogSink* m_logSink = nullptr;
double m_lastRxTime = 0;
unsigned long m_rxCount = 0;
unsigned long m_txCount = 0;
unsigned long m_errorCount = 0;
};
} // namespace ccu
#endif // PCCU_LINK_MANAGER_H