build-test-deploy / ci (push) Successful in 1h13m13s
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
662 lines
32 KiB
C++
662 lines
32 KiB
C++
#include "PmProtocol.h"
|
||
#include "FieldCodec.h"
|
||
#include "Frame.h"
|
||
#include "MessageRegistry.h"
|
||
|
||
namespace ccu {
|
||
|
||
void registerPmMessages(MessageRegistry& reg) {
|
||
reg.registerMessage(std::unique_ptr<Message>(new PmControlMessage()));
|
||
reg.registerMessage(std::unique_ptr<Message>(new PmParamSetMessage()));
|
||
reg.registerMessage(std::unique_ptr<Message>(new PmParamSetFbMessage()));
|
||
reg.registerMessage(std::unique_ptr<Message>(new PmStatusMessage()));
|
||
}
|
||
|
||
//============================================================================
|
||
// 0x0001 操控指令域编解码
|
||
// 数据域 35 字节,偏移 0~34(对应文档字节 7~41)
|
||
//============================================================================
|
||
|
||
namespace {
|
||
enum : size_t {
|
||
PO_YEAR = 0, // u16
|
||
PO_MONTH = 2,
|
||
PO_DAY = 3,
|
||
PO_HOUR = 4,
|
||
PO_MINUTE = 5,
|
||
PO_SECOND = 6,
|
||
PO_MS10 = 7,
|
||
PO_MODE = 8,
|
||
PO_CMD = 9,
|
||
PO_OUTPOWER = 10,
|
||
PO_PITCH = 11, // 纵倾姿态数据1 int16 (字节18-19)
|
||
PO_ROLL = 13, // 横倾姿态数据1 int16 (字节20-21)
|
||
PO_EMER_ALLOW = 15,
|
||
PO_DEPTH = 16, // u16
|
||
PO_SUPPLY_CMD = 18,
|
||
PO_RESV_CMD5 = 19,
|
||
PO_RESV_CMD6 = 20,
|
||
PO_INS_BAT_CMD = 21,
|
||
PO_DYN_BAT_CMD = 22,
|
||
PO_DYN_BAT_PWR = 23, // u16
|
||
PO_HEARTBEAT = 25,
|
||
PO_HOST_STATE = 26,
|
||
PO_RESV1 = 27, // u32
|
||
PO_RESV2 = 31, // u32
|
||
};
|
||
}
|
||
|
||
std::vector<uint8_t> PmControlMessage::encode(const void* obj) const {
|
||
const PmControlValue* v = static_cast<const PmControlValue*>(obj);
|
||
std::vector<uint8_t> p(payloadLength(), 0);
|
||
|
||
FieldCodec::putU16(p, PO_YEAR, v->year);
|
||
FieldCodec::putU8(p, PO_MONTH, v->month);
|
||
FieldCodec::putU8(p, PO_DAY, v->day);
|
||
FieldCodec::putU8(p, PO_HOUR, v->hour);
|
||
FieldCodec::putU8(p, PO_MINUTE, v->minute);
|
||
FieldCodec::putU8(p, PO_SECOND, v->second);
|
||
FieldCodec::putU8(p, PO_MS10, v->millisecond10);
|
||
FieldCodec::putU8(p, PO_MODE, v->mode);
|
||
FieldCodec::putU8(p, PO_CMD, v->cmd);
|
||
FieldCodec::putU8(p, PO_OUTPOWER, v->outputPower);
|
||
FieldCodec::putU16(p, PO_PITCH, static_cast<uint16_t>(v->pitch)); // 姿态数据1,数据2字节预留
|
||
FieldCodec::putU16(p, PO_ROLL, static_cast<uint16_t>(v->roll));
|
||
FieldCodec::putU8(p, PO_EMER_ALLOW, v->emergencyAllow);
|
||
FieldCodec::putU16(p, PO_DEPTH, v->depth);
|
||
FieldCodec::putU8(p, PO_SUPPLY_CMD, v->supplyCmd);
|
||
FieldCodec::putU8(p, PO_RESV_CMD5, v->reservedCmd5);
|
||
FieldCodec::putU8(p, PO_RESV_CMD6, v->reservedCmd6);
|
||
FieldCodec::putU8(p, PO_INS_BAT_CMD, v->insBatCmd);
|
||
FieldCodec::putU8(p, PO_DYN_BAT_CMD, v->dynBatCmd);
|
||
FieldCodec::putU16(p, PO_DYN_BAT_PWR, v->dynBatPower);
|
||
FieldCodec::putU8(p, PO_HEARTBEAT, v->heartbeat);
|
||
FieldCodec::putU8(p, PO_HOST_STATE, v->hostState);
|
||
FieldCodec::putU32(p, PO_RESV1, v->reserved1);
|
||
FieldCodec::putU32(p, PO_RESV2, v->reserved2);
|
||
|
||
return Frame::build(id(), p, checksum());
|
||
}
|
||
|
||
bool PmControlMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
|
||
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
|
||
PmControlValue* v = static_cast<PmControlValue*>(obj);
|
||
size_t o = FRAME_HEADER_LEN;
|
||
|
||
v->year = FieldCodec::getU16(frame, o + PO_YEAR);
|
||
v->month = FieldCodec::getU8(frame, o + PO_MONTH);
|
||
v->day = FieldCodec::getU8(frame, o + PO_DAY);
|
||
v->hour = FieldCodec::getU8(frame, o + PO_HOUR);
|
||
v->minute = FieldCodec::getU8(frame, o + PO_MINUTE);
|
||
v->second = FieldCodec::getU8(frame, o + PO_SECOND);
|
||
v->millisecond10 = FieldCodec::getU8(frame, o + PO_MS10);
|
||
v->mode = FieldCodec::getU8(frame, o + PO_MODE);
|
||
v->cmd = FieldCodec::getU8(frame, o + PO_CMD);
|
||
v->outputPower = FieldCodec::getU8(frame, o + PO_OUTPOWER);
|
||
v->pitch = static_cast<int16_t>(FieldCodec::getU16(frame, o + PO_PITCH));
|
||
v->roll = static_cast<int16_t>(FieldCodec::getU16(frame, o + PO_ROLL));
|
||
v->emergencyAllow= FieldCodec::getU8(frame, o + PO_EMER_ALLOW);
|
||
v->depth = FieldCodec::getU16(frame, o + PO_DEPTH);
|
||
v->supplyCmd = FieldCodec::getU8(frame, o + PO_SUPPLY_CMD);
|
||
v->reservedCmd5 = FieldCodec::getU8(frame, o + PO_RESV_CMD5);
|
||
v->reservedCmd6 = FieldCodec::getU8(frame, o + PO_RESV_CMD6);
|
||
v->insBatCmd = FieldCodec::getU8(frame, o + PO_INS_BAT_CMD);
|
||
v->dynBatCmd = FieldCodec::getU8(frame, o + PO_DYN_BAT_CMD);
|
||
v->dynBatPower = FieldCodec::getU16(frame, o + PO_DYN_BAT_PWR);
|
||
v->heartbeat = FieldCodec::getU8(frame, o + PO_HEARTBEAT);
|
||
v->hostState = FieldCodec::getU8(frame, o + PO_HOST_STATE);
|
||
v->reserved1 = FieldCodec::getU32(frame, o + PO_RESV1);
|
||
v->reserved2 = FieldCodec::getU32(frame, o + PO_RESV2);
|
||
return true;
|
||
}
|
||
|
||
//============================================================================
|
||
// 0x0002 参数设定指令域
|
||
// 数据域 18 字节,偏移 0~17
|
||
//============================================================================
|
||
|
||
namespace {
|
||
enum : size_t {
|
||
PP_INS_H1 = 0,
|
||
PP_INS_H2 = 1,
|
||
PP_INS_H3 = 2,
|
||
PP_INS_PWR = 3,
|
||
PP_INS_RESV = 4,
|
||
PP_DYN_H1 = 5,
|
||
PP_DYN_H2 = 6,
|
||
PP_DYN_H3 = 7,
|
||
PP_DYN_PWR = 8,
|
||
PP_DYN_RESV = 9,
|
||
PP_RESV1 = 10, // u32
|
||
PP_RESV2 = 14, // u32
|
||
};
|
||
}
|
||
|
||
std::vector<uint8_t> PmParamSetMessage::encode(const void* obj) const {
|
||
const PmParamSetValue* v = static_cast<const PmParamSetValue*>(obj);
|
||
std::vector<uint8_t> p(payloadLength(), 0);
|
||
|
||
FieldCodec::putU8(p, PP_INS_H1, v->insSocHold1);
|
||
FieldCodec::putU8(p, PP_INS_H2, v->insSocHold2);
|
||
FieldCodec::putU8(p, PP_INS_H3, v->insSocHold3);
|
||
FieldCodec::putU8(p, PP_INS_PWR, v->insOutputPower);
|
||
FieldCodec::putU8(p, PP_INS_RESV, v->insReserved);
|
||
FieldCodec::putU8(p, PP_DYN_H1, v->dynSocHold1);
|
||
FieldCodec::putU8(p, PP_DYN_H2, v->dynSocHold2);
|
||
FieldCodec::putU8(p, PP_DYN_H3, v->dynSocHold3);
|
||
FieldCodec::putU8(p, PP_DYN_PWR, v->dynOutputPower);
|
||
FieldCodec::putU8(p, PP_DYN_RESV, v->dynReserved);
|
||
FieldCodec::putU32(p, PP_RESV1, v->reserved1);
|
||
FieldCodec::putU32(p, PP_RESV2, v->reserved2);
|
||
|
||
return Frame::build(id(), p, checksum());
|
||
}
|
||
|
||
bool PmParamSetMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
|
||
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
|
||
PmParamSetValue* v = static_cast<PmParamSetValue*>(obj);
|
||
size_t o = FRAME_HEADER_LEN;
|
||
|
||
v->insSocHold1 = FieldCodec::getU8(frame, o + PP_INS_H1);
|
||
v->insSocHold2 = FieldCodec::getU8(frame, o + PP_INS_H2);
|
||
v->insSocHold3 = FieldCodec::getU8(frame, o + PP_INS_H3);
|
||
v->insOutputPower = FieldCodec::getU8(frame, o + PP_INS_PWR);
|
||
v->insReserved = FieldCodec::getU8(frame, o + PP_INS_RESV);
|
||
v->dynSocHold1 = FieldCodec::getU8(frame, o + PP_DYN_H1);
|
||
v->dynSocHold2 = FieldCodec::getU8(frame, o + PP_DYN_H2);
|
||
v->dynSocHold3 = FieldCodec::getU8(frame, o + PP_DYN_H3);
|
||
v->dynOutputPower = FieldCodec::getU8(frame, o + PP_DYN_PWR);
|
||
v->dynReserved = FieldCodec::getU8(frame, o + PP_DYN_RESV);
|
||
v->reserved1 = FieldCodec::getU32(frame, o + PP_RESV1);
|
||
v->reserved2 = FieldCodec::getU32(frame, o + PP_RESV2);
|
||
return true;
|
||
}
|
||
|
||
//============================================================================
|
||
// 0x0003 参数设定反馈域
|
||
// 数据域 2 字节
|
||
//============================================================================
|
||
|
||
std::vector<uint8_t> PmParamSetFbMessage::encode(const void* obj) const {
|
||
const PmParamSetFbValue* v = static_cast<const PmParamSetFbValue*>(obj);
|
||
std::vector<uint8_t> p(payloadLength(), 0);
|
||
FieldCodec::putU8(p, 0, v->flag);
|
||
FieldCodec::putU8(p, 1, v->failCode);
|
||
return Frame::build(id(), p, checksum());
|
||
}
|
||
|
||
bool PmParamSetFbMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
|
||
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
|
||
PmParamSetFbValue* v = static_cast<PmParamSetFbValue*>(obj);
|
||
size_t o = FRAME_HEADER_LEN;
|
||
v->flag = FieldCodec::getU8(frame, o + 0);
|
||
v->failCode = FieldCodec::getU8(frame, o + 1);
|
||
return true;
|
||
}
|
||
|
||
//============================================================================
|
||
// 0x0004 状态报文域
|
||
// 数据域 238 字节,偏移 0~237(对应文档字节 7~244)
|
||
//============================================================================
|
||
|
||
namespace {
|
||
enum : size_t {
|
||
PS_MODE = 0,
|
||
PS_STATUS = 1,
|
||
PS_FL1 = 2, // u16
|
||
PS_FL2 = 4,
|
||
PS_FL3 = 6,
|
||
PS_FL4 = 8,
|
||
PS_GEN_TIME = 10, // u16
|
||
PS_FAULT_LEVEL = 12,
|
||
PS_OUT_POWER_LIMIT = 13, // u16
|
||
PS_GEN_POWER = 15, // u16
|
||
PS_H2_CAP = 17,
|
||
PS_LO2_CAP = 18,
|
||
PS_FC1_MIN_V = 19,
|
||
PS_FC1_MIN_POS = 20,
|
||
PS_FC1_AVG_V = 21,
|
||
PS_FC2_MIN_V = 22,
|
||
PS_FC2_MIN_POS = 23,
|
||
PS_FC2_AVG_V = 24,
|
||
PS_PALLADIUM = 25, // u16
|
||
PS_BUFFER_PRES = 27,
|
||
PS_FLUE_TOTAL = 29,
|
||
PS_FLUE_PRES = 31,
|
||
PS_REACTOR_PRES = 33,
|
||
PS_EVALVE_OPEN = 35,
|
||
PS_MAIN_PIPE_PRES = 37,
|
||
PS_AUX_PIPE_PRES = 39,
|
||
PS_DCDC1_IN_V = 41,
|
||
PS_DCDC1_IN_I = 43,
|
||
PS_DCDC2_IN_V = 45,
|
||
PS_DCDC2_IN_I = 47,
|
||
PS_DCDC_OUT_V = 49,
|
||
PS_DCDC_OUT_I = 51,
|
||
PS_DCDC_CTRL_V = 53,
|
||
PS_DCDC_AUX_V = 54,
|
||
PS_METHANOL_TOTAL = 55, // u16
|
||
PS_METHANOL_FEED = 57,
|
||
PS_O2_WATER = 59,
|
||
PS_H2_WATER = 61,
|
||
PS_BALLAST_WATER = 63,
|
||
PS_EXH_IN_PRES = 65,
|
||
PS_EXH_OUT_PRES = 67,
|
||
PS_EXH_FREQ = 69,
|
||
PS_EXH_IN_TEMP = 71,
|
||
PS_EXH_OUT_TEMP = 73,
|
||
PS_EXH_WIN_PRES = 75,
|
||
PS_EXH_WOUT_PRES = 77,
|
||
PS_TANK_LO2_PRES = 79,
|
||
PS_TANK_CO2_PRES = 81,
|
||
PS_TANK_LO2_LEVEL = 83,
|
||
PS_ALLOY_H2_FLOW = 85,
|
||
PS_FC_H2_FLOW = 87,
|
||
PS_FC_O2_FLOW = 89,
|
||
PS_EMER_DEPTH = 91, // u16
|
||
PS_EMER_TIME = 93,
|
||
PS_CABIN_P1 = 95,
|
||
PS_CABIN_P2 = 97,
|
||
PS_CABIN_T1 = 99,
|
||
PS_CABIN_T2 = 101,
|
||
PS_CABIN_H1 = 103,
|
||
PS_CABIN_H2 = 105,
|
||
PS_H2_C1 = 107,
|
||
PS_H2_C2 = 109,
|
||
PS_H2_C3 = 111,
|
||
PS_O2_C1 = 113,
|
||
PS_O2_C2 = 115,
|
||
PS_CH3OH_C1 = 117,
|
||
PS_CH3OH_C2 = 119,
|
||
PS_FLAME1 = 121,
|
||
PS_FLAME2 = 122,
|
||
PS_RESV1 = 123, // u16
|
||
PS_RESV2 = 125, // u16
|
||
PS_EB1_VOLTAGE = 127, // u16
|
||
PS_EB1_CURRENT = 129,
|
||
PS_EB1_MAX_TEMP = 131,
|
||
PS_EB1_FAULT = 133,
|
||
PS_EB2_VOLTAGE = 135,
|
||
PS_EB2_CURRENT = 137,
|
||
PS_EB2_MAX_TEMP = 139,
|
||
PS_EB2_FAULT = 141,
|
||
PS_INS_CABIN_OX = 143, // u16
|
||
PS_INS_CABIN_TEMP = 145,
|
||
PS_INS_CABIN_HUM = 147,
|
||
PS_INS_CABIN_PRES = 149,
|
||
PS_DYN_CABIN_OX = 151,
|
||
PS_DYN_CABIN_TEMP = 153,
|
||
PS_DYN_CABIN_HUM = 155,
|
||
PS_DYN_CABIN_PRES = 157,
|
||
PS_RESV3 = 159, // u8
|
||
PS_DYN_ALARM = 160, // u8 * 6
|
||
PS_INS_ALARM = 166, // u8 * 6
|
||
PS_INS_RELAY1 = 172,
|
||
PS_INS_RELAY2 = 173,
|
||
PS_DYN_RELAY1 = 174,
|
||
PS_DYN_RELAY2 = 175,
|
||
PS_INS_MAX_PWR = 176, // u16
|
||
PS_DYN_MAX_PWR = 178, // u16
|
||
PS_INS_SOC = 180,
|
||
PS_DYN_SOC = 181,
|
||
PS_INS_TOTAL_ENERGY= 182, // u16
|
||
PS_DYN_TOTAL_ENERGY= 184, // u16
|
||
PS_INS_PWR_IN = 186, // u16
|
||
PS_DYN_PWR_IN = 188, // u16
|
||
PS_INS_CHARGE_ST = 190,
|
||
PS_DYN_CHARGE_ST = 191,
|
||
PS_INS_V_LINK = 192, // u16
|
||
PS_INS_V_PACK = 194, // u16
|
||
PS_INS_CURRENT = 196, // u16
|
||
PS_INS_RES_POS = 198, // u16
|
||
PS_INS_RES_NEG = 200, // u16
|
||
PS_DYN_V_LINK = 202, // u16
|
||
PS_DYN_V_PACK = 204, // u16
|
||
PS_DYN_CURRENT = 206, // u16
|
||
PS_DYN_RES_POS = 208, // u16
|
||
PS_DYN_RES_NEG = 210, // u16
|
||
PS_INS_EMERGENCY = 212,
|
||
PS_DYN_EMERGENCY = 213,
|
||
PS_INS_SOC_H1 = 214,
|
||
PS_INS_SOC_H2 = 215,
|
||
PS_INS_SOC_H3 = 216,
|
||
PS_INS_PWR_L1 = 217,
|
||
PS_INS_PWR_L2 = 218,
|
||
PS_DYN_SOC_H1 = 219,
|
||
PS_DYN_SOC_H2 = 220,
|
||
PS_DYN_SOC_H3 = 221,
|
||
PS_DYN_PWR_L1 = 222,
|
||
PS_DYN_PWR_L2 = 223,
|
||
PS_ONLINE_FLAG1 = 224, // u32
|
||
PS_ONLINE_FLAG2 = 228, // u32
|
||
PS_RESV4 = 232, // u32
|
||
PS_HEARTBEAT = 236,
|
||
PS_EMERGENCY_CMD = 237,
|
||
};
|
||
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> PmStatusMessage::encode(const void* obj) const {
|
||
const PmStatusValue* v = static_cast<const PmStatusValue*>(obj);
|
||
std::vector<uint8_t> p(payloadLength(), 0);
|
||
|
||
FieldCodec::putU8(p, PS_MODE, v->fc_mode);
|
||
FieldCodec::putU8(p, PS_STATUS, v->fc_status);
|
||
FieldCodec::putU16(p, PS_FL1, v->fault_level_1);
|
||
FieldCodec::putU16(p, PS_FL2, v->fault_level_2);
|
||
FieldCodec::putU16(p, PS_FL3, v->fault_level_3);
|
||
FieldCodec::putU16(p, PS_FL4, v->fault_level_4);
|
||
FieldCodec::putU16(p, PS_GEN_TIME, v->total_generation_time);
|
||
FieldCodec::putU8(p, PS_FAULT_LEVEL, v->fc_fault_level);
|
||
FieldCodec::putU16(p, PS_OUT_POWER_LIMIT, v->output_power_limit);
|
||
FieldCodec::putU16(p, PS_GEN_POWER, v->generation_power);
|
||
FieldCodec::putU8(p, PS_H2_CAP, v->hydrogen_capacity);
|
||
FieldCodec::putU8(p, PS_LO2_CAP, v->liquid_oxygen_capacity);
|
||
|
||
FieldCodec::putU8(p, PS_FC1_MIN_V, v->fc1_min_cell_voltage);
|
||
FieldCodec::putU8(p, PS_FC1_MIN_POS, v->fc1_min_cell_pos);
|
||
FieldCodec::putU8(p, PS_FC1_AVG_V, v->fc1_avg_cell_voltage);
|
||
FieldCodec::putU8(p, PS_FC2_MIN_V, v->fc2_min_cell_voltage);
|
||
FieldCodec::putU8(p, PS_FC2_MIN_POS, v->fc2_min_cell_pos);
|
||
FieldCodec::putU8(p, PS_FC2_AVG_V, v->fc2_avg_cell_voltage);
|
||
|
||
FieldCodec::putU16(p, PS_PALLADIUM, v->palladium_temp);
|
||
FieldCodec::putU16(p, PS_BUFFER_PRES, v->buffer_tank_pressure);
|
||
FieldCodec::putU16(p, PS_FLUE_TOTAL, v->flue_total_emission);
|
||
FieldCodec::putU16(p, PS_FLUE_PRES, v->flue_pressure);
|
||
FieldCodec::putU16(p, PS_REACTOR_PRES, v->reactor_pressure);
|
||
FieldCodec::putU16(p, PS_EVALVE_OPEN, v->electric_valve_open);
|
||
FieldCodec::putU16(p, PS_MAIN_PIPE_PRES, v->main_pipe_pressure);
|
||
FieldCodec::putU16(p, PS_AUX_PIPE_PRES, v->aux_pipe_pressure);
|
||
|
||
FieldCodec::putU16(p, PS_DCDC1_IN_V, v->dcdc1_in_voltage);
|
||
FieldCodec::putU16(p, PS_DCDC1_IN_I, v->dcdc1_in_current);
|
||
FieldCodec::putU16(p, PS_DCDC2_IN_V, v->dcdc2_in_voltage);
|
||
FieldCodec::putU16(p, PS_DCDC2_IN_I, v->dcdc2_in_current);
|
||
FieldCodec::putU16(p, PS_DCDC_OUT_V, v->dcdc_out_voltage);
|
||
FieldCodec::putU16(p, PS_DCDC_OUT_I, v->dcdc_out_current);
|
||
FieldCodec::putU8(p, PS_DCDC_CTRL_V, v->dcdc_ctrl_voltage);
|
||
FieldCodec::putU8(p, PS_DCDC_AUX_V, v->dcdc_aux_voltage);
|
||
|
||
FieldCodec::putU16(p, PS_METHANOL_TOTAL, v->methanol_total_use);
|
||
FieldCodec::putU16(p, PS_METHANOL_FEED, v->methanol_feed);
|
||
FieldCodec::putU16(p, PS_O2_WATER, v->oxygen_side_water_level);
|
||
FieldCodec::putU16(p, PS_H2_WATER, v->hydrogen_side_water_level);
|
||
FieldCodec::putU16(p, PS_BALLAST_WATER, v->ballast_water_level);
|
||
|
||
FieldCodec::putU16(p, PS_EXH_IN_PRES, v->exhaust_inlet_pressure);
|
||
FieldCodec::putU16(p, PS_EXH_OUT_PRES, v->exhaust_outlet_pressure);
|
||
FieldCodec::putU16(p, PS_EXH_FREQ, v->exhaust_run_freq);
|
||
FieldCodec::putU16(p, PS_EXH_IN_TEMP, v->exhaust_inlet_temp);
|
||
FieldCodec::putU16(p, PS_EXH_OUT_TEMP, v->exhaust_outlet_temp);
|
||
FieldCodec::putU16(p, PS_EXH_WIN_PRES, v->exhaust_water_in_pressure);
|
||
FieldCodec::putU16(p, PS_EXH_WOUT_PRES, v->exhaust_water_out_pressure);
|
||
|
||
FieldCodec::putU16(p, PS_TANK_LO2_PRES, v->tank_lo2_pressure);
|
||
FieldCodec::putU16(p, PS_TANK_CO2_PRES, v->tank_co2_pressure);
|
||
FieldCodec::putU16(p, PS_TANK_LO2_LEVEL, v->tank_lo2_level);
|
||
FieldCodec::putU16(p, PS_ALLOY_H2_FLOW, v->alloy_h2_flow);
|
||
FieldCodec::putU16(p, PS_FC_H2_FLOW, v->fc_h2_flow);
|
||
FieldCodec::putU16(p, PS_FC_O2_FLOW, v->fc_o2_flow);
|
||
|
||
FieldCodec::putU16(p, PS_EMER_DEPTH, v->emergency_float_depth);
|
||
FieldCodec::putU16(p, PS_EMER_TIME, v->emergency_float_time);
|
||
|
||
FieldCodec::putU16(p, PS_CABIN_P1, v->cabin_pressure1);
|
||
FieldCodec::putU16(p, PS_CABIN_P2, v->cabin_pressure2);
|
||
FieldCodec::putU16(p, PS_CABIN_T1, v->cabin_temp1);
|
||
FieldCodec::putU16(p, PS_CABIN_T2, v->cabin_temp2);
|
||
FieldCodec::putU16(p, PS_CABIN_H1, v->cabin_humidity1);
|
||
FieldCodec::putU16(p, PS_CABIN_H2, v->cabin_humidity2);
|
||
FieldCodec::putU16(p, PS_H2_C1, v->h2_concentration1);
|
||
FieldCodec::putU16(p, PS_H2_C2, v->h2_concentration2);
|
||
FieldCodec::putU16(p, PS_H2_C3, v->h2_concentration3);
|
||
FieldCodec::putU16(p, PS_O2_C1, v->o2_concentration1);
|
||
FieldCodec::putU16(p, PS_O2_C2, v->o2_concentration2);
|
||
FieldCodec::putU16(p, PS_CH3OH_C1, v->ch3oh_concentration1);
|
||
FieldCodec::putU16(p, PS_CH3OH_C2, v->ch3oh_concentration2);
|
||
|
||
FieldCodec::putU8(p, PS_FLAME1, v->flame_detector1);
|
||
FieldCodec::putU8(p, PS_FLAME2, v->flame_detector2);
|
||
FieldCodec::putU16(p, PS_RESV1, v->pmReserved1);
|
||
FieldCodec::putU16(p, PS_RESV2, v->pmReserved2);
|
||
|
||
FieldCodec::putU16(p, PS_EB1_VOLTAGE, v->emergency_battery1_voltage);
|
||
FieldCodec::putU16(p, PS_EB1_CURRENT, v->emergency_battery1_current);
|
||
FieldCodec::putU16(p, PS_EB1_MAX_TEMP, v->emergency_battery1_max_temp);
|
||
FieldCodec::putU16(p, PS_EB1_FAULT, v->emergency_battery1_fault_word);
|
||
FieldCodec::putU16(p, PS_EB2_VOLTAGE, v->emergency_battery2_voltage);
|
||
FieldCodec::putU16(p, PS_EB2_CURRENT, v->emergency_battery2_current);
|
||
FieldCodec::putU16(p, PS_EB2_MAX_TEMP, v->emergency_battery2_max_temp);
|
||
FieldCodec::putU16(p, PS_EB2_FAULT, v->emergency_battery2_fault_word);
|
||
|
||
FieldCodec::putU16(p, PS_INS_CABIN_OX, v->ins_cabin_ox_concentration);
|
||
FieldCodec::putU16(p, PS_INS_CABIN_TEMP, v->ins_cabin_temperature);
|
||
FieldCodec::putU16(p, PS_INS_CABIN_HUM, v->ins_cabin_humidity);
|
||
FieldCodec::putU16(p, PS_INS_CABIN_PRES, v->ins_cabin_pressure);
|
||
FieldCodec::putU16(p, PS_DYN_CABIN_OX, v->dyn_cabin_ox_concentration);
|
||
FieldCodec::putU16(p, PS_DYN_CABIN_TEMP, v->dyn_cabin_temperature);
|
||
FieldCodec::putU16(p, PS_DYN_CABIN_HUM, v->dyn_cabin_humidity);
|
||
FieldCodec::putU16(p, PS_DYN_CABIN_PRES, v->dyn_cabin_pressure);
|
||
FieldCodec::putU8(p, PS_RESV3, v->pmReserved3);
|
||
|
||
putU8Arr(p, PS_DYN_ALARM, v->dyn_alarm_flag, 6);
|
||
putU8Arr(p, PS_INS_ALARM, v->ins_alarm_flag, 6);
|
||
|
||
FieldCodec::putU8(p, PS_INS_RELAY1, v->ins_relay_status1);
|
||
FieldCodec::putU8(p, PS_INS_RELAY2, v->ins_relay_status2);
|
||
FieldCodec::putU8(p, PS_DYN_RELAY1, v->dyn_relay_status1);
|
||
FieldCodec::putU8(p, PS_DYN_RELAY2, v->dyn_relay_status2);
|
||
|
||
FieldCodec::putU16(p, PS_INS_MAX_PWR, v->ins_max_discharge_power);
|
||
FieldCodec::putU16(p, PS_DYN_MAX_PWR, v->dyn_max_discharge_power);
|
||
FieldCodec::putU8(p, PS_INS_SOC, v->ins_soc);
|
||
FieldCodec::putU8(p, PS_DYN_SOC, v->dyn_soc);
|
||
FieldCodec::putU16(p, PS_INS_TOTAL_ENERGY, v->ins_total_energy);
|
||
FieldCodec::putU16(p, PS_DYN_TOTAL_ENERGY, v->dyn_total_energy);
|
||
FieldCodec::putU16(p, PS_INS_PWR_IN, v->ins_power_input);
|
||
FieldCodec::putU16(p, PS_DYN_PWR_IN, v->dyn_power_input);
|
||
|
||
FieldCodec::putU8(p, PS_INS_CHARGE_ST, v->ins_charge_status);
|
||
FieldCodec::putU8(p, PS_DYN_CHARGE_ST, v->dyn_charge_status);
|
||
|
||
FieldCodec::putU16(p, PS_INS_V_LINK, v->ins_voltage_link);
|
||
FieldCodec::putU16(p, PS_INS_V_PACK, v->ins_voltage_pack);
|
||
FieldCodec::putU16(p, PS_INS_CURRENT, v->ins_current);
|
||
FieldCodec::putU16(p, PS_INS_RES_POS, v->ins_resistance_pos);
|
||
FieldCodec::putU16(p, PS_INS_RES_NEG, v->ins_resistance_neg);
|
||
FieldCodec::putU16(p, PS_DYN_V_LINK, v->dyn_voltage_link);
|
||
FieldCodec::putU16(p, PS_DYN_V_PACK, v->dyn_voltage_pack);
|
||
FieldCodec::putU16(p, PS_DYN_CURRENT, v->dyn_current);
|
||
FieldCodec::putU16(p, PS_DYN_RES_POS, v->dyn_resistance_pos);
|
||
FieldCodec::putU16(p, PS_DYN_RES_NEG, v->dyn_resistance_neg);
|
||
|
||
FieldCodec::putU8(p, PS_INS_EMERGENCY, v->ins_emergency_status);
|
||
FieldCodec::putU8(p, PS_DYN_EMERGENCY, v->dyn_emergency_status);
|
||
|
||
FieldCodec::putU8(p, PS_INS_SOC_H1, v->ins_soc_threshold1);
|
||
FieldCodec::putU8(p, PS_INS_SOC_H2, v->ins_soc_threshold2);
|
||
FieldCodec::putU8(p, PS_INS_SOC_H3, v->ins_soc_threshold3);
|
||
FieldCodec::putU8(p, PS_INS_PWR_L1, v->ins_power_limit1);
|
||
FieldCodec::putU8(p, PS_INS_PWR_L2, v->ins_power_limit2);
|
||
FieldCodec::putU8(p, PS_DYN_SOC_H1, v->dyn_soc_threshold1);
|
||
FieldCodec::putU8(p, PS_DYN_SOC_H2, v->dyn_soc_threshold2);
|
||
FieldCodec::putU8(p, PS_DYN_SOC_H3, v->dyn_soc_threshold3);
|
||
FieldCodec::putU8(p, PS_DYN_PWR_L1, v->dyn_power_limit1);
|
||
FieldCodec::putU8(p, PS_DYN_PWR_L2, v->dyn_power_limit2);
|
||
|
||
FieldCodec::putU32(p, PS_ONLINE_FLAG1, v->device_online_flag1);
|
||
FieldCodec::putU32(p, PS_ONLINE_FLAG2, v->device_online_flag2);
|
||
FieldCodec::putU32(p, PS_RESV4, v->pmReserved4);
|
||
|
||
FieldCodec::putU8(p, PS_HEARTBEAT, v->heartbeat);
|
||
FieldCodec::putU8(p, PS_EMERGENCY_CMD, v->emergency_cmd);
|
||
|
||
return Frame::build(id(), p, checksum());
|
||
}
|
||
|
||
bool PmStatusMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
|
||
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
|
||
PmStatusValue* v = static_cast<PmStatusValue*>(obj);
|
||
size_t o = FRAME_HEADER_LEN;
|
||
|
||
v->fc_mode = FieldCodec::getU8(frame, o + PS_MODE);
|
||
v->fc_status = FieldCodec::getU8(frame, o + PS_STATUS);
|
||
v->fault_level_1 = FieldCodec::getU16(frame, o + PS_FL1);
|
||
v->fault_level_2 = FieldCodec::getU16(frame, o + PS_FL2);
|
||
v->fault_level_3 = FieldCodec::getU16(frame, o + PS_FL3);
|
||
v->fault_level_4 = FieldCodec::getU16(frame, o + PS_FL4);
|
||
v->total_generation_time = FieldCodec::getU16(frame, o + PS_GEN_TIME);
|
||
v->fc_fault_level = FieldCodec::getU8(frame, o + PS_FAULT_LEVEL);
|
||
v->output_power_limit = FieldCodec::getU16(frame, o + PS_OUT_POWER_LIMIT);
|
||
v->generation_power = FieldCodec::getU16(frame, o + PS_GEN_POWER);
|
||
v->hydrogen_capacity = FieldCodec::getU8(frame, o + PS_H2_CAP);
|
||
v->liquid_oxygen_capacity = FieldCodec::getU8(frame, o + PS_LO2_CAP);
|
||
|
||
v->fc1_min_cell_voltage = FieldCodec::getU8(frame, o + PS_FC1_MIN_V);
|
||
v->fc1_min_cell_pos = FieldCodec::getU8(frame, o + PS_FC1_MIN_POS);
|
||
v->fc1_avg_cell_voltage = FieldCodec::getU8(frame, o + PS_FC1_AVG_V);
|
||
v->fc2_min_cell_voltage = FieldCodec::getU8(frame, o + PS_FC2_MIN_V);
|
||
v->fc2_min_cell_pos = FieldCodec::getU8(frame, o + PS_FC2_MIN_POS);
|
||
v->fc2_avg_cell_voltage = FieldCodec::getU8(frame, o + PS_FC2_AVG_V);
|
||
|
||
v->palladium_temp = FieldCodec::getU16(frame, o + PS_PALLADIUM);
|
||
v->buffer_tank_pressure = FieldCodec::getU16(frame, o + PS_BUFFER_PRES);
|
||
v->flue_total_emission = FieldCodec::getU16(frame, o + PS_FLUE_TOTAL);
|
||
v->flue_pressure = FieldCodec::getU16(frame, o + PS_FLUE_PRES);
|
||
v->reactor_pressure = FieldCodec::getU16(frame, o + PS_REACTOR_PRES);
|
||
v->electric_valve_open = FieldCodec::getU16(frame, o + PS_EVALVE_OPEN);
|
||
v->main_pipe_pressure = FieldCodec::getU16(frame, o + PS_MAIN_PIPE_PRES);
|
||
v->aux_pipe_pressure = FieldCodec::getU16(frame, o + PS_AUX_PIPE_PRES);
|
||
|
||
v->dcdc1_in_voltage = FieldCodec::getU16(frame, o + PS_DCDC1_IN_V);
|
||
v->dcdc1_in_current = FieldCodec::getU16(frame, o + PS_DCDC1_IN_I);
|
||
v->dcdc2_in_voltage = FieldCodec::getU16(frame, o + PS_DCDC2_IN_V);
|
||
v->dcdc2_in_current = FieldCodec::getU16(frame, o + PS_DCDC2_IN_I);
|
||
v->dcdc_out_voltage = FieldCodec::getU16(frame, o + PS_DCDC_OUT_V);
|
||
v->dcdc_out_current = FieldCodec::getU16(frame, o + PS_DCDC_OUT_I);
|
||
v->dcdc_ctrl_voltage = FieldCodec::getU8(frame, o + PS_DCDC_CTRL_V);
|
||
v->dcdc_aux_voltage = FieldCodec::getU8(frame, o + PS_DCDC_AUX_V);
|
||
|
||
v->methanol_total_use = FieldCodec::getU16(frame, o + PS_METHANOL_TOTAL);
|
||
v->methanol_feed = FieldCodec::getU16(frame, o + PS_METHANOL_FEED);
|
||
v->oxygen_side_water_level = FieldCodec::getU16(frame, o + PS_O2_WATER);
|
||
v->hydrogen_side_water_level = FieldCodec::getU16(frame, o + PS_H2_WATER);
|
||
v->ballast_water_level = FieldCodec::getU16(frame, o + PS_BALLAST_WATER);
|
||
|
||
v->exhaust_inlet_pressure = FieldCodec::getU16(frame, o + PS_EXH_IN_PRES);
|
||
v->exhaust_outlet_pressure = FieldCodec::getU16(frame, o + PS_EXH_OUT_PRES);
|
||
v->exhaust_run_freq = FieldCodec::getU16(frame, o + PS_EXH_FREQ);
|
||
v->exhaust_inlet_temp = FieldCodec::getU16(frame, o + PS_EXH_IN_TEMP);
|
||
v->exhaust_outlet_temp = FieldCodec::getU16(frame, o + PS_EXH_OUT_TEMP);
|
||
v->exhaust_water_in_pressure = FieldCodec::getU16(frame, o + PS_EXH_WIN_PRES);
|
||
v->exhaust_water_out_pressure = FieldCodec::getU16(frame, o + PS_EXH_WOUT_PRES);
|
||
|
||
v->tank_lo2_pressure = FieldCodec::getU16(frame, o + PS_TANK_LO2_PRES);
|
||
v->tank_co2_pressure = FieldCodec::getU16(frame, o + PS_TANK_CO2_PRES);
|
||
v->tank_lo2_level = FieldCodec::getU16(frame, o + PS_TANK_LO2_LEVEL);
|
||
v->alloy_h2_flow = FieldCodec::getU16(frame, o + PS_ALLOY_H2_FLOW);
|
||
v->fc_h2_flow = FieldCodec::getU16(frame, o + PS_FC_H2_FLOW);
|
||
v->fc_o2_flow = FieldCodec::getU16(frame, o + PS_FC_O2_FLOW);
|
||
|
||
v->emergency_float_depth = FieldCodec::getU16(frame, o + PS_EMER_DEPTH);
|
||
v->emergency_float_time = FieldCodec::getU16(frame, o + PS_EMER_TIME);
|
||
|
||
v->cabin_pressure1 = FieldCodec::getU16(frame, o + PS_CABIN_P1);
|
||
v->cabin_pressure2 = FieldCodec::getU16(frame, o + PS_CABIN_P2);
|
||
v->cabin_temp1 = FieldCodec::getU16(frame, o + PS_CABIN_T1);
|
||
v->cabin_temp2 = FieldCodec::getU16(frame, o + PS_CABIN_T2);
|
||
v->cabin_humidity1 = FieldCodec::getU16(frame, o + PS_CABIN_H1);
|
||
v->cabin_humidity2 = FieldCodec::getU16(frame, o + PS_CABIN_H2);
|
||
v->h2_concentration1 = FieldCodec::getU16(frame, o + PS_H2_C1);
|
||
v->h2_concentration2 = FieldCodec::getU16(frame, o + PS_H2_C2);
|
||
v->h2_concentration3 = FieldCodec::getU16(frame, o + PS_H2_C3);
|
||
v->o2_concentration1 = FieldCodec::getU16(frame, o + PS_O2_C1);
|
||
v->o2_concentration2 = FieldCodec::getU16(frame, o + PS_O2_C2);
|
||
v->ch3oh_concentration1 = FieldCodec::getU16(frame, o + PS_CH3OH_C1);
|
||
v->ch3oh_concentration2 = FieldCodec::getU16(frame, o + PS_CH3OH_C2);
|
||
|
||
v->flame_detector1 = FieldCodec::getU8(frame, o + PS_FLAME1);
|
||
v->flame_detector2 = FieldCodec::getU8(frame, o + PS_FLAME2);
|
||
v->pmReserved1 = FieldCodec::getU16(frame, o + PS_RESV1);
|
||
v->pmReserved2 = FieldCodec::getU16(frame, o + PS_RESV2);
|
||
|
||
v->emergency_battery1_voltage = FieldCodec::getU16(frame, o + PS_EB1_VOLTAGE);
|
||
v->emergency_battery1_current = FieldCodec::getU16(frame, o + PS_EB1_CURRENT);
|
||
v->emergency_battery1_max_temp = FieldCodec::getU16(frame, o + PS_EB1_MAX_TEMP);
|
||
v->emergency_battery1_fault_word = FieldCodec::getU16(frame, o + PS_EB1_FAULT);
|
||
v->emergency_battery2_voltage = FieldCodec::getU16(frame, o + PS_EB2_VOLTAGE);
|
||
v->emergency_battery2_current = FieldCodec::getU16(frame, o + PS_EB2_CURRENT);
|
||
v->emergency_battery2_max_temp = FieldCodec::getU16(frame, o + PS_EB2_MAX_TEMP);
|
||
v->emergency_battery2_fault_word = FieldCodec::getU16(frame, o + PS_EB2_FAULT);
|
||
|
||
v->ins_cabin_ox_concentration = FieldCodec::getU16(frame, o + PS_INS_CABIN_OX);
|
||
v->ins_cabin_temperature = FieldCodec::getU16(frame, o + PS_INS_CABIN_TEMP);
|
||
v->ins_cabin_humidity = FieldCodec::getU16(frame, o + PS_INS_CABIN_HUM);
|
||
v->ins_cabin_pressure = FieldCodec::getU16(frame, o + PS_INS_CABIN_PRES);
|
||
v->dyn_cabin_ox_concentration = FieldCodec::getU16(frame, o + PS_DYN_CABIN_OX);
|
||
v->dyn_cabin_temperature = FieldCodec::getU16(frame, o + PS_DYN_CABIN_TEMP);
|
||
v->dyn_cabin_humidity = FieldCodec::getU16(frame, o + PS_DYN_CABIN_HUM);
|
||
v->dyn_cabin_pressure = FieldCodec::getU16(frame, o + PS_DYN_CABIN_PRES);
|
||
v->pmReserved3 = FieldCodec::getU8(frame, o + PS_RESV3);
|
||
|
||
getU8Arr(frame, o + PS_DYN_ALARM, v->dyn_alarm_flag, 6);
|
||
getU8Arr(frame, o + PS_INS_ALARM, v->ins_alarm_flag, 6);
|
||
|
||
v->ins_relay_status1 = FieldCodec::getU8(frame, o + PS_INS_RELAY1);
|
||
v->ins_relay_status2 = FieldCodec::getU8(frame, o + PS_INS_RELAY2);
|
||
v->dyn_relay_status1 = FieldCodec::getU8(frame, o + PS_DYN_RELAY1);
|
||
v->dyn_relay_status2 = FieldCodec::getU8(frame, o + PS_DYN_RELAY2);
|
||
|
||
v->ins_max_discharge_power = FieldCodec::getU16(frame, o + PS_INS_MAX_PWR);
|
||
v->dyn_max_discharge_power = FieldCodec::getU16(frame, o + PS_DYN_MAX_PWR);
|
||
v->ins_soc = FieldCodec::getU8(frame, o + PS_INS_SOC);
|
||
v->dyn_soc = FieldCodec::getU8(frame, o + PS_DYN_SOC);
|
||
v->ins_total_energy = FieldCodec::getU16(frame, o + PS_INS_TOTAL_ENERGY);
|
||
v->dyn_total_energy = FieldCodec::getU16(frame, o + PS_DYN_TOTAL_ENERGY);
|
||
v->ins_power_input = FieldCodec::getU16(frame, o + PS_INS_PWR_IN);
|
||
v->dyn_power_input = FieldCodec::getU16(frame, o + PS_DYN_PWR_IN);
|
||
|
||
v->ins_charge_status = FieldCodec::getU8(frame, o + PS_INS_CHARGE_ST);
|
||
v->dyn_charge_status = FieldCodec::getU8(frame, o + PS_DYN_CHARGE_ST);
|
||
|
||
v->ins_voltage_link = FieldCodec::getU16(frame, o + PS_INS_V_LINK);
|
||
v->ins_voltage_pack = FieldCodec::getU16(frame, o + PS_INS_V_PACK);
|
||
v->ins_current = FieldCodec::getU16(frame, o + PS_INS_CURRENT);
|
||
v->ins_resistance_pos = FieldCodec::getU16(frame, o + PS_INS_RES_POS);
|
||
v->ins_resistance_neg = FieldCodec::getU16(frame, o + PS_INS_RES_NEG);
|
||
v->dyn_voltage_link = FieldCodec::getU16(frame, o + PS_DYN_V_LINK);
|
||
v->dyn_voltage_pack = FieldCodec::getU16(frame, o + PS_DYN_V_PACK);
|
||
v->dyn_current = FieldCodec::getU16(frame, o + PS_DYN_CURRENT);
|
||
v->dyn_resistance_pos = FieldCodec::getU16(frame, o + PS_DYN_RES_POS);
|
||
v->dyn_resistance_neg = FieldCodec::getU16(frame, o + PS_DYN_RES_NEG);
|
||
|
||
v->ins_emergency_status = FieldCodec::getU8(frame, o + PS_INS_EMERGENCY);
|
||
v->dyn_emergency_status = FieldCodec::getU8(frame, o + PS_DYN_EMERGENCY);
|
||
|
||
v->ins_soc_threshold1 = FieldCodec::getU8(frame, o + PS_INS_SOC_H1);
|
||
v->ins_soc_threshold2 = FieldCodec::getU8(frame, o + PS_INS_SOC_H2);
|
||
v->ins_soc_threshold3 = FieldCodec::getU8(frame, o + PS_INS_SOC_H3);
|
||
v->ins_power_limit1 = FieldCodec::getU8(frame, o + PS_INS_PWR_L1);
|
||
v->ins_power_limit2 = FieldCodec::getU8(frame, o + PS_INS_PWR_L2);
|
||
v->dyn_soc_threshold1 = FieldCodec::getU8(frame, o + PS_DYN_SOC_H1);
|
||
v->dyn_soc_threshold2 = FieldCodec::getU8(frame, o + PS_DYN_SOC_H2);
|
||
v->dyn_soc_threshold3 = FieldCodec::getU8(frame, o + PS_DYN_SOC_H3);
|
||
v->dyn_power_limit1 = FieldCodec::getU8(frame, o + PS_DYN_PWR_L1);
|
||
v->dyn_power_limit2 = FieldCodec::getU8(frame, o + PS_DYN_PWR_L2);
|
||
|
||
v->device_online_flag1 = FieldCodec::getU32(frame, o + PS_ONLINE_FLAG1);
|
||
v->device_online_flag2 = FieldCodec::getU32(frame, o + PS_ONLINE_FLAG2);
|
||
v->pmReserved4 = FieldCodec::getU32(frame, o + PS_RESV4);
|
||
|
||
v->heartbeat = FieldCodec::getU8(frame, o + PS_HEARTBEAT);
|
||
v->emergency_cmd = FieldCodec::getU8(frame, o + PS_EMERGENCY_CMD);
|
||
return true;
|
||
}
|
||
|
||
} // namespace ccu
|