pCCU新增锂电池通信/协调操作 + 电源协调状态机骨架(惰性)

锂电池通信(docs/锂电池协议20230324.docx):
- 协议层 BatProtocol:自检0x0000(2B)/设备控制0x0001(17B)/电池组状态0x0003(80B)/
  电池包报警0x0004(68B),uint32字节和校验、小端
- 链路层 BatLinkManager:动力/仪表锂电池独立UDP链路,本机监听与远端IP端口
  均由.moos配置(dyn_bat_*/ins_bat_*/bat_work_condition)
- SystemData/SnapshotBuilder/网页:电池数据按动力/仪表归类展示(运行状态/接触器
  电气量/电池包电压温度/报警),收发帧落库SQLite,网页新增电池标签页

操作->指令下发(PowerCoordinator):
- 操作接口:自检/上下电(母线接触器55H接通77H断开,含预充)/功率设定(0~500kW)/
  电池切换(低压->高压6步、高压->低压5步,按协议时序)
- 步骤引擎:每电池独立步骤队列,下发->状态反馈确认->超时兜底;周期1s心跳控制帧
- PM操控指令insBatCmd/dynBatCmd/dynBatPower自动映射为电池操作

电源协调状态机骨架(CoordFsm, TinyFSM):
- 事件Tick/PmControl/StepDone + 状态Normal/Switching/Fault,react均为TODO占位
- 当前未接线(无start/dispatch调用,运行行为与接入前一致),CoordFsm.hpp头部附接线指南

测试与部署:
- pccuTest新增电池协议编解码/帧长/链路分发用例(175项通过);集成测试覆盖电池
  心跳、启停映射(0x10->0x55/0x20->0x77)、状态落库;同步pccu_it.moos与ws_check
