Compare commits
2 Commits
dfd5aceef3
...
49f139f508
Author | SHA1 | Date | |
---|---|---|---|
49f139f508 | |||
3ec47bdc72 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -34,3 +34,4 @@
|
||||
|
||||
# CMakeBuild
|
||||
build/
|
||||
log/
|
||||
|
@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scenario>
|
||||
<Environment
|
||||
OSName="Debian"
|
||||
Version="11"
|
||||
RTXVersion="preempt-rt"
|
||||
CPUAffinity="0,1"
|
||||
BaseFrequency="120"
|
||||
WorkPath="/home/jin/Myprj/XNSim/Release/"
|
||||
ModelsPath="Models/"
|
||||
ServicesPath="Services/"
|
||||
DomainID="10"
|
||||
/>
|
||||
<ConsoleOutput Debug="1" Info="1" Error="1" Warning="1" />
|
||||
<Log Debug="0" Info="1" Error="1" Warning="1" />
|
||||
<ModelGroup Name="新模型组" FreqGroup="0" Priority="99" CPUAff="0">
|
||||
<!-- 这里添加模型 -->
|
||||
</ModelGroup>
|
||||
<ServicesList>
|
||||
<!-- 这里添加服务 -->
|
||||
</ServicesList>
|
||||
</Scenario>
|
@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scenario>
|
||||
<Environment
|
||||
OSName="Debian"
|
||||
Version="11"
|
||||
RTXVersion="preempt-rt"
|
||||
CPUAffinity="0,1"
|
||||
BaseFrequency="120"
|
||||
WorkPath="/home/jin/Myprj/XNSim/Release/"
|
||||
ModelsPath="Models/"
|
||||
ServicesPath="Services/"
|
||||
DomainID="10"
|
||||
/>
|
||||
<ConsoleOutput Debug="1" Info="1" Error="1" Warning="1" />
|
||||
<Log Debug="0" Info="1" Error="1" Warning="1" />
|
||||
<ModelGroup Name="新模型组" FreqGroup="0" Priority="99" CPUAff="0">
|
||||
<!-- 这里添加模型 -->
|
||||
</ModelGroup>
|
||||
<ServicesList>
|
||||
<!-- 这里添加服务 -->
|
||||
</ServicesList>
|
||||
</Scenario>
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scenario>
|
||||
<Environment OSName="Debian" Version="11" RTXVersion="preempt-rt" CPUAffinity="0,1" BaseFrequency="120" WorkPath="/home/jin/Myprj/XNSim/Release/" ModelsPath="Models/" ServicesPath="Services/" DomainID="10"/>
|
||||
<ConsoleOutput Debug="1" Info="1" Error="1" Warning="1"/>
|
||||
<Log Debug="0" Info="1" Error="1" Warning="1"/>
|
||||
<ModelGroup Name="新模型组" FreqGroup="0" Priority="99" CPUAff="0">
|
||||
<!-- 这里添加模型 -->
|
||||
</ModelGroup>
|
||||
<ServicesList>
|
||||
<!-- 这里添加服务 -->
|
||||
</ServicesList>
|
||||
</Scenario>
|
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scenario>
|
||||
<Environment OSName="RT-Linux" Version="5.10.0-26-rt-amd64" RTXVersion="none" BaseFrequency="100" WorkPath="." ModelsPath="./models" ServicesPath="./services" CPUAffinity="0,1" DomainID="0"/>
|
||||
<ConsoleOutput Debug="1" Info="1" Warning="1" Error="1"/>
|
||||
<Log Debug="0" Info="1" Warning="1" Error="1"/>
|
||||
<ModelGroupList>
|
||||
<ModelGroup Name="DefaultGroup" FreqGroup="0" Priority="99" CPUAff="0">
|
||||
<Model Name="DefaultModel" ClassName="XNModel"/>
|
||||
</ModelGroup>
|
||||
</ModelGroupList>
|
||||
<ServicesList>
|
||||
<Service Name="DefaultService" ClassName="XNService"/>
|
||||
</ServicesList>
|
||||
</Scenario>
|
@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scenario>
|
||||
<Environment OSName="Debian" Version="11" RTXVersion="preempt-rt" CPUAffinity="0,1" BaseFrequency="120" WorkPath="/home/jin/Myprj/XNSim/Release/" ModelsPath="Models/" ServicesPath="Services/" DomainID="10"/>
|
||||
<Environment OSName="Debian" Version="11" RTXVersion="preempt-rt" CPUAffinity="0,1" BaseFrequency="120" WorkPath="/home/jin/MyCode/XNSim/Release/" ModelsPath="Models/" ServicesPath="Services/" DomainID="10"/>
|
||||
<ConsoleOutput Debug="1" Info="1" Error="1" Warning="1"/>
|
||||
<Log Debug="0" Info="1" Error="1" Warning="1"/>
|
||||
<ModelGroup Name="本体模型组" FreqGroup="0" Priority="99" CPUAff="0">
|
||||
<Model Name="ATA04气动模型" ClassName="XNAerodynamics"/>
|
||||
<Model Name="ATA04地面操纵模型" ClassName="XNGroundHandling"/>
|
||||
<Model Name="ATA04质量模型" ClassName="XNWeightBalance"/>
|
||||
<Model Name="ATA04数据处理模型" ClassName="XNATA04DataProcessor"/>
|
||||
<!--Model Name="ATA04数据处理模型" ClassName="XNATA04DataProcessor"/-->
|
||||
</ModelGroup>
|
||||
<ServicesList>
|
||||
<Service Name="UDP通信服务" ClassName="XNUDPService"/>
|
||||
|
@ -5,8 +5,8 @@
|
||||
Version="11"
|
||||
RTXVersion="preempt-rt"
|
||||
CPUAffinity="0,1"
|
||||
BaseFrequency="120"
|
||||
WorkPath="/home/jin/Myprj/XNSim/Release/"
|
||||
BaseFrequency="60"
|
||||
WorkPath="/home/jin/MyCode/XNSim/Release/"
|
||||
ModelsPath="Models/"
|
||||
ServicesPath="Services/"
|
||||
DomainID="10"
|
16
Release/Scenario/OnlyFlightModel_test.xml
Executable file
16
Release/Scenario/OnlyFlightModel_test.xml
Executable file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scenario>
|
||||
<Environment OSName="Debian" Version="11" RTXVersion="preempt-rt" CPUAffinity="0,1" BaseFrequency="120" WorkPath="/home/jin/MyCode/XNSim/Release/" ModelsPath="Models/" ServicesPath="Services/" DomainID="10"/>
|
||||
<ConsoleOutput Debug="1" Info="1" Error="1" Warning="1"/>
|
||||
<Log Debug="0" Info="1" Error="1" Warning="1"/>
|
||||
<ModelGroup Name="本体模型组" FreqGroup="0" Priority="99" CPUAff="0">
|
||||
<Model Name="ATA04气动模型" ClassName="XNAerodynamics"/>
|
||||
<Model Name="ATA04地面操纵模型" ClassName="XNGroundHandling"/>
|
||||
<Model Name="ATA04质量模型" ClassName="XNWeightBalance"/>
|
||||
<Model Name="ATA04数据处理模型" ClassName="XNATA04DataProcessor"/>
|
||||
</ModelGroup>
|
||||
<ServicesList>
|
||||
<Service Name="UDP通信服务" ClassName="XNUDPService"/>
|
||||
<Service Name="UDP通信测试服务" ClassName="XNUDPTestService"/>
|
||||
</ServicesList>
|
||||
</Scenario>
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Service>
|
||||
<Name>123</Name>
|
||||
<Description>服务描述</Description>
|
||||
<Author>sdgsdf</Author>
|
||||
<Version>1.0.0</Version>
|
||||
<CreateTime>2025-04-21 16:16:14</CreateTime>
|
||||
<ChangeTime>2025-04-21 16:16:46</ChangeTime>
|
||||
<CommandList>
|
||||
<Command Name="asdf" Call="asdf" Description="asdf" />
|
||||
</CommandList>
|
||||
</Service>
|
2
Release/Services/XNUDPService.scfg
Executable file → Normal file
2
Release/Services/XNUDPService.scfg
Executable file → Normal file
@ -7,7 +7,7 @@
|
||||
<CreateTime>2025-02-04 10:00:00</CreateTime>
|
||||
<ChangeTime>2025-02-04 10:00:00</ChangeTime>
|
||||
<CommandList>
|
||||
<Command Name="TestCmd" Description="Test" Call="TestCall" />
|
||||
<Command Name="TestCmd" Description="Test" Call="TestCall"/>
|
||||
</CommandList>
|
||||
<UDP>
|
||||
<LocalPort>12345</LocalPort>
|
||||
|
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Service>
|
||||
<Name>XNUDPService</Name>
|
||||
<Description>UDP通信服务</Description>
|
||||
<Author>Jin</Author>
|
||||
<Version>1.0.0</Version>
|
||||
<CreateTime>2025-02-04 10:00:00</CreateTime>
|
||||
<ChangeTime>2025-02-04 10:00:00</ChangeTime>
|
||||
<CommandList></CommandList>
|
||||
<UDP>
|
||||
<LocalPort>12345</LocalPort>
|
||||
<TargetHost>127.0.0.1</TargetHost>
|
||||
<TargetPort>54321</TargetPort>
|
||||
</UDP>
|
||||
</Service>
|
17
Release/Services/XNUDPTestService.scfg
Normal file
17
Release/Services/XNUDPTestService.scfg
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Service>
|
||||
<Name>XNUDPTestService</Name>
|
||||
<Description>UDP通信服务</Description>
|
||||
<Author>Jin</Author>
|
||||
<Version>1.0.0</Version>
|
||||
<CreateTime>2025-02-04 10:00:00</CreateTime>
|
||||
<ChangeTime>2025-02-04 10:00:00</ChangeTime>
|
||||
<CommandList>
|
||||
<Command Name="TestCmd" Description="Test" Call="TestCall"/>
|
||||
</CommandList>
|
||||
<UDP>
|
||||
<LocalPort>54321</LocalPort>
|
||||
<TargetHost>127.0.0.1</TargetHost>
|
||||
<TargetPort>12345</TargetPort>
|
||||
</UDP>
|
||||
</Service>
|
@ -1,3 +1,3 @@
|
||||
/home/jin/Myprj/XNSim/Release/lib
|
||||
/home/jin/Myprj/XNSim/Release/Models
|
||||
/home/jin/Myprj/XNSim/Release/Services
|
||||
/home/jin/MyCode/XNSim/Release/lib
|
||||
/home/jin/MyCode/XNSim/Release/Models
|
||||
/home/jin/MyCode/XNSim/Release/Services
|
||||
|
@ -1,4 +1,4 @@
|
||||
export XNCore=/home/jin/Myprj/XNSim/Release
|
||||
export XNCore=/home/jin/MyCode/XNSim/Release
|
||||
export PATH=$XNCore:$PATH
|
||||
export LD_LIBRARY_PATH=$XNCore/lib:$LD_LIBRARY_PATH
|
||||
export QT_QPA_PLATFORM=xcb
|
||||
|
@ -54,6 +54,7 @@ void XNATA04DataProcessor::StepUpdate()
|
||||
Q_D(XNATA04DataProcessor);
|
||||
XNModelObject::StepUpdate();
|
||||
SendUdpData();
|
||||
SendUdpTestData();
|
||||
}
|
||||
|
||||
void XNATA04DataProcessor::SendUdpData()
|
||||
@ -981,18 +982,38 @@ void XNATA04DataProcessor::OnAeroInput(const QVariant &data)
|
||||
{
|
||||
Q_D(XNATA04DataProcessor);
|
||||
QByteArray inputData = data.toByteArray();
|
||||
if (inputData.size() <= 5 || inputData[0] != 0x0b || inputData[1] != 0x04
|
||||
|| inputData[2] != 0x00 || inputData[3] != 0x00 || inputData[4] != inputData.size()) {
|
||||
LOG_WARNING("ATA04DataProcessor::OnAeroInput: invalid input data");
|
||||
|
||||
// 基本验证:长度和包头前四个字节
|
||||
if (inputData.size() <= 5) {
|
||||
LOG_WARNING("ATA04DataProcessor::OnAeroInput: data too short, size=%d", inputData.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// 现在我们知道数据包确实以0b 04 00 00开头
|
||||
if (inputData[0] != 0x0b || inputData[1] != 0x04 || inputData[2] != 0x00
|
||||
|| inputData[3] != 0x00) {
|
||||
LOG_WARNING("ATA04DataProcessor::OnAeroInput: invalid header, expected 0b 04 00 00, got "
|
||||
"%02x %02x %02x %02x",
|
||||
(quint8)inputData[0], (quint8)inputData[1], (quint8)inputData[2],
|
||||
(quint8)inputData[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用与发送方相同版本的QDataStream读取数据
|
||||
QDataStream inputStream(&inputData, QIODevice::ReadOnly);
|
||||
inputStream.setByteOrder(QDataStream::LittleEndian);
|
||||
inputStream.setVersion(QDataStream::Qt_6_0);
|
||||
|
||||
// 跳过5字节的头
|
||||
for (int i = 0; i < 5; i++) {
|
||||
char tmp;
|
||||
inputStream >> tmp;
|
||||
}
|
||||
|
||||
QMutexLocker locker(&d->_aeroInputMutex);
|
||||
|
||||
// 尝试读取数据,并添加异常处理
|
||||
try {
|
||||
double tmp;
|
||||
inputStream >> tmp;
|
||||
d->_aeroInput.l_04_i_aerocomac_alpha_f8(tmp);
|
||||
@ -1072,6 +1093,13 @@ void XNATA04DataProcessor::OnAeroInput(const QVariant &data)
|
||||
inputStream >> tmp;
|
||||
d->_aeroInput.l_04_i_aerocomac_alt_agl_f8(tmp);
|
||||
d->_dataWriters["XNSim::ATA04::Aerodynamics_input"]->write(&d->_aeroInput);
|
||||
} catch (const std::exception &e) {
|
||||
LOG_WARNING("ATA04DataProcessor::OnAeroInput: exception during data parsing: %s", e.what());
|
||||
return;
|
||||
} catch (...) {
|
||||
LOG_WARNING("ATA04DataProcessor::OnAeroInput: unknown exception during data parsing");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void XNATA04DataProcessor::OnWbOutput(const XNSim::ATA04::WeightBalance_output &input)
|
||||
@ -1115,3 +1143,280 @@ void XNATA04DataProcessor::OnGhHeartbeat(const XNSim::ATA04::GroundHandling_hear
|
||||
QMutexLocker locker(&d->_ghHeartbeatMutex);
|
||||
d->_ghHeartbeat = input;
|
||||
}
|
||||
|
||||
void XNATA04DataProcessor::SendUdpTestData()
|
||||
{
|
||||
Q_D(XNATA04DataProcessor);
|
||||
|
||||
// 创建气动输入(AeroInput)数据包
|
||||
QByteArray aeroData;
|
||||
QDataStream aeroStream(&aeroData, QIODevice::WriteOnly);
|
||||
aeroStream.setByteOrder(QDataStream::LittleEndian);
|
||||
aeroStream.setVersion(QDataStream::Qt_6_0);
|
||||
|
||||
// 气动输入数据包头 (0x0b=从外部输入, 0x04=ATA04, 0x00=气动模型, 0x00=输入数据)
|
||||
quint8 aeroHeader[5] = {0x0b, 0x04, 0x00, 0x00, 0x00};
|
||||
aeroStream << aeroHeader[0] << aeroHeader[1] << aeroHeader[2] << aeroHeader[3] << aeroHeader[4];
|
||||
|
||||
// 气动数据字段
|
||||
aeroStream << (double)5.0; // alpha
|
||||
aeroStream << (double)0.5; // alpdot
|
||||
aeroStream << (double)1.0; // beta
|
||||
aeroStream << (double)10000.0; // press_alt
|
||||
aeroStream << (double)250.0; // tas
|
||||
aeroStream << (double)0.8; // mach
|
||||
aeroStream << (double)0.2; // nx
|
||||
aeroStream << (double)0.0; // ny
|
||||
aeroStream << (double)1.0; // nz
|
||||
aeroStream << (double)0.0; // p
|
||||
aeroStream << (double)0.0; // q
|
||||
aeroStream << (double)0.0; // r
|
||||
aeroStream << (double)12000.0; // qbar
|
||||
aeroStream << (double)0.0; // blcg
|
||||
aeroStream << (double)0.0; // bscg
|
||||
aeroStream << (double)0.0; // wlcg
|
||||
aeroStream << (double)0.0; // stab
|
||||
|
||||
// ail_f8 数组,需要10个double
|
||||
for (int i = 0; i < 10; i++) {
|
||||
aeroStream << (double)0.0;
|
||||
}
|
||||
|
||||
// elv_f8 数组,需要4个double
|
||||
for (int i = 0; i < 4; i++) {
|
||||
aeroStream << (double)0.0;
|
||||
}
|
||||
|
||||
// rud_f8 数组,需要2个double
|
||||
for (int i = 0; i < 2; i++) {
|
||||
aeroStream << (double)0.0;
|
||||
}
|
||||
|
||||
// gear_f8 数组,需要7个double
|
||||
for (int i = 0; i < 7; i++) {
|
||||
aeroStream << (double)0.0;
|
||||
}
|
||||
|
||||
// flap_f8 数组,需要10个double
|
||||
for (int i = 0; i < 10; i++) {
|
||||
aeroStream << (double)0.0;
|
||||
}
|
||||
|
||||
// slat_f8 数组,需要20个double
|
||||
for (int i = 0; i < 20; i++) {
|
||||
aeroStream << (double)0.0;
|
||||
}
|
||||
|
||||
// spl_f8 数组,需要20个double
|
||||
for (int i = 0; i < 20; i++) {
|
||||
aeroStream << (double)0.0;
|
||||
}
|
||||
|
||||
// tnet_f8 数组,需要4个double
|
||||
for (int i = 0; i < 4; i++) {
|
||||
aeroStream << (double)20000.0;
|
||||
}
|
||||
|
||||
// kice_f8 数组,需要20个double
|
||||
for (int i = 0; i < 20; i++) {
|
||||
aeroStream << (double)0.0;
|
||||
}
|
||||
|
||||
// alt_agl
|
||||
aeroStream << (double)1000.0;
|
||||
|
||||
// 更新数据包大小,确保不会溢出
|
||||
if (aeroData.size() <= 255) {
|
||||
aeroData[4] = aeroData.size();
|
||||
} else {
|
||||
LOG_WARNING("ATA04DataProcessor::SendUdpTestData: aeroData size exceeds byte limit: %d",
|
||||
aeroData.size());
|
||||
aeroData[4] = 255; // 设置为最大值
|
||||
}
|
||||
|
||||
// 创建地面操作输入(GhInput)数据包
|
||||
QByteArray ghData;
|
||||
QDataStream ghStream(&ghData, QIODevice::WriteOnly);
|
||||
ghStream.setByteOrder(QDataStream::LittleEndian);
|
||||
ghStream.setVersion(QDataStream::Qt_6_0);
|
||||
// 地面操作输入数据包头 (0x0b=从外部输入, 0x04=ATA04, 0x01=地面操作模型, 0x00=输入数据)
|
||||
quint8 ghHeader[5] = {0x0b, 0x04, 0x01, 0x00, 0x00};
|
||||
ghStream << ghHeader[0] << ghHeader[1] << ghHeader[2] << ghHeader[3] << ghHeader[4];
|
||||
|
||||
// 地面操作数据字段
|
||||
ghStream << (quint8)0; // frz_l1
|
||||
ghStream << (quint8)0; // chocks_l1
|
||||
ghStream << (double)100.0; // alt_agl_f8
|
||||
ghStream << (quint8)0; // frzflt_l1
|
||||
ghStream << (double)0.0; // p_f8
|
||||
ghStream << (double)0.0; // q_f8
|
||||
ghStream << (double)0.0; // r_f8
|
||||
ghStream << (double)0.0; // ug_f8
|
||||
ghStream << (double)0.0; // vg_f8
|
||||
ghStream << (double)0.0; // wg_f8
|
||||
ghStream << (double)0.0; // blcg_f8
|
||||
ghStream << (double)0.0; // bscg_f8
|
||||
ghStream << (double)0.0; // wlcg_f8
|
||||
ghStream << (quint8)0; // pb_active_l1
|
||||
ghStream << (double)0.0; // pb_towforce_f8
|
||||
|
||||
// brake_torq_f8 数组 3x2
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
ghStream << (double)0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// gear_f8 数组,需要3个double
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ghStream << (double)0.0;
|
||||
}
|
||||
|
||||
// 另一个3个double的数组
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ghStream << (double)0.0;
|
||||
}
|
||||
|
||||
// gsteer_f8 数组,需要10个double
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ghStream << (double)0.0;
|
||||
}
|
||||
|
||||
// tire_pres_f8 数组 3x2
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
ghStream << (double)30.0; // 30 psi的胎压
|
||||
}
|
||||
}
|
||||
|
||||
// 4个double数组
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ghStream << (double)0.0;
|
||||
}
|
||||
|
||||
ghStream << (quint8)0; // onjax_l1
|
||||
|
||||
// contdep_f8 数组,需要7个double
|
||||
for (int i = 0; i < 7; i++) {
|
||||
ghStream << (double)0.0;
|
||||
}
|
||||
|
||||
ghStream << (double)0.0; // thetag_f8
|
||||
ghStream << (double)0.0; // phig_f8
|
||||
ghStream << (qint32)0; // rwyrgh_i2
|
||||
ghStream << (double)0.0; // rwyhdg_f8
|
||||
ghStream << (quint8)0; // reset_braketemp_l1
|
||||
ghStream << (quint8)0; // reset_tirepress_l1
|
||||
ghStream << (double)20.0; // temp_c_f8
|
||||
|
||||
// brake_temp_f8 数组 3x2
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
ghStream << (double)50.0; // 50度的刹车温度
|
||||
}
|
||||
}
|
||||
|
||||
// tire_tburst_l1 数组 3x2
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
ghStream << (char)0;
|
||||
}
|
||||
}
|
||||
|
||||
// tire_tflat_l1 数组 3x2
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
ghStream << (char)0;
|
||||
}
|
||||
}
|
||||
|
||||
ghStream << (quint8)0; // brk_reset_tpres_l1
|
||||
|
||||
// rcon_ci_f8 数组,需要14个double
|
||||
for (int i = 0; i < 14; i++) {
|
||||
ghStream << (double)0.0;
|
||||
}
|
||||
|
||||
ghStream << (qint32)0; // gsteer_state_i4
|
||||
ghStream << (quint8)0; // trim_active_l1
|
||||
ghStream << (double)0.0; // phi_deg_f8
|
||||
ghStream << (double)0.0; // theta_deg_f8
|
||||
ghStream << (double)0.0; // psi_deg_f8
|
||||
ghStream << (quint8)0; // resetint_l1
|
||||
|
||||
// 更新数据包大小,确保不会溢出
|
||||
if (ghData.size() <= 255) {
|
||||
ghData[4] = ghData.size();
|
||||
} else {
|
||||
LOG_WARNING("ATA04DataProcessor::SendUdpTestData: ghData size exceeds byte limit: %d",
|
||||
ghData.size());
|
||||
ghData[4] = 255; // 设置为最大值
|
||||
}
|
||||
|
||||
// 创建重量平衡输入(WbInput)数据包
|
||||
QByteArray wbData;
|
||||
QDataStream wbStream(&wbData, QIODevice::WriteOnly);
|
||||
wbStream.setByteOrder(QDataStream::LittleEndian);
|
||||
wbStream.setVersion(QDataStream::Qt_6_0);
|
||||
// 重量平衡输入数据包头 (0x0b=从外部输入, 0x04=ATA04, 0x02=重量平衡模型, 0x00=输入数据)
|
||||
quint8 wbHeader[5] = {0x0b, 0x04, 0x02, 0x00, 0x00};
|
||||
wbStream << wbHeader[0] << wbHeader[1] << wbHeader[2] << wbHeader[3] << wbHeader[4];
|
||||
|
||||
// 重量平衡数据字段
|
||||
wbStream << (double)0.0; // theta_deg_f8
|
||||
wbStream << (double)0.0; // phi_deg_f8
|
||||
wbStream << (double)0.0; // psi_deg_f8
|
||||
wbStream << (quint8)0; // gear_mode_l1
|
||||
wbStream << (double)60000.0; // acset_gw_f8 (60000kg飞机重量)
|
||||
wbStream << (double)25.0; // acset_cg_f8 (25%MAC重心位置)
|
||||
|
||||
// acset_tankfuel_f4 数组,需要20个float
|
||||
for (int i = 0; i < 20; i++) {
|
||||
wbStream << (float)(i < 10 ? 1000.0 : 0.0); // 前10个油箱各1000kg
|
||||
}
|
||||
|
||||
wbStream << (double)10000.0; // acset_totfuel_f8 (总油量10000kg)
|
||||
wbStream << (double)50000.0; // acset_zfw_f8 (零油重50000kg)
|
||||
wbStream << (double)24.0; // acset_zfwcg_f8 (零油重重心24%MAC)
|
||||
|
||||
// eng_efsep_l1 数组,需要4个char
|
||||
for (int i = 0; i < 4; i++) {
|
||||
wbStream << (char)0;
|
||||
}
|
||||
|
||||
// fuel_f8 数组,需要20个double
|
||||
for (int i = 0; i < 20; i++) {
|
||||
wbStream << (double)(i < 10 ? 1000.0 : 0.0); // 前10个油箱各1000kg
|
||||
}
|
||||
|
||||
wbStream << (double)0.0; // gear_avg_f8
|
||||
|
||||
// kice_f8 数组,需要20个double
|
||||
for (int i = 0; i < 20; i++) {
|
||||
wbStream << (double)0.0;
|
||||
}
|
||||
|
||||
wbStream << (quint8)0; // bycglim_l1
|
||||
wbStream << (quint8)0; // bygwlim_l1
|
||||
wbStream << (quint8)0; // frz_l1
|
||||
wbStream << (quint8)0; // zcgfrz_l1
|
||||
wbStream << (quint8)0; // zcgfrz_grfx_l1
|
||||
wbStream << (quint8)0; // ycgfrz_l1
|
||||
wbStream << (quint8)0; // inertfrz_l1
|
||||
wbStream << (double)60000.0; // potreq_gw_f8
|
||||
wbStream << (double)25.0; // potreq_gwcg_f8
|
||||
|
||||
// 更新数据包大小,确保不会溢出
|
||||
if (wbData.size() <= 255) {
|
||||
wbData[4] = wbData.size();
|
||||
} else {
|
||||
LOG_WARNING("ATA04DataProcessor::SendUdpTestData: wbData size exceeds byte limit: %d",
|
||||
wbData.size());
|
||||
wbData[4] = 255; // 设置为最大值
|
||||
}
|
||||
|
||||
// 发送测试数据包
|
||||
TriggerRTEvent("SendTestUDPData", QVariant::fromValue(aeroData));
|
||||
TriggerRTEvent("SendTestUDPData", QVariant::fromValue(ghData));
|
||||
TriggerRTEvent("SendTestUDPData", QVariant::fromValue(wbData));
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ private:
|
||||
void SendWbHeartbeat();
|
||||
|
||||
void SendGhHeartbeat();
|
||||
|
||||
void SendUdpTestData();
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(XNATA04DataProcessor)
|
||||
|
@ -89,25 +89,56 @@ void XNUDPService::HandleIncomingData()
|
||||
|
||||
d->udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
|
||||
|
||||
// 处理接收到的数据
|
||||
if (datagram.size() <= 5 || datagram[0] != 0x0b || datagram[4] != datagram.size()) {
|
||||
LOG_WARNING("Invalid UDP datagram received");
|
||||
// 数据包头在第9个位置,直接跳过前9个字节
|
||||
if (datagram.size() <= 9) {
|
||||
LOG_WARNING("Invalid size of UDP datagram received, size:%1", datagram.size());
|
||||
continue;
|
||||
}
|
||||
if (datagram[1] == 0x04) {
|
||||
if (datagram[2] == 0x00 && datagram[3] == 0x00) {
|
||||
TriggerRTEvent("ATA04AeroInput", datagram);
|
||||
|
||||
// 创建一个新的数据包,去除前面的额外头信息
|
||||
QByteArray actualData = datagram.mid(9);
|
||||
|
||||
// 使用处理后的数据
|
||||
quint8 header = (quint8)actualData[0];
|
||||
quint8 type = (quint8)actualData[1];
|
||||
quint8 subType1 = (quint8)actualData[2];
|
||||
quint8 subType2 = (quint8)actualData[3];
|
||||
quint8 size = (quint8)actualData[4];
|
||||
|
||||
// 处理接收到的数据
|
||||
if (actualData.size() <= 5) {
|
||||
LOG_WARNING("Invalid size of UDP datagram received, size:%1", actualData.size());
|
||||
continue;
|
||||
} else if (datagram[2] == 0x01 && datagram[3] == 0x00) {
|
||||
TriggerRTEvent("ATA04GhInput", datagram);
|
||||
}
|
||||
|
||||
if (header != 0x0b) {
|
||||
LOG_WARNING("Invalid header of UDP datagram received, header:%1", header);
|
||||
continue;
|
||||
} else if (datagram[2] == 0x02 && datagram[3] == 0x00) {
|
||||
TriggerRTEvent("ATA04WbInput", datagram);
|
||||
}
|
||||
|
||||
//如果数据包大小大于size,则截取size大小的数据
|
||||
if (actualData.size() > size) {
|
||||
actualData = actualData.mid(0, size);
|
||||
} else if (actualData.size() < size) {
|
||||
LOG_WARNING("Invalid size of UDP datagram received, size:%1, expected:%2",
|
||||
actualData.size(), size);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == 0x04) {
|
||||
if (subType1 == 0x00 && subType2 == 0x00) {
|
||||
TriggerRTEvent("ATA04AeroInput", actualData);
|
||||
continue;
|
||||
} else if (subType1 == 0x01 && subType2 == 0x00) {
|
||||
TriggerRTEvent("ATA04GhInput", actualData);
|
||||
continue;
|
||||
} else if (subType1 == 0x02 && subType2 == 0x00) {
|
||||
TriggerRTEvent("ATA04WbInput", actualData);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// TODO: 根据具体需求处理其它数据
|
||||
TriggerRTEvent("ReceiveUDPData", datagram);
|
||||
TriggerRTEvent("ReceiveUDPData", actualData);
|
||||
}
|
||||
}
|
||||
|
||||
|
9
XNServices/XNUDPTestService/.vscode/c_cpp_properties.json
vendored
Executable file
9
XNServices/XNUDPTestService/.vscode/c_cpp_properties.json
vendored
Executable file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cmake-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
5
XNServices/XNUDPTestService/.vscode/settings.json
vendored
Normal file
5
XNServices/XNUDPTestService/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"functional": "cpp"
|
||||
}
|
||||
}
|
65
XNServices/XNUDPTestService/CMakeLists.txt
Executable file
65
XNServices/XNUDPTestService/CMakeLists.txt
Executable file
@ -0,0 +1,65 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNUDPTestService LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# 获取环境变量
|
||||
if(DEFINED ENV{XNCore})
|
||||
set(XNCore_PATH $ENV{XNCore})
|
||||
else()
|
||||
message(FATAL_ERROR "Environment variable XNCore is not set.")
|
||||
endif()
|
||||
|
||||
# 添加 XNCore_PATH 下的 include 目录为包含目录
|
||||
include_directories(${XNCore_PATH}/include)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Network Xml)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Network Xml)
|
||||
|
||||
add_library(XNUDPTestService SHARED
|
||||
XNUDPTestService_global.h
|
||||
XNUDPTestService.cpp
|
||||
XNUDPTestService.h
|
||||
XNUDPTestService_p.h
|
||||
)
|
||||
|
||||
target_link_libraries(XNUDPTestService PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
Qt${QT_VERSION_MAJOR}::Xml
|
||||
${XNCore_PATH}/lib/libXNCore.so
|
||||
)
|
||||
|
||||
# 获取Qt库的安装路径
|
||||
get_target_property(QT_LIB_DIR Qt${QT_VERSION_MAJOR}::Core LOCATION)
|
||||
get_filename_component(QT_LIB_DIR ${QT_LIB_DIR} DIRECTORY)
|
||||
|
||||
# 设置rpath
|
||||
set_target_properties(XNUDPTestService PROPERTIES
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
INSTALL_RPATH "${QT_LIB_DIR}"
|
||||
)
|
||||
|
||||
target_compile_definitions(XNUDPTestService PRIVATE XNUDPSERVICE_LIBRARY)
|
||||
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}/Services" CACHE PATH "Install path prefix" FORCE)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS XNUDPTestService
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION .
|
||||
RUNTIME DESTINATION .
|
||||
)
|
||||
|
||||
# 添加自定义命令和目标以拷贝配置文件
|
||||
file(GLOB CONFIG_FILE "*.scfg")
|
||||
|
||||
# 使用 install 命令在安装时拷贝配置文件
|
||||
install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
424
XNServices/XNUDPTestService/CMakeLists.txt.user
Executable file
424
XNServices/XNUDPTestService/CMakeLists.txt.user
Executable file
@ -0,0 +1,424 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 14.0.1, 2025-01-26T10:40:40. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{5b958118-2d32-49ab-8eab-9018ac74c7d6}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="qlonglong">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<value type="bool" key="AutoTest.ApplyFilter">false</value>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">5</value>
|
||||
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ClangdSettings">
|
||||
<value type="bool" key="blockIndexing">true</value>
|
||||
<value type="bool" key="useGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.7.2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.7.2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.672.linux_gcc_64_kit</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||
-DCMAKE_BUILD_TYPE:STRING=Debug</value>
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="CMake.Build.Type">Release</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||
-DCMAKE_BUILD_TYPE:STRING=Release</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-RelWithDebInfo</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release with Debug Information</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.3">
|
||||
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo</value>
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Profile</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.4">
|
||||
<value type="QString" key="CMake.Build.Type">MinSizeRel</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||
-DCMAKE_BUILD_TYPE:STRING=MinSizeRel</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-MinSizeRel</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Minimum Size Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">5</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="qlonglong">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
135
XNServices/XNUDPTestService/XNUDPTestService.cpp
Executable file
135
XNServices/XNUDPTestService/XNUDPTestService.cpp
Executable file
@ -0,0 +1,135 @@
|
||||
#include "XNUDPTestService.h"
|
||||
#include "XNUDPTestService_p.h"
|
||||
#include <XNCore/XNServiceManager.h>
|
||||
#include <XNCore/XNDDSManager.h>
|
||||
#include <QFile>
|
||||
#include <QDomDocument>
|
||||
|
||||
XN_DLL_INITIALIZE(XNUDPTestService)
|
||||
|
||||
XN_REGISTER_SERVICE_BEGIN_SERVICE(XNUDPTestService)
|
||||
XN_REGISTER_SERVICE_END_SERVICE(XNUDPTestService)
|
||||
|
||||
XNUDPTestService::XNUDPTestService(QObject *parent)
|
||||
: XNServiceObject(*new XNUDPTestServicePrivate(this), parent)
|
||||
{
|
||||
}
|
||||
|
||||
XNUDPTestService::~XNUDPTestService()
|
||||
{
|
||||
}
|
||||
|
||||
XNUDPTestService::XNUDPTestService(XNUDPTestServicePrivate &dd, QObject *parent)
|
||||
: XNServiceObject(dd, parent)
|
||||
{
|
||||
}
|
||||
|
||||
void XNUDPTestService::OnInitialize()
|
||||
{
|
||||
Q_D(XNUDPTestService);
|
||||
XNServiceObject::OnInitialize();
|
||||
|
||||
// 读取配置文件
|
||||
QFile file(GetXmlPath());
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
LOG_WARNING("Failed to open config file:%1", GetXmlPath());
|
||||
return;
|
||||
}
|
||||
|
||||
QDomDocument doc;
|
||||
if (!doc.setContent(&file)) {
|
||||
file.close();
|
||||
LOG_WARNING("Failed to parse config file:%1", GetXmlPath());
|
||||
return;
|
||||
}
|
||||
file.close();
|
||||
|
||||
// 读取UDP配置
|
||||
QDomElement udpElement = doc.documentElement().firstChildElement("UDP");
|
||||
if (!udpElement.isNull()) {
|
||||
d->localPort = udpElement.firstChildElement("LocalPort").text().toUInt();
|
||||
d->targetHost = udpElement.firstChildElement("TargetHost").text();
|
||||
d->targetPort = udpElement.firstChildElement("TargetPort").text().toUInt();
|
||||
} else {
|
||||
LOG_WARNING("UDP configuration not found, using default values");
|
||||
d->localPort = 12345;
|
||||
d->targetHost = "127.0.0.1";
|
||||
d->targetPort = 54321;
|
||||
}
|
||||
}
|
||||
|
||||
void XNUDPTestService::OnPrepareForExecute()
|
||||
{
|
||||
Q_D(XNUDPTestService);
|
||||
XNServiceObject::OnPrepareForExecute();
|
||||
|
||||
// 初始化UDP socket
|
||||
d->udpSocket = new QUdpSocket(this);
|
||||
|
||||
// 绑定本地端口
|
||||
if (!d->udpSocket->bind(QHostAddress::Any, d->localPort)) {
|
||||
LOG_WARNING("UDP socket bind failed on port:%1", d->localPort);
|
||||
return;
|
||||
}
|
||||
|
||||
// 连接UDP socket的信号
|
||||
connect(d->udpSocket, &QUdpSocket::readyRead, this, &XNUDPTestService::HandleIncomingData);
|
||||
|
||||
RegisterRTEventHandler("SendTestUDPData",
|
||||
std::bind(&XNUDPTestService::SendData, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void XNUDPTestService::HandleIncomingData()
|
||||
{
|
||||
Q_D(XNUDPTestService);
|
||||
return;
|
||||
while (d->udpSocket->hasPendingDatagrams()) {
|
||||
QByteArray datagram;
|
||||
datagram.resize(d->udpSocket->pendingDatagramSize());
|
||||
QHostAddress sender;
|
||||
quint16 senderPort;
|
||||
|
||||
d->udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
|
||||
|
||||
// 处理接收到的数据
|
||||
if (datagram.size() <= 5 || datagram[0] != 0x0b || datagram[4] != datagram.size()) {
|
||||
LOG_WARNING("Invalid UDP datagram received");
|
||||
continue;
|
||||
}
|
||||
if (datagram[1] == 0x04) {
|
||||
if (datagram[2] == 0x00 && datagram[3] == 0x00) {
|
||||
TriggerRTEvent("ATA04AeroInput", datagram);
|
||||
continue;
|
||||
} else if (datagram[2] == 0x01 && datagram[3] == 0x00) {
|
||||
TriggerRTEvent("ATA04GhInput", datagram);
|
||||
continue;
|
||||
} else if (datagram[2] == 0x02 && datagram[3] == 0x00) {
|
||||
TriggerRTEvent("ATA04WbInput", datagram);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// TODO: 根据具体需求处理其它数据
|
||||
//TriggerRTEvent("ReceiveUDPData", datagram);
|
||||
}
|
||||
}
|
||||
|
||||
void XNUDPTestService::SendData(const QVariant &data)
|
||||
{
|
||||
Q_D(XNUDPTestService);
|
||||
if (!d->udpSocket) {
|
||||
LOG_WARNING("UDP socket not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
// 将QVariant转换为字节数组
|
||||
QByteArray datagram;
|
||||
QDataStream stream(&datagram, QIODevice::WriteOnly);
|
||||
stream << data;
|
||||
|
||||
// 发送数据
|
||||
qint64 bytesSent =
|
||||
d->udpSocket->writeDatagram(datagram, QHostAddress(d->targetHost), d->targetPort);
|
||||
if (bytesSent == -1) {
|
||||
LOG_WARNING("Failed to send UDP datagram:%1", d->udpSocket->errorString());
|
||||
}
|
||||
}
|
29
XNServices/XNUDPTestService/XNUDPTestService.h
Executable file
29
XNServices/XNUDPTestService/XNUDPTestService.h
Executable file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "XNUDPTestService_global.h"
|
||||
#include <XNCore/XNServiceObject.h>
|
||||
#include <QVariant>
|
||||
class XNUDPTestServicePrivate;
|
||||
|
||||
class XNUDPTESTSERVICE_EXPORT XNUDPTestService : public XNServiceObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(XNUDPTestService)
|
||||
Q_DECLARE_PRIVATE(XNUDPTestService)
|
||||
XN_DECLARE_DDS_SERVICE()
|
||||
public:
|
||||
explicit XNUDPTestService(QObject *parent = nullptr);
|
||||
virtual ~XNUDPTestService();
|
||||
|
||||
protected:
|
||||
XNUDPTestService(XNUDPTestServicePrivate &dd, QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
virtual void OnInitialize() override;
|
||||
virtual void OnPrepareForExecute() override;
|
||||
void HandleIncomingData();
|
||||
|
||||
public:
|
||||
void SendData(const QVariant &data);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(XNUDPTestService)
|
17
XNServices/XNUDPTestService/XNUDPTestService.scfg
Executable file
17
XNServices/XNUDPTestService/XNUDPTestService.scfg
Executable file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Service>
|
||||
<Name>XNUDPTestService</Name>
|
||||
<Description>UDP通信服务</Description>
|
||||
<Author>Jin</Author>
|
||||
<Version>1.0.0</Version>
|
||||
<CreateTime>2025-02-04 10:00:00</CreateTime>
|
||||
<ChangeTime>2025-02-04 10:00:00</ChangeTime>
|
||||
<CommandList>
|
||||
<Command Name="TestCmd" Description="Test" Call="TestCall"/>
|
||||
</CommandList>
|
||||
<UDP>
|
||||
<LocalPort>54321</LocalPort>
|
||||
<TargetHost>127.0.0.1</TargetHost>
|
||||
<TargetPort>12345</TargetPort>
|
||||
</UDP>
|
||||
</Service>
|
12
XNServices/XNUDPTestService/XNUDPTestService_global.h
Executable file
12
XNServices/XNUDPTestService/XNUDPTestService_global.h
Executable file
@ -0,0 +1,12 @@
|
||||
#ifndef XNUDPTESTSERVICE_GLOBAL_H
|
||||
#define XNUDPTESTSERVICE_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(XNUDPTESTSERVICE_LIBRARY)
|
||||
# define XNUDPTESTSERVICE_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define XNUDPTESTSERVICE_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // XNUDPTESTSERVICE_GLOBAL_H
|
17
XNServices/XNUDPTestService/XNUDPTestService_p.h
Executable file
17
XNServices/XNUDPTestService/XNUDPTestService_p.h
Executable file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <XNCore/XNServiceObject_p.h>
|
||||
#include <QUdpSocket>
|
||||
#include <QString>
|
||||
|
||||
class XNUDPTestServicePrivate : public XNServiceObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNUDPTestService)
|
||||
|
||||
XNUDPTestServicePrivate(XNUDPTestService *q) : XNServiceObjectPrivate(q) {}
|
||||
|
||||
QUdpSocket *udpSocket{nullptr};
|
||||
QString targetHost;
|
||||
quint16 targetPort{0};
|
||||
quint16 localPort{0};
|
||||
};
|
@ -2,12 +2,225 @@ class DataMonitor extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
this.currentMode = 'udp'; // 默认显示UDP模式
|
||||
this.udpPort = 54321; // 默认UDP端口
|
||||
this.udpIp = '127.0.0.1'; // 默认监听所有接口
|
||||
this.isMonitoring = false; // 监控状态
|
||||
this.udpData = []; // 存储接收到的UDP数据
|
||||
|
||||
// UDP数据注入默认值
|
||||
this.injectIp = '127.0.0.1';
|
||||
this.injectPort = 12345;
|
||||
this.injectData = '{"message": "测试数据"}';
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
switchMode(mode) {
|
||||
this.currentMode = mode;
|
||||
this.render();
|
||||
}
|
||||
|
||||
async startMonitoring() {
|
||||
if (this.isMonitoring) return;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/udp-monitor/start', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
port: this.udpPort,
|
||||
ip: this.udpIp
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.isMonitoring = true;
|
||||
this.updateMonitoringStatus();
|
||||
this.setupDataFetch();
|
||||
} else {
|
||||
this.showError(data.error || '启动监控失败');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showError('无法连接到服务器');
|
||||
console.error('启动UDP监控失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async stopMonitoring() {
|
||||
if (!this.isMonitoring) return;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/udp-monitor/stop', {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.isMonitoring = false;
|
||||
this.updateMonitoringStatus();
|
||||
if (this.dataFetchInterval) {
|
||||
clearInterval(this.dataFetchInterval);
|
||||
this.dataFetchInterval = null;
|
||||
}
|
||||
} else {
|
||||
this.showError(data.error || '停止监控失败');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showError('无法连接到服务器');
|
||||
console.error('停止UDP监控失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async injectUdpData() {
|
||||
try {
|
||||
// 验证数据格式
|
||||
let parsedData;
|
||||
try {
|
||||
parsedData = JSON.parse(this.injectData);
|
||||
} catch (e) {
|
||||
this.showError('数据格式无效,请输入有效的JSON');
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch('/api/udp-monitor/inject', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
targetIp: this.injectIp,
|
||||
targetPort: this.injectPort,
|
||||
data: parsedData
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.showSuccess('数据已成功发送');
|
||||
} else {
|
||||
this.showError(data.error || '发送数据失败');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showError('无法连接到服务器');
|
||||
console.error('发送UDP数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
setupDataFetch() {
|
||||
// 清除可能存在的之前的定时器
|
||||
if (this.dataFetchInterval) {
|
||||
clearInterval(this.dataFetchInterval);
|
||||
}
|
||||
|
||||
// 每秒拉取一次新数据
|
||||
this.dataFetchInterval = setInterval(async () => {
|
||||
try {
|
||||
const response = await fetch('/api/udp-monitor/data');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.data) {
|
||||
this.updateDataDisplay(data.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取UDP数据失败:', error);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
updateDataDisplay(newData) {
|
||||
if (!newData || newData.length === 0) return;
|
||||
|
||||
// 更新数据并限制显示的数据条数
|
||||
this.udpData = [...this.udpData, ...newData].slice(-100);
|
||||
|
||||
const dataContainer = this.shadowRoot.querySelector('.data-container');
|
||||
if (!dataContainer) return;
|
||||
|
||||
dataContainer.innerHTML = this.udpData.map(item => {
|
||||
return `<div class="data-item">
|
||||
<span class="timestamp">${new Date(item.timestamp).toLocaleTimeString()}</span>
|
||||
<span class="source">${item.source}</span>
|
||||
<span class="data">${this.formatData(item.data)}</span>
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
// 自动滚动到底部
|
||||
dataContainer.scrollTop = dataContainer.scrollHeight;
|
||||
}
|
||||
|
||||
formatData(data) {
|
||||
// 简单显示为字符串,真实实现可能更复杂
|
||||
if (typeof data === 'object') {
|
||||
return JSON.stringify(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
updateMonitoringStatus() {
|
||||
const statusLabel = this.shadowRoot.querySelector('.status-label');
|
||||
const startButton = this.shadowRoot.querySelector('#start-monitoring');
|
||||
const stopButton = this.shadowRoot.querySelector('#stop-monitoring');
|
||||
const portInput = this.shadowRoot.querySelector('#udp-port');
|
||||
const ipInput = this.shadowRoot.querySelector('#udp-ip');
|
||||
|
||||
if (statusLabel) {
|
||||
statusLabel.textContent = this.isMonitoring ? '监控中' : '未监控';
|
||||
statusLabel.className = `status-label ${this.isMonitoring ? 'active' : 'inactive'}`;
|
||||
}
|
||||
|
||||
if (startButton) {
|
||||
startButton.disabled = this.isMonitoring;
|
||||
}
|
||||
|
||||
if (stopButton) {
|
||||
stopButton.disabled = !this.isMonitoring;
|
||||
}
|
||||
|
||||
if (portInput) {
|
||||
portInput.disabled = this.isMonitoring;
|
||||
}
|
||||
|
||||
if (ipInput) {
|
||||
ipInput.disabled = this.isMonitoring;
|
||||
}
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
const errorElement = this.shadowRoot.querySelector('.error-message');
|
||||
if (errorElement) {
|
||||
errorElement.textContent = message;
|
||||
errorElement.style.display = 'block';
|
||||
errorElement.className = 'message-box error-message';
|
||||
|
||||
// 3秒后自动隐藏错误消息
|
||||
setTimeout(() => {
|
||||
errorElement.style.display = 'none';
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
showSuccess(message) {
|
||||
const successElement = this.shadowRoot.querySelector('.success-message');
|
||||
if (successElement) {
|
||||
successElement.textContent = message;
|
||||
successElement.style.display = 'block';
|
||||
|
||||
// 3秒后自动隐藏成功消息
|
||||
setTimeout(() => {
|
||||
successElement.style.display = 'none';
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
this.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
@ -26,30 +239,428 @@ class DataMonitor extends HTMLElement {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monitor-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.monitor-title {
|
||||
font-size: 18px;
|
||||
.mode-switcher {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mode-button {
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.mode-button.active {
|
||||
background-color: #1890ff;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mode-button:not(.active) {
|
||||
background-color: #f0f0f0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.mode-content {
|
||||
flex-grow: 1;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.udp-content {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.monitor-section, .inject-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.section-divider {
|
||||
width: 1px;
|
||||
background-color: #e0e0e0;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 16px;
|
||||
color: #333;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.mode-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.placeholder-content {
|
||||
color: #888;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.control-panel {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.port-input, .ip-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.port-input label, .ip-input label {
|
||||
margin-right: 8px;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.port-input input, .ip-input input {
|
||||
padding: 6px 8px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.port-input input {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.ip-input input {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
padding: 6px 16px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.action-button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.start-button {
|
||||
background-color: #52c41a;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.stop-button {
|
||||
background-color: #f5222d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.inject-button {
|
||||
background-color: #1890ff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
font-size: 14px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.status-label.active {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.status-label.inactive {
|
||||
background-color: #f5f5f5;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.message-box {
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background-color: #fff2f0;
|
||||
border: 1px solid #ffccc7;
|
||||
color: #f5222d;
|
||||
}
|
||||
|
||||
.success-message {
|
||||
background-color: #f6ffed;
|
||||
border: 1px solid #b7eb8f;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.data-view {
|
||||
flex-grow: 1;
|
||||
margin-top: 16px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.data-container {
|
||||
flex-grow: 1;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
overflow-y: auto;
|
||||
background-color: #fafafa;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.data-item {
|
||||
padding: 4px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.data-item .timestamp {
|
||||
color: #888;
|
||||
margin-right: 8px;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.data-item .source {
|
||||
color: #1890ff;
|
||||
margin-right: 8px;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.data-item .data {
|
||||
color: #333;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.data-input {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.data-input label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.data-input textarea {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
padding: 8px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
resize: vertical;
|
||||
font-family: monospace;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.inject-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
<div class="monitor-container">
|
||||
<div class="monitor-header">
|
||||
<div class="monitor-title">数据监控</div>
|
||||
<div class="mode-switcher">
|
||||
<button class="mode-button ${this.currentMode === 'udp' ? 'active' : ''}" id="udp-mode">UDP监控</button>
|
||||
<button class="mode-button ${this.currentMode === 'fastdds' ? 'active' : ''}" id="fastdds-mode">FastDDS监控</button>
|
||||
</div>
|
||||
|
||||
<div class="mode-content">
|
||||
${this.currentMode === 'udp'
|
||||
? `<div class="mode-title">UDP数据监控</div>
|
||||
<div class="udp-content">
|
||||
<!-- 左侧:UDP数据监控 -->
|
||||
<div class="monitor-section">
|
||||
<div class="section-title">UDP数据监控</div>
|
||||
|
||||
<div class="control-panel">
|
||||
<div class="ip-input">
|
||||
<label for="udp-ip">监听IP:</label>
|
||||
<input type="text" id="udp-ip" value="${this.udpIp}"
|
||||
${this.isMonitoring ? 'disabled' : ''} placeholder="0.0.0.0">
|
||||
</div>
|
||||
<div class="port-input">
|
||||
<label for="udp-port">监听端口:</label>
|
||||
<input type="number" id="udp-port" min="1024" max="65535" value="${this.udpPort}"
|
||||
${this.isMonitoring ? 'disabled' : ''}>
|
||||
</div>
|
||||
<button id="start-monitoring" class="action-button start-button"
|
||||
${this.isMonitoring ? 'disabled' : ''}>开始监控</button>
|
||||
<button id="stop-monitoring" class="action-button stop-button"
|
||||
${!this.isMonitoring ? 'disabled' : ''}>停止监控</button>
|
||||
<div class="status-container">
|
||||
<span class="status-label ${this.isMonitoring ? 'active' : 'inactive'}">
|
||||
${this.isMonitoring ? '监控中' : '未监控'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="message-box error-message"></div>
|
||||
|
||||
<div class="data-view">
|
||||
<div class="data-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 分隔线 -->
|
||||
<div class="section-divider"></div>
|
||||
|
||||
<!-- 右侧:UDP数据注入 -->
|
||||
<div class="inject-section">
|
||||
<div class="section-title">UDP数据注入</div>
|
||||
|
||||
<div class="control-panel">
|
||||
<div class="ip-input">
|
||||
<label for="inject-ip">目标IP:</label>
|
||||
<input type="text" id="inject-ip" value="${this.injectIp}" placeholder="127.0.0.1">
|
||||
</div>
|
||||
<div class="port-input">
|
||||
<label for="inject-port">目标端口:</label>
|
||||
<input type="number" id="inject-port" min="1024" max="65535" value="${this.injectPort}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="data-input">
|
||||
<label for="inject-data">数据内容 (JSON格式):</label>
|
||||
<textarea id="inject-data">${this.injectData}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="message-box success-message"></div>
|
||||
|
||||
<div class="inject-actions">
|
||||
<button id="inject-data-btn" class="action-button inject-button">发送数据</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
: `<div class="mode-title">FastDDS数据监控</div>
|
||||
<div class="placeholder-content">FastDDS数据监控内容(待实现)</div>`}
|
||||
</div>
|
||||
<div>数据监控组件内容(待实现)</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 添加切换模式的事件监听
|
||||
this.shadowRoot.getElementById('udp-mode').addEventListener('click', () => this.switchMode('udp'));
|
||||
this.shadowRoot.getElementById('fastdds-mode').addEventListener('click', () => this.switchMode('fastdds'));
|
||||
|
||||
// 如果是UDP模式,添加控制按钮的事件监听
|
||||
if (this.currentMode === 'udp') {
|
||||
// 监控部分事件监听
|
||||
// IP输入事件
|
||||
const ipInput = this.shadowRoot.getElementById('udp-ip');
|
||||
if (ipInput) {
|
||||
ipInput.addEventListener('change', (e) => {
|
||||
const value = e.target.value.trim();
|
||||
// 简单的IP地址验证,可以接受0.0.0.0或具体IP
|
||||
if (value === '0.0.0.0' || /^(\d{1,3}\.){3}\d{1,3}$/.test(value)) {
|
||||
this.udpIp = value;
|
||||
} else {
|
||||
e.target.value = this.udpIp;
|
||||
this.showError('请输入有效的IP地址');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 端口输入事件
|
||||
const portInput = this.shadowRoot.getElementById('udp-port');
|
||||
if (portInput) {
|
||||
portInput.addEventListener('change', (e) => {
|
||||
const value = parseInt(e.target.value, 10);
|
||||
if (value >= 1024 && value <= 65535) {
|
||||
this.udpPort = value;
|
||||
} else {
|
||||
e.target.value = this.udpPort;
|
||||
this.showError('端口号必须在1024-65535之间');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 开始监控按钮
|
||||
const startButton = this.shadowRoot.getElementById('start-monitoring');
|
||||
if (startButton) {
|
||||
startButton.addEventListener('click', () => this.startMonitoring());
|
||||
}
|
||||
|
||||
// 停止监控按钮
|
||||
const stopButton = this.shadowRoot.getElementById('stop-monitoring');
|
||||
if (stopButton) {
|
||||
stopButton.addEventListener('click', () => this.stopMonitoring());
|
||||
}
|
||||
|
||||
// 数据注入部分事件监听
|
||||
// 注入IP输入事件
|
||||
const injectIpInput = this.shadowRoot.getElementById('inject-ip');
|
||||
if (injectIpInput) {
|
||||
injectIpInput.addEventListener('change', (e) => {
|
||||
const value = e.target.value.trim();
|
||||
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(value)) {
|
||||
this.injectIp = value;
|
||||
} else {
|
||||
e.target.value = this.injectIp;
|
||||
this.showError('请输入有效的IP地址');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 注入端口输入事件
|
||||
const injectPortInput = this.shadowRoot.getElementById('inject-port');
|
||||
if (injectPortInput) {
|
||||
injectPortInput.addEventListener('change', (e) => {
|
||||
const value = parseInt(e.target.value, 10);
|
||||
if (value >= 1024 && value <= 65535) {
|
||||
this.injectPort = value;
|
||||
} else {
|
||||
e.target.value = this.injectPort;
|
||||
this.showError('端口号必须在1024-65535之间');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 注入数据输入事件
|
||||
const injectDataInput = this.shadowRoot.getElementById('inject-data');
|
||||
if (injectDataInput) {
|
||||
injectDataInput.addEventListener('change', (e) => {
|
||||
this.injectData = e.target.value;
|
||||
});
|
||||
}
|
||||
|
||||
// 发送数据按钮
|
||||
const injectButton = this.shadowRoot.getElementById('inject-data-btn');
|
||||
if (injectButton) {
|
||||
injectButton.addEventListener('click', () => this.injectUdpData());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
257
XNSimHtml/routes/udp-monitor.js
Normal file
257
XNSimHtml/routes/udp-monitor.js
Normal file
@ -0,0 +1,257 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const dgram = require('dgram');
|
||||
|
||||
// 全局变量存储UDP服务器实例和接收到的数据
|
||||
let udpServer = null;
|
||||
let udpData = [];
|
||||
let isMonitoring = false;
|
||||
let currentPort = null;
|
||||
let currentIp = null;
|
||||
|
||||
// 开始UDP监控
|
||||
router.post('/start', (req, res) => {
|
||||
try {
|
||||
const { port, ip } = req.body;
|
||||
|
||||
// 验证端口参数
|
||||
if (!port || port < 1024 || port > 65535) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: '端口号必须在1024-65535之间'
|
||||
});
|
||||
}
|
||||
|
||||
// 验证IP参数
|
||||
if (!ip) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'IP地址不能为空'
|
||||
});
|
||||
}
|
||||
|
||||
// 如果已经在监控,先停止之前的监控
|
||||
if (isMonitoring) {
|
||||
stopUdpServer();
|
||||
}
|
||||
|
||||
// 创建UDP服务器
|
||||
udpServer = dgram.createSocket('udp4');
|
||||
currentPort = port;
|
||||
currentIp = ip;
|
||||
|
||||
// 清空之前的数据
|
||||
udpData = [];
|
||||
|
||||
// 监听错误事件
|
||||
udpServer.on('error', (err) => {
|
||||
console.error(`UDP服务器错误:`, err);
|
||||
isMonitoring = false;
|
||||
udpServer.close();
|
||||
udpServer = null;
|
||||
});
|
||||
|
||||
// 监听消息事件
|
||||
udpServer.on('message', (msg, rinfo) => {
|
||||
// 将收到的数据添加到数据队列
|
||||
try {
|
||||
let processedData;
|
||||
|
||||
// 尝试将数据解析为JSON
|
||||
try {
|
||||
processedData = JSON.parse(msg.toString());
|
||||
} catch (e) {
|
||||
// 如果不是JSON,则保存为字符串
|
||||
processedData = msg.toString();
|
||||
}
|
||||
|
||||
// 将数据添加到队列
|
||||
udpData.push({
|
||||
timestamp: Date.now(),
|
||||
source: `${rinfo.address}:${rinfo.port}`,
|
||||
data: processedData
|
||||
});
|
||||
|
||||
// 限制数据队列大小,最多保存1000条记录
|
||||
if (udpData.length > 1000) {
|
||||
udpData = udpData.slice(-1000);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('处理UDP数据时出错:', error);
|
||||
}
|
||||
});
|
||||
|
||||
// 监听监听事件
|
||||
udpServer.on('listening', () => {
|
||||
const address = udpServer.address();
|
||||
console.log(`UDP数据监控已启动在 ${address.address}:${address.port}`);
|
||||
isMonitoring = true;
|
||||
});
|
||||
|
||||
// 绑定IP和端口
|
||||
udpServer.bind(port, ip);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: `UDP监控已在 ${ip}:${port} 上启动`
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('启动UDP监控失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: '启动UDP监控失败: ' + error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 停止UDP监控
|
||||
router.post('/stop', (req, res) => {
|
||||
try {
|
||||
if (!isMonitoring) {
|
||||
return res.json({
|
||||
success: true,
|
||||
message: '没有正在运行的UDP监控'
|
||||
});
|
||||
}
|
||||
|
||||
stopUdpServer();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'UDP监控已停止'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('停止UDP监控失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: '停止UDP监控失败: ' + error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 注入UDP数据
|
||||
router.post('/inject', (req, res) => {
|
||||
try {
|
||||
const { targetIp, targetPort, data } = req.body;
|
||||
|
||||
// 验证参数
|
||||
if (!targetIp) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: '目标IP地址不能为空'
|
||||
});
|
||||
}
|
||||
|
||||
if (!targetPort || targetPort < 1024 || targetPort > 65535) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: '目标端口号必须在1024-65535之间'
|
||||
});
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: '数据内容不能为空'
|
||||
});
|
||||
}
|
||||
|
||||
// 创建临时UDP客户端
|
||||
const client = dgram.createSocket('udp4');
|
||||
|
||||
// 将数据对象转换为JSON字符串
|
||||
const message = JSON.stringify(data);
|
||||
|
||||
// 发送数据
|
||||
client.send(message, targetPort, targetIp, (err) => {
|
||||
// 关闭客户端
|
||||
client.close();
|
||||
|
||||
if (err) {
|
||||
console.error('发送UDP数据失败:', err);
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
error: '发送UDP数据失败: ' + err.message
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`已发送UDP数据到 ${targetIp}:${targetPort}`);
|
||||
res.json({
|
||||
success: true,
|
||||
message: `数据已成功发送到 ${targetIp}:${targetPort}`
|
||||
});
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('发送UDP数据失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: '发送UDP数据失败: ' + error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取UDP监控数据
|
||||
router.get('/data', (req, res) => {
|
||||
try {
|
||||
// 创建一个新数组来保存返回的数据
|
||||
const dataToSend = [...udpData];
|
||||
|
||||
// 清空数据队列
|
||||
udpData = [];
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: dataToSend,
|
||||
isMonitoring,
|
||||
port: currentPort,
|
||||
ip: currentIp
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取UDP监控数据失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: '获取UDP监控数据失败: ' + error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取当前监控状态
|
||||
router.get('/status', (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
isMonitoring,
|
||||
port: currentPort,
|
||||
ip: currentIp
|
||||
});
|
||||
});
|
||||
|
||||
// 辅助函数:停止UDP服务器
|
||||
function stopUdpServer() {
|
||||
if (udpServer) {
|
||||
try {
|
||||
udpServer.close();
|
||||
console.log('UDP监控已停止');
|
||||
} catch (error) {
|
||||
console.error('关闭UDP服务器时出错:', error);
|
||||
}
|
||||
|
||||
udpServer = null;
|
||||
isMonitoring = false;
|
||||
currentPort = null;
|
||||
currentIp = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 当应用程序关闭时,确保UDP服务器也关闭
|
||||
process.on('exit', stopUdpServer);
|
||||
process.on('SIGINT', () => {
|
||||
stopUdpServer();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
module.exports = router;
|
@ -17,6 +17,7 @@ const idlRoutes = require('./routes/idl');
|
||||
const projectModelRoutes = require('./routes/project-model');
|
||||
const ataChaptersRoutes = require('./routes/model-dev');
|
||||
const simulationRoutes = require('./routes/run-simulation');
|
||||
const udpMonitorRoutes = require('./routes/udp-monitor');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
@ -64,6 +65,7 @@ app.use('/api/idl', idlRoutes);
|
||||
app.use('/api', projectModelRoutes);
|
||||
app.use('/api', ataChaptersRoutes);
|
||||
app.use('/api', simulationRoutes);
|
||||
app.use('/api/udp-monitor', udpMonitorRoutes);
|
||||
|
||||
// 主页路由
|
||||
app.get('/', (req, res) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user