- pCCU/CanBms:按《04KT38电池BCU-MBMS通信(CAN)定义》重写解码, BmsStatus 单状态模型改为 BcuNodeStatus 多节点模型(0x10XX00YY, 节点地址 01~36h),支持 0x0000 电压/电流/SOC/告警码、0x0001 单体 电压、0x0002 单体温度、0x0003 继电器、0x0006 绝缘/端口电压、 0x0010 告警位(附录1 中文码表)六类报文 - 平均单体温度偏移修正:协议文档 BYTE5 写"偏移0"有误,实测固件与 最高/最低一致均带 -40℃ 偏移(实车 0x10020002 原始 68/69 减 40 后 为 28/29℃,落在最低28~最高30区间内,按文档直读则超出物理范围) - pCCU/DbStore:新增 bcu_node 解析数据表,锂电池 BMS 报文每帧落一行 节点合成状态(原 comm_log 仅原始帧,BMS/CAN 帧此前不落 pCCU 库), buildReport 增加 BMS 记录数 - 快照/网页:BCU 按节点分组展示(告警位解析中文含义、数据 age), PM 状态报文锂电池/应急电池卡片 - pPowerManger:新增 iport 本地输入端口配置(UDP bind 延迟到 OnStartUp 读取配置后执行,保证 iport/ccuhost/ccuport 生效), 各 mission 文件补充注释 - test:CAN BCU 解码用例按新协议/新偏移更新(实车抓包 + 文档示例值), 133 项全部通过 - docs:删除旧 BMS 协议(xlsx/20230324docx),归档 04KT38 BCU-MBMS CAN 定义、配电控制器通信协议 20260824、配电系统 CAN 通讯协议 - scripts:新增 sync-board-time.sh,223 板卡(RK3588)时间校正 (本机为基准 + RTT 折半补偿对时,尽力写 RTC,支持 status/--time)
891 lines
37 KiB
C++
891 lines
37 KiB
C++
#include "LowerCommManager.h"
|
|
#include "PowerManger.h"
|
|
#include "driver.h"
|
|
#include "udpcomm/udpComm.h"
|
|
|
|
bool _ListenCB(void * pParam)
|
|
{
|
|
LowerCommManager* pMe = (LowerCommManager* )pParam;
|
|
return pMe->listenThreadFunc();
|
|
}
|
|
|
|
LowerCommManager::LowerCommManager(PowerManger* pm, long myPort, long ccuPort, const std::string& cccHost){
|
|
m_pm = pm;
|
|
m_udpComm = new udpComm();
|
|
m_port = myPort;
|
|
m_udpComm->ccuHost = cccHost;
|
|
m_udpComm->ccuPort = ccuPort;
|
|
m_udpComm->udpScoket = new XPCUdpSocket(m_port);
|
|
|
|
std::cout << MOOS::ConsoleColours::yellow() << "╔════════════════════════╗" << MOOS::ConsoleColours::reset() << std::endl;
|
|
std::cout << MOOS::ConsoleColours::yellow() << "║ [LOCAL PORT] "
|
|
<< MOOS::ConsoleColours::cyan() << m_port
|
|
<< MOOS::ConsoleColours::yellow() << std::setw(15) << " ║" << MOOS::ConsoleColours::reset() << std::endl;
|
|
|
|
std::cout << MOOS::ConsoleColours::yellow() << "║ [CCU HOST ] "
|
|
<< MOOS::ConsoleColours::cyan() << m_udpComm->ccuHost
|
|
<< MOOS::ConsoleColours::yellow() << std::setw(8) << " ║" << MOOS::ConsoleColours::reset() << std::endl;
|
|
|
|
std::cout << MOOS::ConsoleColours::yellow() << "║ [CCU PORT ] "
|
|
<< MOOS::ConsoleColours::cyan() << m_udpComm->ccuPort
|
|
<< MOOS::ConsoleColours::yellow() << std::setw(15) << " ║" << MOOS::ConsoleColours::reset() << std::endl;
|
|
std::cout << MOOS::ConsoleColours::yellow() << "╚════════════════════════╝" << MOOS::ConsoleColours::reset() << std::endl;
|
|
}
|
|
|
|
LowerCommManager::~LowerCommManager(){
|
|
try {
|
|
stopListenThread();
|
|
if (m_udpComm) {
|
|
delete m_udpComm;
|
|
m_udpComm = nullptr;
|
|
}
|
|
} catch (...) {
|
|
cerr << "Error during cleanup" << endl;
|
|
}
|
|
}
|
|
bool LowerCommManager::initUdpComm(){
|
|
if (m_udpComm->udpScoket) {
|
|
try {
|
|
std::cout << MOOS::ConsoleColours::yellow() << "Attempting to bind UDP socket..." << MOOS::ConsoleColours::reset() << std::endl;
|
|
m_udpComm->udpScoket->vBindSocket(); // 可能会抛出 XPCException 或其他 std::exception
|
|
std::cout << MOOS::ConsoleColours::green() << "UDP bind succeeded!" << MOOS::ConsoleColours::reset() << std::endl;
|
|
LOG_F(INFO, "UDP bind succeeded!");
|
|
}
|
|
catch (const std::exception& e) {
|
|
std::cerr << MOOS::ConsoleColours::red()
|
|
<< "[UDP Bind Failed] Exception: " << e.what()
|
|
<< MOOS::ConsoleColours::reset() << std::endl;
|
|
LOG_F(ERROR, "UDP bind failed: %s", e.what());
|
|
return false;
|
|
}
|
|
catch (...) {
|
|
std::cerr << MOOS::ConsoleColours::red()
|
|
<< "[UDP Bind Failed] Unknown exception occurred!"
|
|
<< MOOS::ConsoleColours::reset() << std::endl;
|
|
LOG_F(ERROR, "Unknown exception occurred during UDP bind");
|
|
return false;
|
|
}
|
|
} else {
|
|
std::cerr << MOOS::ConsoleColours::red()
|
|
<< "[UDP Init Failed] udpSocket is null!"
|
|
<< MOOS::ConsoleColours::reset() << std::endl;
|
|
LOG_F(ERROR, "udpSocket is null!");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
void LowerCommManager::setLocalPort(long port){
|
|
if (port <= 0 || port == m_port) return;
|
|
m_port = port;
|
|
if (m_udpComm && m_udpComm->udpScoket) {
|
|
// 套接字构造时即记录接收端口,改端口须重建(此时尚未 bind,重建安全)
|
|
delete m_udpComm->udpScoket;
|
|
m_udpComm->udpScoket = new XPCUdpSocket(m_port);
|
|
}
|
|
}
|
|
|
|
void LowerCommManager::setCcuAddress(const std::string& host, long port){
|
|
m_ccuHost = host;
|
|
m_ccuPort = port;
|
|
if (m_udpComm) {
|
|
m_udpComm->ccuHost = host;
|
|
m_udpComm->ccuPort = port;
|
|
}
|
|
}
|
|
|
|
void LowerCommManager::setCommLogger(ICommLogger* logger)
|
|
{
|
|
if (m_udpComm) m_udpComm->setCommLogger(logger);
|
|
}
|
|
void LowerCommManager::processPeriodicTasks() {
|
|
ccuColCmd cmd;
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_stateMutex);
|
|
cmd = m_pm->m_CcuColCmd;
|
|
}
|
|
sendCcuCommand(cmd);
|
|
m_pm->m_db->insertData(cmd);
|
|
//延时5ms
|
|
usleep(5000);
|
|
auto devStatus = m_pm->m_systemData->getDeviceCommonStatus();
|
|
if(devStatus.dis_hv_c1.isTimeout )
|
|
{
|
|
disHighVolBusCmd clr1{};
|
|
m_udpComm->sendDisSysCmd(clr1);
|
|
MOOSPause(200);
|
|
}
|
|
if(devStatus.dis_lv_c1.isTimeout )
|
|
{
|
|
disHighBVolBusCmd clr3{};
|
|
m_udpComm->sendDisSysCmd(clr3);
|
|
MOOSPause(200);
|
|
}
|
|
m_udpComm->clearMsgQueue();
|
|
}
|
|
void LowerCommManager::operate_hold()
|
|
{
|
|
disHighVolBusCmd clr1{};
|
|
disHighAVolBusCmd clr2{};
|
|
disHighBVolBusCmd clr3{};
|
|
disLowBusCmd clr4{};
|
|
m_udpComm->sendDisSysCmd(clr1);
|
|
MOOSPause(200);
|
|
m_udpComm->sendDisSysCmd(clr2);
|
|
MOOSPause(200);
|
|
m_udpComm->sendDisSysCmd(clr3);
|
|
MOOSPause(200);
|
|
m_udpComm->sendDisSysCmd(clr4);
|
|
}
|
|
bool LowerCommManager::sendCcuCommand(const ccuColCmd cmd){
|
|
// m_pm->m_db->insertCcuSysCmd(cmd);
|
|
if(!m_udpComm->sendCcuColCmd(cmd))
|
|
cout << "send ccu command failed!" << endl;
|
|
return true;
|
|
}
|
|
|
|
bool LowerCommManager::sendDisSysCommand(const disSysBreakerList& cmd){
|
|
//根据目标状态进行断路器操作
|
|
//a. 高压母线的断路器
|
|
disHighVolBusCmd a;
|
|
a.fuelCellCircuitBreaker = getBreakerOption(cmd.bus1Breaker.fuelCellCircuitBreaker);
|
|
a.lithiumBatteryGroupInstrumentCircuitBreaker = getBreakerOption(cmd.bus1Breaker.lithiumBatteryGroupInstrumentCircuitBreaker);
|
|
a.dcDc5ModuleCircuitBreaker = getBreakerOption(cmd.bus1Breaker.dcDc5ModuleCircuitBreaker);
|
|
a.powerLithiumBatteryCircuitBreaker = getBreakerOption(cmd.bus1Breaker.powerLithiumBatteryCircuitBreaker);
|
|
a.propulsionMotorCircuitBreaker = getBreakerOption(cmd.bus1Breaker.propulsionMotorCircuitBreaker);
|
|
a.bowHighVoltageDistributionBoxCircuitBreaker = getBreakerOption(cmd.bus1Breaker.bowHighVoltageDistributionBoxCircuitBreaker);
|
|
a.tyzReservedCircuitBreaker = getBreakerOption(cmd.bus1Breaker.tyzReservedCircuitBreaker);
|
|
a.sternFTDevice45CircuitBreaker = getBreakerOption(cmd.bus1Breaker.sternFTDevice45CircuitBreaker);
|
|
a.sternRudderSwitch1CircuitBreaker = getBreakerOption(cmd.bus1Breaker.sternRudderSwitch1CircuitBreaker);
|
|
a.sternRudderSwitch2CircuitBreaker = getBreakerOption(cmd.bus1Breaker.sternRudderSwitch2CircuitBreaker);
|
|
a.reservedCircuitBreaker = getBreakerOption(cmd.bus1Breaker.reservedCircuitBreaker);
|
|
a.fbReservedCircuitBreaker = getBreakerOption(cmd.bus1Breaker.fbReservedCircuitBreaker);
|
|
a.dcdc5Module = getBreakerOption(cmd.bus1Breaker.dcdcmodel);
|
|
a.coolingSystem = getBreakerOption(cmd.bus1Breaker.coolingSystem);
|
|
|
|
m_udpComm->sendDisSysCmd(a);
|
|
m_pm->m_db->insertData(a);
|
|
usleep(5000);
|
|
//b. 高压汇流排A断路器
|
|
disHighAVolBusCmd b;
|
|
b.bowFTDevice123CircuitBreaker = getBreakerOption(cmd.bus2Breaker.bowFTDevice123CircuitBreaker);
|
|
b.actuatorCircuitBreaker = getBreakerOption(cmd.bus2Breaker.actuatorCircuitBreaker);
|
|
b.mastSteeringGearControlBoxCircuitBreaker = getBreakerOption(cmd.bus2Breaker.mastSteeringGearControlBoxCircuitBreaker);
|
|
b.xczCircuitBreaker = getBreakerOption(cmd.bus2Breaker.xczCircuitBreaker);
|
|
b.bowRudderControlBoxCircuitBreaker = getBreakerOption(cmd.bus2Breaker.bowRudderControlBoxCircuitBreaker);
|
|
b.openWaterCoverStartCylinderCircuitBreaker = getBreakerOption(cmd.bus2Breaker.openWaterCoverStartCylinderCircuitBreaker);
|
|
m_udpComm->sendDisSysCmd(b);
|
|
m_pm->m_db->insertData(b);
|
|
usleep(5000);
|
|
//c. 低压主母线断路器
|
|
disHighBVolBusCmd c;
|
|
|
|
c.lithiumBatteryGroupInstrumentCircuitBreaker = 0x55;
|
|
c.bowLowVoltageDistributionBoxCircuitBreaker = 0xAA;
|
|
c.unit4InstrumentDC48VCircuitBreaker = 0xAA;
|
|
c.dcC1DCDistributionPanelCircuitBreaker = 0xAA;
|
|
c.reservedCircuitBreaker1 = 0xAA;
|
|
c.reservedCircuitBreaker2 = 0xAA;
|
|
c.emergencyLithiumBatteryGroup2CircuitBreaker = 0xAA;
|
|
|
|
m_udpComm->sendDisSysCmd(c);
|
|
m_pm->m_db->insertData(c);
|
|
usleep(5000);
|
|
//d. 闭合低压汇流排断路器
|
|
disLowBusCmd d;
|
|
d.unit1CircuitBreaker = getBreakerOption(cmd.bus4Breaker.unit1CircuitBreaker);
|
|
d.unit2CircuitBreaker = getBreakerOption(cmd.bus4Breaker.unit2CircuitBreaker);
|
|
d.unit3CircuitBreaker = getBreakerOption(cmd.bus4Breaker.unit3CircuitBreaker);
|
|
d.unit5CircuitBreaker = getBreakerOption(cmd.bus4Breaker.unit5CircuitBreaker);
|
|
d.bowPZDeviceCircuitBreaker = getBreakerOption(cmd.bus4Breaker.bowPZDeviceCircuitBreaker);
|
|
d.reservedCircuitBreaker1 = getBreakerOption(cmd.bus4Breaker.reservedCircuitBreaker1);
|
|
d.reservedCircuitBreaker2 = getBreakerOption(cmd.bus4Breaker.reservedCircuitBreaker2);
|
|
d.emergencyLithiumBatteryGroup1CircuitBreaker = getBreakerOption(cmd.bus4Breaker.emergencyLithiumBatteryGroup1CircuitBreaker);
|
|
m_udpComm->sendDisSysCmd(d);
|
|
m_pm->m_db->insertData(d);
|
|
usleep(5000);
|
|
return true;
|
|
}
|
|
|
|
|
|
void LowerCommManager::clearMsgQueue(){
|
|
m_udpComm->clearMsgQueue();
|
|
}
|
|
|
|
|
|
bool LowerCommManager::updatePoweSystemStates(){
|
|
// std::cout << "updatePoweSystemStates" << std::endl;
|
|
if(!m_udpComm->m_qReceiveCcuStateBuffer.empty())
|
|
{
|
|
double time;
|
|
if(m_udpComm->popMsgFormQueue(time, m_CcuCurrentState))
|
|
{
|
|
ccuState local = m_CcuCurrentState.data;
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_stateMutex);
|
|
m_pm->m_pmCurrentState.ccustate = local;
|
|
}
|
|
m_pm->m_db->insertData(local); //写入数据库
|
|
msg_CcuStateFbMsg_Update_time = time;
|
|
m_pm->m_systemData->updateSystemData(local);
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_systemData->m_dataMutex);
|
|
m_pm->m_systemData->device_common_status.ccu_status.lastUpdateTime = m_pm->m_lowerCommManager->msg_CcuStateFbMsg_Update_time;
|
|
}
|
|
}
|
|
}
|
|
if(!m_udpComm->m_qReceiveCcuSetParmBuffer.empty())
|
|
{
|
|
double time;
|
|
msg_CcuSetParmFbMsg setParmFb;
|
|
if(m_udpComm->popMsgFormQueue(time, setParmFb))
|
|
{
|
|
m_pm->m_db->insertData(setParmFb); //写入数据库
|
|
}
|
|
}
|
|
if(!m_udpComm->m_qReceiveDisHighVolBusBuffer.empty())
|
|
{
|
|
double time;
|
|
if(m_udpComm->popMsgFormQueue(time, m_disHighVolBusCurrentState))
|
|
{
|
|
disHighVolBusState local = m_disHighVolBusCurrentState.data;
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_stateMutex);
|
|
m_pm->m_pmCurrentState.bus1State = local;
|
|
disBus1Breaker pdis1{};
|
|
pdis1.fuelCellCircuitBreaker = (local.fuelCellCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.powerLithiumBatteryCircuitBreaker = (local.powerLithiumBatteryCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.propulsionMotorCircuitBreaker = (local.propulsionMotorCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.lithiumBatteryGroupInstrumentCircuitBreaker = (local.lithiumBatteryGroupInstrumentCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.dcDc5ModuleCircuitBreaker = (local.dcDc5ModuleCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.bowHighVoltageDistributionBoxCircuitBreaker = (local.bowHighVoltageDistributionBoxCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.sternFTDevice45CircuitBreaker = (local.sternFTDevice45CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.sternRudderSwitch1CircuitBreaker = (local.sternRudderSwitch1CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.sternRudderSwitch2CircuitBreaker = (local.sternRudderSwitch2CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.fbReservedCircuitBreaker = (local.fbReservedCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.tyzReservedCircuitBreaker = (local.tyzReservedCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.reservedCircuitBreaker = (local.reservedCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis1.paceholder = 0;
|
|
m_pm->m_currentDisBreakerState.bus1Breaker = pdis1;
|
|
}
|
|
m_pm->m_db->insertData(local); //写入数据库
|
|
msg_disHighVolBusFbMsg_Update_time = time;
|
|
m_pm->m_systemData->updateSystemData(local);
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_systemData->m_dataMutex);
|
|
m_pm->m_systemData->device_common_status.dis_hv_c1.lastUpdateTime = m_pm->m_lowerCommManager->msg_disHighVolBusFbMsg_Update_time;
|
|
}
|
|
}
|
|
}
|
|
if(!m_udpComm->m_qReceiveDisHighAVolBusBuffer.empty())
|
|
{
|
|
double time;
|
|
if(m_udpComm->popMsgFormQueue(time,m_disHighAVolBusCurrentState))
|
|
{
|
|
disHighAVolBusState local = m_disHighAVolBusCurrentState.data;
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_stateMutex);
|
|
m_pm->m_pmCurrentState.bus2State = local;
|
|
disBus2Breaker pdis2{};
|
|
pdis2.bowFTDevice123CircuitBreaker = (local.bowFTDevice123CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis2.actuatorCircuitBreaker = (local.actuatorCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis2.mastSteeringGearControlBoxCircuitBreaker = (local.mastSteeringGearControlBoxCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis2.xczCircuitBreaker = (local.xczCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis2.bowRudderControlBoxCircuitBreaker = (local.bowRudderControlBoxCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis2.openWaterCoverStartCylinderCircuitBreaker = (local.openWaterCoverStartCylinderCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis2.paceholder = 0;
|
|
m_pm->m_currentDisBreakerState.bus2Breaker = pdis2;
|
|
}
|
|
m_pm->m_db->insertData(local); //写入数据库
|
|
msg_disHighAVolBusFbMsg_Update_time = time;
|
|
m_pm->m_systemData->updateSystemData(local);
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_systemData->m_dataMutex);
|
|
m_pm->m_systemData->device_common_status.dis_hv_c2.lastUpdateTime = m_pm->m_lowerCommManager->msg_disHighAVolBusFbMsg_Update_time;
|
|
}
|
|
|
|
}
|
|
}
|
|
if(!m_udpComm->m_qReceiveDisHighBVolBusBuffer.empty())
|
|
{
|
|
double time;
|
|
if(m_udpComm->popMsgFormQueue(time,m_disHighBVolBusCurrentState))
|
|
{
|
|
disLowMainBusState local = m_disHighBVolBusCurrentState.data;
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_stateMutex);
|
|
m_pm->m_pmCurrentState.bus3State = local;
|
|
disBus3Breaker pdis3{};
|
|
pdis3.lithiumBatteryGroupInstrumentCircuitBreaker = (local.lithiumBatteryGroupInstrumentCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis3.bowLowVoltageDistributionBoxCircuitBreaker = (local.bowLowVoltageDistributionBoxCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis3.unit4InstrumentDC48VCircuitBreaker = (local.unit4InstrumentDC48VCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis3.dcC1DCDistributionPanelCircuitBreaker = (local.dcC1DCDistributionPanelCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis3.reservedCircuitBreaker1 = (local.reservedCircuitBreaker1 == BREAK_ON) ? 1 : 0;
|
|
pdis3.reservedCircuitBreaker2 = (local.reservedCircuitBreaker2 == BREAK_ON) ? 1 : 0;
|
|
pdis3.emergencyLithiumBatteryGroup2CircuitBreaker = (local.emergencyLithiumBatteryGroup2CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis3.paceholder = 0;
|
|
m_pm->m_currentDisBreakerState.bus3Breaker = pdis3;
|
|
}
|
|
m_pm->m_db->insertData(local); //写入数据库
|
|
msg_disHighBVolBusFbMsg_Update_time = time;
|
|
m_pm->m_systemData->updateSystemData(local);
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_systemData->m_dataMutex);
|
|
m_pm->m_systemData->device_common_status.dis_lv_c1.lastUpdateTime = m_pm->m_lowerCommManager->msg_disHighBVolBusFbMsg_Update_time;
|
|
}
|
|
}
|
|
}
|
|
if(!m_udpComm->m_qReceiveDisLowBusBuffer.empty())
|
|
{
|
|
double time;
|
|
if(m_udpComm->popMsgFormQueue(time,m_disLowBusState))
|
|
{
|
|
disLowBusState local = m_disLowBusState.data;
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_stateMutex);
|
|
m_pm->m_pmCurrentState.bus4State = local;
|
|
disBus4Breaker pdis4{};
|
|
pdis4.unit1CircuitBreaker = (local.unit1CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis4.unit2CircuitBreaker = (local.unit2CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis4.unit3CircuitBreaker = (local.unit3CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis4.unit5CircuitBreaker = (local.unit5CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis4.bowPZDeviceCircuitBreaker = (local.bowPZDeviceCircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis4.reservedCircuitBreaker1 = (local.reservedCircuitBreaker1 == BREAK_ON) ? 1 : 0;
|
|
pdis4.reservedCircuitBreaker2 = (local.reservedCircuitBreaker2 == BREAK_ON) ? 1 : 0;
|
|
pdis4.emergencyLithiumBatteryGroup1CircuitBreaker = (local.emergencyLithiumBatteryGroup1CircuitBreaker == BREAK_ON) ? 1 : 0;
|
|
pdis4.paceholder = 0;
|
|
m_pm->m_currentDisBreakerState.bus4Breaker = pdis4;
|
|
}
|
|
m_pm->m_db->insertData(local); //写入数据库
|
|
msg_disLowBusFbMsg_Update_time = time;
|
|
m_pm->m_systemData->updateSystemData(local);
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_systemData->m_dataMutex);
|
|
m_pm->m_systemData->device_common_status.dis_lv_c2.lastUpdateTime = m_pm->m_lowerCommManager->msg_disLowBusFbMsg_Update_time;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool LowerCommManager::listenThreadFunc()
|
|
{
|
|
cout<<MOOS::ConsoleColours::green()<< "LowerCommManager::listenThreadFunc" << MOOS::ConsoleColours::reset() << endl;
|
|
unsigned char Buff[1024];
|
|
while(!m_ListenThread.IsQuitRequested())
|
|
{
|
|
try
|
|
{
|
|
memset(Buff, 0, sizeof(Buff));
|
|
int nRead = m_udpComm->udpScoket->iRecieveMessage(Buff, sizeof(Buff));
|
|
cout<<MOOS::ConsoleColours::yellow()<< "RECEVE DATA COUNT:" << nRead << MOOS::ConsoleColours::reset() << endl;
|
|
if(nRead > 0)
|
|
{
|
|
try {
|
|
if(m_udpComm->pushMsgToQueue(Buff, nRead))
|
|
{
|
|
//更新当前状态
|
|
if(!updatePoweSystemStates())
|
|
{
|
|
std::cerr << "Error updating power system states" << std::endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(int i=0; i<m_udpComm->sError.size(); i++)
|
|
{
|
|
cout<<MOOS::ConsoleColours::red()<< m_udpComm->sError[i] << MOOS::ConsoleColours::reset() << endl;
|
|
}
|
|
}
|
|
}
|
|
catch(const std::exception& e) {
|
|
cerr << "Error processing message: " << e.what() << endl;
|
|
}
|
|
}
|
|
|
|
// 打印通信错误信息
|
|
if(!m_udpComm->sError.empty())
|
|
{
|
|
for(int i=0; i<m_udpComm->sError.size(); i++)
|
|
{
|
|
cout<<MOOS::ConsoleColours::red() << m_udpComm->sError[i] << MOOS::ConsoleColours::reset() << endl;
|
|
}
|
|
m_udpComm->sError.clear();
|
|
}
|
|
}
|
|
catch(const XPCException& e)
|
|
{
|
|
cerr << "XPCException in listenThreadFunc" << endl;
|
|
// 短暂休眠后继续尝试
|
|
MOOSPause(100);
|
|
}
|
|
catch(const std::exception& e)
|
|
{
|
|
cerr << "Exception in listenThreadFunc: " << e.what() << endl;
|
|
MOOSPause(100);
|
|
}
|
|
catch(...)
|
|
{
|
|
cerr << "Unknown exception in listenThreadFunc" << endl;
|
|
MOOSPause(100);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void LowerCommManager::startListenThread()
|
|
{
|
|
if(!m_ListenThread.IsThreadRunning())
|
|
{
|
|
m_ListenThread.Initialise(_ListenCB,this);
|
|
m_ListenThread.Start();
|
|
std::cout << "LowerCommManager::startListenThread" << std::endl;
|
|
}
|
|
}
|
|
|
|
void LowerCommManager::stopListenThread()
|
|
{
|
|
if(m_ListenThread.IsThreadRunning())
|
|
{
|
|
m_ListenThread.Stop();
|
|
std::cout << "LowerCommManager::stopListenThread" << std::endl;
|
|
}
|
|
}
|
|
|
|
char LowerCommManager::getBreakerOption(char cmd)
|
|
{
|
|
if(cmd ==1)
|
|
return 0x55;
|
|
else if(cmd ==0)
|
|
return 0xAA;
|
|
else
|
|
return 0x00;
|
|
}
|
|
|
|
//================================================================================================================
|
|
// 高电压母线断路器操作函数
|
|
bool LowerCommManager::operate_HV_fuelCellCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_fuelCellCircuit_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.fuelCellCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.fuelCellCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_powerLithiumBattery_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_powerLithiumBattery_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.powerLithiumBatteryCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.powerLithiumBatteryCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_propulsionMotor_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_propulsionMotor_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.propulsionMotorCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.propulsionMotorCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_lithiumBatteryMeter_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_lithiumBatteryMeter_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.lithiumBatteryGroupInstrumentCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.lithiumBatteryGroupInstrumentCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_dcDc5Module_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_dcDc5Module_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.dcDc5ModuleCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.dcDc5ModuleCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_bowHighVoltageBox_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_bowHighVoltageBox_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.bowHighVoltageDistributionBoxCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.bowHighVoltageDistributionBoxCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_sternFt45_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_sternFt45_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.sternFTDevice45CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.sternFTDevice45CircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_sternRudder1_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_sternRudder1_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.sternRudderSwitch1CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.sternRudderSwitch1CircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_sternRudder2_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_sternRudder2_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.sternRudderSwitch2CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.sternRudderSwitch2CircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_fbReserved_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_fbReserved_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.fbReservedCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.fbReservedCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_tyzReserved_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_tyzReserved_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.tyzReservedCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.tyzReservedCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HV_reserved_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
"HV_reserved_Breaker",
|
|
opt,
|
|
[&](disHighVolBusCmd& c){ c.reservedCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus1State.reservedCircuitBreaker; }
|
|
);
|
|
}
|
|
// bool LowerCommManager::operate_HV_dcDc5_Breaker(char opt){
|
|
// return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
// "HV_dcDc5_Breaker",
|
|
// opt,
|
|
// [&](disHighVolBusCmd& c){ c.dcdc5Module = getBreakerOption(opt); },
|
|
// [&](){ return m_pm->m_pmCurrentState.bus1State.dcDcFaultWord1&(0x02); }
|
|
// );
|
|
// }
|
|
bool LowerCommManager::operate_HV_dcDc5_Breaker(char opt)
|
|
{
|
|
disHighVolBusCmd cmd{}; // 默认全零
|
|
double t0 = MOOSTime();
|
|
bool ok = false;
|
|
const char* name = "DCDC Module";
|
|
LOG_F(INFO, "operate %s: opt=%d", name, opt);
|
|
|
|
cmd.dcdc5Module = getBreakerOption(opt);
|
|
|
|
m_udpComm->sendDisSysCmd(cmd);
|
|
|
|
// ok = m_pm->m_pmCurrentState.bus1State.dcDcFaultWord1&(0x02);
|
|
ok = m_pm->m_systemData->getDcdcStatus().workingStatus;
|
|
|
|
MOOSPause(100);
|
|
while ( !ok ) {
|
|
if( m_pm->m_systemData->getDcdcStatus().workingStatus )
|
|
{
|
|
ok = true;
|
|
break;
|
|
}
|
|
if (!m_udpComm->sendDisSysCmd(cmd)) {
|
|
LOG_F(ERROR, "operate %s: sendDisSysCmd failed", name);
|
|
ok = false;
|
|
break;
|
|
}
|
|
if (MOOSTime() > t0 + 6) {
|
|
LOG_F(ERROR, "operate %s: timeout", name);
|
|
ok = false;
|
|
break;
|
|
}
|
|
MOOSPause(200);
|
|
}
|
|
//继电器复位
|
|
disHighVolBusCmd clr{};
|
|
for (int i = 0; i < 3; ++i)
|
|
{
|
|
m_udpComm->sendDisSysCmd(clr);
|
|
MOOSPause(200);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
// bool LowerCommManager::operate_HV_coolingSystem_Breaker(char opt){
|
|
// return operateBreakerGeneric<disHighVolBusCmd, char>(
|
|
// "HV_coolingSystem_Breaker",
|
|
// opt,
|
|
// [&](disHighVolBusCmd& c){ c.coolingSystem = getBreakerOption(opt); },
|
|
// [&](){ return (m_pm->m_pmCurrentState.bus1State.dcDcFaultWord1 & 0x20) ? 0x55 : 0xAA; }
|
|
// );
|
|
// }
|
|
bool LowerCommManager::operate_HV_coolingSystem_Breaker(char opt)
|
|
{
|
|
disHighVolBusCmd cmd{}; // 默认全零
|
|
double t0 = MOOSTime();
|
|
bool ok = false;
|
|
const char* name = "CoolingSystem";
|
|
LOG_F(INFO, "operate %s: opt=%d", name, opt);
|
|
|
|
cmd.coolingSystem = getBreakerOption(opt);
|
|
|
|
m_udpComm->sendDisSysCmd(cmd);
|
|
|
|
// ok = m_pm->m_pmCurrentState.bus1State.dcDcFaultWord1 & 0x60;
|
|
ok = m_pm->m_systemData->getDcdcStatus().coolingPump1Running || m_pm->m_systemData->getDcdcStatus().coolingPump2Running;
|
|
|
|
MOOSPause(100);
|
|
while ( !ok ) {
|
|
if( (m_pm->m_systemData->getDcdcStatus().coolingPump1Running || m_pm->m_systemData->getDcdcStatus().coolingPump2Running) )
|
|
{
|
|
ok = true;
|
|
break;
|
|
}
|
|
if (!m_udpComm->sendDisSysCmd(cmd)) {
|
|
LOG_F(ERROR, "operate %s: sendDisSysCmd failed", name);
|
|
ok = false;
|
|
break;
|
|
}
|
|
if (MOOSTime() > t0 + 6) {
|
|
LOG_F(ERROR, "operate %s: timeout", name);
|
|
ok = false;
|
|
break;
|
|
}
|
|
MOOSPause(200);
|
|
}
|
|
//继电器复位
|
|
disHighVolBusCmd clr{};
|
|
for (int i = 0; i < 3; ++i)
|
|
{
|
|
m_udpComm->sendDisSysCmd(clr);
|
|
MOOSPause(200);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
// 高压汇流排断路器操作函数
|
|
bool LowerCommManager::operate_HVA_bowFTDevice123Circuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighAVolBusCmd, char>(
|
|
"HVA_bowFTDevice123Circuit_Breaker",
|
|
opt,
|
|
[&](disHighAVolBusCmd& c){ c.bowFTDevice123CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus2State.bowFTDevice123CircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HVA_actuatorCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighAVolBusCmd, char>(
|
|
"HVA_actuatorCircuit_Breaker",
|
|
opt,
|
|
[&](disHighAVolBusCmd& c){ c.actuatorCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus2State.actuatorCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HVA_mastSteeringGearControlBoxCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighAVolBusCmd, char>(
|
|
"HVA_mastSteeringGearControlBoxCircuit_Breaker",
|
|
opt,
|
|
[&](disHighAVolBusCmd& c){ c.mastSteeringGearControlBoxCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus2State.mastSteeringGearControlBoxCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HVA_xczCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighAVolBusCmd, char>(
|
|
"HVA_xczCircuit_Breaker",
|
|
opt,
|
|
[&](disHighAVolBusCmd& c){ c.xczCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus2State.xczCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HVA_bowRudderControlBoxCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighAVolBusCmd, char>(
|
|
"HVA_bowRudderControlBoxCircuit_Breaker",
|
|
opt,
|
|
[&](disHighAVolBusCmd& c){ c.bowRudderControlBoxCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus2State.bowRudderControlBoxCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_HVA_openWaterCoverStartCylinderCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disHighAVolBusCmd, char>(
|
|
"HVA_openWaterCoverStartCylinderCircuit_Breaker",
|
|
opt,
|
|
[&](disHighAVolBusCmd& c){ c.openWaterCoverStartCylinderCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus2State.openWaterCoverStartCylinderCircuitBreaker; }
|
|
);
|
|
}
|
|
|
|
// 仪表汇流排断路器操作函数
|
|
|
|
bool LowerCommManager::operate_LVA_unit1Circuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowBusCmd, char>(
|
|
"LVA_unit1Circuit_Breaker",
|
|
opt,
|
|
[&](disLowBusCmd& c){ c.unit1CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus4State.unit1CircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LVA_unit2Circuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowBusCmd, char>(
|
|
"LVA_unit2Circuit_Breaker",
|
|
opt,
|
|
[&](disLowBusCmd& c){ c.unit2CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus4State.unit2CircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LVA_unit3Circuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowBusCmd, char>(
|
|
"LVA_unit3Circuit_Breaker",
|
|
opt,
|
|
[&](disLowBusCmd& c){ c.unit3CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus4State.unit3CircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LVA_unit5Circuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowBusCmd, char>(
|
|
"LVA_unit5Circuit_Breaker",
|
|
opt,
|
|
[&](disLowBusCmd& c){ c.unit5CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus4State.unit5CircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LVA_bowPZDeviceCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowBusCmd, char>(
|
|
"LVA_bowPZDeviceCircuit_Breaker",
|
|
opt,
|
|
[&](disLowBusCmd& c){ c.bowPZDeviceCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus4State.bowPZDeviceCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LVA_reservedCircuit1_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowBusCmd, char>(
|
|
"LVA_reservedCircuit1_Breaker",
|
|
opt,
|
|
[&](disLowBusCmd& c){ c.reservedCircuitBreaker1 = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus4State.reservedCircuitBreaker1; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LVA_reservedCircuit2_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowBusCmd, char>(
|
|
"LVA_reservedCircuit2_Breaker",
|
|
opt,
|
|
[&](disLowBusCmd& c){ c.reservedCircuitBreaker2 = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus4State.reservedCircuitBreaker2; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LVA_mergencyLithiumBatteryGroup1Circuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowBusCmd, char>(
|
|
"LVA_mergencyLithiumBatteryGroup1Circuit_Breaker",
|
|
opt,
|
|
[&](disLowBusCmd& c){ c.emergencyLithiumBatteryGroup1CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus4State.emergencyLithiumBatteryGroup1CircuitBreaker; }
|
|
);
|
|
}
|
|
|
|
// 仪表母线断路器操作函数
|
|
bool LowerCommManager::operate_LV_lithiumBatteryGroupInstrumentCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowMainBusCmd, char>(
|
|
"lithiumBatteryGroupInstrumentCircuitBreaker",
|
|
opt,
|
|
[&](disLowMainBusCmd& c){ c.lithiumBatteryGroupInstrumentCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus3State.lithiumBatteryGroupInstrumentCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LV_bowLowVoltageDistributionBoxCircuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowMainBusCmd, char>(
|
|
"bowLowVoltageDistributionBoxCircuitBreaker",
|
|
opt,
|
|
[&](disLowMainBusCmd& c){ c.bowLowVoltageDistributionBoxCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus3State.bowLowVoltageDistributionBoxCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LV_unit4Dc48V_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowMainBusCmd, char>(
|
|
"unit4InstrumentDC48VCircuitBreaker",
|
|
opt,
|
|
[&](disLowMainBusCmd& c){ c.unit4InstrumentDC48VCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus3State.unit4InstrumentDC48VCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LV_dcC1Panel_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowMainBusCmd, char>(
|
|
"dcC1DCDistributionPanelCircuitBreaker",
|
|
opt,
|
|
[&](disLowMainBusCmd& c){ c.dcC1DCDistributionPanelCircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus3State.dcC1DCDistributionPanelCircuitBreaker; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LV_reservedCircuit1_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowMainBusCmd, char>(
|
|
"reservedCircuitBreaker1",
|
|
opt,
|
|
[&](disLowMainBusCmd& c){ c.reservedCircuitBreaker1 = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus3State.reservedCircuitBreaker1; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LV_reservedCircuit2_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowMainBusCmd, char>(
|
|
"reservedCircuitBreaker2",
|
|
opt,
|
|
[&](disLowMainBusCmd& c){ c.reservedCircuitBreaker2 = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus3State.reservedCircuitBreaker2; }
|
|
);
|
|
}
|
|
bool LowerCommManager::operate_LV_mergencyLithiumBatteryGroup2Circuit_Breaker(char opt){
|
|
return operateBreakerGeneric<disLowMainBusCmd, char>(
|
|
"emergencyLithiumBatteryGroup2CircuitBreaker",
|
|
opt,
|
|
[&](disLowMainBusCmd& c){ c.emergencyLithiumBatteryGroup2CircuitBreaker = getBreakerOption(opt); },
|
|
[&](){ return m_pm->m_pmCurrentState.bus3State.emergencyLithiumBatteryGroup2CircuitBreaker; }
|
|
);
|
|
}
|
|
|
|
// 通用模板
|
|
template<typename CmdT, typename StateT>
|
|
bool LowerCommManager::operateBreakerGeneric(
|
|
char const* name,
|
|
char opt,
|
|
std::function<void(CmdT&)> fillCmd, // 填 cmd 对应字段
|
|
std::function<StateT()> readState // 读 pmCurrentState 对应字段
|
|
) {
|
|
CmdT cmd{}; // 默认全零
|
|
double t0 = MOOSTime();
|
|
bool ok = false;
|
|
LOG_F(INFO, "operate %s: opt=%d", name, opt);
|
|
|
|
// 第一次发包
|
|
fillCmd(cmd);
|
|
m_udpComm->sendDisSysCmd(cmd);
|
|
MOOSPause(100);
|
|
while ( !ok ) {
|
|
StateT cur;
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_pm->m_stateMutex);
|
|
cur = readState();
|
|
}
|
|
if( cur == getBreakerOption(opt) )
|
|
{
|
|
ok = true;
|
|
break;
|
|
}
|
|
if (!m_udpComm->sendDisSysCmd(cmd)) {
|
|
LOG_F(ERROR, "operate %s: sendDisSysCmd failed", name);
|
|
ok = false;
|
|
break;
|
|
}
|
|
if (MOOSTime() > t0 + 6) {
|
|
LOG_F(ERROR, "operate %s: timeout", name);
|
|
ok = false;
|
|
break;
|
|
}
|
|
MOOSPause(200);
|
|
}
|
|
//继电器复位
|
|
CmdT clr{};
|
|
for (int i = 0; i < 3; ++i)
|
|
{
|
|
m_udpComm->sendDisSysCmd(clr);
|
|
MOOSPause(200);
|
|
}
|
|
return ok;
|
|
}
|