- h100.moos与pCCU.moos增加锂电池链路配置;归档锂电池协议文档
This commit is contained in:
zjk
2026-08-30 14:40:27 +08:00
parent 2590282aed
commit 7e4d08808a
25 changed files with 2691 additions and 23 deletions
+168
View File
@@ -0,0 +1,168 @@
#ifndef PCCU_COORD_FSM_HPP
#define PCCU_COORD_FSM_HPP
#include "../fsm/tinyfsm.hpp"
#include "../protocol/FcProtocol.h"
#include "../protocol/PmProtocol.h"
#include "../protocol/BatProtocol.h"
#include "PowerCoordinator.h"
namespace ccu {
class SystemData;
//============================================================================
// CoordFsm:pCCU 电源协调状态机骨架(TinyFSM,事件驱动)。
//
// 【当前状态:框架已参与编译,未接入运行流程(惰性)】
// - 无任何代码调用 CoordFsm::start() / CoordFsm::dispatch(),
// 运行行为与接入前完全一致;
// - 各状态 react() 均为 TODO 空实现,由开发者填写协调策略。
//
// 【设计约定】
// - 边沿事件走 dispatch:指令到达(PmControlEvent)、操作步骤完成(StepDoneEvent)、
// 周期节拍(TickEvent);
// - 电平状态不进事件:最新 FC/电池状态由状态机在 TickEvent 中直接读取
// SystemData 快照,避免 1Hz 状态报文淹没事件队列;
// - TinyFSM 非线程安全:dispatch 必须收敛到单线程(MOOS 主循环线程),
// 链路接收线程产生的事件一律经 PowerCoordinator::pushEvent() 排队,
// 由 tick() 在主线程统一 drain 后逐个 dispatch(见接线指南第 1 步)。
//
// 【接线指南:将来启用时按以下步骤操作】
//
// 1) PowerCoordinator 增加事件桥(core/PowerCoordinator.h/.cpp):
// a. 新增成员:
// std::function<void(double)> m_tickHook = nullptr; // 节拍转发
// std::mutex m_evtMutex;
// std::deque<std::function<void()>> m_events; // 事件队列(闭包)
// 新增方法:
// void setTickHook(std::function<void(double)> h) { m_tickHook = std::move(h); }
// void pushEvent(std::function<void()> fn) { // 线程安全;带上限防积压
// std::lock_guard<std::mutex> l(m_evtMutex);
// if (m_events.size() >= 512) { m_events.pop_front(); /*LOG告警*/ }
// m_events.push_back(std::move(fn));
// }
// b. tick() 末尾 drain(单线程执行闭包;coordinationTick 占位改为转发):
// if (m_tickHook) m_tickHook(now);
// std::deque<std::function<void()>> evs;
// { std::lock_guard<std::mutex> l(m_evtMutex); evs.swap(m_events); }
// for (auto& f : evs) f();
// c. processSteps 步骤完成/超时处(pop_front 之前,仅接线后产生事件):
// if (m_tickHook) {
// BatOpStep info = s; // 拷贝步骤信息
// BatStatusValue st = m_sys ? m_sys->batStatus(static_cast<int>(s.role))
// : BatStatusValue();
// bool ok = confirmed;
// pushEvent([info, st, ok]() {
// CoordFsm::dispatch(StepDoneEvent(info.role, info.type, ok, st));
// });
// }
// (事件产生以 m_tickHook 非空为前提:未接线时零开销、零行为)
//
// 2) CCU::OnStartUp(m_coord->setup(...) 之后):
// CoordFsm::init(m_coord, m_sysData);
// CoordFsm::start();
// m_coord->setTickHook([](double now) {
// CoordFsm::dispatch(TickEvent(now));
// });
//
// 3) CCU::handlePmMessage 的 0x0001 分支(decode 成功后):
// m_coord->pushEvent([c]() { CoordFsm::dispatch(PmControlEvent(c)); });
// (c 为已解析的 PmControlValue,按值捕获)
//
// 4) 验证:编译运行后日志出现 "[CoordFsm] 进入状态: CoordNormalState" 即接线成功。
//
// 【状态说明】
// CoordNormalState 正常运行(初始状态):周期功率分配/阈值判断、响应主机指令
// CoordSwitchingState 电池切换中:等待 StepDoneEvent 推进,完成后返回 Normal
// CoordFaultState 故障处理:告警抑制/降级运行/恢复判断
//============================================================================
//---- 事件定义(边沿触发) ------------------------------------------------
// 周期节拍:由 coordinationTick 转发(AppTick 频率,默认 4Hz)
struct TickEvent : tinyfsm::Event {
double now; // MOOSTime
TickEvent() : now(0) {}
explicit TickEvent(double t) : now(t) {}
};
// 主机操控指令到达:PM 0x0001 每次成功解析触发一次
struct PmControlEvent : tinyfsm::Event {
PmControlValue cmd;
PmControlEvent() {}
explicit PmControlEvent(const PmControlValue& c) : cmd(c) {}
};
// 电池操作步骤完成/超时:由协调器步骤引擎产生
struct StepDoneEvent : tinyfsm::Event {
BatRole role; // 目标电池
BatOpType type; // 步骤类型
bool confirmed; // true=状态反馈确认;false=超时未确认
BatStatusValue status; // 完成时刻状态快照(含接触器状态/报警标识字,可判 0x33/0x44 等故障)
StepDoneEvent()
: role(BatRole::Dyn), type(BatOpType::ApplyControl), confirmed(false) {}
StepDoneEvent(BatRole r, BatOpType t, bool ok, const BatStatusValue& s)
: role(r), type(t), confirmed(ok), status(s) {}
};
//---- 状态机 ---------------------------------------------------------------
class CoordFsm : public tinyfsm::Fsm<CoordFsm> {
public:
// 启用时注入上下文(见接线指南)
static void init(PowerCoordinator* coord, SystemData* sys) {
m_coord = coord;
m_sys = sys;
}
static PowerCoordinator* coord() { return m_coord; }
static SystemData* sys() { return m_sys; }
// 事件处理默认实现:状态类按需覆盖;未覆盖的事件静默忽略
virtual void react(tinyfsm::Event const &) {}
virtual void react(TickEvent const &) {}
virtual void react(PmControlEvent const &) {}
virtual void react(StepDoneEvent const &) {}
// 状态进入/退出钩子(状态类覆盖以打日志/做进出动作)
virtual void entry() {}
virtual void exit() {}
private:
static PowerCoordinator* m_coord;
static SystemData* m_sys;
};
//---- 状态类 ---------------------------------------------------------------
// 正常运行(初始状态)
class CoordNormalState : public CoordFsm {
public:
void entry() override;
void exit() override;
void react(TickEvent const &e) override;
void react(PmControlEvent const &e) override;
void react(StepDoneEvent const &e) override;
};
// 电池切换中(提交 submitSwitchLowToHigh/HighToLow 后进入)
class CoordSwitchingState : public CoordFsm {
public:
void entry() override;
void exit() override;
void react(TickEvent const &e) override;
void react(StepDoneEvent const &e) override;
};
// 故障处理
class CoordFaultState : public CoordFsm {
public:
void entry() override;
void exit() override;
void react(TickEvent const &e) override;
void react(StepDoneEvent const &e) override;
};
} // namespace ccu
#endif // PCCU_COORD_FSM_HPP