Files
H100PowerManger/src/pCCU/protocol/FcProtocol.cpp
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

345 lines
20 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.
#include "FcProtocol.h"
#include "FieldCodec.h"
#include "Frame.h"
#include "MessageRegistry.h"
namespace ccu {
void registerFcMessages(MessageRegistry& reg) {
reg.registerMessage(std::unique_ptr<Message>(new FcControlMessage()));
reg.registerMessage(std::unique_ptr<Message>(new FcStatusMessage()));
}
//============================================================================
// 0x0001 控制指令域编解码
// 数据域 18 字节(字节7~24),偏移 0~17;整包 24 字节
//============================================================================
namespace {
// 数据域内偏移(相对数据域起点,offset = 文档字节号 - 7)
enum : size_t {
CO_MODE = 0, // 模式设定 (字节7)
CO_CMD = 1, // 操控指令 (字节8)
CO_OUT_POWER = 2, // 输出功率指令 (字节9)
CO_PITCH1 = 3, // 纵倾姿态数据1 int16 (字节10,11)
CO_RESERVED1 = 5, // 预留 (字节12,13),0827协议由纵倾姿态数据2改为预留
CO_ROLL1 = 7, // 横倾姿态数据1 int16 (字节14,15)
CO_RESERVED2 = 9, // 预留 (字节16,17),0827协议由横倾姿态数据2改为预留
CO_EMER_ALLOW = 11, // 应急允许 (字节18)
CO_DEPTH = 12, // 潜深深度 u16 (字节19,20)
CO_SUPPLY_CMD = 14, // 补给/排放指令 (字节21)
CO_RESERVED5 = 15, // 预留指令5 (字节22)
CO_RESERVED6 = 16, // 预留指令6 (字节23)
CO_HEARTBEAT = 17, // 通信心跳 (字节24)
};
} // namespace
std::vector<uint8_t> FcControlMessage::encode(const void* obj) const {
const FcControlValue* v = static_cast<const FcControlValue*>(obj);
std::vector<uint8_t> payload(payloadLength(), 0);
FieldCodec::putU8(payload, CO_MODE, v->mode);
FieldCodec::putU8(payload, CO_CMD, v->cmd);
FieldCodec::putU8(payload, CO_OUT_POWER, v->outputPower);
FieldCodec::putU16(payload, CO_PITCH1, static_cast<uint16_t>(v->pitch1));
FieldCodec::putU16(payload, CO_RESERVED1, 0); // 预留恒填0
FieldCodec::putU16(payload, CO_ROLL1, static_cast<uint16_t>(v->roll1));
FieldCodec::putU16(payload, CO_RESERVED2, 0); // 预留恒填0
FieldCodec::putU8(payload, CO_EMER_ALLOW, v->emergencyAllow);
FieldCodec::putU16(payload, CO_DEPTH, v->depth);
FieldCodec::putU8(payload, CO_SUPPLY_CMD, v->supplyCmd);
FieldCodec::putU8(payload, CO_RESERVED5, v->reservedCmd5);
FieldCodec::putU8(payload, CO_RESERVED6, v->reservedCmd6);
FieldCodec::putU8(payload, CO_HEARTBEAT, v->heartbeat);
return Frame::build(id(), payload, checksum());
}
bool FcControlMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
FcControlValue* v = static_cast<FcControlValue*>(obj);
size_t o = FRAME_HEADER_LEN; // 数据域起点
v->mode = FieldCodec::getU8(frame, o + CO_MODE);
v->cmd = FieldCodec::getU8(frame, o + CO_CMD);
v->outputPower = FieldCodec::getU8(frame, o + CO_OUT_POWER);
v->pitch1 = static_cast<int16_t>(FieldCodec::getU16(frame, o + CO_PITCH1));
// 字节12,13 预留,忽略
v->roll1 = static_cast<int16_t>(FieldCodec::getU16(frame, o + CO_ROLL1));
// 字节16,17 预留,忽略
v->emergencyAllow = FieldCodec::getU8(frame, o + CO_EMER_ALLOW);
v->depth = FieldCodec::getU16(frame, o + CO_DEPTH);
v->supplyCmd = FieldCodec::getU8(frame, o + CO_SUPPLY_CMD);
v->reservedCmd5 = FieldCodec::getU8(frame, o + CO_RESERVED5);
v->reservedCmd6 = FieldCodec::getU8(frame, o + CO_RESERVED6);
v->heartbeat = FieldCodec::getU8(frame, o + CO_HEARTBEAT);
return true;
}
//============================================================================
// 0x0002 状态反馈域编解码
// 数据域 144 字节
//============================================================================
namespace {
// 数据域内各字段偏移(相对数据域起点,offset = 文档字节号 - 7)
// 注意:文档中"系统故障等级"为字节19(1字节),字节20为隐式保留位,
// "系统发电功率"从字节21(offset 14)开始,其后的字段均按此定位。
enum : size_t {
OFF_MODE = 0, // 运行模式 (字节7)
OFF_STATUS = 1, // 运行状态 (字节8)
OFF_FL1 = 2, // 一级故障码 u16 (字节9-10)
OFF_FL2 = 4, // 二级故障码 (字节11-12)
OFF_FL3 = 6, // 三级故障码 (字节13-14)
OFF_FL4 = 8, // 四级故障码 (字节15-16)
OFF_GEN_TIME = 10, // 累积发电时间 u16 (字节17-18)
OFF_FAULT_LEVEL = 12, // 系统故障等级 (字节19)
// 字节20 隐式保留(offset 13)
OFF_GEN_POWER = 14, // 系统发电功率 u16 (字节21-22)
OFF_H2_CAP = 16, // 储氢剩余容量 (字节23)
OFF_LO2_CAP = 17, // 液氧剩余容量 (字节24)
OFF_FC1_MIN_V = 18, // I#FC最低单片电压 (字节25)
OFF_FC1_MIN_POS = 19, // I#FC最低单片电压位置 (字节26)
OFF_FC1_AVG_V = 20, // I#FC平均单片电压 (字节27)
OFF_FC2_MIN_V = 21, // 2#FC最低单片电压 (字节28)
OFF_FC2_MIN_POS = 22, // 2#FC最低单片电压位置 (字节29)
OFF_FC2_AVG_V = 23, // 2#FC平均单片电压 (字节30)
OFF_PALLADIUM_TEMP = 24, // 钯膜最高温度 u16 (字节31-32)
OFF_BUFFER_PRES = 26, // 缓冲罐压力 (字节33-34)
OFF_FLUE_TOTAL = 28, // 烟气累计排放量 (字节35-36)
OFF_FLUE_PRES = 30, // 烟气压力 (字节37-38)
OFF_REACTOR_PRES = 32, // 反应器压力 (字节39-40)
OFF_EVALVE_OPEN = 34, // 电动阀开度 (字节41-42)
OFF_DCDC1_IN_V = 36, // DC/DC通道1输入电压 (字节43-44)
OFF_DCDC1_IN_I = 38, // DC/DC通道1输入电流 (字节45-46)
OFF_DCDC2_IN_V = 40, // DC/DC通道2输入电压 (字节47-48)
OFF_DCDC2_IN_I = 42, // DC/DC通道2输入电流 (字节49-50)
OFF_DCDC_OUT_V = 44, // DC/DC输出电压 (字节51-52)
OFF_DCDC_OUT_I = 46, // DC/DC输出电流 (字节53-54)
OFF_DCDC_CTRL_V = 48, // DC/DC控制电源电压 (字节55)
OFF_DCDC_AUX_V = 49, // DC/DC辅电输出电压 (字节56)
OFF_METHANOL_TOTAL = 50, // 甲醇累计使用量 u16 (字节57-58)
OFF_METHANOL_FEED = 52, // 甲醇溶液进料量 (字节59-60)
OFF_O2_WATER = 54, // 氧侧生成水箱液位 (字节61-62)
OFF_H2_WATER = 56, // 氢侧生成水箱液位 (字节63-64)
OFF_BALLAST_WATER = 58, // 配重水箱液位 (字节65-66)
OFF_EXH_IN_PRES = 60, // 尾气装置进气压力 (字节67-68)
OFF_EXH_OUT_PRES = 62, // 尾气装置排气压力 (字节69-70)
OFF_CABIN_P1 = 64, // 舱室压力1 (字节71-72)
OFF_CABIN_P2 = 66, // 舱室压力2 (字节73-74)
OFF_CABIN_T1 = 68, // 舱室温度1 (字节75-76)
OFF_CABIN_T2 = 70, // 舱室温度2 (字节77-78)
OFF_CABIN_H1 = 72, // 舱室湿度1 (字节79-80)
OFF_CABIN_H2 = 74, // 舱室湿度2 (字节81-82)
OFF_H2_C1 = 76, // 舱室H2浓度1 (字节83-84)
OFF_H2_C2 = 78, // 舱室H2浓度2 (字节85-86)
OFF_H2_C3 = 80, // 舱室H2浓度3 (字节87-88)
OFF_O2_C1 = 82, // 舱室O2浓度1 (字节89-90)
OFF_O2_C2 = 84, // 舱室O2浓度2 (字节91-92)
OFF_CH3OH_C1 = 86, // 舱室甲醇浓度1 (字节93-94)
OFF_CH3OH_C2 = 88, // 舱室甲醇浓度2 (字节95-96)
OFF_FLAME1 = 90, // 火焰探测器1 (字节97)
OFF_FLAME2 = 91, // 火焰探测器2 (字节98)
OFF_EMER_DEPTH = 92, // 应急上浮深度 u16 (字节99-100)
OFF_EMER_TIME = 94, // 应急上浮时间 (字节101-102)
OFF_EXH_FREQ = 96, // 尾气运行频率 (字节103-104)
OFF_EXH_IN_TEMP = 98, // 尾气进气温度 (字节105-106)
OFF_EXH_OUT_TEMP = 100, // 尾气排气温度 (字节107-108)
OFF_EXH_WIN_PRES = 102, // 尾气进水压力 (字节109-110)
OFF_EXH_WOUT_PRES = 104, // 尾气排水压力 (字节111-112)
OFF_TANK_LO2_PRES = 106, // 液氧罐压力 (字节113-114)
OFF_TANK_CO2_PRES = 108, // 二氧化碳压力 (字节115-116)
OFF_TANK_LO2_LEVEL = 110, // 液氧罐液位 (字节117-118)
OFF_ALLOY_H2_FLOW = 112, // 合金供氢流量 (字节119-120)
OFF_FC_H2_FLOW = 114, // FC供氢流量 (字节121-122)
OFF_FC_O2_FLOW = 116, // FC供氧流量 (字节123-124)
OFF_RESERVED = 118, // 预留1~11 u16*11 -> 118..138 (字节125-146)
OFF_REMAIN_GEN = 140, // 剩余发电量 u16 (字节147,148),0827协议由预留12改为
OFF_HEARTBEAT = 142, // 通信心跳 (字节149)
OFF_EMERGENCY_CMD = 143, // 应急指令 (字节150)
};
inline void getU16Arr(const std::vector<uint8_t>& frame, size_t off, uint16_t* dst, size_t n) {
for (size_t i = 0; i < n; ++i) dst[i] = FieldCodec::getU16(frame, off + i * 2);
}
inline void putU16Arr(std::vector<uint8_t>& p, size_t off, const uint16_t* src, size_t n) {
for (size_t i = 0; i < n; ++i) FieldCodec::putU16(p, off + i * 2, src[i]);
}
} // namespace
std::vector<uint8_t> FcStatusMessage::encode(const void* obj) const {
const FcStatusValue* v = static_cast<const FcStatusValue*>(obj);
std::vector<uint8_t> p(payloadLength(), 0);
FieldCodec::putU8(p, OFF_MODE, v->fc_mode);
FieldCodec::putU8(p, OFF_STATUS, v->fc_status);
FieldCodec::putU16(p, OFF_FL1, v->fault_level_1);
FieldCodec::putU16(p, OFF_FL2, v->fault_level_2);
FieldCodec::putU16(p, OFF_FL3, v->fault_level_3);
FieldCodec::putU16(p, OFF_FL4, v->fault_level_4);
FieldCodec::putU16(p, OFF_GEN_TIME, v->total_generation_time);
FieldCodec::putU8(p, OFF_FAULT_LEVEL, v->fc_fault_level);
FieldCodec::putU16(p, OFF_GEN_POWER, v->generation_power);
FieldCodec::putU8(p, OFF_H2_CAP, v->hydrogen_capacity);
FieldCodec::putU8(p, OFF_LO2_CAP, v->liquid_oxygen_capacity);
FieldCodec::putU8(p, OFF_FC1_MIN_V, v->fc1_min_cell_voltage);
FieldCodec::putU8(p, OFF_FC1_MIN_POS, v->fc1_min_cell_pos);
FieldCodec::putU8(p, OFF_FC1_AVG_V, v->fc1_avg_cell_voltage);
FieldCodec::putU8(p, OFF_FC2_MIN_V, v->fc2_min_cell_voltage);
FieldCodec::putU8(p, OFF_FC2_MIN_POS, v->fc2_min_cell_pos);
FieldCodec::putU8(p, OFF_FC2_AVG_V, v->fc2_avg_cell_voltage);
FieldCodec::putU16(p, OFF_PALLADIUM_TEMP, v->palladium_temp);
FieldCodec::putU16(p, OFF_BUFFER_PRES, v->buffer_tank_pressure);
FieldCodec::putU16(p, OFF_FLUE_TOTAL, v->flue_total_emission);
FieldCodec::putU16(p, OFF_FLUE_PRES, v->flue_pressure);
FieldCodec::putU16(p, OFF_REACTOR_PRES, v->reactor_pressure);
FieldCodec::putU16(p, OFF_EVALVE_OPEN, v->electric_valve_open);
FieldCodec::putU16(p, OFF_DCDC1_IN_V, v->dcdc1_in_voltage);
FieldCodec::putU16(p, OFF_DCDC1_IN_I, v->dcdc1_in_current);
FieldCodec::putU16(p, OFF_DCDC2_IN_V, v->dcdc2_in_voltage);
FieldCodec::putU16(p, OFF_DCDC2_IN_I, v->dcdc2_in_current);
FieldCodec::putU16(p, OFF_DCDC_OUT_V, v->dcdc_out_voltage);
FieldCodec::putU16(p, OFF_DCDC_OUT_I, v->dcdc_out_current);
FieldCodec::putU8(p, OFF_DCDC_CTRL_V, v->dcdc_ctrl_voltage);
FieldCodec::putU8(p, OFF_DCDC_AUX_V, v->dcdc_aux_voltage);
FieldCodec::putU16(p, OFF_METHANOL_TOTAL, v->methanol_total_use);
FieldCodec::putU16(p, OFF_METHANOL_FEED, v->methanol_feed);
FieldCodec::putU16(p, OFF_O2_WATER, v->oxygen_side_water_level);
FieldCodec::putU16(p, OFF_H2_WATER, v->hydrogen_side_water_level);
FieldCodec::putU16(p, OFF_BALLAST_WATER, v->ballast_water_level);
FieldCodec::putU16(p, OFF_EXH_IN_PRES, v->exhaust_inlet_pressure);
FieldCodec::putU16(p, OFF_EXH_OUT_PRES, v->exhaust_outlet_pressure);
FieldCodec::putU16(p, OFF_CABIN_P1, v->cabin_pressure1);
FieldCodec::putU16(p, OFF_CABIN_P2, v->cabin_pressure2);
FieldCodec::putU16(p, OFF_CABIN_T1, v->cabin_temp1);
FieldCodec::putU16(p, OFF_CABIN_T2, v->cabin_temp2);
FieldCodec::putU16(p, OFF_CABIN_H1, v->cabin_humidity1);
FieldCodec::putU16(p, OFF_CABIN_H2, v->cabin_humidity2);
FieldCodec::putU16(p, OFF_H2_C1, v->h2_concentration1);
FieldCodec::putU16(p, OFF_H2_C2, v->h2_concentration2);
FieldCodec::putU16(p, OFF_H2_C3, v->h2_concentration3);
FieldCodec::putU16(p, OFF_O2_C1, v->o2_concentration1);
FieldCodec::putU16(p, OFF_O2_C2, v->o2_concentration2);
FieldCodec::putU16(p, OFF_CH3OH_C1, v->ch3oh_concentration1);
FieldCodec::putU16(p, OFF_CH3OH_C2, v->ch3oh_concentration2);
FieldCodec::putU8(p, OFF_FLAME1, v->flame_detector1);
FieldCodec::putU8(p, OFF_FLAME2, v->flame_detector2);
FieldCodec::putU16(p, OFF_EMER_DEPTH, v->emergency_float_depth);
FieldCodec::putU16(p, OFF_EMER_TIME, v->emergency_float_time);
FieldCodec::putU16(p, OFF_EXH_FREQ, v->exhaust_run_freq);
FieldCodec::putU16(p, OFF_EXH_IN_TEMP, v->exhaust_inlet_temp);
FieldCodec::putU16(p, OFF_EXH_OUT_TEMP, v->exhaust_outlet_temp);
FieldCodec::putU16(p, OFF_EXH_WIN_PRES, v->exhaust_water_in_pressure);
FieldCodec::putU16(p, OFF_EXH_WOUT_PRES, v->exhaust_water_out_pressure);
FieldCodec::putU16(p, OFF_TANK_LO2_PRES, v->tank_lo2_pressure);
FieldCodec::putU16(p, OFF_TANK_CO2_PRES, v->tank_co2_pressure);
FieldCodec::putU16(p, OFF_TANK_LO2_LEVEL, v->tank_lo2_level);
FieldCodec::putU16(p, OFF_ALLOY_H2_FLOW, v->alloy_h2_flow);
FieldCodec::putU16(p, OFF_FC_H2_FLOW, v->fc_h2_flow);
FieldCodec::putU16(p, OFF_FC_O2_FLOW, v->fc_o2_flow);
putU16Arr(p, OFF_RESERVED, v->reserved, 11);
FieldCodec::putU16(p, OFF_REMAIN_GEN, v->remaining_generation);
FieldCodec::putU8(p, OFF_HEARTBEAT, v->heartbeat);
FieldCodec::putU8(p, OFF_EMERGENCY_CMD, v->emergency_cmd);
return Frame::build(id(), p, checksum());
}
bool FcStatusMessage::decode(const std::vector<uint8_t>& frame, void* obj) const {
if (!validateFrame(frame, id(), checksum(), totalLength())) return false;
FcStatusValue* v = static_cast<FcStatusValue*>(obj);
size_t o = FRAME_HEADER_LEN;
v->fc_mode = FieldCodec::getU8(frame, o + OFF_MODE);
v->fc_status = FieldCodec::getU8(frame, o + OFF_STATUS);
v->fault_level_1 = FieldCodec::getU16(frame, o + OFF_FL1);
v->fault_level_2 = FieldCodec::getU16(frame, o + OFF_FL2);
v->fault_level_3 = FieldCodec::getU16(frame, o + OFF_FL3);
v->fault_level_4 = FieldCodec::getU16(frame, o + OFF_FL4);
v->total_generation_time = FieldCodec::getU16(frame, o + OFF_GEN_TIME);
v->fc_fault_level = FieldCodec::getU8(frame, o + OFF_FAULT_LEVEL);
v->generation_power = FieldCodec::getU16(frame, o + OFF_GEN_POWER);
v->hydrogen_capacity = FieldCodec::getU8(frame, o + OFF_H2_CAP);
v->liquid_oxygen_capacity = FieldCodec::getU8(frame, o + OFF_LO2_CAP);
v->fc1_min_cell_voltage = FieldCodec::getU8(frame, o + OFF_FC1_MIN_V);
v->fc1_min_cell_pos = FieldCodec::getU8(frame, o + OFF_FC1_MIN_POS);
v->fc1_avg_cell_voltage = FieldCodec::getU8(frame, o + OFF_FC1_AVG_V);
v->fc2_min_cell_voltage = FieldCodec::getU8(frame, o + OFF_FC2_MIN_V);
v->fc2_min_cell_pos = FieldCodec::getU8(frame, o + OFF_FC2_MIN_POS);
v->fc2_avg_cell_voltage = FieldCodec::getU8(frame, o + OFF_FC2_AVG_V);
v->palladium_temp = FieldCodec::getU16(frame, o + OFF_PALLADIUM_TEMP);
v->buffer_tank_pressure = FieldCodec::getU16(frame, o + OFF_BUFFER_PRES);
v->flue_total_emission = FieldCodec::getU16(frame, o + OFF_FLUE_TOTAL);
v->flue_pressure = FieldCodec::getU16(frame, o + OFF_FLUE_PRES);
v->reactor_pressure = FieldCodec::getU16(frame, o + OFF_REACTOR_PRES);
v->electric_valve_open = FieldCodec::getU16(frame, o + OFF_EVALVE_OPEN);
v->dcdc1_in_voltage = FieldCodec::getU16(frame, o + OFF_DCDC1_IN_V);
v->dcdc1_in_current = FieldCodec::getU16(frame, o + OFF_DCDC1_IN_I);
v->dcdc2_in_voltage = FieldCodec::getU16(frame, o + OFF_DCDC2_IN_V);
v->dcdc2_in_current = FieldCodec::getU16(frame, o + OFF_DCDC2_IN_I);
v->dcdc_out_voltage = FieldCodec::getU16(frame, o + OFF_DCDC_OUT_V);
v->dcdc_out_current = FieldCodec::getU16(frame, o + OFF_DCDC_OUT_I);
v->dcdc_ctrl_voltage = FieldCodec::getU8(frame, o + OFF_DCDC_CTRL_V);
v->dcdc_aux_voltage = FieldCodec::getU8(frame, o + OFF_DCDC_AUX_V);
v->methanol_total_use = FieldCodec::getU16(frame, o + OFF_METHANOL_TOTAL);
v->methanol_feed = FieldCodec::getU16(frame, o + OFF_METHANOL_FEED);
v->oxygen_side_water_level= FieldCodec::getU16(frame, o + OFF_O2_WATER);
v->hydrogen_side_water_level = FieldCodec::getU16(frame, o + OFF_H2_WATER);
v->ballast_water_level = FieldCodec::getU16(frame, o + OFF_BALLAST_WATER);
v->exhaust_inlet_pressure = FieldCodec::getU16(frame, o + OFF_EXH_IN_PRES);
v->exhaust_outlet_pressure= FieldCodec::getU16(frame, o + OFF_EXH_OUT_PRES);
v->cabin_pressure1 = FieldCodec::getU16(frame, o + OFF_CABIN_P1);
v->cabin_pressure2 = FieldCodec::getU16(frame, o + OFF_CABIN_P2);
v->cabin_temp1 = FieldCodec::getU16(frame, o + OFF_CABIN_T1);
v->cabin_temp2 = FieldCodec::getU16(frame, o + OFF_CABIN_T2);
v->cabin_humidity1 = FieldCodec::getU16(frame, o + OFF_CABIN_H1);
v->cabin_humidity2 = FieldCodec::getU16(frame, o + OFF_CABIN_H2);
v->h2_concentration1 = FieldCodec::getU16(frame, o + OFF_H2_C1);
v->h2_concentration2 = FieldCodec::getU16(frame, o + OFF_H2_C2);
v->h2_concentration3 = FieldCodec::getU16(frame, o + OFF_H2_C3);
v->o2_concentration1 = FieldCodec::getU16(frame, o + OFF_O2_C1);
v->o2_concentration2 = FieldCodec::getU16(frame, o + OFF_O2_C2);
v->ch3oh_concentration1 = FieldCodec::getU16(frame, o + OFF_CH3OH_C1);
v->ch3oh_concentration2 = FieldCodec::getU16(frame, o + OFF_CH3OH_C2);
v->flame_detector1 = FieldCodec::getU8(frame, o + OFF_FLAME1);
v->flame_detector2 = FieldCodec::getU8(frame, o + OFF_FLAME2);
v->emergency_float_depth = FieldCodec::getU16(frame, o + OFF_EMER_DEPTH);
v->emergency_float_time = FieldCodec::getU16(frame, o + OFF_EMER_TIME);
v->exhaust_run_freq = FieldCodec::getU16(frame, o + OFF_EXH_FREQ);
v->exhaust_inlet_temp = FieldCodec::getU16(frame, o + OFF_EXH_IN_TEMP);
v->exhaust_outlet_temp = FieldCodec::getU16(frame, o + OFF_EXH_OUT_TEMP);
v->exhaust_water_in_pressure = FieldCodec::getU16(frame, o + OFF_EXH_WIN_PRES);
v->exhaust_water_out_pressure= FieldCodec::getU16(frame, o + OFF_EXH_WOUT_PRES);
v->tank_lo2_pressure = FieldCodec::getU16(frame, o + OFF_TANK_LO2_PRES);
v->tank_co2_pressure = FieldCodec::getU16(frame, o + OFF_TANK_CO2_PRES);
v->tank_lo2_level = FieldCodec::getU16(frame, o + OFF_TANK_LO2_LEVEL);
v->alloy_h2_flow = FieldCodec::getU16(frame, o + OFF_ALLOY_H2_FLOW);
v->fc_h2_flow = FieldCodec::getU16(frame, o + OFF_FC_H2_FLOW);
v->fc_o2_flow = FieldCodec::getU16(frame, o + OFF_FC_O2_FLOW);
getU16Arr(frame, o + OFF_RESERVED, v->reserved, 11);
v->remaining_generation = FieldCodec::getU16(frame, o + OFF_REMAIN_GEN);
v->heartbeat = FieldCodec::getU8(frame, o + OFF_HEARTBEAT);
v->emergency_cmd = FieldCodec::getU8(frame, o + OFF_EMERGENCY_CMD);
return true;
}
} // namespace ccu