Files
H100PowerManger/src/pCCU/protocol/PmProtocol.h
T
zjk 2590282aed
build-test-deploy / ci (push) Successful in 1h13m13s
0827协议修订:姿态数据2改预留 + 状态帧新增剩余发电量 + CCU地址可配置
FC协议(0827 docx):
- 控制指令域:字节12,13/16,17由纵倾/横倾姿态数据2改为预留(编码恒0、解码忽略)
- 状态反馈域:字节147,148由预留12改为剩余发电量(MWh),贯通JSON/网页显示
- PM→CCU链路:姿态字段4xuchar改为2xshort(数据1),结构体大小与线上布局不变
- 同步更新:CCU转发映射、SnapshotBuilder、pCCU网页、fuelcell网页、SQLite列描述、单测/模拟器
- 修正集成测试遗留断言(20B→24B、心跳d[19]→d[23])并增强预留字节校验

CCU地址可配置:
- pPowerManger 支持 moos 配置项 ccuhost/ccuport(默认127.0.0.1:7000)
- build-board.sh 增加 --ccu-host/--ccu-port 参数

文档:FC协议文档更新为0827版,清理过期协议docx
2026-08-28 00:09:17 +08:00

318 lines
17 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef PCCU_PM_PROTOCOL_H
#define PCCU_PM_PROTOCOL_H
#include <cstdint>
#include <vector>
#include "Message.h"
namespace ccu {
//============================================================================
// PM 协议(复合管控器 <-> 控制主机 pPowerManger)
// 依据:docs/控制主机与复合管控器通信协议 - 0824.xlsx
//
// 帧格式统一:0x40 0x40 + 域标识符(2B) + 域字节数(2B) + 数据域 + uint32 校验和
// 校验和为从域起始符到校验和之前所有数据的字节和。
//
// 四条消息(均带 uint32 校验和):
// 0x0001 操控指令域 (控制主机->复合管控器)payload 35B,总长 45B
// 0x0002 参数设定指令域 (控制主机->复合管控器)payload 18B,总长 28B
// 0x0003 参数设定反馈域 (复合管控器->控制主机)payload 2B,总长 12B
// 0x0004 状态报文域 (复合管控器->控制主机)payload 238B,总长 248B
//============================================================================
//--------------------------------------------------------------------------
// 0x0001 操控指令域
// payload 35 字节,对应文档字节 7~41
//--------------------------------------------------------------------------
struct PmControlValue {
// 系统时间
uint16_t year = 0;
uint8_t month = 0;
uint8_t day = 0;
uint8_t hour = 0;
uint8_t minute = 0;
uint8_t second = 0;
uint8_t millisecond10 = 0; // 10毫秒
// 指令
uint8_t mode = 0; // 模式设定 00~03
uint8_t cmd = 0; // 操控指令 00~0B
uint8_t outputPower = 0; // 输出功率指令 0~250,0.1kW
int16_t pitch = 0; // 纵倾姿态数据1 int16,分辨率0.1°(字节18,19)
int16_t roll = 0; // 横倾姿态数据1 int16,分辨率0.1°(字节20,21)
uint8_t emergencyAllow = 0; // 应急允许
uint16_t depth = 0; // 潜深深度 m
uint8_t supplyCmd = 0; // 补给/排放指令
uint8_t reservedCmd5 = 0; // 预留指令5
uint8_t reservedCmd6 = 0; // 预留指令6
uint8_t insBatCmd = 0; // 仪表锂电池启停指令 00/10/20
uint8_t dynBatCmd = 0; // 动力锂电池启停指令 00/10/20
uint16_t dynBatPower = 0; // 动力锂电池功率配置值 kW
uint8_t heartbeat = 0; // 通信心跳,每次+1
uint8_t hostState = 0; // 主机状态 运行AAH/关机FFH/故障其他
uint32_t reserved1 = 0; // 预留
uint32_t reserved2 = 0; // 预留
};
//--------------------------------------------------------------------------
// 0x0002 参数设定指令域
// payload 18 字节,对应文档字节 7~24
//--------------------------------------------------------------------------
struct PmParamSetValue {
uint8_t insSocHold1 = 0; // 仪表电池充电一级功率SOC门限
uint8_t insSocHold2 = 0; // 仪表电池充电二级功率SOC门限
uint8_t insSocHold3 = 0; // 仪表电池充电三级功率SOC门限
uint8_t insOutputPower = 0; // 仪表锂电池输出功率 %
uint8_t insReserved = 0; // 预留
uint8_t dynSocHold1 = 0; // 动力电池充电一级功率SOC门限
uint8_t dynSocHold2 = 0; // 动力电池充电二级功率SOC门限
uint8_t dynSocHold3 = 0; // 动力电池充电三级功率SOC门限
uint8_t dynOutputPower = 0; // 动力电池输出功率 %
uint8_t dynReserved = 0; // 预留
uint32_t reserved1 = 0; // 预留
uint32_t reserved2 = 0; // 预留
};
//--------------------------------------------------------------------------
// 0x0003 参数设定反馈域
// payload 2 字节,对应文档字节 7~8
//--------------------------------------------------------------------------
struct PmParamSetFbValue {
uint8_t flag = 0; // 设定标志:00H无效 / 10H成功 / 20H失败
uint8_t failCode = 0; // 设定失败原因
};
//--------------------------------------------------------------------------
// 0x0004 状态报文域
// payload 238 字节,对应文档字节 7~244
//--------------------------------------------------------------------------
struct PmStatusValue {
uint8_t fc_mode = 0; // 燃料电池系统运行模式
uint8_t fc_status = 0; // 燃料电池系统运行状态
uint16_t fault_level_1 = 0; // 一级故障码
uint16_t fault_level_2 = 0; // 二级故障码
uint16_t fault_level_3 = 0; // 三级故障码
uint16_t fault_level_4 = 0; // 四级故障码
uint16_t total_generation_time = 0; // 累积发电时间 0.1h
uint8_t fc_fault_level = 0; // 系统故障等级 00~04
uint16_t output_power_limit = 0; // 系统输出功率限定功率 W
uint16_t generation_power = 0; // 系统发电功率 0.01kW
uint8_t hydrogen_capacity = 0; // 储氢剩余容量 %
uint8_t liquid_oxygen_capacity = 0; // 液氧剩余容量 %
uint8_t fc1_min_cell_voltage = 0; // I#FC最低单片电压 10mV
uint8_t fc1_min_cell_pos = 0; // I#FC最低单片电压位置
uint8_t fc1_avg_cell_voltage = 0; // I#FC平均单片电压
uint8_t fc2_min_cell_voltage = 0; // 2#FC最低单片电压
uint8_t fc2_min_cell_pos = 0; // 2#FC最低单片电压位置
uint8_t fc2_avg_cell_voltage = 0; // 2#FC平均单片电压
uint16_t palladium_temp = 0; // 甲醇制氢装置钯膜最高温度 0.1℃
uint16_t buffer_tank_pressure = 0; // 缓冲罐压力 0.1kPa
uint16_t flue_total_emission = 0; // 烟气累计排放量 0.1kg
uint16_t flue_pressure = 0; // 烟气压力 0.001MPa
uint16_t reactor_pressure = 0; // 反应器压力 0.001MPa
uint16_t electric_valve_open = 0; // 电动阀开度 0.1%
uint16_t main_pipe_pressure = 0; // 主水路盘管侧压力 0.01kPa
uint16_t aux_pipe_pressure = 0; // 辅水路盘管侧压力 0.01kPa
uint16_t dcdc1_in_voltage = 0; // DC/DC通道1输入电压 0.1V
uint16_t dcdc1_in_current = 0; // DC/DC通道1输入电流 0.1A
uint16_t dcdc2_in_voltage = 0; // DC/DC通道2输入电压 0.1V
uint16_t dcdc2_in_current = 0; // DC/DC通道2输入电流 0.1A
uint16_t dcdc_out_voltage = 0; // DC/DC输出电压 0.1V
uint16_t dcdc_out_current = 0; // DC/DC输出电流 0.1A
uint8_t dcdc_ctrl_voltage = 0; // DC/DC控制电源电压 0.25V
uint8_t dcdc_aux_voltage = 0; // DC/DC辅电输出电压 0.125V
uint16_t methanol_total_use = 0; // 甲醇累计使用量 0.1kg
uint16_t methanol_feed = 0; // 甲醇溶液进料量 1mL/min
uint16_t oxygen_side_water_level = 0; // 氧侧生成水箱液位 0.01mm
uint16_t hydrogen_side_water_level = 0; // 氢侧生成水箱液位
uint16_t ballast_water_level = 0; // 配重水箱液位
uint16_t exhaust_inlet_pressure = 0; // 尾气装置进气压力 0.01MPa
uint16_t exhaust_outlet_pressure = 0; // 尾气装置排气压力 0.01MPa
uint16_t exhaust_run_freq = 0; // 尾气装置运行频率 0.01Hz
uint16_t exhaust_inlet_temp = 0; // 尾气装置进气温度 0.01℃
uint16_t exhaust_outlet_temp = 0; // 尾气装置排气温度 0.01℃
uint16_t exhaust_water_in_pressure = 0; // 尾气装置进水压力 0.01kPa
uint16_t exhaust_water_out_pressure = 0; // 尾气装置排水压力 0.01kPa
uint16_t tank_lo2_pressure = 0; // 一体化罐装置液氧罐压力 0.01MPa
uint16_t tank_co2_pressure = 0; // 一体化罐装置二氧化碳压力 0.01MPa
uint16_t tank_lo2_level = 0; // 一体化罐装置液氧罐液位 0.01mm
uint16_t alloy_h2_flow = 0; // 合金供氢流量 0.01L/min
uint16_t fc_h2_flow = 0; // FC供氢流量 0.01L/min
uint16_t fc_o2_flow = 0; // FC供氧流量 0.01L/min
uint16_t emergency_float_depth = 0; // 应急上浮深度 1m
uint16_t emergency_float_time = 0; // 应急上浮时间 1min
uint16_t cabin_pressure1 = 0; // 舱室压力1 0.01kPa
uint16_t cabin_pressure2 = 0; // 舱室压力2
uint16_t cabin_temp1 = 0; // 舱室温度1 0.01℃
uint16_t cabin_temp2 = 0; // 舱室温度2
uint16_t cabin_humidity1 = 0; // 舱室湿度1 0.01%RH
uint16_t cabin_humidity2 = 0; // 舱室湿度2
uint16_t h2_concentration1 = 0; // 舱室H2浓度1 0.01%LEL
uint16_t h2_concentration2 = 0; // 舱室H2浓度2
uint16_t h2_concentration3 = 0; // 舱室H2浓度3
uint16_t o2_concentration1 = 0; // 舱室O2浓度1 0.01%Vol
uint16_t o2_concentration2 = 0; // 舱室O2浓度2
uint16_t ch3oh_concentration1 = 0; // 舱室甲醇浓度1 0.01%LEL
uint16_t ch3oh_concentration2 = 0; // 舱室甲醇浓度2
uint8_t flame_detector1 = 0; // 火焰探测器1状态
uint8_t flame_detector2 = 0; // 火焰探测器2状态
uint16_t pmReserved1 = 0; // 预留
uint16_t pmReserved2 = 0; // 预留
uint16_t emergency_battery1_voltage = 0; // 应急电池1总电压
uint16_t emergency_battery1_current = 0; // 应急电池1总电流
uint16_t emergency_battery1_max_temp = 0; // 应急电池1最高温度
uint16_t emergency_battery1_fault_word = 0;// 应急电池1故障字
uint16_t emergency_battery2_voltage = 0; // 应急电池2总电压
uint16_t emergency_battery2_current = 0; // 应急电池2总电流
uint16_t emergency_battery2_max_temp = 0; // 应急电池2最高温度
uint16_t emergency_battery2_fault_word = 0;// 应急电池2故障字
uint16_t ins_cabin_ox_concentration = 0; // 仪表舱内氧气浓度 %
uint16_t ins_cabin_temperature = 0; // 仪表舱内温度 ℃
uint16_t ins_cabin_humidity = 0; // 仪表舱内湿度 %RH
uint16_t ins_cabin_pressure = 0; // 仪表舱内大气压 kPa
uint16_t dyn_cabin_ox_concentration = 0; // 动力舱内氧气浓度 %
uint16_t dyn_cabin_temperature = 0; // 动力舱内温度 ℃
uint16_t dyn_cabin_humidity = 0; // 动力舱内湿度 %RH
uint16_t dyn_cabin_pressure = 0; // 动力舱内大气压 kPa
uint8_t pmReserved3 = 0; // 预留
uint8_t dyn_alarm_flag[6] = {0}; // 动力锂电池报警标识字1~6
uint8_t ins_alarm_flag[6] = {0}; // 仪表锂电池报警标识字1~6
uint8_t ins_relay_status1 = 0; // 仪表电池正极+充电继电器状态
uint8_t ins_relay_status2 = 0; // 仪表电池预充+负极继电器状态
uint8_t dyn_relay_status1 = 0; // 动力电池正极+充电继电器状态
uint8_t dyn_relay_status2 = 0; // 动力电池预充+负极继电器状态
uint16_t ins_max_discharge_power = 0; // 仪表电池允许最高放电功率 0.05kW
uint16_t dyn_max_discharge_power = 0; // 动力电池允许最高放电功率 0.05kW
uint8_t ins_soc = 0; // 仪表锂电池SOC %
uint8_t dyn_soc = 0; // 动力锂电池SOC %
uint16_t ins_total_energy = 0; // 仪表锂电池总能量 0.1kWh
uint16_t dyn_total_energy = 0; // 动力锂电池总电量 0.1kWh
uint16_t ins_power_input = 0; // 仪表电池当前接入功率 kW
uint16_t dyn_power_input = 0; // 动力电池当前接入功率 kW
uint8_t ins_charge_status = 0; // 仪表电池充电状态
uint8_t dyn_charge_status = 0; // 动力电池充电状态
uint16_t ins_voltage_link = 0; // 仪表电池电压LINK端 0.01V
uint16_t ins_voltage_pack = 0; // 仪表电池电压PACK端 0.01V
uint16_t ins_current = 0; // 仪表电池放电电流 0.05A
uint16_t ins_resistance_pos = 0; // 仪表电池正端绝缘电阻 kΩ
uint16_t ins_resistance_neg = 0; // 仪表电池负端绝缘电阻 kΩ
uint16_t dyn_voltage_link = 0; // 动力电池电压LINK端 0.01V
uint16_t dyn_voltage_pack = 0; // 动力电池电压PACK端 0.01V
uint16_t dyn_current = 0; // 动力电池放电电流 0.05A
uint16_t dyn_resistance_pos = 0; // 动力电池正端绝缘电阻 kΩ
uint16_t dyn_resistance_neg = 0; // 动力电池负端绝缘电阻 kΩ
uint8_t ins_emergency_status = 0; // 仪表电池紧急状态
uint8_t dyn_emergency_status = 0; // 动力电池紧急状态
uint8_t ins_soc_threshold1 = 0; // 仪表电池充电一级功率SOC门限当前值
uint8_t ins_soc_threshold2 = 0; // 仪表电池充电二级
uint8_t ins_soc_threshold3 = 0; // 仪表电池充电三级
uint8_t ins_power_limit1 = 0; // 仪表通路FC输出功率一级限制当前值
uint8_t ins_power_limit2 = 0; // 仪表通路FC输出功率二级限制当前值
uint8_t dyn_soc_threshold1 = 0; // 动力电池充电一级功率SOC门限当前值
uint8_t dyn_soc_threshold2 = 0; // 动力电池充电二级
uint8_t dyn_soc_threshold3 = 0; // 动力电池充电三级
uint8_t dyn_power_limit1 = 0; // 动力通路FC输出功率一级限制当前值
uint8_t dyn_power_limit2 = 0; // 动力通路FC输出功率二级限制当前值
uint32_t device_online_flag1 = 0; // 设备在线状态标志字1
uint32_t device_online_flag2 = 0; // 设备在线状态标志字2
uint32_t pmReserved4 = 0; // 预留
uint8_t heartbeat = 0; // 通信心跳,每次+1
uint8_t emergency_cmd = 0; // 应急指令
};
//--------------------------------------------------------------------------
// 消息类
//--------------------------------------------------------------------------
class PmControlMessage : public Message {
public:
uint16_t id() const override { return 0x0001; }
const char* name() const override { return "pm_control"; }
const ChecksumPolicy& checksum() const override { return m_checksum; }
size_t payloadLength() const override { return 35; }
std::vector<uint8_t> encode(const void* obj) const override;
bool decode(const std::vector<uint8_t>& frame, void* obj) const override;
std::vector<uint8_t> encode(const PmControlValue& v) const { return encode(&v); }
bool decode(const std::vector<uint8_t>& frame, PmControlValue& v) const {
return decode(frame, static_cast<void*>(&v));
}
private:
ChecksumPolicy m_checksum{ChecksumType::Sum32};
};
class PmParamSetMessage : public Message {
public:
uint16_t id() const override { return 0x0002; }
const char* name() const override { return "pm_param_set"; }
const ChecksumPolicy& checksum() const override { return m_checksum; }
size_t payloadLength() const override { return 18; }
std::vector<uint8_t> encode(const void* obj) const override;
bool decode(const std::vector<uint8_t>& frame, void* obj) const override;
std::vector<uint8_t> encode(const PmParamSetValue& v) const { return encode(&v); }
bool decode(const std::vector<uint8_t>& frame, PmParamSetValue& v) const {
return decode(frame, static_cast<void*>(&v));
}
private:
ChecksumPolicy m_checksum{ChecksumType::Sum32};
};
class PmParamSetFbMessage : public Message {
public:
uint16_t id() const override { return 0x0003; }
const char* name() const override { return "pm_param_set_fb"; }
const ChecksumPolicy& checksum() const override { return m_checksum; }
size_t payloadLength() const override { return 2; }
std::vector<uint8_t> encode(const void* obj) const override;
bool decode(const std::vector<uint8_t>& frame, void* obj) const override;
std::vector<uint8_t> encode(const PmParamSetFbValue& v) const { return encode(&v); }
bool decode(const std::vector<uint8_t>& frame, PmParamSetFbValue& v) const {
return decode(frame, static_cast<void*>(&v));
}
private:
ChecksumPolicy m_checksum{ChecksumType::Sum32};
};
class PmStatusMessage : public Message {
public:
uint16_t id() const override { return 0x0004; }
const char* name() const override { return "pm_status"; }
const ChecksumPolicy& checksum() const override { return m_checksum; }
size_t payloadLength() const override { return 238; }
std::vector<uint8_t> encode(const void* obj) const override;
bool decode(const std::vector<uint8_t>& frame, void* obj) const override;
std::vector<uint8_t> encode(const PmStatusValue& v) const { return encode(&v); }
bool decode(const std::vector<uint8_t>& frame, PmStatusValue& v) const {
return decode(frame, static_cast<void*>(&v));
}
private:
ChecksumPolicy m_checksum{ChecksumType::Sum32};
};
// 注册 PM 消息到给定注册表
void registerPmMessages(class MessageRegistry& reg);
} // namespace ccu
#endif // PCCU_PM_PROTOCOL_H