为XNSim添加了可以从数据库直接读取数据进行仿真的能力。现在同时支持数据库和配置文件两种模式
This commit is contained in:
parent
7da7a8a5ee
commit
896b46a1b1
BIN
Release/Models/libXNATA04DataProcessor.so.1.0.0.0
Normal file
BIN
Release/Models/libXNATA04DataProcessor.so.1.0.0.0
Normal file
Binary file not shown.
BIN
Release/Models/libXNAerodynamics.so.1.0.0.0
Normal file
BIN
Release/Models/libXNAerodynamics.so.1.0.0.0
Normal file
Binary file not shown.
BIN
Release/Models/libXNGroundHandling.so.1.0.0.0
Normal file
BIN
Release/Models/libXNGroundHandling.so.1.0.0.0
Normal file
Binary file not shown.
BIN
Release/Models/libXNWeightBalance.so.1.0.0.0
Normal file
BIN
Release/Models/libXNWeightBalance.so.1.0.0.0
Normal file
Binary file not shown.
@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scenario>
|
||||
<Environment OSName="Debian" Version="11" RTXVersion="preempt-rt" CPUAffinity="0,1" WorkPath="/home/jin/MyCode/XNSim/Release/" ModelsPath="Models/" ServicesPath="Services/" DomainID="10"/>
|
||||
<Environment OSName="Debian" Version="11" RTXVersion="preempt-rt" CPUAffinity="0,1" PlaneName = "C909" 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="本体模型组" Freq="120" 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="XNAerodynamics" Version="1.0.0.0"/>
|
||||
<Model Name="ATA04地面操纵模型" ClassName="XNGroundHandling" Version="1.0.0.0"/>
|
||||
<Model Name="ATA04质量模型" ClassName="XNWeightBalance" Version="1.0.0.0"/>
|
||||
<Model Name="ATA04数据处理模型" ClassName="XNATA04DataProcessor" Version="1.0.0.0"/>
|
||||
</ModelGroup>
|
||||
<ServicesList>
|
||||
<Service Name="UDP通信服务" ClassName="XNUDPService"/>
|
||||
<Service Name="UDP通信服务" ClassName="XNUDPService" Version="1.0.0.0"/>
|
||||
</ServicesList>
|
||||
</Scenario>
|
||||
|
17
Release/Services/XNUDPService_V1.0.0.0.mcfg
Normal file
17
Release/Services/XNUDPService_V1.0.0.0.mcfg
Normal file
@ -0,0 +1,17 @@
|
||||
<?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>
|
||||
<Command Name="TestCmd" Description="Test" Call="TestCall"/>
|
||||
</CommandList>
|
||||
<UDP>
|
||||
<LocalPort>12345</LocalPort>
|
||||
<TargetHost>127.0.0.1</TargetHost>
|
||||
<TargetPort>54321</TargetPort>
|
||||
</UDP>
|
||||
</Service>
|
BIN
Release/Services/libXNUDPService.so.1.0.0.0
Normal file
BIN
Release/Services/libXNUDPService.so.1.0.0.0
Normal file
Binary file not shown.
BIN
Release/XNEngine
BIN
Release/XNEngine
Binary file not shown.
Binary file not shown.
@ -40,6 +40,8 @@
|
||||
# include <array>
|
||||
# include <cstring>
|
||||
# include <iostream>
|
||||
# include <sqlite3.h>
|
||||
# include <nlohmann/json.hpp>
|
||||
#endif
|
||||
|
||||
#include <fastdds/dds/domain/DomainParticipant.hpp>
|
||||
@ -53,6 +55,8 @@
|
||||
#include <fastcdr/xcdr/optional.hpp>
|
||||
#define FAST_DDS_MACRO eprosima::fastdds::dds
|
||||
|
||||
using XN_JSON = nlohmann::json;
|
||||
|
||||
/**
|
||||
* @brief 默认基频定义,单位 Hz
|
||||
*/
|
||||
@ -91,13 +95,6 @@ struct PERIOD_INFO {
|
||||
*/
|
||||
using XNTimePoint = std::chrono::system_clock::time_point;
|
||||
|
||||
/**
|
||||
* @brief 将ISO格式的时间字符串转换为系统时间点
|
||||
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
|
||||
* @return 系统时间点
|
||||
*/
|
||||
extern "C" XNTimePoint XNCORE_EXPORT parseISOTime(const std::string &timeStr);
|
||||
|
||||
/**
|
||||
* @brief 系统运行状态枚举类
|
||||
*/
|
||||
@ -258,3 +255,37 @@ public:
|
||||
public: \
|
||||
using ThisType = cls; \
|
||||
using SuperType = sup;
|
||||
|
||||
#define XN_UNUSED(x) (void)x
|
||||
|
||||
namespace XNSim
|
||||
{
|
||||
template <typename T>
|
||||
constexpr typename std::underlying_type<T>::type enumValue(T e)
|
||||
{
|
||||
return static_cast<typename std::underlying_type<T>::type>(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将ISO格式的时间字符串转换为系统时间点
|
||||
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
|
||||
* @return 系统时间点
|
||||
*/
|
||||
extern "C" XNTimePoint XNCORE_EXPORT parseISOTime(const std::string &timeStr);
|
||||
|
||||
extern "C" std::vector<std::string> XNCORE_EXPORT split(const std::string &str,
|
||||
const std::string &delim);
|
||||
|
||||
extern "C" std::string XNCORE_EXPORT getFileNameWithoutExt(const std::string &path);
|
||||
|
||||
extern "C" int XNCORE_EXPORT safe_stoi(const std::string &str, int defaultValue = 0);
|
||||
|
||||
inline std::string getStringFromSqlite3(sqlite3_stmt *stmt, int column)
|
||||
{
|
||||
const char *text = reinterpret_cast<const char *>(sqlite3_column_text(stmt, column));
|
||||
if (text == nullptr) {
|
||||
return "";
|
||||
}
|
||||
return std::string(text);
|
||||
}
|
||||
} // namespace XNSim
|
||||
|
@ -77,4 +77,9 @@ struct XNFrameworkPrivate : public XNObjectPrivate {
|
||||
* @brief 场景XML
|
||||
*/
|
||||
std::string scenarioXml;
|
||||
|
||||
/**
|
||||
* @brief 构型ID
|
||||
*/
|
||||
uint32_t configId;
|
||||
};
|
||||
|
@ -61,10 +61,14 @@ public:
|
||||
* @brief 加载模型
|
||||
* @param modelPath: QString类型,模型动态链接库路径
|
||||
* @param className: QString类型,模型类名
|
||||
* @param modelVersion: QString类型,模型版本号
|
||||
* @param initialType: UINT32类型,初始化类型
|
||||
* @param threadID: UINT32类型,线程ID
|
||||
* @details 加载模型
|
||||
*/
|
||||
void LoadModel(const std::string &modelPath, const std::string &className, uint32_t initialType,
|
||||
uint32_t threadID);
|
||||
void LoadModel(const std::string &modelPath, const std::string &className,
|
||||
const std::string &modelVersion, const std::string &planeName,
|
||||
uint32_t initialType, uint32_t threadID);
|
||||
|
||||
/**
|
||||
* @brief 注册模型信息
|
||||
|
@ -238,6 +238,10 @@ public:
|
||||
|
||||
public:
|
||||
virtual void RegisterDDSParticipant();
|
||||
|
||||
private:
|
||||
void ParseXml();
|
||||
void ParseConfig();
|
||||
};
|
||||
|
||||
#define XN_MODEL_INITIALIZE(ClassName) \
|
||||
|
@ -76,4 +76,21 @@ public:
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
virtual bool AnalysisScenarioXml(const std::string &XmlPath, uint32_t initialType);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 解析运行环境配置文件
|
||||
* @param XmlPath: std::string类型,运行环境配置文件解析路径
|
||||
* @return true: 解析成功
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
bool ParseScenarioXml(const std::string &XmlPath);
|
||||
|
||||
/**
|
||||
* @brief 解析构型配置文件
|
||||
* @param ConfigID: std::string类型,构型配置文件在数据库中的ID
|
||||
* @return true: 解析成功
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
bool ParseConfig(const std::string &ConfigID);
|
||||
};
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
virtual bool Initialize() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
void LoadService(const std::string &servicePath, const std::string &serviceName,
|
||||
uint32_t initialType);
|
||||
const std::string &serviceVersion, uint32_t initialType);
|
||||
|
||||
public:
|
||||
XNServiceObjectPtr GetService(uint32_t serviceID);
|
||||
|
@ -54,6 +54,10 @@ public:
|
||||
|
||||
protected:
|
||||
XNFrameworkPtr GetFramework() const;
|
||||
|
||||
private:
|
||||
void ParseXml();
|
||||
void ParseConfig();
|
||||
};
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNServiceObject)
|
||||
|
@ -11,4 +11,5 @@ struct XNServiceObjectPrivate : public XNObjectPrivate {
|
||||
std::unordered_map<std::string, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
XNFrameworkPtr pFramework;
|
||||
uint32_t _initialType;
|
||||
XN_JSON _otherParams;
|
||||
};
|
||||
|
@ -16,8 +16,10 @@ endif()
|
||||
|
||||
file(GLOB DDS_XNIDL_SOURCES_CXX "XNIDL/*.cxx")
|
||||
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
|
||||
add_library(XNCore SHARED
|
||||
XNCore_global.h
|
||||
@ -76,6 +78,7 @@ target_link_libraries(XNCore PRIVATE
|
||||
pthread
|
||||
OpenSSL::SSL
|
||||
OpenSSL::Crypto
|
||||
nlohmann_json
|
||||
dl
|
||||
)
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "XNCore_global.h"
|
||||
|
||||
namespace XNSim
|
||||
{
|
||||
XNTimePoint parseISOTime(const std::string &timeStr)
|
||||
{
|
||||
std::tm tm = {};
|
||||
@ -8,3 +10,49 @@ XNTimePoint parseISOTime(const std::string &timeStr)
|
||||
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
|
||||
return tp;
|
||||
}
|
||||
|
||||
// 辅助函数:分割字符串
|
||||
std::vector<std::string> split(const std::string &str, const std::string &delim)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
size_t prev = 0, pos = 0;
|
||||
do {
|
||||
pos = str.find(delim, prev);
|
||||
if (pos == std::string::npos)
|
||||
pos = str.length();
|
||||
std::string token = str.substr(prev, pos - prev);
|
||||
if (!token.empty())
|
||||
tokens.push_back(token);
|
||||
prev = pos + delim.length();
|
||||
} while (pos < str.length() && prev < str.length());
|
||||
return tokens;
|
||||
}
|
||||
|
||||
// 辅助函数:获取文件名(不含扩展名)
|
||||
std::string getFileNameWithoutExt(const std::string &path)
|
||||
{
|
||||
size_t lastDot = path.find_last_of('.');
|
||||
if (lastDot != std::string::npos) {
|
||||
return path.substr(0, lastDot);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 安全地将字符串转换为整数
|
||||
* @param str 要转换的字符串
|
||||
* @param defaultValue 转换失败时的默认值
|
||||
* @return 转换后的整数值
|
||||
*/
|
||||
int safe_stoi(const std::string &str, int defaultValue)
|
||||
{
|
||||
if (str.empty()) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return std::stoi(str);
|
||||
} catch (const std::exception &) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
} // namespace XNSim
|
@ -40,6 +40,8 @@
|
||||
# include <array>
|
||||
# include <cstring>
|
||||
# include <iostream>
|
||||
# include <sqlite3.h>
|
||||
# include <nlohmann/json.hpp>
|
||||
#endif
|
||||
|
||||
#include <fastdds/dds/domain/DomainParticipant.hpp>
|
||||
@ -53,6 +55,8 @@
|
||||
#include <fastcdr/xcdr/optional.hpp>
|
||||
#define FAST_DDS_MACRO eprosima::fastdds::dds
|
||||
|
||||
using XN_JSON = nlohmann::json;
|
||||
|
||||
/**
|
||||
* @brief 默认基频定义,单位 Hz
|
||||
*/
|
||||
@ -91,13 +95,6 @@ struct PERIOD_INFO {
|
||||
*/
|
||||
using XNTimePoint = std::chrono::system_clock::time_point;
|
||||
|
||||
/**
|
||||
* @brief 将ISO格式的时间字符串转换为系统时间点
|
||||
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
|
||||
* @return 系统时间点
|
||||
*/
|
||||
extern "C" XNTimePoint XNCORE_EXPORT parseISOTime(const std::string &timeStr);
|
||||
|
||||
/**
|
||||
* @brief 系统运行状态枚举类
|
||||
*/
|
||||
@ -258,3 +255,37 @@ public:
|
||||
public: \
|
||||
using ThisType = cls; \
|
||||
using SuperType = sup;
|
||||
|
||||
#define XN_UNUSED(x) (void)x
|
||||
|
||||
namespace XNSim
|
||||
{
|
||||
template <typename T>
|
||||
constexpr typename std::underlying_type<T>::type enumValue(T e)
|
||||
{
|
||||
return static_cast<typename std::underlying_type<T>::type>(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将ISO格式的时间字符串转换为系统时间点
|
||||
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
|
||||
* @return 系统时间点
|
||||
*/
|
||||
extern "C" XNTimePoint XNCORE_EXPORT parseISOTime(const std::string &timeStr);
|
||||
|
||||
extern "C" std::vector<std::string> XNCORE_EXPORT split(const std::string &str,
|
||||
const std::string &delim);
|
||||
|
||||
extern "C" std::string XNCORE_EXPORT getFileNameWithoutExt(const std::string &path);
|
||||
|
||||
extern "C" int XNCORE_EXPORT safe_stoi(const std::string &str, int defaultValue = 0);
|
||||
|
||||
inline std::string getStringFromSqlite3(sqlite3_stmt *stmt, int column)
|
||||
{
|
||||
const char *text = reinterpret_cast<const char *>(sqlite3_column_text(stmt, column));
|
||||
if (text == nullptr) {
|
||||
return "";
|
||||
}
|
||||
return std::string(text);
|
||||
}
|
||||
} // namespace XNSim
|
||||
|
@ -77,4 +77,9 @@ struct XNFrameworkPrivate : public XNObjectPrivate {
|
||||
* @brief 场景XML
|
||||
*/
|
||||
std::string scenarioXml;
|
||||
|
||||
/**
|
||||
* @brief 构型ID
|
||||
*/
|
||||
uint32_t configId;
|
||||
};
|
||||
|
@ -55,6 +55,7 @@ bool XNModelManager::Initialize()
|
||||
}
|
||||
|
||||
void XNModelManager::LoadModel(const std::string &modelPath, const std::string &className,
|
||||
const std::string &modelVersion, const std::string &planeName,
|
||||
uint32_t initialType, uint32_t threadID)
|
||||
{
|
||||
T_D();
|
||||
@ -77,10 +78,15 @@ void XNModelManager::LoadModel(const std::string &modelPath, const std::string &
|
||||
model->SetFramework(GetFramework());
|
||||
model->SetInitializeType(initialType);
|
||||
model->SetThreadID(threadID);
|
||||
if (initialType == 0) {
|
||||
// 使用std::filesystem处理路径
|
||||
std::filesystem::path configPath =
|
||||
std::filesystem::path(modelPath).parent_path() / (className + ".mcfg");
|
||||
std::filesystem::path(modelPath).parent_path()
|
||||
/ (className + "_V" + modelVersion + ".mcfg");
|
||||
model->SetXmlPath(configPath.string());
|
||||
} else if (initialType == 1) {
|
||||
model->SetXmlPath(planeName + "," + className + "," + modelVersion);
|
||||
}
|
||||
|
||||
// 注册模型到管理器
|
||||
d->ModelMap[modelID] = model;
|
||||
@ -92,9 +98,10 @@ void XNModelManager::LoadModel(const std::string &modelPath, const std::string &
|
||||
if (threadID != 0) {
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
framework->GetThreadManager()->RegisterFunction(
|
||||
modelID, std::bind(&XNModelObject::StepUpdate, model.get()), threadID,
|
||||
model->GetRunFreq(), model->GetRunNode(), model->GetRunPriority());
|
||||
// 注册到线程管理器 (重复注册了,暂删除)
|
||||
// framework->GetThreadManager()->RegisterFunction(
|
||||
// modelID, std::bind(&XNModelObject::StepUpdate, model.get()), threadID,
|
||||
// model->GetRunFreq(), model->GetRunNode(), model->GetRunPriority());
|
||||
// 设置模型设置频率
|
||||
double threadFreq =
|
||||
framework->GetThreadManager()->GetThreadFreqByID(threadID);
|
||||
|
@ -61,10 +61,14 @@ public:
|
||||
* @brief 加载模型
|
||||
* @param modelPath: QString类型,模型动态链接库路径
|
||||
* @param className: QString类型,模型类名
|
||||
* @param modelVersion: QString类型,模型版本号
|
||||
* @param initialType: UINT32类型,初始化类型
|
||||
* @param threadID: UINT32类型,线程ID
|
||||
* @details 加载模型
|
||||
*/
|
||||
void LoadModel(const std::string &modelPath, const std::string &className, uint32_t initialType,
|
||||
uint32_t threadID);
|
||||
void LoadModel(const std::string &modelPath, const std::string &className,
|
||||
const std::string &modelVersion, const std::string &planeName,
|
||||
uint32_t initialType, uint32_t threadID);
|
||||
|
||||
/**
|
||||
* @brief 注册模型信息
|
||||
|
@ -195,9 +195,17 @@ void XNModelObject::SetSetFreq(double setFreq)
|
||||
// 初始化函数
|
||||
void XNModelObject::Initialize()
|
||||
{
|
||||
// 先尝试调取动态库
|
||||
T_D();
|
||||
if (d->_initialType == 0) {
|
||||
ParseXml();
|
||||
} else {
|
||||
ParseConfig();
|
||||
}
|
||||
}
|
||||
|
||||
void XNModelObject::ParseXml()
|
||||
{
|
||||
T_D();
|
||||
// 读取配置文件,设置循环执行函数
|
||||
std::ifstream file(GetXmlPath());
|
||||
if (!file.is_open()) {
|
||||
@ -214,8 +222,7 @@ void XNModelObject::Initialize()
|
||||
// 读取配置文件的模型参数
|
||||
const char *modelName = rootNode->FirstChildElement("Name")->GetText();
|
||||
if (!modelName || std::string(modelName) != GetObjectName()) {
|
||||
LOG_WARNING(
|
||||
"0x2162 The model name in the configuration file of model %1 is not consistent "
|
||||
LOG_WARNING("0x2162 The model name in the configuration file of model %1 is not consistent "
|
||||
"with the model name in the configuration file of model %2!",
|
||||
GetObjectName(), modelName ? modelName : "null");
|
||||
return;
|
||||
@ -227,25 +234,24 @@ void XNModelObject::Initialize()
|
||||
// 使用标准C++时间处理
|
||||
std::string createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText();
|
||||
std::string changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText();
|
||||
d->_cCreatTime = parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = parseISOTime(changeTimeStr);
|
||||
d->_cCreatTime = XNSim::parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = XNSim::parseISOTime(changeTimeStr);
|
||||
|
||||
std::string funcNode = rootNode->FirstChildElement("Node")->GetText();
|
||||
d->_runPriority = std::stoi(rootNode->FirstChildElement("Priority")->GetText());
|
||||
d->_runPriority = XNSim::safe_stoi(rootNode->FirstChildElement("Priority")->GetText());
|
||||
|
||||
// 检查运行节点是否是 "x-x" 形式
|
||||
size_t tmp = funcNode.find('-');
|
||||
if (tmp == std::string::npos || tmp == 0) {
|
||||
LOG_WARNING(
|
||||
"0x2162 The value of the run node attribute in the configuration file of model "
|
||||
LOG_WARNING("0x2162 The value of the run node attribute in the configuration file of model "
|
||||
"%1 is not in the x-x format, registration not executed!",
|
||||
GetObjectName());
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用标准C++字符串处理
|
||||
d->_runFreq = std::stoi(funcNode.substr(0, tmp));
|
||||
d->_runNode = std::stoi(funcNode.substr(tmp + 1));
|
||||
d->_runFreq = XNSim::safe_stoi(funcNode.substr(0, tmp));
|
||||
d->_runNode = XNSim::safe_stoi(funcNode.substr(tmp + 1));
|
||||
|
||||
// 注册周期性函数
|
||||
auto framework = GetFramework();
|
||||
@ -290,7 +296,109 @@ void XNModelObject::Initialize()
|
||||
// TODO: 处理命令列表
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XNModelObject::ParseConfig()
|
||||
{
|
||||
T_D();
|
||||
std::vector<std::string> nameAndVersion = XNSim::split(GetXmlPath(), ",");
|
||||
std::string planeName = nameAndVersion[0];
|
||||
std::string modelName = nameAndVersion[1];
|
||||
std::string modelVersion = nameAndVersion[2];
|
||||
// 获取数据库路径
|
||||
std::string dbPath = std::getenv("XNCore");
|
||||
if (dbPath.empty()) {
|
||||
LOG_ERROR("0x1015 未设置XNCore环境变量, 引擎将退出!");
|
||||
return;
|
||||
}
|
||||
dbPath += "/database/XNSim.db";
|
||||
|
||||
// 打开数据库
|
||||
sqlite3 *db;
|
||||
if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1016 打开数据库失败: %1", sqlite3_errmsg(db));
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备SQL语句
|
||||
std::string sql =
|
||||
"SELECT * FROM XNModelsVersion WHERE PlaneName = ? AND ClassName = ? AND Version = ?";
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1017 准备SQL语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_text(stmt, 1, planeName.c_str(), planeName.length(), nullptr) != SQLITE_OK
|
||||
|| sqlite3_bind_text(stmt, 2, modelName.c_str(), modelName.length(), nullptr) != SQLITE_OK
|
||||
|| sqlite3_bind_text(stmt, 3, modelVersion.c_str(), modelVersion.length(), nullptr)
|
||||
!= SQLITE_OK) {
|
||||
LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||||
LOG_ERROR("0x1019 未找到机型为%1,模型名称为%2,版本号%3的记录", planeName.c_str(),
|
||||
modelName.c_str(), modelVersion.c_str());
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
|
||||
d->_sDescription = XNSim::getStringFromSqlite3(stmt, 7);
|
||||
d->_sAuthor = XNSim::getStringFromSqlite3(stmt, 6);
|
||||
d->_sVersion = XNSim::getStringFromSqlite3(stmt, 2);
|
||||
|
||||
// 解析时间
|
||||
std::string createTimeStr = XNSim::getStringFromSqlite3(stmt, 8);
|
||||
std::string changeTimeStr = XNSim::getStringFromSqlite3(stmt, 9);
|
||||
d->_cCreatTime = XNSim::parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = XNSim::parseISOTime(changeTimeStr);
|
||||
d->_runFreq = XNSim::safe_stoi(XNSim::getStringFromSqlite3(stmt, 10));
|
||||
d->_runNode = XNSim::safe_stoi(XNSim::getStringFromSqlite3(stmt, 11));
|
||||
d->_runPriority = XNSim::safe_stoi(XNSim::getStringFromSqlite3(stmt, 12));
|
||||
|
||||
// 注册周期性函数
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
auto threadManager = framework->GetThreadManager();
|
||||
if (threadManager) {
|
||||
threadManager->RegisterFunction(
|
||||
GetUniqueId(), std::bind(&XNModelObject::StepUpdate, this), d->_threadID,
|
||||
d->_runFreq, d->_runNode, d->_runPriority);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载动态库
|
||||
std::string mathlib = XNSim::getStringFromSqlite3(stmt, 13);
|
||||
if (mathlib.length() > 0) {
|
||||
// 使用标准C++文件路径处理
|
||||
std::filesystem::path xmlPath(GetXmlPath());
|
||||
d->_sLibPath = xmlPath.parent_path().string() + "/" + mathlib;
|
||||
|
||||
// 使用标准C++动态库加载
|
||||
d->_dynamicLib = dlopen(d->_sLibPath.c_str(), RTLD_LAZY);
|
||||
if (d->_dynamicLib) { // 动态库加载成功
|
||||
LOG_INFO("0x2163 Model %1 loaded algorithm dynamic library %2 successfully!",
|
||||
GetObjectName(), d->_sLibPath);
|
||||
} else {
|
||||
LOG_WARNING(
|
||||
"0x2160 Model %1 failed to find algorithm dynamic library %2, will not call "
|
||||
"algorithm!",
|
||||
GetObjectName(), d->_sLibPath);
|
||||
d->_dynamicLib = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 读取模型命令列表
|
||||
// 清理资源
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
// 单步执行函数
|
||||
|
@ -238,6 +238,10 @@ public:
|
||||
|
||||
public:
|
||||
virtual void RegisterDDSParticipant();
|
||||
|
||||
private:
|
||||
void ParseXml();
|
||||
void ParseConfig();
|
||||
};
|
||||
|
||||
#define XN_MODEL_INITIALIZE(ClassName) \
|
||||
|
@ -66,35 +66,19 @@ bool XNScenarioManager::PrepareForExecute()
|
||||
return true;
|
||||
}
|
||||
|
||||
// 辅助函数:分割字符串
|
||||
std::vector<std::string> split(const std::string &str, const std::string &delim)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
size_t prev = 0, pos = 0;
|
||||
do {
|
||||
pos = str.find(delim, prev);
|
||||
if (pos == std::string::npos)
|
||||
pos = str.length();
|
||||
std::string token = str.substr(prev, pos - prev);
|
||||
if (!token.empty())
|
||||
tokens.push_back(token);
|
||||
prev = pos + delim.length();
|
||||
} while (pos < str.length() && prev < str.length());
|
||||
return tokens;
|
||||
}
|
||||
|
||||
// 辅助函数:获取文件名(不含扩展名)
|
||||
std::string getFileNameWithoutExt(const std::string &path)
|
||||
{
|
||||
size_t lastDot = path.find_last_of('.');
|
||||
if (lastDot != std::string::npos) {
|
||||
return path.substr(0, lastDot);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// 运行环境配置文件解析
|
||||
bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t initialType)
|
||||
{
|
||||
T_D();
|
||||
if (initialType == 0) {
|
||||
return ParseScenarioXml(XmlPath);
|
||||
} else {
|
||||
return ParseConfig(XmlPath);
|
||||
}
|
||||
}
|
||||
|
||||
// 解析运行环境描述文件
|
||||
bool XNScenarioManager::ParseScenarioXml(const std::string &XmlPath)
|
||||
{
|
||||
T_D();
|
||||
std::ifstream file(XmlPath);
|
||||
@ -114,6 +98,7 @@ bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t
|
||||
std::string OSName = envInfo->Attribute("OSName");
|
||||
std::string version = envInfo->Attribute("Version");
|
||||
std::string kernel = envInfo->Attribute("RTXVersion");
|
||||
std::string planeName = envInfo->Attribute("PlaneName");
|
||||
// 设置工作目录
|
||||
std::string rootPath = envInfo->Attribute("WorkPath");
|
||||
GetFramework()->SetWorkPath(rootPath);
|
||||
@ -128,7 +113,7 @@ bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t
|
||||
GetFramework()->GetDDSManager()->SetDomainID(domainID);
|
||||
// 读取CPU亲和性
|
||||
std::string cpuAff = envInfo->Attribute("CPUAffinity");
|
||||
std::vector<std::string> cpuAffList = split(cpuAff, ",");
|
||||
std::vector<std::string> cpuAffList = XNSim::split(cpuAff, ",");
|
||||
|
||||
//读取服务列表
|
||||
tinyxml2::XMLElement *serviceList = root->FirstChildElement("ServicesList");
|
||||
@ -137,10 +122,12 @@ bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t
|
||||
while (service) {
|
||||
std::string serviceName = service->Attribute("Name");
|
||||
std::string libName = service->Attribute("ClassName");
|
||||
libName = getFileNameWithoutExt(libName);
|
||||
std::string dynamicLibName = servicePath + "lib" + libName + ".so";
|
||||
std::string serviceVersion = service->Attribute("Version");
|
||||
libName = XNSim::getFileNameWithoutExt(libName);
|
||||
std::string dynamicLibName = servicePath + "lib" + libName + ".so." + serviceVersion;
|
||||
// 加载动态库
|
||||
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, libName, 0);
|
||||
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, libName,
|
||||
serviceVersion, 0);
|
||||
service = service->NextSiblingElement("Service");
|
||||
}
|
||||
}
|
||||
@ -153,14 +140,14 @@ bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t
|
||||
// 读取模型分组频率
|
||||
double modelGroupFreq = std::stod(modelGroup->Attribute("Freq"));
|
||||
// 读取模型分组优先级
|
||||
int modelGroupPriority = std::stoi(modelGroup->Attribute("Priority"));
|
||||
int modelGroupPriority = XNSim::safe_stoi(modelGroup->Attribute("Priority"));
|
||||
if (modelGroupPriority > 99 || modelGroupPriority < 0) {
|
||||
LOG_ERROR("0x2100 模型分组优先级设置错误,优先级值:%d", modelGroupPriority);
|
||||
return false;
|
||||
}
|
||||
// 读取模型分组CPU亲和性
|
||||
std::string modelGroupCPUAff = modelGroup->Attribute("CPUAff");
|
||||
std::vector<std::string> modelGroupCPUAffList = split(modelGroupCPUAff, ",");
|
||||
std::vector<std::string> modelGroupCPUAffList = XNSim::split(modelGroupCPUAff, ",");
|
||||
|
||||
// 验证CPU亲和性
|
||||
for (const auto &cpu : modelGroupCPUAffList) {
|
||||
@ -188,10 +175,12 @@ bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t
|
||||
while (model) {
|
||||
std::string modelName = model->Attribute("Name");
|
||||
std::string libName = model->Attribute("ClassName");
|
||||
libName = getFileNameWithoutExt(libName);
|
||||
std::string dynamicLibName = modelPath + "lib" + libName + ".so";
|
||||
std::string modelVersion = model->Attribute("Version");
|
||||
libName = XNSim::getFileNameWithoutExt(libName);
|
||||
std::string dynamicLibName = modelPath + "lib" + libName + ".so." + modelVersion;
|
||||
// 加载动态库
|
||||
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, libName, 0, threadID);
|
||||
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, libName, modelVersion,
|
||||
planeName, 0, threadID);
|
||||
model = model->NextSiblingElement("Model");
|
||||
}
|
||||
|
||||
@ -200,3 +189,204 @@ bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 解析构型配置文件
|
||||
bool XNScenarioManager::ParseConfig(const std::string &ConfigID)
|
||||
{
|
||||
T_D();
|
||||
// 获取数据库路径
|
||||
std::string dbPath = std::getenv("XNCore");
|
||||
if (dbPath.empty()) {
|
||||
LOG_ERROR("0x1015 未设置XNCore环境变量, 引擎将退出!");
|
||||
return false;
|
||||
}
|
||||
dbPath += "/database/XNSim.db";
|
||||
|
||||
// 打开数据库
|
||||
sqlite3 *db;
|
||||
if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1016 打开数据库失败: %1", sqlite3_errmsg(db));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 准备SQL语句
|
||||
std::string sql = "SELECT * FROM Configuration WHERE ConfID = ?";
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1017 准备SQL语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
int configIdInt = XNSim::safe_stoi(ConfigID);
|
||||
if (sqlite3_bind_int(stmt, 1, configIdInt) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||||
LOG_ERROR("0x1019 未找到配置ID为%1的记录", ConfigID);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
std::string planeName = XNSim::getStringFromSqlite3(stmt, 1);
|
||||
std::string osName = XNSim::getStringFromSqlite3(stmt, 3);
|
||||
std::string version = XNSim::getStringFromSqlite3(stmt, 4);
|
||||
std::string kernel = XNSim::getStringFromSqlite3(stmt, 5);
|
||||
std::string rootPath = XNSim::getStringFromSqlite3(stmt, 7);
|
||||
GetFramework()->SetWorkPath(rootPath);
|
||||
// 设置模型库目录
|
||||
std::string modelPath = rootPath + XNSim::getStringFromSqlite3(stmt, 8);
|
||||
GetFramework()->SetModelPath(modelPath);
|
||||
// 设置服务库目录
|
||||
std::string servicePath = rootPath + XNSim::getStringFromSqlite3(stmt, 9);
|
||||
GetFramework()->SetServicePath(servicePath);
|
||||
// 设置域ID
|
||||
uint32_t domainID = std::stoul(XNSim::getStringFromSqlite3(stmt, 10));
|
||||
GetFramework()->GetDDSManager()->SetDomainID(domainID);
|
||||
// 读取CPU亲和性
|
||||
std::string cpuAff = XNSim::getStringFromSqlite3(stmt, 6);
|
||||
std::vector<std::string> cpuAffList = XNSim::split(cpuAff, ",");
|
||||
|
||||
//查询LoadServices表读取服务信息
|
||||
std::string servicesSql = "SELECT * FROM LoadServices WHERE ConfID = ?";
|
||||
sqlite3_stmt *servicesStmt;
|
||||
if (sqlite3_prepare_v2(db, servicesSql.c_str(), -1, &servicesStmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1020 准备LoadServices查询语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_int(servicesStmt, 1, configIdInt) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1021 绑定LoadServices参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并处理结果
|
||||
while (sqlite3_step(servicesStmt) == SQLITE_ROW) {
|
||||
// 获取服务信息
|
||||
std::string ClassName = XNSim::getStringFromSqlite3(servicesStmt, 1);
|
||||
std::string ServiceVersion = XNSim::getStringFromSqlite3(servicesStmt, 2);
|
||||
std::string ServiceName = XNSim::getStringFromSqlite3(servicesStmt, 3);
|
||||
|
||||
ClassName = XNSim::getFileNameWithoutExt(ClassName);
|
||||
std::string dynamicLibName = servicePath + "lib" + ClassName + ".so." + ServiceVersion;
|
||||
// 加载动态库
|
||||
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, ClassName, ServiceVersion,
|
||||
1);
|
||||
}
|
||||
|
||||
// 查询LoadModelGroups表读取模型组信息
|
||||
std::string modelGroupsSql = "SELECT * FROM LoadModelGroups WHERE ConfID = ?";
|
||||
sqlite3_stmt *modelGroupsStmt;
|
||||
if (sqlite3_prepare_v2(db, modelGroupsSql.c_str(), -1, &modelGroupsStmt, nullptr)
|
||||
!= SQLITE_OK) {
|
||||
LOG_ERROR("0x1020 准备LoadModelGroups查询语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_int(modelGroupsStmt, 1, configIdInt) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1021 绑定LoadModelGroups参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并处理结果
|
||||
while (sqlite3_step(modelGroupsStmt) == SQLITE_ROW) {
|
||||
// 获取模型组信息
|
||||
std::string GroupID = XNSim::getStringFromSqlite3(modelGroupsStmt, 1);
|
||||
std::string GroupName = XNSim::getStringFromSqlite3(modelGroupsStmt, 2);
|
||||
double GroupFreq = std::stod(XNSim::getStringFromSqlite3(modelGroupsStmt, 3));
|
||||
uint32_t GroupPriority = XNSim::safe_stoi(XNSim::getStringFromSqlite3(modelGroupsStmt, 4));
|
||||
std::string GroupCPUAff = XNSim::getStringFromSqlite3(modelGroupsStmt, 5);
|
||||
std::vector<std::string> GroupCPUAffList = XNSim::split(GroupCPUAff, ",");
|
||||
|
||||
// 验证CPU亲和性
|
||||
for (const auto &cpu : GroupCPUAffList) {
|
||||
if (std::find(cpuAffList.begin(), cpuAffList.end(), cpu) == cpuAffList.end()) {
|
||||
LOG_ERROR("0x2100 模型分组CPU亲和性设置错误,CPU亲和性值:%s,进程CPU亲和性值:%s",
|
||||
cpu.c_str(), cpuAff.c_str());
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int ThreadCpuAffinity = 0;
|
||||
for (const auto &cpu : GroupCPUAffList) {
|
||||
auto it = std::find(cpuAffList.begin(), cpuAffList.end(), cpu);
|
||||
if (it != cpuAffList.end()) {
|
||||
ThreadCpuAffinity |= 1 << std::distance(cpuAffList.begin(), it);
|
||||
}
|
||||
}
|
||||
LOG_INFO("0x1021 添加线程池: %1", GroupName);
|
||||
// 添加线程池
|
||||
uint32_t threadID = GetFramework()->GetThreadManager()->AddThreadPool(
|
||||
GroupName, GroupFreq, GroupPriority, ThreadCpuAffinity);
|
||||
|
||||
// 准备查询LoadModels表的SQL语句
|
||||
std::string modelsSql = "SELECT * FROM LoadModels WHERE GroupID = ?";
|
||||
sqlite3_stmt *modelsStmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db, modelsSql.c_str(), -1, &modelsStmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1022 准备LoadModels查询语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_int(modelsStmt, 1, XNSim::safe_stoi(GroupID)) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1023 绑定LoadModels参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(modelsStmt);
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并处理结果
|
||||
while (sqlite3_step(modelsStmt) == SQLITE_ROW) {
|
||||
// 获取模型信息
|
||||
std::string ClassName = XNSim::getStringFromSqlite3(modelsStmt, 1);
|
||||
std::string ModelVersion = XNSim::getStringFromSqlite3(modelsStmt, 2);
|
||||
std::string ModelName = XNSim::getStringFromSqlite3(modelsStmt, 3);
|
||||
|
||||
ClassName = XNSim::getFileNameWithoutExt(ClassName);
|
||||
std::string dynamicLibName = modelPath + "lib" + ClassName + ".so." + ModelVersion;
|
||||
// 加载动态库
|
||||
LOG_INFO("0x1021 加载模型: %1", dynamicLibName);
|
||||
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, ClassName, ModelVersion,
|
||||
planeName, 1, threadID);
|
||||
}
|
||||
// 清理资源
|
||||
sqlite3_finalize(modelsStmt);
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return true;
|
||||
}
|
||||
|
@ -76,4 +76,21 @@ public:
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
virtual bool AnalysisScenarioXml(const std::string &XmlPath, uint32_t initialType);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 解析运行环境配置文件
|
||||
* @param XmlPath: std::string类型,运行环境配置文件解析路径
|
||||
* @return true: 解析成功
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
bool ParseScenarioXml(const std::string &XmlPath);
|
||||
|
||||
/**
|
||||
* @brief 解析构型配置文件
|
||||
* @param ConfigID: std::string类型,构型配置文件在数据库中的ID
|
||||
* @return true: 解析成功
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
bool ParseConfig(const std::string &ConfigID);
|
||||
};
|
||||
|
@ -38,7 +38,7 @@ bool XNServiceManager::PrepareForExecute()
|
||||
}
|
||||
|
||||
void XNServiceManager::LoadService(const std::string &servicePath, const std::string &serviceName,
|
||||
uint32_t initialType)
|
||||
const std::string &serviceVersion, uint32_t initialType)
|
||||
{
|
||||
T_D();
|
||||
void *handle = dlopen(servicePath.c_str(), RTLD_LAZY);
|
||||
@ -59,15 +59,26 @@ void XNServiceManager::LoadService(const std::string &servicePath, const std::st
|
||||
service->SetUniqueId(serviceID);
|
||||
service->SetObjectName(serviceName);
|
||||
service->SetFramework(GetFramework());
|
||||
if (initialType == 0) {
|
||||
// 使用std::filesystem处理路径
|
||||
std::filesystem::path configPath =
|
||||
std::filesystem::path(servicePath).parent_path() / (serviceName + ".scfg");
|
||||
std::filesystem::path(servicePath).parent_path()
|
||||
/ (serviceName + "_V" + serviceVersion + ".scfg");
|
||||
service->SetXmlPath(configPath.string());
|
||||
} else if (initialType == 1) {
|
||||
LOG_INFO("0x2176 加载服务: %1", serviceName + "," + serviceVersion);
|
||||
service->SetXmlPath(serviceName + "," + serviceVersion);
|
||||
} else {
|
||||
LOG_WARNING("0x2175 InitialType Error, InitialType: %d", initialType);
|
||||
dlclose(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// 注册服务到管理器
|
||||
d->ServiceList[serviceID] = service;
|
||||
service->SetInitializeType(initialType);
|
||||
// 初始化服务
|
||||
LOG_INFO("0x2176 初始化服务: %1", serviceName);
|
||||
service->Initialize();
|
||||
} else {
|
||||
LOG_WARNING("0x2173 Service %s Not found in dynamic link library %s!",
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
virtual bool Initialize() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
void LoadService(const std::string &servicePath, const std::string &serviceName,
|
||||
uint32_t initialType);
|
||||
const std::string &serviceVersion, uint32_t initialType);
|
||||
|
||||
public:
|
||||
XNServiceObjectPtr GetService(uint32_t serviceID);
|
||||
|
@ -139,6 +139,15 @@ void XNServiceObject::Initialize()
|
||||
{
|
||||
T_D();
|
||||
if (d->_initialType == 0) {
|
||||
ParseXml();
|
||||
} else {
|
||||
ParseConfig();
|
||||
}
|
||||
}
|
||||
|
||||
void XNServiceObject::ParseXml()
|
||||
{
|
||||
T_D();
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (doc.LoadFile(GetXmlPath().c_str()) != tinyxml2::XML_SUCCESS) {
|
||||
LOG_WARNING("Failed to open the service configuration file: %1!", GetXmlPath());
|
||||
@ -153,8 +162,7 @@ void XNServiceObject::Initialize()
|
||||
|
||||
const char *serviceName = rootNode->FirstChildElement("Name")->GetText();
|
||||
if (serviceName != GetObjectName()) {
|
||||
LOG_WARNING(
|
||||
"The service name in the configuration file of service %1 is not consistent "
|
||||
LOG_WARNING("The service name in the configuration file of service %1 is not consistent "
|
||||
"with the service name in the configuration file of service %2!",
|
||||
GetObjectName(), serviceName);
|
||||
return;
|
||||
@ -167,8 +175,8 @@ void XNServiceObject::Initialize()
|
||||
// 解析时间
|
||||
const char *createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText();
|
||||
const char *changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText();
|
||||
d->_cCreateTime = parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = parseISOTime(changeTimeStr);
|
||||
d->_cCreateTime = XNSim::parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = XNSim::parseISOTime(changeTimeStr);
|
||||
|
||||
tinyxml2::XMLElement *nodeCmds = rootNode->FirstChildElement("CommandList");
|
||||
if (nodeCmds) {
|
||||
@ -180,8 +188,103 @@ void XNServiceObject::Initialize()
|
||||
// TODO: 处理命令信息
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
void XNServiceObject::ParseConfig()
|
||||
{
|
||||
T_D();
|
||||
std::vector<std::string> nameAndVersion = XNSim::split(GetXmlPath(), ",");
|
||||
std::string serviceName = nameAndVersion[0];
|
||||
std::string serviceVersion = nameAndVersion[1];
|
||||
// 获取数据库路径
|
||||
std::string dbPath = std::getenv("XNCore");
|
||||
if (dbPath.empty()) {
|
||||
LOG_ERROR("0x1015 未设置XNCore环境变量, 引擎将退出!");
|
||||
return;
|
||||
}
|
||||
dbPath += "/database/XNSim.db";
|
||||
|
||||
// 打开数据库
|
||||
sqlite3 *db;
|
||||
if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1016 打开数据库失败: %1", sqlite3_errmsg(db));
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备SQL语句
|
||||
std::string sql = "SELECT * FROM XNServiceVersion WHERE ClassName = ? AND Version = ?";
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1017 准备SQL语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_text(stmt, 1, serviceName.c_str(), serviceName.length(), nullptr) != SQLITE_OK
|
||||
|| sqlite3_bind_text(stmt, 2, serviceVersion.c_str(), serviceVersion.length(), nullptr)
|
||||
!= SQLITE_OK) {
|
||||
LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||||
LOG_ERROR("0x1019 未找到服务名称为%1,版本号%2的记录", serviceName.c_str(),
|
||||
serviceVersion.c_str());
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
d->_sDescription = XNSim::getStringFromSqlite3(stmt, 5);
|
||||
d->_sAuthor = XNSim::getStringFromSqlite3(stmt, 4);
|
||||
d->_sVersion = XNSim::getStringFromSqlite3(stmt, 2);
|
||||
|
||||
// 解析时间
|
||||
std::string createTimeStr = XNSim::getStringFromSqlite3(stmt, 6);
|
||||
std::string changeTimeStr = XNSim::getStringFromSqlite3(stmt, 7);
|
||||
d->_cCreateTime = XNSim::parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = XNSim::parseISOTime(changeTimeStr);
|
||||
|
||||
// 读取服务命令列表
|
||||
std::string commandListStr = XNSim::getStringFromSqlite3(stmt, 8);
|
||||
if (!commandListStr.empty()) {
|
||||
try {
|
||||
XN_JSON commandList = XN_JSON::parse(commandListStr);
|
||||
if (commandList.is_array()) {
|
||||
for (const auto &cmd : commandList) {
|
||||
if (cmd.contains("Name") && cmd.contains("Description")
|
||||
&& cmd.contains("Call")) {
|
||||
LOG_INFO("0x1021 服务命令: %1", cmd["Name"].get<std::string>());
|
||||
// TODO: 处理服务命令信息
|
||||
// d->_commandList.emplace_back(
|
||||
// cmd["Name"].get<std::string>(),
|
||||
// cmd["Description"].get<std::string>(),
|
||||
// cmd["Call"].get<std::string>()
|
||||
// );
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_WARNING("0x1020 解析服务命令列表失败: %1", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// 读取其他参数
|
||||
std::string otherParamsStr = XNSim::getStringFromSqlite3(stmt, 9);
|
||||
if (!otherParamsStr.empty()) {
|
||||
try {
|
||||
d->_otherParams = XN_JSON::parse(otherParamsStr);
|
||||
} catch (const std::exception &e) {
|
||||
LOG_WARNING("0x1020 解析其他参数失败: %1", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
void XNServiceObject::PrepareForExecute()
|
||||
|
@ -54,6 +54,10 @@ public:
|
||||
|
||||
protected:
|
||||
XNFrameworkPtr GetFramework() const;
|
||||
|
||||
private:
|
||||
void ParseXml();
|
||||
void ParseConfig();
|
||||
};
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNServiceObject)
|
||||
|
@ -11,4 +11,5 @@ struct XNServiceObjectPrivate : public XNObjectPrivate {
|
||||
std::unordered_map<std::string, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
XNFrameworkPtr pFramework;
|
||||
uint32_t _initialType;
|
||||
XN_JSON _otherParams;
|
||||
};
|
||||
|
@ -403,11 +403,12 @@ void XNEngine::PublishEngineStatus()
|
||||
}
|
||||
|
||||
// 运行引擎
|
||||
bool XNEngine::Run(const std::string &XmlPath)
|
||||
bool XNEngine::Run(const std::string &XmlPath, const uint32_t InitializeType)
|
||||
{
|
||||
if (!framework) {
|
||||
return false;
|
||||
}
|
||||
if (InitializeType == 0) {
|
||||
// 解析配置文件
|
||||
bool isReady = ParseConfig(XmlPath);
|
||||
// 如果解析配置文件失败
|
||||
@ -415,12 +416,22 @@ bool XNEngine::Run(const std::string &XmlPath)
|
||||
// 返回失败
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (InitializeType == 1) {
|
||||
// 解析数据库
|
||||
bool isReady = ParseDataBase(XmlPath);
|
||||
// 如果解析数据库失败
|
||||
if (!isReady) {
|
||||
// 返回失败
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 设置场景XML路径
|
||||
framework->SetScenarioXml(XmlPath);
|
||||
// 设置CPU亲和性
|
||||
framework->SetCpuAffinity(CPUAffinity);
|
||||
// 单次触发初始化信号
|
||||
bool ret = framework->Initialize(0);
|
||||
bool ret = framework->Initialize(InitializeType);
|
||||
// 如果初始化失败
|
||||
if (!ret) {
|
||||
LOG_ERROR("0x1012 初始化失败, 引擎将退出!");
|
||||
@ -488,7 +499,7 @@ bool XNEngine::Run(const std::string &XmlPath)
|
||||
}
|
||||
|
||||
// 运行引擎
|
||||
bool XNEngine::ParseDataBase(const uint32_t &ConfigId)
|
||||
bool XNEngine::ParseDataBase(const std::string &ConfigId)
|
||||
{
|
||||
// 获取数据库路径
|
||||
std::string dbPath = std::getenv("XNCore");
|
||||
@ -501,7 +512,7 @@ bool XNEngine::ParseDataBase(const uint32_t &ConfigId)
|
||||
// 打开数据库
|
||||
sqlite3 *db;
|
||||
if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1016 打开数据库失败: {}", sqlite3_errmsg(db));
|
||||
LOG_ERROR("0x1016 打开数据库失败: %1", sqlite3_errmsg(db));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -509,14 +520,15 @@ bool XNEngine::ParseDataBase(const uint32_t &ConfigId)
|
||||
std::string sql = "SELECT * FROM Configuration WHERE ConfID = ?";
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1017 准备SQL语句失败: {}", sqlite3_errmsg(db));
|
||||
LOG_ERROR("0x1017 准备SQL语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_int(stmt, 1, ConfigId) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1018 绑定参数失败: {}", sqlite3_errmsg(db));
|
||||
int configIdInt = std::stoi(ConfigId);
|
||||
if (sqlite3_bind_int(stmt, 1, configIdInt) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
@ -524,7 +536,7 @@ bool XNEngine::ParseDataBase(const uint32_t &ConfigId)
|
||||
|
||||
// 执行查询
|
||||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||||
LOG_ERROR("0x1019 未找到配置ID为{}的记录", ConfigId);
|
||||
LOG_ERROR("0x1019 未找到配置ID为%1的记录", ConfigId);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
@ -539,7 +551,8 @@ bool XNEngine::ParseDataBase(const uint32_t &ConfigId)
|
||||
CPUAffinity = 0;
|
||||
|
||||
// 读取配置信息
|
||||
std::string CPUAff = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 6));
|
||||
std::string CPUAff = XNSim::getStringFromSqlite3(stmt, 6);
|
||||
//std::string CPUAff = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 6));
|
||||
|
||||
std::istringstream iss(CPUAff);
|
||||
std::string cpuIndex;
|
||||
@ -591,88 +604,6 @@ bool XNEngine::ParseDataBase(const uint32_t &ConfigId)
|
||||
sqlite3_close(db);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNEngine::Run(const uint32_t &ConfigId)
|
||||
{
|
||||
if (!framework) {
|
||||
return false;
|
||||
}
|
||||
// 解析数据库
|
||||
bool isReady = ParseDataBase(ConfigId);
|
||||
// 如果解析数据库失败
|
||||
if (!isReady) {
|
||||
// 返回失败
|
||||
return false;
|
||||
}
|
||||
// 设置构型ID
|
||||
//framework->SetScenarioId(ConfigId);
|
||||
// 设置CPU亲和性
|
||||
framework->SetCpuAffinity(CPUAffinity);
|
||||
// 单次触发初始化信号
|
||||
bool ret = framework->Initialize(1);
|
||||
// 如果初始化失败
|
||||
if (!ret) {
|
||||
LOG_ERROR("0x1012 初始化失败, 引擎将退出!");
|
||||
// 返回失败
|
||||
return false;
|
||||
}
|
||||
// 如果初始化成功
|
||||
// 设置框架状态
|
||||
frameworkStatus = XNFrameObjectStatus::Initialized;
|
||||
// 记录信息日志
|
||||
LOG_INFO("引擎初始化成功!");
|
||||
// 如果测试模式
|
||||
if (isTestMode) {
|
||||
// 记录信息日志
|
||||
LOG_INFO("引擎测试通过!");
|
||||
// 返回成功
|
||||
return true;
|
||||
}
|
||||
ret = framework->PrepareForExecute();
|
||||
// 如果准备执行失败
|
||||
if (!ret) {
|
||||
LOG_ERROR("0x1013 准备执行失败, 引擎将退出!");
|
||||
// 返回失败
|
||||
return false;
|
||||
}
|
||||
// 设置框架状态
|
||||
frameworkStatus = XNFrameObjectStatus::Ready;
|
||||
// 获取DDS管理器
|
||||
XNDDSManagerPtr ddsManager = framework->GetDDSManager();
|
||||
// 如果DDS管理器存在
|
||||
if (ddsManager) {
|
||||
// 注册仿真控制订阅者
|
||||
auto func = std::bind(&XNEngine::SimControlListener, this, std::placeholders::_1);
|
||||
ddsManager->RegisterSubscriber<XNSim::XNSimControl::XNRuntimeControlPubSubType>(
|
||||
"XNSim::XNSimControl::XNRuntimeControl", 0, func);
|
||||
// 触发仿真控制信号
|
||||
framework->SimControl(0, SimControlCmd::Start);
|
||||
// 注册引擎状态发布者
|
||||
engineStatusWriter =
|
||||
ddsManager->RegisterPublisher<XNSim::XNSimStatus::XNEngineStatusPubSubType>(
|
||||
"XNSim::XNSimStatus::XNEngineStatus", 0);
|
||||
// 如果引擎状态写入器存在
|
||||
if (engineStatusWriter) {
|
||||
// 设置引擎运行标志
|
||||
engineRunning = true;
|
||||
while (engineRunning) {
|
||||
// 发布一次初始状态
|
||||
PublishEngineStatus();
|
||||
// 等待1秒
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
if (!engineRunning) {
|
||||
// 取消注册引擎状态发布者
|
||||
//ddsManager->UnregisterPublisher("XNSim::XNSimStatus::XNEngineStatus");
|
||||
//ddsManager->UnregisterSubscriber("XNSim::XNSimControl::XNRuntimeControl");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 记录错误日志
|
||||
LOG_ERROR("0x1014 无法发送引擎运行状态, 引擎将退出!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 设置测试模式
|
||||
void XNEngine::SetTestMode(bool isTestMode)
|
||||
{
|
||||
|
@ -40,13 +40,8 @@ public:
|
||||
* @param XmlPath 场景XML路径
|
||||
* @return 是否成功
|
||||
*/
|
||||
bool Run(const std::string &XmlPath);
|
||||
/**
|
||||
* @brief 运行引擎
|
||||
* @param ConfigId 构型ID
|
||||
* @return 是否成功
|
||||
*/
|
||||
bool Run(const uint32_t &ConfigId);
|
||||
bool Run(const std::string &XmlPath, const uint32_t InitializeType);
|
||||
|
||||
/**
|
||||
* @brief 设置测试模式
|
||||
* @param isTestMode 是否为测试模式
|
||||
@ -66,7 +61,7 @@ private:
|
||||
* @param ConfigId 配置ID
|
||||
* @return 是否成功
|
||||
*/
|
||||
bool ParseDataBase(const uint32_t &ConfigId);
|
||||
bool ParseDataBase(const std::string &ConfigId);
|
||||
|
||||
/**
|
||||
* @brief 设置控制台输出
|
||||
|
@ -72,9 +72,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
//检测配置文件格式
|
||||
if (hasConfigPath) {
|
||||
return engine.Run(configPath);
|
||||
return engine.Run(configPath, 0);
|
||||
} else if (hasConfigId) {
|
||||
return engine.Run(configId);
|
||||
return engine.Run(configId, 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNATA04DataProcessor LANGUAGES CXX)
|
||||
|
||||
set(MODEL_VERSION "1.0.0.0")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
@ -23,6 +25,14 @@ add_library(XNATA04DataProcessor SHARED
|
||||
XNATA04DataProcessor_p.h
|
||||
)
|
||||
|
||||
set_target_properties(XNATA04DataProcessor PROPERTIES
|
||||
LIBRARY_OUTPUT_NAME "libXNATA04DataProcessor.so.${MODEL_VERSION}"
|
||||
PREFIX ""
|
||||
SUFFIX ""
|
||||
SKIP_BUILD_RPATH TRUE
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(XNATA04DataProcessor PRIVATE
|
||||
${XNCore_PATH}/lib/libXNCore.so
|
||||
${XNCore_PATH}/lib/libC909_V1_Interface.so
|
||||
@ -45,4 +55,7 @@ install(TARGETS XNATA04DataProcessor
|
||||
file(GLOB CONFIG_FILE "*.mcfg")
|
||||
|
||||
# 使用 install 命令在安装时拷贝配置文件
|
||||
install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(FILES ${CONFIG_FILE}
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
RENAME "XNATA04DataProcessor_V${MODEL_VERSION}.mcfg"
|
||||
)
|
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNAerodynamics LANGUAGES CXX)
|
||||
|
||||
set(MODEL_VERSION "1.0.0.0")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
@ -24,6 +26,14 @@ add_library(XNAerodynamics SHARED
|
||||
XNAerodynamics_p.h
|
||||
)
|
||||
|
||||
set_target_properties(XNAerodynamics PROPERTIES
|
||||
LIBRARY_OUTPUT_NAME "libXNAerodynamics.so.${MODEL_VERSION}"
|
||||
PREFIX ""
|
||||
SUFFIX ""
|
||||
SKIP_BUILD_RPATH TRUE
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(XNAerodynamics PRIVATE
|
||||
${XNCore_PATH}/lib/libXNCore.so
|
||||
${XNCore_PATH}/lib/libC909_V1_Interface.so
|
||||
@ -47,4 +57,7 @@ install(TARGETS XNAerodynamics
|
||||
file(GLOB CONFIG_FILE "*.mcfg")
|
||||
|
||||
# 使用 install 命令在安装时拷贝配置文件
|
||||
install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(FILES ${CONFIG_FILE}
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
RENAME "XNAerodynamics_V${MODEL_VERSION}.mcfg"
|
||||
)
|
||||
|
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNGroundHandling LANGUAGES CXX)
|
||||
|
||||
set(MODEL_VERSION "1.0.0.0")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
@ -24,6 +26,14 @@ add_library(XNGroundHandling SHARED
|
||||
XNGroundHandling_p.h
|
||||
)
|
||||
|
||||
set_target_properties(XNGroundHandling PROPERTIES
|
||||
LIBRARY_OUTPUT_NAME "libXNGroundHandling.so.${MODEL_VERSION}"
|
||||
PREFIX ""
|
||||
SUFFIX ""
|
||||
SKIP_BUILD_RPATH TRUE
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(XNGroundHandling PRIVATE
|
||||
${XNCore_PATH}/lib/libXNCore.so
|
||||
${XNCore_PATH}/lib/libC909_V1_Interface.so
|
||||
@ -46,4 +56,7 @@ install(TARGETS XNGroundHandling
|
||||
file(GLOB CONFIG_FILE "*.mcfg")
|
||||
|
||||
# 使用 install 命令在安装时拷贝配置文件
|
||||
install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(FILES ${CONFIG_FILE}
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
RENAME "XNGroundHandling_V${MODEL_VERSION}.mcfg"
|
||||
)
|
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNWeightBalance LANGUAGES CXX)
|
||||
|
||||
set(MODEL_VERSION "1.0.0.0")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
@ -24,6 +26,14 @@ add_library(XNWeightBalance SHARED
|
||||
XNWeightBalance_p.h
|
||||
)
|
||||
|
||||
set_target_properties(XNWeightBalance PROPERTIES
|
||||
LIBRARY_OUTPUT_NAME "libXNWeightBalance.so.${MODEL_VERSION}"
|
||||
PREFIX ""
|
||||
SUFFIX ""
|
||||
SKIP_BUILD_RPATH TRUE
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(XNWeightBalance PRIVATE
|
||||
${XNCore_PATH}/lib/libXNCore.so
|
||||
${XNCore_PATH}/lib/libC909_V1_Interface.so
|
||||
@ -47,4 +57,7 @@ install(TARGETS XNWeightBalance
|
||||
file(GLOB CONFIG_FILE "*.mcfg")
|
||||
|
||||
# 使用 install 命令在安装时拷贝配置文件
|
||||
install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(FILES ${CONFIG_FILE}
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
RENAME "XNWeightBalance_V${MODEL_VERSION}.mcfg"
|
||||
)
|
77
XNServices/XNUDPService/.vscode/settings.json
vendored
Normal file
77
XNServices/XNUDPService/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"complex": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"set": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"regex": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"fstream": "cpp",
|
||||
"future": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ranges": "cpp",
|
||||
"span": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp",
|
||||
"variant": "cpp"
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNUDPService LANGUAGES CXX)
|
||||
|
||||
set(MODEL_VERSION "1.0.0.0")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
@ -22,6 +24,14 @@ add_library(XNUDPService SHARED
|
||||
XNUDPService_p.h
|
||||
)
|
||||
|
||||
set_target_properties(XNUDPService PROPERTIES
|
||||
LIBRARY_OUTPUT_NAME "libXNUDPService.so.${MODEL_VERSION}"
|
||||
PREFIX ""
|
||||
SUFFIX ""
|
||||
SKIP_BUILD_RPATH TRUE
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(XNUDPService PRIVATE
|
||||
${XNCore_PATH}/lib/libXNCore.so
|
||||
)
|
||||
@ -43,4 +53,7 @@ install(TARGETS XNUDPService
|
||||
file(GLOB CONFIG_FILE "*.scfg")
|
||||
|
||||
# 使用 install 命令在安装时拷贝配置文件
|
||||
install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(FILES ${CONFIG_FILE}
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
RENAME "XNUDPService_V${MODEL_VERSION}.mcfg"
|
||||
)
|
@ -36,10 +36,14 @@ void XNUDPService::Initialize()
|
||||
{
|
||||
XNServiceObject::Initialize();
|
||||
T_D();
|
||||
if (d->_initialType == 0) {
|
||||
// 读取配置文件
|
||||
std::ifstream file(GetXmlPath());
|
||||
if (!file.is_open()) {
|
||||
LOG_WARNING("无法打开配置文件:%s", GetXmlPath().c_str());
|
||||
LOG_WARNING("无法打开配置文件:%1,使用默认值", GetXmlPath().c_str());
|
||||
d->localPort = 12345;
|
||||
d->targetHost = "127.0.0.1";
|
||||
d->targetPort = 54321;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -57,7 +61,8 @@ void XNUDPService::Initialize()
|
||||
|
||||
if (localPortPos != std::string::npos) {
|
||||
size_t endPos = content.find("</LocalPort>", localPortPos);
|
||||
d->localPort = std::stoi(content.substr(localPortPos + 11, endPos - localPortPos - 11));
|
||||
d->localPort =
|
||||
std::stoi(content.substr(localPortPos + 11, endPos - localPortPos - 11));
|
||||
}
|
||||
if (targetHostPos != std::string::npos) {
|
||||
size_t endPos = content.find("</TargetHost>", targetHostPos);
|
||||
@ -74,6 +79,26 @@ void XNUDPService::Initialize()
|
||||
d->targetHost = "127.0.0.1";
|
||||
d->targetPort = 54321;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (d->_otherParams.contains("LocalPort")) {
|
||||
d->localPort = d->_otherParams["LocalPort"].get<int>();
|
||||
}
|
||||
if (d->_otherParams.contains("TargetHost")) {
|
||||
d->targetHost = d->_otherParams["TargetHost"].get<std::string>();
|
||||
}
|
||||
if (d->_otherParams.contains("TargetPort")) {
|
||||
d->targetPort = d->_otherParams["TargetPort"].get<int>();
|
||||
}
|
||||
LOG_INFO("UDP配置: 本地端口:%1, 目标主机:%2, 目标端口:%3", d->localPort, d->targetHost,
|
||||
d->targetPort);
|
||||
} catch (const std::exception &e) {
|
||||
LOG_WARNING("解析JSON参数失败: %1, 使用默认值", e.what());
|
||||
d->localPort = 12345;
|
||||
d->targetHost = "127.0.0.1";
|
||||
d->targetPort = 54321;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XNUDPService::PrepareForExecute()
|
||||
|
Loading…
x
Reference in New Issue
Block a user