Files
H100PowerManger/test/integration/full_feeder.cpp
T
zjk e0488d513b 协议:按0824协议更新复合管控通信解析 + 新增燃料电池监控网页
- pmSysvariable/ccuUdpMsg: 域起始符改为0x40 0x40,域标识符重编号0x0001~0x0004,
  ccuState/ccuColCmd/ccuSetParmCmd 按新协议字段布局与字节序重写(状态248B/操控45B/参数28B)
- systemData/httpserver: 新增FC单片电压、甲醇制氢装置、DC/DC、尾气装置、一体化罐、
  供氢供氧流量、应急上浮等字段解析与WebSocket JSON推送
- 新增 /fcs 燃料电池监控页(fuelcell.h):实时数据显示 + 操控指令交互按钮,
  过滤日志推送消息避免界面闪烁
- SQLite/LowerCommManager/测试:更新建表列、解析打印与单元/集成测试适配新协议
2026-08-26 20:56:39 +08:00

334 lines
14 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.
//=======================================================================
// full_feeder.cpp: 集成测试用 — 仿真真实 CCU + 配电系统,向 pPowerManger
// 发送全部 5 类状态反馈 UDP 消息(CCU 状态 + 4 路配电反馈)。
// 直接使用真实 C++ 结构体构造消息(字节级与协议一致,无打包漂移)。
// 用法: fullFeeder [host] [port] [rounds] [interval_ms]
// rounds=0 表示持续发送直到被 kill。
//=======================================================================
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <thread>
#include <chrono>
#include "udpcomm/ccuUdpMsg.h"
static int g_fd = -1;
static sockaddr_in g_addr{};
static bool sendBuf(const void* buf, size_t len) {
ssize_t n = sendto(g_fd, buf, len, 0,
reinterpret_cast<sockaddr*>(&g_addr), sizeof(g_addr));
return n == (ssize_t)len;
}
// CCU 消息校验和:4 字节全宽(sum 覆盖 sizeof-4 字节)
static unsigned int ccuChecksum(const unsigned char* d, int size) {
unsigned int s = 0;
for (int i = 0; i < size - (int)sizeof(Checksum); ++i) s += d[i];
return s;
}
// 配电消息校验和:1 字节(sum 覆盖 sizeof-1 字节,&0xFF)
static unsigned char disChecksum(const unsigned char* d, int size) {
unsigned int s = 0;
for (int i = 0; i < size - (int)sizeof(cChecksum); ++i) s += d[i];
return (unsigned char)(s & 0xFF);
}
static void fillCcuState(msg_CcuStateFbMsg& m, unsigned int beat) {
memset(&m, 0, sizeof(m));
m.header.start1 = CCU_UDPMSG_START1;
m.header.start2 = CCU_UDPMSG_START2;
m.header.id = CCU_STATE_FB_ID;
m.header.length = sizeof(msg_CcuStateFbMsg); // 域字节数为整个协议包长度
m.data.fc_mode = 0x02; // 自动
m.data.fc_status = 0x06; // 运行
m.data.fc_fault_level = 0x00; // 无故障
m.data.output_power_limit = 30000;
m.data.total_generation_time = 1234;
m.data.total_generation_power = 8000;
m.data.hydrogen_capacity = 70;
m.data.liquid_oxygen_capacity = 65;
m.data.fc1_min_cell_voltage = 85; // 850mV
m.data.fc1_min_cell_pos = 12;
m.data.fc1_avg_cell_voltage = 90; // 900mV
m.data.fc2_min_cell_voltage = 84;
m.data.fc2_min_cell_pos = 8;
m.data.fc2_avg_cell_voltage = 89;
m.data.palladium_temp = 600; // 60.0℃
m.data.buffer_tank_pressure = 200; // 20.0kPa
m.data.flue_total_emission = 500; // 50.0kg
m.data.flue_pressure = 20000; // 20.000MPa
m.data.reactor_pressure = 30000; // 30.000MPa
m.data.electric_valve_open = 500; // 50.0%
m.data.main_pipe_pressure = 2000; // 20.00kPa
m.data.aux_pipe_pressure = 1800;
m.data.dcdc1_in_voltage = 700; // 70.0V
m.data.dcdc1_in_current = 120; // 12.0A
m.data.dcdc2_in_voltage = 700;
m.data.dcdc2_in_current = 120;
m.data.dcdc_out_voltage = 4800; // 480.0V
m.data.dcdc_out_current = 160; // 16.0A
m.data.dcdc_control_voltage = 100; // 25.0V
m.data.dcdc_aux_out_voltage = 100; // 12.5V
m.data.methanol_total_usage = 1000; // 100.0kg
m.data.methanol_solution_feed = 100; // 100mL/min
m.data.oxygen_water_tank_level = 50000; // 500.00mm
m.data.hydrogen_water_tank_level = 45000;
m.data.ballast_water_tank_level = 40000;
m.data.exhaust_in_pressure = 2000; // 20.00MPa
m.data.exhaust_out_pressure = 1800;
m.data.exhaust_run_freq = 5000; // 50.00Hz
m.data.exhaust_in_temp = 6000; // 60.00℃
m.data.exhaust_out_temp = 5500;
m.data.exhaust_in_water_pressure = 3000; // 30.00kPa
m.data.exhaust_out_water_pressure = 2800;
m.data.tank_lo2_pressure = 1000; // 10.00MPa
m.data.tank_co2_pressure = 800;
m.data.tank_lo2_level = 20000; // 200.00mm
m.data.alloy_h2_flow = 500; // 5.00L/min
m.data.fc_h2_flow = 450;
m.data.fc_o2_flow = 300;
m.data.emergency_float_depth = 50; // 50m
m.data.emergency_float_time = 20; // 20min
m.data.cabin_pressure1 = 10100; // 101.00kPa
m.data.cabin_pressure2 = 10100;
m.data.cabin_temp1 = 2500; // 25.00℃
m.data.cabin_temp2 = 2600;
m.data.cabin_humidity1 = 5000; // 50.00%RH
m.data.cabin_humidity2 = 5200;
m.data.flame_detector1 = 0x00;
m.data.flame_detector2 = 0x00;
m.data.h2_concentration1 = 500; // 5.00%LEL
m.data.o2_concentration1 = 200000; // 2000.00%Vol
m.data.ch3oh_concentration1 = 300;
m.data.emergency_battery1_voltage = 240;
m.data.emergency_battery1_current = 10;
m.data.emergency_battery1_max_temp = 30;
m.data.emergency_battery2_voltage = 240;
m.data.emergency_battery2_current = 10;
m.data.emergency_battery2_max_temp = 31;
m.data.cabin_ox_concentration = 2000;
m.data.cabin_temperature = 250;
m.data.cabin_humidity = 500;
m.data.cabin_pressure = 1010;
m.data.power_cabin_ox_concentration = 2000;
m.data.power_cabin_temperature = 280;
m.data.power_cabin_humidity = 480;
m.data.power_cabin_pressure = 1010;
m.data.ins_relay_status1 = 0x11;
m.data.ins_relay_status2 = 0x12;
m.data.dyn_relay_status1 = 0x11;
m.data.dyn_relay_status2 = 0x12;
m.data.ins_max_discharge_power = 200;
m.data.dyn_max_discharge_power = 400;
m.data.ins_soc = 85;
m.data.dyn_soc = 80;
m.data.ins_total_energy = 100;
m.data.dyn_total_energy = 500;
m.data.ins_power_input = 10;
m.data.dyn_power_input = 30;
m.data.ins_charge_status = 0x20; // 放电
m.data.dyn_charge_status = 0x20;
m.data.ins_voltage_link = 2400; // 24.00V
m.data.ins_voltage_pack = 2350;
m.data.ins_current = 400; // 20.0A
m.data.ins_resistance_pos = 999;
m.data.ins_resistance_neg = 999;
m.data.dyn_voltage_link = 5200; // 52.00V
m.data.dyn_voltage_pack = 5150;
m.data.dyn_current = 600; // 30.0A
m.data.dyn_resistance_pos = 999;
m.data.dyn_resistance_neg = 999;
m.data.ins_emergency_status = 0x00;
m.data.dyn_emergency_status = 0x00;
m.data.ins_soc_threshold1 = 90;
m.data.ins_soc_threshold2 = 80;
m.data.ins_soc_threshold3 = 70;
m.data.dyn_soc_threshold1 = 90;
m.data.dyn_soc_threshold2 = 80;
m.data.dyn_soc_threshold3 = 70;
m.data.ins_power_limit1 = 8;
m.data.ins_power_limit2 = 4;
m.data.dyn_power_limit1 = 8;
m.data.dyn_power_limit2 = 4;
m.data.device_online_flag1 = 0x000000FF;
m.data.device_online_flag2 = 0x0000001F;
m.data.heartbeat = static_cast<uint8_t>(beat);
m.data.emergency_command = 0x03;
m.checkCode = ccuChecksum(reinterpret_cast<unsigned char*>(&m), sizeof(m));
}
static void fillDisHighVolBus(msg_disHighVolBusFbMsg& m) {
memset(&m, 0, sizeof(m));
m.header.start1 = DIS_MSG_HEAD1;
m.header.start2 = DIS_MSG_HEAD2;
m.header.id = DIS_HVBUS_FB_ID;
m.header.length = sizeof(disHighVolBusState);
m.data.fuelCellCircuitBreaker = BREAK_ON;
m.data.powerLithiumBatteryCircuitBreaker = BREAK_ON;
m.data.propulsionMotorCircuitBreaker = BREAK_OFF;
m.data.lithiumBatteryGroupInstrumentCircuitBreaker = BREAK_ON;
m.data.dcDc5ModuleCircuitBreaker = BREAK_ON;
m.data.bowHighVoltageDistributionBoxCircuitBreaker = BREAK_ON;
m.data.sternFTDevice45CircuitBreaker = BREAK_OFF;
m.data.sternRudderSwitch1CircuitBreaker = BREAK_OFF;
m.data.sternRudderSwitch2CircuitBreaker = BREAK_OFF;
m.data.fbReservedCircuitBreaker = BREAK_OFF;
m.data.tyzReservedCircuitBreaker = BREAK_OFF;
m.data.reservedCircuitBreaker = BREAK_OFF;
m.data.dcDcFaultWord1 = 0x00;
m.data.dcDcFaultWord2 = 0x62; // 工作状态启动 + 冷却泵运行
m.data.powerBusInsulationStatus = BREAK_ON; // 正常
m.data.aBusInsulationStatus = BREAK_ON;
m.data.meterPowerLossSignal = BREAK_ON;
m.data.emergencyPowerLossSignal = BREAK_ON;
m.data.dcDcTemperature = 60;
m.data.powerBusVoltage = 5000; // 500.0V
m.data.dcDc5ModuleCurrent = 200;
m.data.powerBusCurrent = 400;
m.data.busbarAVoltage = 5000;
m.data.propulsionMotorControlBoxCurrent = 10;
m.data.busbarACurrent = 300;
m.data.lithiumBatteryGroupMeterCurrent = 50;
m.data.bowHighVoltageDistributionBoxCurrent = 100;
m.data.sternFTDevice45Current = 0;
m.data.tyzReservedSwitchCurrent = 0;
m.data.sternRudderSwitch1Current = 0;
m.data.sternRudderSwitch2Current = 0;
m.data.coolWaterPressure = 150;
m.checkCode = disChecksum(reinterpret_cast<unsigned char*>(&m), sizeof(m));
}
static void fillDisHighAVolBus(msg_disHighAVolBusFbMsg& m) {
memset(&m, 0, sizeof(m));
m.header.start1 = DIS_MSG_HEAD1;
m.header.start2 = DIS_MSG_HEAD2;
m.header.id = DIS_HVBUSA_FB_ID;
m.header.length = sizeof(disHighAVolBusState);
m.data.bowFTDevice123CircuitBreaker = BREAK_ON;
m.data.actuatorCircuitBreaker = BREAK_OFF;
m.data.mastSteeringGearControlBoxCircuitBreaker = BREAK_OFF;
m.data.xczCircuitBreaker = BREAK_ON;
m.data.bowRudderControlBoxCircuitBreaker = BREAK_OFF;
m.data.openWaterCoverStartCylinderCircuitBreaker = BREAK_OFF;
m.data.instrumentPowerFailureSignal = BREAK_ON;
m.data.emergencyPowerFailureSignal = BREAK_ON;
m.data.waterIngressionAlarm = BREAK_ON; // 正常
m.data.busbarBVoltage = 5000;
m.data.busbarBCurrent = 300;
m.data.bowFTDevice123Current = 80;
m.data.actuatorCurrent = 0;
m.data.mastSteeringGearControlBoxCurrent = 0;
m.data.xczCurrent = 40;
m.data.bowRudderControlBoxCurrent = 0;
m.data.openWaterCoverStartCylinderCurrent = 0;
m.checkCode = disChecksum(reinterpret_cast<unsigned char*>(&m), sizeof(m));
}
static void fillDisLowMainBus(msg_disLowMainBusFbMsg& m) {
memset(&m, 0, sizeof(m));
m.header.start1 = DIS_MSG_HEAD1;
m.header.start2 = DIS_MSG_HEAD2;
m.header.id = DIS_HVBUSB_FB_ID;
m.header.length = sizeof(disLowMainBusState);
m.data.lithiumBatteryGroupInstrumentCircuitBreaker = BREAK_ON;
m.data.bowLowVoltageDistributionBoxCircuitBreaker = BREAK_ON;
m.data.unit4InstrumentDC48VCircuitBreaker = BREAK_ON;
m.data.dcC1DCDistributionPanelCircuitBreaker = BREAK_ON;
m.data.reservedCircuitBreaker1 = BREAK_OFF;
m.data.reservedCircuitBreaker2 = BREAK_OFF;
m.data.emergencyLithiumBatteryGroup2CircuitBreaker = BREAK_ON;
m.data.instrumentPowerFailureSignal = BREAK_ON;
m.data.emergencyPowerFailureSignal = BREAK_ON;
m.data.instrumentBusbarInsulationLow = BREAK_ON; // 正常
m.data.instrumentBusbarVoltage = 480; // 48.0V
m.data.bowLowVoltageDistributionBoxCurrent = 50;
m.data.dcC1InstrumentDC48VCurrent = 30;
m.data.emergencyLithiumBatteryGroup2Current = 10;
m.data.lithiumBatteryGroupInstrumentCurrent = 20;
m.data.unit4InstrumentDC48VCurrent = 15;
m.data.emergency2BusbarVoltage = 480;
m.data.compositeEnergyManagementSystemEmergencyDC48VCurrent = 5;
m.data.fuelCellSecuritySystemEmergencyDC48VCurrent = 5;
m.data.plcControlPowerCurrent = 8;
m.checkCode = disChecksum(reinterpret_cast<unsigned char*>(&m), sizeof(m));
}
static void fillDisLowBus(msg_disLowBusFbMsg& m) {
memset(&m, 0, sizeof(m));
m.header.start1 = DIS_MSG_HEAD1;
m.header.start2 = DIS_MSG_HEAD2;
m.header.id = DIS_LVBUS_FB_ID;
m.header.length = sizeof(disLowBusState);
m.data.unit1CircuitBreaker = BREAK_ON;
m.data.unit2CircuitBreaker = BREAK_ON;
m.data.unit3CircuitBreaker = BREAK_ON;
m.data.unit5CircuitBreaker = BREAK_OFF;
m.data.bowPZDeviceCircuitBreaker = BREAK_ON;
m.data.reservedCircuitBreaker1 = BREAK_OFF;
m.data.reservedCircuitBreaker2 = BREAK_OFF;
m.data.emergencyLithiumBatteryGroup1CircuitBreaker = BREAK_ON;
m.data.powerFailureSignal = BREAK_ON;
m.data.emergencyPowerFailureSignal = BREAK_ON;
m.data.waterIngressionAlarm = BREAK_ON; // 正常
m.data.instrumentBusbarVoltage = 240; // 24.0V
m.data.instrumentBusbarCurrent = 60;
m.data.unit1Current = 15;
m.data.unit2Current = 15;
m.data.unit3Current = 15;
m.data.unit5Current = 0;
m.data.bowPZDeviceCurrent = 10;
m.data.emergencyLithiumBatteryGroup1Current = 8;
m.data.emergency1BusbarVoltage = 240;
m.checkCode = disChecksum(reinterpret_cast<unsigned char*>(&m), sizeof(m));
}
int main(int argc, char* argv[]) {
const char* host = (argc > 1) ? argv[1] : "127.0.0.1";
int port = (argc > 2) ? atoi(argv[2]) : 5001;
int rounds = (argc > 3) ? atoi(argv[3]) : 0; // 0 = 持续
int intervalMs = (argc > 4) ? atoi(argv[4]) : 200;
g_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (g_fd < 0) { perror("socket"); return 1; }
g_addr.sin_family = AF_INET;
g_addr.sin_port = htons(static_cast<unsigned short>(port));
if (inet_pton(AF_INET, host, &g_addr.sin_addr) != 1) {
perror("inet_pton"); close(g_fd); return 1;
}
unsigned int beat = 1;
int sent = 0;
while (rounds == 0 || sent < rounds) {
msg_CcuStateFbMsg ccu;
msg_disHighVolBusFbMsg hv;
msg_disHighAVolBusFbMsg hva;
msg_disLowMainBusFbMsg lvmain;
msg_disLowBusFbMsg lv;
fillCcuState(ccu, beat);
fillDisHighVolBus(hv);
fillDisHighAVolBus(hva);
fillDisLowMainBus(lvmain);
fillDisLowBus(lv);
if (!sendBuf(&ccu, sizeof(ccu)) ||
!sendBuf(&hv, sizeof(hv)) ||
!sendBuf(&hva, sizeof(hva)) ||
!sendBuf(&lvmain, sizeof(lvmain)) ||
!sendBuf(&lv, sizeof(lv))) {
perror("sendto"); break;
}
++beat;
++sent;
std::this_thread::sleep_for(std::chrono::milliseconds(intervalMs));
}
close(g_fd);
printf("sent %d round(s) of 5 message types to %s:%d\n", sent, host, port);
return 0;
}