- 新增 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 补充编译产物/临时文件忽略
112 lines
3.9 KiB
C++
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
|