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:
@@ -0,0 +1,446 @@
|
||||
#include "BatProtocol.h"
|
||||
#include "FieldCodec.h"
|
||||
#include "Frame.h"
|
||||
#include "MessageRegistry.h"
|
||||
|
||||
namespace ccu {
|
||||
|
||||
void registerBatMessages(MessageRegistry& reg) {
|
||||
reg.registerMessage(std::unique_ptr<Message>(new BatSelfCheckMessage()));
|
||||
reg.registerMessage(std::unique_ptr<Message>(new BatControlMessage()));
|
||||
reg.registerMessage(std::unique_ptr<Message>(new BatStatusMessage()));
|
||||
reg.registerMessage(std::unique_ptr<Message>(new BatPackAlarmMessage()));
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// 0x0000 自检指令
|
||||
// 数据域 2 字节,偏移 0~1
|
||||
//============================================================================
|
||||
|
||||
namespace {
|
||||
enum : size_t {
|
||||
BO_SELFCHECK = 0, // 电池自检 00/01
|
||||
BO_SELFCHECK_RST = 1, // 自检复位指令 00/55
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> BatSelfCheckMessage::encode(const void* obj) const {
|
||||
const BatSelfCheckValue* v = static_cast<const BatSelfCheckValue*>(obj);
|
||||
std::vector<uint8_t> p(payloadLength(), 0);
|
||||
FieldCodec::putU8(p, BO_SELFCHECK, v->selfCheck);
|
||||
FieldCodec::putU8(p, BO_SELFCHECK_RST, v->selfCheckReset);
|
||||
return Frame::build(id(), p, checksum());
|
||||
}
|
||||
|
||||
bool BatSelfCheckMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
|
||||
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
|
||||
BatSelfCheckValue* v = static_cast<BatSelfCheckValue*>(obj);
|
||||
size_t o = FRAME_HEADER_LEN;
|
||||
v->selfCheck = FieldCodec::getU8(frame, o + BO_SELFCHECK);
|
||||
v->selfCheckReset = FieldCodec::getU8(frame, o + BO_SELFCHECK_RST);
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// 0x0001 设备控制指令
|
||||
// 数据域 17 字节,偏移 0~16
|
||||
//============================================================================
|
||||
|
||||
namespace {
|
||||
enum : size_t {
|
||||
BC_YEAR = 0, // u16
|
||||
BC_MONTH = 2,
|
||||
BC_DAY = 3,
|
||||
BC_HOUR = 4,
|
||||
BC_MINUTE = 5,
|
||||
BC_SECOND = 6,
|
||||
BC_MS10 = 7,
|
||||
BC_WORKCOND = 8, // 工况设定
|
||||
BC_BUS_CTR = 9, // 母线接触器
|
||||
BC_POS_CTR = 10, // 正极接触器
|
||||
BC_DIODE_CTR = 11, // 二极管路接触器
|
||||
BC_POWER = 12, // u16 电池组功率 kW
|
||||
BC_RESV = 14, // u16 预留
|
||||
BC_HEARTBEAT = 16, // 通信心跳
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> BatControlMessage::encode(const void* obj) const {
|
||||
const BatControlValue* v = static_cast<const BatControlValue*>(obj);
|
||||
std::vector<uint8_t> p(payloadLength(), 0);
|
||||
|
||||
FieldCodec::putU16(p, BC_YEAR, v->year);
|
||||
FieldCodec::putU8(p, BC_MONTH, v->month);
|
||||
FieldCodec::putU8(p, BC_DAY, v->day);
|
||||
FieldCodec::putU8(p, BC_HOUR, v->hour);
|
||||
FieldCodec::putU8(p, BC_MINUTE, v->minute);
|
||||
FieldCodec::putU8(p, BC_SECOND, v->second);
|
||||
FieldCodec::putU8(p, BC_MS10, v->ms10);
|
||||
FieldCodec::putU8(p, BC_WORKCOND, v->workCondition);
|
||||
FieldCodec::putU8(p, BC_BUS_CTR, v->busContactor);
|
||||
FieldCodec::putU8(p, BC_POS_CTR, v->posContactor);
|
||||
FieldCodec::putU8(p, BC_DIODE_CTR, v->diodeContactor);
|
||||
FieldCodec::putU16(p, BC_POWER, v->powerKw);
|
||||
FieldCodec::putU16(p, BC_RESV, v->reserved);
|
||||
FieldCodec::putU8(p, BC_HEARTBEAT, v->heartbeat);
|
||||
|
||||
return Frame::build(id(), p, checksum());
|
||||
}
|
||||
|
||||
bool BatControlMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
|
||||
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
|
||||
BatControlValue* v = static_cast<BatControlValue*>(obj);
|
||||
size_t o = FRAME_HEADER_LEN;
|
||||
|
||||
v->year = FieldCodec::getU16(frame, o + BC_YEAR);
|
||||
v->month = FieldCodec::getU8(frame, o + BC_MONTH);
|
||||
v->day = FieldCodec::getU8(frame, o + BC_DAY);
|
||||
v->hour = FieldCodec::getU8(frame, o + BC_HOUR);
|
||||
v->minute = FieldCodec::getU8(frame, o + BC_MINUTE);
|
||||
v->second = FieldCodec::getU8(frame, o + BC_SECOND);
|
||||
v->ms10 = FieldCodec::getU8(frame, o + BC_MS10);
|
||||
v->workCondition = FieldCodec::getU8(frame, o + BC_WORKCOND);
|
||||
v->busContactor = FieldCodec::getU8(frame, o + BC_BUS_CTR);
|
||||
v->posContactor = FieldCodec::getU8(frame, o + BC_POS_CTR);
|
||||
v->diodeContactor= FieldCodec::getU8(frame, o + BC_DIODE_CTR);
|
||||
v->powerKw = FieldCodec::getU16(frame, o + BC_POWER);
|
||||
v->reserved = FieldCodec::getU16(frame, o + BC_RESV);
|
||||
v->heartbeat = FieldCodec::getU8(frame, o + BC_HEARTBEAT);
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// 0x0003 状态反馈——电池组状态
|
||||
// 数据域 80 字节,偏移 0~79
|
||||
//============================================================================
|
||||
|
||||
namespace {
|
||||
enum : size_t {
|
||||
BS_YEAR = 0, // u16
|
||||
BS_MONTH = 2,
|
||||
BS_DAY = 3,
|
||||
BS_HOUR = 4,
|
||||
BS_MINUTE = 5,
|
||||
BS_SECOND = 6,
|
||||
BS_MS10 = 7,
|
||||
BS_WORKCOND = 8, // 工况
|
||||
BS_SELFCHECK = 9, // 电池自检状态
|
||||
BS_POWERCFG = 10, // 电池功率配置状态
|
||||
BS_BUS_CTR = 11, // 电池母线接触器状态
|
||||
BS_POS_DIODE = 12, // 正极接触器与二极管回路状态
|
||||
BS_EMERGENCY = 13, // 电池紧急状态
|
||||
BS_SOC = 14, // u16 0.1%
|
||||
BS_ENERGY = 16, // u16 0.1kWh
|
||||
BS_MAX_DIS_PWR = 18, // u16 0.1kW 允许最高放电功率
|
||||
BS_MAX_CHG_PWR = 20, // u16 0.1kW 允许充电功率
|
||||
BS_CUR_ACC_PWR = 22, // u16 0.1kW 当前接入功率
|
||||
BS_ONLINE = 24, // u32 电池包在线信息
|
||||
BS_ACCESS = 28, // u32 电池包接入信息
|
||||
BS_RELAY_POS = 32, // 总控正极+充电继电器
|
||||
BS_RELAY_PRE = 33, // 总控预充+负极继电器
|
||||
BS_RELAY_OUT2 = 34, // 第二路输出+预充
|
||||
BS_RELAY_CHG = 35, // 在线充电+预充
|
||||
BS_V_LOAD = 36, // u16 0.01V
|
||||
BS_V_PACK = 38, // u16 0.01V
|
||||
BS_CURRENT = 40, // s16 0.05A
|
||||
BS_INS_POS = 42, // u16 10kΩ
|
||||
BS_INS_NEG = 44, // u16 10kΩ
|
||||
BS_M_TEMP1 = 46, // u8 总控温度1(文档标注删除,保留偏移)
|
||||
BS_M_TEMP2 = 47, // u8 总控温度2(文档标注删除,保留偏移)
|
||||
BS_PK_V_MID = 48, // u16 0.1V
|
||||
BS_PK_V_MIN = 50, // u16 0.1V
|
||||
BS_PK_V_MIN_NO = 52,
|
||||
BS_PK_V_MAX = 53, // u16 0.1V
|
||||
BS_PK_V_MAX_NO = 55,
|
||||
BS_PK_DELTA = 56, // u16 0.1mV
|
||||
BS_PK_DELTA_NO = 58,
|
||||
BS_PK_DELTA_V = 59, // u16 0.1mV
|
||||
BS_T_AVG = 61, // u8 -40℃
|
||||
BS_T_MIN = 62, // u8 -40℃
|
||||
BS_T_MIN_NO = 63,
|
||||
BS_T_MAX = 64, // u8 -40℃
|
||||
BS_T_MAX_NO = 65,
|
||||
BS_ALARM1 = 66, // u8 * 6 报警标识字1~6
|
||||
BS_ALARM_POS = 72, // u32 报警位置标识字
|
||||
BS_CHARGE_ST = 76, // u8 充放电状态
|
||||
BS_RESV = 77, // u16
|
||||
BS_HEARTBEAT = 79,
|
||||
};
|
||||
inline void getU8Arr(const std::vector<uint8_t>& f, size_t off, uint8_t* dst, size_t n) {
|
||||
for (size_t i = 0; i < n; ++i) dst[i] = f[off + i];
|
||||
}
|
||||
inline void putU8Arr(std::vector<uint8_t>& p, size_t off, const uint8_t* src, size_t n) {
|
||||
for (size_t i = 0; i < n; ++i) p[off + i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> BatStatusMessage::encode(const void* obj) const {
|
||||
const BatStatusValue* v = static_cast<const BatStatusValue*>(obj);
|
||||
std::vector<uint8_t> p(payloadLength(), 0);
|
||||
|
||||
FieldCodec::putU16(p, BS_YEAR, v->year);
|
||||
FieldCodec::putU8(p, BS_MONTH, v->month);
|
||||
FieldCodec::putU8(p, BS_DAY, v->day);
|
||||
FieldCodec::putU8(p, BS_HOUR, v->hour);
|
||||
FieldCodec::putU8(p, BS_MINUTE, v->minute);
|
||||
FieldCodec::putU8(p, BS_SECOND, v->second);
|
||||
FieldCodec::putU8(p, BS_MS10, v->ms10);
|
||||
FieldCodec::putU8(p, BS_WORKCOND, v->workCondition);
|
||||
FieldCodec::putU8(p, BS_SELFCHECK, v->selfCheckState);
|
||||
FieldCodec::putU8(p, BS_POWERCFG, v->powerCfgState);
|
||||
FieldCodec::putU8(p, BS_BUS_CTR, v->busContactorState);
|
||||
FieldCodec::putU8(p, BS_POS_DIODE, v->posDiodeState);
|
||||
FieldCodec::putU8(p, BS_EMERGENCY, v->emergencyState);
|
||||
FieldCodec::putU16(p, BS_SOC, v->soc);
|
||||
FieldCodec::putU16(p, BS_ENERGY, v->energy);
|
||||
FieldCodec::putU16(p, BS_MAX_DIS_PWR, v->maxDischargePower);
|
||||
FieldCodec::putU16(p, BS_MAX_CHG_PWR, v->maxChargePower);
|
||||
FieldCodec::putU16(p, BS_CUR_ACC_PWR, v->currentAccessPower);
|
||||
FieldCodec::putU32(p, BS_ONLINE, v->packOnlineFlag);
|
||||
FieldCodec::putU32(p, BS_ACCESS, v->packAccessFlag);
|
||||
FieldCodec::putU8(p, BS_RELAY_POS, v->relayPosCharge);
|
||||
FieldCodec::putU8(p, BS_RELAY_PRE, v->relayPreNeg);
|
||||
FieldCodec::putU8(p, BS_RELAY_OUT2, v->relayOut2Pre);
|
||||
FieldCodec::putU8(p, BS_RELAY_CHG, v->relayChgOnlinePre);
|
||||
FieldCodec::putU16(p, BS_V_LOAD, v->voltageLoad);
|
||||
FieldCodec::putU16(p, BS_V_PACK, v->voltagePack);
|
||||
FieldCodec::putU16(p, BS_CURRENT, static_cast<uint16_t>(v->current));
|
||||
FieldCodec::putU16(p, BS_INS_POS, v->insulationPos);
|
||||
FieldCodec::putU16(p, BS_INS_NEG, v->insulationNeg);
|
||||
FieldCodec::putU8(p, BS_M_TEMP1, v->masterTemp1);
|
||||
FieldCodec::putU8(p, BS_M_TEMP2, v->masterTemp2);
|
||||
FieldCodec::putU16(p, BS_PK_V_MID, v->packVoltageMid);
|
||||
FieldCodec::putU16(p, BS_PK_V_MIN, v->packVoltageMin);
|
||||
FieldCodec::putU8(p, BS_PK_V_MIN_NO, v->packVoltageMinNo);
|
||||
FieldCodec::putU16(p, BS_PK_V_MAX, v->packVoltageMax);
|
||||
FieldCodec::putU8(p, BS_PK_V_MAX_NO, v->packVoltageMaxNo);
|
||||
FieldCodec::putU16(p, BS_PK_DELTA, v->packDeltaMax);
|
||||
FieldCodec::putU8(p, BS_PK_DELTA_NO, v->packDeltaMaxNo);
|
||||
FieldCodec::putU16(p, BS_PK_DELTA_V, v->packDeltaMaxVoltage);
|
||||
FieldCodec::putU8(p, BS_T_AVG, v->cellTempAvg);
|
||||
FieldCodec::putU8(p, BS_T_MIN, v->cellTempMin);
|
||||
FieldCodec::putU8(p, BS_T_MIN_NO, v->cellTempMinNo);
|
||||
FieldCodec::putU8(p, BS_T_MAX, v->cellTempMax);
|
||||
FieldCodec::putU8(p, BS_T_MAX_NO, v->cellTempMaxNo);
|
||||
putU8Arr(p, BS_ALARM1, v->alarmFlag, 6);
|
||||
FieldCodec::putU32(p, BS_ALARM_POS, v->alarmPosFlag);
|
||||
FieldCodec::putU8(p, BS_CHARGE_ST, v->chargeStatus);
|
||||
FieldCodec::putU16(p, BS_RESV, v->reserved);
|
||||
FieldCodec::putU8(p, BS_HEARTBEAT, v->heartbeat);
|
||||
|
||||
return Frame::build(id(), p, checksum());
|
||||
}
|
||||
|
||||
bool BatStatusMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
|
||||
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
|
||||
BatStatusValue* v = static_cast<BatStatusValue*>(obj);
|
||||
size_t o = FRAME_HEADER_LEN;
|
||||
|
||||
v->year = FieldCodec::getU16(frame, o + BS_YEAR);
|
||||
v->month = FieldCodec::getU8(frame, o + BS_MONTH);
|
||||
v->day = FieldCodec::getU8(frame, o + BS_DAY);
|
||||
v->hour = FieldCodec::getU8(frame, o + BS_HOUR);
|
||||
v->minute = FieldCodec::getU8(frame, o + BS_MINUTE);
|
||||
v->second = FieldCodec::getU8(frame, o + BS_SECOND);
|
||||
v->ms10 = FieldCodec::getU8(frame, o + BS_MS10);
|
||||
v->workCondition = FieldCodec::getU8(frame, o + BS_WORKCOND);
|
||||
v->selfCheckState = FieldCodec::getU8(frame, o + BS_SELFCHECK);
|
||||
v->powerCfgState = FieldCodec::getU8(frame, o + BS_POWERCFG);
|
||||
v->busContactorState = FieldCodec::getU8(frame, o + BS_BUS_CTR);
|
||||
v->posDiodeState = FieldCodec::getU8(frame, o + BS_POS_DIODE);
|
||||
v->emergencyState = FieldCodec::getU8(frame, o + BS_EMERGENCY);
|
||||
v->soc = FieldCodec::getU16(frame, o + BS_SOC);
|
||||
v->energy = FieldCodec::getU16(frame, o + BS_ENERGY);
|
||||
v->maxDischargePower = FieldCodec::getU16(frame, o + BS_MAX_DIS_PWR);
|
||||
v->maxChargePower = FieldCodec::getU16(frame, o + BS_MAX_CHG_PWR);
|
||||
v->currentAccessPower = FieldCodec::getU16(frame, o + BS_CUR_ACC_PWR);
|
||||
v->packOnlineFlag = FieldCodec::getU32(frame, o + BS_ONLINE);
|
||||
v->packAccessFlag = FieldCodec::getU32(frame, o + BS_ACCESS);
|
||||
v->relayPosCharge = FieldCodec::getU8(frame, o + BS_RELAY_POS);
|
||||
v->relayPreNeg = FieldCodec::getU8(frame, o + BS_RELAY_PRE);
|
||||
v->relayOut2Pre = FieldCodec::getU8(frame, o + BS_RELAY_OUT2);
|
||||
v->relayChgOnlinePre = FieldCodec::getU8(frame, o + BS_RELAY_CHG);
|
||||
v->voltageLoad = FieldCodec::getU16(frame, o + BS_V_LOAD);
|
||||
v->voltagePack = FieldCodec::getU16(frame, o + BS_V_PACK);
|
||||
v->current = static_cast<int16_t>(FieldCodec::getU16(frame, o + BS_CURRENT));
|
||||
v->insulationPos = FieldCodec::getU16(frame, o + BS_INS_POS);
|
||||
v->insulationNeg = FieldCodec::getU16(frame, o + BS_INS_NEG);
|
||||
v->masterTemp1 = FieldCodec::getU8(frame, o + BS_M_TEMP1);
|
||||
v->masterTemp2 = FieldCodec::getU8(frame, o + BS_M_TEMP2);
|
||||
v->packVoltageMid = FieldCodec::getU16(frame, o + BS_PK_V_MID);
|
||||
v->packVoltageMin = FieldCodec::getU16(frame, o + BS_PK_V_MIN);
|
||||
v->packVoltageMinNo = FieldCodec::getU8(frame, o + BS_PK_V_MIN_NO);
|
||||
v->packVoltageMax = FieldCodec::getU16(frame, o + BS_PK_V_MAX);
|
||||
v->packVoltageMaxNo = FieldCodec::getU8(frame, o + BS_PK_V_MAX_NO);
|
||||
v->packDeltaMax = FieldCodec::getU16(frame, o + BS_PK_DELTA);
|
||||
v->packDeltaMaxNo = FieldCodec::getU8(frame, o + BS_PK_DELTA_NO);
|
||||
v->packDeltaMaxVoltage= FieldCodec::getU16(frame, o + BS_PK_DELTA_V);
|
||||
v->cellTempAvg = FieldCodec::getU8(frame, o + BS_T_AVG);
|
||||
v->cellTempMin = FieldCodec::getU8(frame, o + BS_T_MIN);
|
||||
v->cellTempMinNo = FieldCodec::getU8(frame, o + BS_T_MIN_NO);
|
||||
v->cellTempMax = FieldCodec::getU8(frame, o + BS_T_MAX);
|
||||
v->cellTempMaxNo = FieldCodec::getU8(frame, o + BS_T_MAX_NO);
|
||||
getU8Arr(frame, o + BS_ALARM1, v->alarmFlag, 6);
|
||||
v->alarmPosFlag = FieldCodec::getU32(frame, o + BS_ALARM_POS);
|
||||
v->chargeStatus = FieldCodec::getU8(frame, o + BS_CHARGE_ST);
|
||||
v->reserved = FieldCodec::getU16(frame, o + BS_RESV);
|
||||
v->heartbeat = FieldCodec::getU8(frame, o + BS_HEARTBEAT);
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// 0x0004 状态反馈——电池包报警信息
|
||||
// 数据域 68 字节,偏移 0~67
|
||||
//============================================================================
|
||||
|
||||
namespace {
|
||||
enum : size_t {
|
||||
BA_YEAR = 0, // u16
|
||||
BA_MONTH = 2,
|
||||
BA_DAY = 3,
|
||||
BA_HOUR = 4,
|
||||
BA_MINUTE = 5,
|
||||
BA_SECOND = 6,
|
||||
BA_MS10 = 7,
|
||||
BA_PACKNO = 8, // 电池包号 1~24
|
||||
BA_ALARM1 = 9, // u8 * 6 报警标识字1~6
|
||||
BA_SOC = 15, // u16 0.1%
|
||||
BA_RELAY = 17, // 正极+负极继电器状态
|
||||
BA_V_LOAD = 18, // u16 0.1V
|
||||
BA_V_PACK = 20, // u16 0.1V
|
||||
BA_CURRENT = 22, // s16 0.05A
|
||||
BA_INS_POS = 24, // u16 10kΩ
|
||||
BA_INS_NEG = 26, // u16 10kΩ
|
||||
BA_T_MAX_NO = 28,
|
||||
BA_T_MAX1 = 29, // u8 -40℃
|
||||
BA_T_MAX2 = 30,
|
||||
BA_T_MAX3 = 31,
|
||||
BA_T_MAX4 = 32,
|
||||
BA_T_MIN4 = 33,
|
||||
BA_T_MIN3 = 34,
|
||||
BA_T_MIN2 = 35,
|
||||
BA_T_MIN1 = 36, // u8 -40℃
|
||||
BA_T_MIN_NO = 37,
|
||||
BA_T_AVG = 38, // u8 -40℃
|
||||
BA_BALANCE = 39, // 均衡状态 0/1
|
||||
BA_V_MAX_NO = 40,
|
||||
BA_V_MAX1 = 41, // u16 0.1mV
|
||||
BA_V_MAX2 = 43,
|
||||
BA_V_MAX3 = 45,
|
||||
BA_V_MAX4 = 47,
|
||||
BA_V_MAX5 = 49,
|
||||
BA_V_MAX6 = 51,
|
||||
BA_V_MIN6 = 53,
|
||||
BA_V_MIN5 = 55,
|
||||
BA_V_MIN4 = 57,
|
||||
BA_V_MIN3 = 59,
|
||||
BA_V_MIN2 = 61,
|
||||
BA_V_MIN1 = 63, // u16 0.1mV
|
||||
BA_V_MIN_NO = 65,
|
||||
BA_V_AVG = 66, // u16
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> BatPackAlarmMessage::encode(const void* obj) const {
|
||||
const BatPackAlarmValue* v = static_cast<const BatPackAlarmValue*>(obj);
|
||||
std::vector<uint8_t> p(payloadLength(), 0);
|
||||
|
||||
FieldCodec::putU16(p, BA_YEAR, v->year);
|
||||
FieldCodec::putU8(p, BA_MONTH, v->month);
|
||||
FieldCodec::putU8(p, BA_DAY, v->day);
|
||||
FieldCodec::putU8(p, BA_HOUR, v->hour);
|
||||
FieldCodec::putU8(p, BA_MINUTE, v->minute);
|
||||
FieldCodec::putU8(p, BA_SECOND, v->second);
|
||||
FieldCodec::putU8(p, BA_MS10, v->ms10);
|
||||
FieldCodec::putU8(p, BA_PACKNO, v->packNo);
|
||||
putU8Arr(p, BA_ALARM1, v->alarmFlag, 6);
|
||||
FieldCodec::putU16(p, BA_SOC, v->soc);
|
||||
FieldCodec::putU8(p, BA_RELAY, v->relayPosNeg);
|
||||
FieldCodec::putU16(p, BA_V_LOAD, v->voltageLoad);
|
||||
FieldCodec::putU16(p, BA_V_PACK, v->voltagePack);
|
||||
FieldCodec::putU16(p, BA_CURRENT, static_cast<uint16_t>(v->current));
|
||||
FieldCodec::putU16(p, BA_INS_POS, v->insulationPos);
|
||||
FieldCodec::putU16(p, BA_INS_NEG, v->insulationNeg);
|
||||
FieldCodec::putU8(p, BA_T_MAX_NO, v->tempMaxNo);
|
||||
FieldCodec::putU8(p, BA_T_MAX1, v->tempMax1);
|
||||
FieldCodec::putU8(p, BA_T_MAX2, v->tempMax2);
|
||||
FieldCodec::putU8(p, BA_T_MAX3, v->tempMax3);
|
||||
FieldCodec::putU8(p, BA_T_MAX4, v->tempMax4);
|
||||
FieldCodec::putU8(p, BA_T_MIN4, v->tempMin4);
|
||||
FieldCodec::putU8(p, BA_T_MIN3, v->tempMin3);
|
||||
FieldCodec::putU8(p, BA_T_MIN2, v->tempMin2);
|
||||
FieldCodec::putU8(p, BA_T_MIN1, v->tempMin1);
|
||||
FieldCodec::putU8(p, BA_T_MIN_NO, v->tempMinNo);
|
||||
FieldCodec::putU8(p, BA_T_AVG, v->tempAvg);
|
||||
FieldCodec::putU8(p, BA_BALANCE, v->balanceState);
|
||||
FieldCodec::putU8(p, BA_V_MAX_NO, v->voltMaxNo);
|
||||
FieldCodec::putU16(p, BA_V_MAX1, v->voltMax1);
|
||||
FieldCodec::putU16(p, BA_V_MAX2, v->voltMax2);
|
||||
FieldCodec::putU16(p, BA_V_MAX3, v->voltMax3);
|
||||
FieldCodec::putU16(p, BA_V_MAX4, v->voltMax4);
|
||||
FieldCodec::putU16(p, BA_V_MAX5, v->voltMax5);
|
||||
FieldCodec::putU16(p, BA_V_MAX6, v->voltMax6);
|
||||
FieldCodec::putU16(p, BA_V_MIN6, v->voltMin6);
|
||||
FieldCodec::putU16(p, BA_V_MIN5, v->voltMin5);
|
||||
FieldCodec::putU16(p, BA_V_MIN4, v->voltMin4);
|
||||
FieldCodec::putU16(p, BA_V_MIN3, v->voltMin3);
|
||||
FieldCodec::putU16(p, BA_V_MIN2, v->voltMin2);
|
||||
FieldCodec::putU16(p, BA_V_MIN1, v->voltMin1);
|
||||
FieldCodec::putU8(p, BA_V_MIN_NO, v->voltMinNo);
|
||||
FieldCodec::putU16(p, BA_V_AVG, v->voltAvg);
|
||||
|
||||
return Frame::build(id(), p, checksum());
|
||||
}
|
||||
|
||||
bool BatPackAlarmMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
|
||||
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
|
||||
BatPackAlarmValue* v = static_cast<BatPackAlarmValue*>(obj);
|
||||
size_t o = FRAME_HEADER_LEN;
|
||||
|
||||
v->year = FieldCodec::getU16(frame, o + BA_YEAR);
|
||||
v->month = FieldCodec::getU8(frame, o + BA_MONTH);
|
||||
v->day = FieldCodec::getU8(frame, o + BA_DAY);
|
||||
v->hour = FieldCodec::getU8(frame, o + BA_HOUR);
|
||||
v->minute = FieldCodec::getU8(frame, o + BA_MINUTE);
|
||||
v->second = FieldCodec::getU8(frame, o + BA_SECOND);
|
||||
v->ms10 = FieldCodec::getU8(frame, o + BA_MS10);
|
||||
v->packNo = FieldCodec::getU8(frame, o + BA_PACKNO);
|
||||
getU8Arr(frame, o + BA_ALARM1, v->alarmFlag, 6);
|
||||
v->soc = FieldCodec::getU16(frame, o + BA_SOC);
|
||||
v->relayPosNeg = FieldCodec::getU8(frame, o + BA_RELAY);
|
||||
v->voltageLoad = FieldCodec::getU16(frame, o + BA_V_LOAD);
|
||||
v->voltagePack = FieldCodec::getU16(frame, o + BA_V_PACK);
|
||||
v->current = static_cast<int16_t>(FieldCodec::getU16(frame, o + BA_CURRENT));
|
||||
v->insulationPos= FieldCodec::getU16(frame, o + BA_INS_POS);
|
||||
v->insulationNeg= FieldCodec::getU16(frame, o + BA_INS_NEG);
|
||||
v->tempMaxNo = FieldCodec::getU8(frame, o + BA_T_MAX_NO);
|
||||
v->tempMax1 = FieldCodec::getU8(frame, o + BA_T_MAX1);
|
||||
v->tempMax2 = FieldCodec::getU8(frame, o + BA_T_MAX2);
|
||||
v->tempMax3 = FieldCodec::getU8(frame, o + BA_T_MAX3);
|
||||
v->tempMax4 = FieldCodec::getU8(frame, o + BA_T_MAX4);
|
||||
v->tempMin4 = FieldCodec::getU8(frame, o + BA_T_MIN4);
|
||||
v->tempMin3 = FieldCodec::getU8(frame, o + BA_T_MIN3);
|
||||
v->tempMin2 = FieldCodec::getU8(frame, o + BA_T_MIN2);
|
||||
v->tempMin1 = FieldCodec::getU8(frame, o + BA_T_MIN1);
|
||||
v->tempMinNo = FieldCodec::getU8(frame, o + BA_T_MIN_NO);
|
||||
v->tempAvg = FieldCodec::getU8(frame, o + BA_T_AVG);
|
||||
v->balanceState = FieldCodec::getU8(frame, o + BA_BALANCE);
|
||||
v->voltMaxNo = FieldCodec::getU8(frame, o + BA_V_MAX_NO);
|
||||
v->voltMax1 = FieldCodec::getU16(frame, o + BA_V_MAX1);
|
||||
v->voltMax2 = FieldCodec::getU16(frame, o + BA_V_MAX2);
|
||||
v->voltMax3 = FieldCodec::getU16(frame, o + BA_V_MAX3);
|
||||
v->voltMax4 = FieldCodec::getU16(frame, o + BA_V_MAX4);
|
||||
v->voltMax5 = FieldCodec::getU16(frame, o + BA_V_MAX5);
|
||||
v->voltMax6 = FieldCodec::getU16(frame, o + BA_V_MAX6);
|
||||
v->voltMin6 = FieldCodec::getU16(frame, o + BA_V_MIN6);
|
||||
v->voltMin5 = FieldCodec::getU16(frame, o + BA_V_MIN5);
|
||||
v->voltMin4 = FieldCodec::getU16(frame, o + BA_V_MIN4);
|
||||
v->voltMin3 = FieldCodec::getU16(frame, o + BA_V_MIN3);
|
||||
v->voltMin2 = FieldCodec::getU16(frame, o + BA_V_MIN2);
|
||||
v->voltMin1 = FieldCodec::getU16(frame, o + BA_V_MIN1);
|
||||
v->voltMinNo = FieldCodec::getU8(frame, o + BA_V_MIN_NO);
|
||||
v->voltAvg = FieldCodec::getU16(frame, o + BA_V_AVG);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ccu
|
||||
@@ -0,0 +1,334 @@
|
||||
#ifndef PCCU_BAT_PROTOCOL_H
|
||||
#define PCCU_BAT_PROTOCOL_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "Message.h"
|
||||
|
||||
namespace ccu {
|
||||
|
||||
//============================================================================
|
||||
// 锂电池协议(信息系统计算机 <-> 动力锂电池组 / 仪表锂电池组)
|
||||
// 依据:docs/锂电池协议20230324.docx
|
||||
//
|
||||
// 网络拓扑(默认值,均可通过 .moos 配置覆盖):
|
||||
// 信息系统计算机(pCCU) 本机监听端口可配置
|
||||
// 动力锂电池 192.168.100.137:7000
|
||||
// 仪表锂电池 192.168.100.136:7000
|
||||
//
|
||||
// 帧格式统一:0x40 0x40 + 域标识符(2B) + 域字节数(2B) + 数据域 + uint32 校验和
|
||||
// 校验和为从域起始符到校验和之前所有数据的字节和。
|
||||
//
|
||||
// 四条消息(均带 uint32 校验和):
|
||||
// 0x0000 自检指令 (信息系统->锂电池) payload 2B,总长 12B
|
||||
// 0x0001 设备控制指令 (信息系统->锂电池) payload 17B,总长 27B
|
||||
// 0x0003 状态反馈-电池组状态(锂电池->信息系统) payload 80B,总长 90B
|
||||
// 0x0004 状态反馈-电池包报警(锂电池->信息系统) payload 68B,总长 78B
|
||||
//============================================================================
|
||||
|
||||
// 锂电池角色:动力 / 仪表(两套设备协议一致,仅网络地址不同)
|
||||
enum class BatRole : int {
|
||||
Dyn = 0, // 动力锂电池
|
||||
Ins = 1, // 仪表锂电池
|
||||
};
|
||||
inline const char* batRoleName(BatRole r) {
|
||||
return (r == BatRole::Dyn) ? "动力锂电池" : "仪表锂电池";
|
||||
}
|
||||
|
||||
// 自检指令取值
|
||||
enum BatSelfCheckCmd : uint8_t {
|
||||
BAT_SC_NONE = 0x00, // 无效
|
||||
BAT_SC_START = 0x01, // 自检
|
||||
};
|
||||
enum BatSelfCheckReset : uint8_t {
|
||||
BAT_SCR_NONE = 0x00, // 无效
|
||||
BAT_SCR_RESET = 0x55, // 复位
|
||||
};
|
||||
|
||||
// 工况设定
|
||||
enum BatWorkCondition : uint8_t {
|
||||
BAT_WC_NONE = 0x00, // 无效
|
||||
BAT_WC_WORKSHOP = 0x10, // 工房调试
|
||||
BAT_WC_SEA_TRIAL = 0x30, // 试验实航
|
||||
BAT_WC_RESEARCH = 0x50, // 科研模式
|
||||
};
|
||||
|
||||
// 接触器指令(母线/正极/二极管路通用)
|
||||
enum BatContactorCmd : uint8_t {
|
||||
BAT_CTR_NONE = 0x00, // 无效(表示"保持不变")
|
||||
BAT_CTR_CLOSE = 0x55, // 接通
|
||||
BAT_CTR_OPEN = 0x77, // 断开
|
||||
};
|
||||
|
||||
// 电池自检状态(0x0003 状态反馈)
|
||||
enum BatSelfCheckState : uint8_t {
|
||||
BAT_SCST_INVALID = 0x00, // 无效
|
||||
BAT_SCST_RUNNING = 0x11, // 自检过程中
|
||||
BAT_SCST_OK = 0x22, // 自检完成,状态正常
|
||||
BAT_SCST_FAULT = 0x33, // 自检完成,状态异常
|
||||
};
|
||||
|
||||
// 母线接触器状态(0x0003 状态反馈)
|
||||
enum BatBusContactorState : uint8_t {
|
||||
BAT_BUSST_INVALID = 0x00, // 无效
|
||||
BAT_BUSST_RUNNING = 0x01, // 执行中
|
||||
BAT_BUSST_CLOSED = 0x11, // 母线接触器闭合完成
|
||||
BAT_BUSST_OPENED = 0x22, // 母线接触器断开完成
|
||||
BAT_BUSST_CLOSE_ERR = 0x33, // 闭合故障
|
||||
BAT_BUSST_OPEN_ERR = 0x44, // 断开故障
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 0x0000 自检指令(信息系统 -> 锂电池)
|
||||
// payload 2 字节
|
||||
//--------------------------------------------------------------------------
|
||||
struct BatSelfCheckValue {
|
||||
uint8_t selfCheck = 0; // 00H无效 / 01H自检
|
||||
uint8_t selfCheckReset = 0; // 00H无效 / 55H复位
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 0x0001 设备控制指令(信息系统 -> 锂电池)
|
||||
// 控制指令随机下发;同时作为心跳帧周期 1s 下发
|
||||
// payload 17 字节
|
||||
//--------------------------------------------------------------------------
|
||||
struct BatControlValue {
|
||||
// 系统时间
|
||||
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 ms10 = 0; // 10毫秒
|
||||
// 指令
|
||||
uint8_t workCondition = 0; // 工况设定 00/10/30/50
|
||||
uint8_t busContactor = 0; // 母线接触器 00/55/77(上下电用,含预充过程)
|
||||
uint8_t posContactor = 0; // 正极接触器 00/55/77(切换用)
|
||||
uint8_t diodeContactor = 0; // 二极管路接触器 00/55/77
|
||||
uint16_t powerKw = 0; // 电池组功率 0~500 kW
|
||||
uint16_t reserved = 0; // 预留
|
||||
uint8_t heartbeat = 0; // 通信心跳 0~255,每次+1
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 0x0003 状态反馈——电池组状态(锂电池 -> 信息系统)
|
||||
// 主动上发周期 1s;接到设备控制指令后回复
|
||||
// payload 80 字节
|
||||
//--------------------------------------------------------------------------
|
||||
struct BatStatusValue {
|
||||
// 系统时间
|
||||
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 ms10 = 0;
|
||||
// 状态
|
||||
uint8_t workCondition = 0; // 工况 00/10/30/50
|
||||
uint8_t selfCheckState = 0; // 电池自检状态 00/11/22/33
|
||||
uint8_t powerCfgState = 0; // 电池功率配置状态 00/11/22/33/44
|
||||
uint8_t busContactorState = 0;// 电池母线接触器状态 00/01/11/22/33/44
|
||||
uint8_t posDiodeState = 0; // 正极接触器(低4位)与二极管回路(高4位)状态
|
||||
uint8_t emergencyState = 0; // 电池紧急状态 0x00/0x1A~0x1F/0x3A~0x3F/0x5A~0x5F
|
||||
// 容量与功率
|
||||
uint16_t soc = 0; // SOC,0.1%
|
||||
uint16_t energy = 0; // 电池电量,0.1kWh
|
||||
uint16_t maxDischargePower = 0;// 电池允许最高放电功率,0.1kW
|
||||
uint16_t maxChargePower = 0; // 电池允许充电功率,0.1kW
|
||||
uint16_t currentAccessPower = 0; // 电池当前接入功率,0.1kW
|
||||
uint32_t packOnlineFlag = 0; // 电池包在线信息 bit=1 在线
|
||||
uint32_t packAccessFlag = 0; // 电池包接入信息 bit=1 接入
|
||||
// 继电器状态
|
||||
uint8_t relayPosCharge = 0; // 总控正极(高4位)与充电(低4位)继电器状态
|
||||
uint8_t relayPreNeg = 0; // 总控预充(高4位)与负极(低4位)继电器状态
|
||||
uint8_t relayOut2Pre = 0; // 第二路输出(高4位)与其预充(低4位)继电器状态
|
||||
uint8_t relayChgOnlinePre = 0;// 在线充电(高4位)与其预充(低4位)继电器状态
|
||||
// 电气量
|
||||
uint16_t voltageLoad = 0; // 总控电池电压负载端,0.01V
|
||||
uint16_t voltagePack = 0; // 总控电池电压电池端,0.01V
|
||||
int16_t current = 0; // 总控电池放电电流,0.05A(放电为正/充电为负)
|
||||
uint16_t insulationPos = 0; // 总控电池正端绝缘电阻,10kΩ
|
||||
uint16_t insulationNeg = 0; // 总控电池负端绝缘电阻,10kΩ
|
||||
uint8_t masterTemp1 = 0; // 总控温度1(文档标注删除,保留占位偏移)
|
||||
uint8_t masterTemp2 = 0; // 总控温度2(文档标注删除,保留占位偏移)
|
||||
// 电池包电压
|
||||
uint16_t packVoltageMid = 0; // 电池包中值电压,0.1V
|
||||
uint16_t packVoltageMin = 0; // 电池包最低电压,0.1V
|
||||
uint8_t packVoltageMinNo = 0; // 最低电压电池包号
|
||||
uint16_t packVoltageMax = 0; // 电池包最高电压,0.1V
|
||||
uint8_t packVoltageMaxNo = 0; // 最高电压电池包号
|
||||
uint16_t packDeltaMax = 0; // 单个电池包最大压差,0.1mV
|
||||
uint8_t packDeltaMaxNo = 0; // 最大压差电池包号
|
||||
uint16_t packDeltaMaxVoltage = 0; // 最大压差电池包最高电压,0.1mV
|
||||
// 温度(偏移量 -40℃)
|
||||
uint8_t cellTempAvg = 0; // 电池单体均值温度,-40℃
|
||||
uint8_t cellTempMin = 0; // 电池单体最低温度,-40℃
|
||||
uint8_t cellTempMinNo = 0; // 最低温度电池包号
|
||||
uint8_t cellTempMax = 0; // 电池单体最高温度,-40℃
|
||||
uint8_t cellTempMaxNo = 0; // 最高温度电池包号
|
||||
// 报警
|
||||
uint8_t alarmFlag[6] = {0}; // 电池报警标识字1~6
|
||||
uint32_t alarmPosFlag = 0; // 电池报警位置标识字
|
||||
// 其它
|
||||
uint8_t chargeStatus = 0; // 电池充放电状态 00无效/10充电中/20功率输出中
|
||||
uint16_t reserved = 0; // 预留
|
||||
uint8_t heartbeat = 0; // 通信心跳 0~255,每次+1
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 0x0004 状态反馈——电池包报警信息(锂电池 -> 信息系统)
|
||||
// 自检完成后和报警状态更改后主动上发,最多 1s 一次
|
||||
// payload 68 字节
|
||||
//--------------------------------------------------------------------------
|
||||
struct BatPackAlarmValue {
|
||||
// 系统时间
|
||||
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 ms10 = 0;
|
||||
uint8_t packNo = 0; // 电池包号 1~24
|
||||
// 报警
|
||||
uint8_t alarmFlag[6] = {0}; // 电池报警标识字1~6
|
||||
// 状态
|
||||
uint16_t soc = 0; // 电池包SOC,0.1%
|
||||
uint8_t relayPosNeg = 0; // 电池包正极(高4位)与负极(低4位)继电器状态
|
||||
// 电气量
|
||||
uint16_t voltageLoad = 0; // 电池包电压负载端,0.1V
|
||||
uint16_t voltagePack = 0; // 电池包电压电池端,0.1V
|
||||
int16_t current = 0; // 电池包放电电流,0.05A(放电为正/充电为负)
|
||||
uint16_t insulationPos = 0; // 电池包正端绝缘电阻,10kΩ
|
||||
uint16_t insulationNeg = 0; // 电池包负端绝缘电阻,10kΩ
|
||||
// 温度(偏移量 -40℃)
|
||||
uint8_t tempMaxNo = 0; // 电池单体最高温度号
|
||||
uint8_t tempMax1 = 0; // 电池单体最高温度1,-40℃
|
||||
uint8_t tempMax2 = 0; // 电池单体高温2
|
||||
uint8_t tempMax3 = 0; // 电池单体高温3
|
||||
uint8_t tempMax4 = 0; // 电池单体高温4
|
||||
uint8_t tempMin4 = 0; // 电池单体低温4
|
||||
uint8_t tempMin3 = 0; // 电池单体低温3
|
||||
uint8_t tempMin2 = 0; // 电池单体低温2
|
||||
uint8_t tempMin1 = 0; // 电池单体最低温度1,-40℃
|
||||
uint8_t tempMinNo = 0; // 电池单体最低温度号
|
||||
uint8_t tempAvg = 0; // 电池单体平均温度,-40℃
|
||||
// 均衡
|
||||
uint8_t balanceState = 0; // 电池单体均衡状态 0无/1有
|
||||
// 单体电压(0.1mV)
|
||||
uint8_t voltMaxNo = 0; // 电池单体最高电压号
|
||||
uint16_t voltMax1 = 0; // 电池单体最高电压1
|
||||
uint16_t voltMax2 = 0; // 电池单体高电压2
|
||||
uint16_t voltMax3 = 0; // 电池单体高电压3
|
||||
uint16_t voltMax4 = 0; // 电池单体高电压4
|
||||
uint16_t voltMax5 = 0; // 电池单体高电压5
|
||||
uint16_t voltMax6 = 0; // 电池单体高电压6
|
||||
uint16_t voltMin6 = 0; // 电池单体低电压6
|
||||
uint16_t voltMin5 = 0; // 电池单体低电压5
|
||||
uint16_t voltMin4 = 0; // 电池单体低电压4
|
||||
uint16_t voltMin3 = 0; // 电池单体低电压3
|
||||
uint16_t voltMin2 = 0; // 电池单体低电压2
|
||||
uint16_t voltMin1 = 0; // 电池单体最低电压1
|
||||
uint8_t voltMinNo = 0; // 电池单体最低电压号
|
||||
uint16_t voltAvg = 0; // 电池单体平均电压
|
||||
};
|
||||
|
||||
// 状态反馈便捷解析:正极接触器部分(低4位)
|
||||
inline uint8_t batPosStateOf(uint8_t posDiodeState) { return posDiodeState & 0x0F; }
|
||||
// 状态反馈便捷解析:二极管回路部分(高4位)
|
||||
inline uint8_t batDiodeStateOf(uint8_t posDiodeState) { return posDiodeState >> 4; }
|
||||
|
||||
// 正极接触器状态值(低4位):X1执行中 X2闭合完成 X3断开完成 X4闭合故障 X5断开故障
|
||||
enum BatPosContactorState : uint8_t {
|
||||
BAT_POSST_RUNNING = 0x1,
|
||||
BAT_POSST_CLOSED = 0x2,
|
||||
BAT_POSST_OPENED = 0x3,
|
||||
BAT_POSST_CLOSE_ERR = 0x4,
|
||||
BAT_POSST_OPEN_ERR = 0x5,
|
||||
};
|
||||
// 二极管回路状态值(高4位):1X执行中 2X闭合完成 3X断开完成 4X闭合故障 5X断开故障 6X负载端无电压
|
||||
enum BatDiodeState : uint8_t {
|
||||
BAT_DIODST_RUNNING = 0x1,
|
||||
BAT_DIODST_CLOSED = 0x2,
|
||||
BAT_DIODST_OPENED = 0x3,
|
||||
BAT_DIODST_CLOSE_ERR = 0x4,
|
||||
BAT_DIODST_OPEN_ERR = 0x5,
|
||||
BAT_DIODST_NO_LOAD_V = 0x6, // 负载端无电压故障
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 消息类
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class BatSelfCheckMessage : public Message {
|
||||
public:
|
||||
uint16_t id() const override { return 0x0000; }
|
||||
const char* name() const override { return "bat_self_check"; }
|
||||
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 BatSelfCheckValue& v) const { return encode(&v); }
|
||||
bool decode(const std::vector<uint8_t>& frame, BatSelfCheckValue& v) const {
|
||||
return decode(frame, static_cast<void*>(&v));
|
||||
}
|
||||
private:
|
||||
ChecksumPolicy m_checksum{ChecksumType::Sum32};
|
||||
};
|
||||
|
||||
class BatControlMessage : public Message {
|
||||
public:
|
||||
uint16_t id() const override { return 0x0001; }
|
||||
const char* name() const override { return "bat_control"; }
|
||||
const ChecksumPolicy& checksum() const override { return m_checksum; }
|
||||
size_t payloadLength() const override { return 17; }
|
||||
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 BatControlValue& v) const { return encode(&v); }
|
||||
bool decode(const std::vector<uint8_t>& frame, BatControlValue& v) const {
|
||||
return decode(frame, static_cast<void*>(&v));
|
||||
}
|
||||
private:
|
||||
ChecksumPolicy m_checksum{ChecksumType::Sum32};
|
||||
};
|
||||
|
||||
class BatStatusMessage : public Message {
|
||||
public:
|
||||
uint16_t id() const override { return 0x0003; }
|
||||
const char* name() const override { return "bat_status"; }
|
||||
const ChecksumPolicy& checksum() const override { return m_checksum; }
|
||||
size_t payloadLength() const override { return 80; }
|
||||
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 BatStatusValue& v) const { return encode(&v); }
|
||||
bool decode(const std::vector<uint8_t>& frame, BatStatusValue& v) const {
|
||||
return decode(frame, static_cast<void*>(&v));
|
||||
}
|
||||
private:
|
||||
ChecksumPolicy m_checksum{ChecksumType::Sum32};
|
||||
};
|
||||
|
||||
class BatPackAlarmMessage : public Message {
|
||||
public:
|
||||
uint16_t id() const override { return 0x0004; }
|
||||
const char* name() const override { return "bat_pack_alarm"; }
|
||||
const ChecksumPolicy& checksum() const override { return m_checksum; }
|
||||
size_t payloadLength() const override { return 68; }
|
||||
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 BatPackAlarmValue& v) const { return encode(&v); }
|
||||
bool decode(const std::vector<uint8_t>& frame, BatPackAlarmValue& v) const {
|
||||
return decode(frame, static_cast<void*>(&v));
|
||||
}
|
||||
private:
|
||||
ChecksumPolicy m_checksum{ChecksumType::Sum32};
|
||||
};
|
||||
|
||||
// 注册锂电池消息到给定注册表
|
||||
void registerBatMessages(class MessageRegistry& reg);
|
||||
|
||||
} // namespace ccu
|
||||
|
||||
#endif // PCCU_BAT_PROTOCOL_H
|
||||
Reference in New Issue
Block a user