diff --git a/Release/Models/XNATA04DataProcessor.mcfg b/Release/Models/XNATA04DataProcessor_V1.0.0.0.mcfg
similarity index 100%
rename from Release/Models/XNATA04DataProcessor.mcfg
rename to Release/Models/XNATA04DataProcessor_V1.0.0.0.mcfg
diff --git a/Release/Models/XNAerodynamics.mcfg b/Release/Models/XNAerodynamics_V1.0.0.0.mcfg
similarity index 100%
rename from Release/Models/XNAerodynamics.mcfg
rename to Release/Models/XNAerodynamics_V1.0.0.0.mcfg
diff --git a/Release/Models/XNGroundHandling.mcfg b/Release/Models/XNGroundHandling_V1.0.0.0.mcfg
similarity index 100%
rename from Release/Models/XNGroundHandling.mcfg
rename to Release/Models/XNGroundHandling_V1.0.0.0.mcfg
diff --git a/Release/Models/XNWeightBalance.mcfg b/Release/Models/XNWeightBalance_V1.0.0.0.mcfg
similarity index 100%
rename from Release/Models/XNWeightBalance.mcfg
rename to Release/Models/XNWeightBalance_V1.0.0.0.mcfg
diff --git a/Release/Models/libXNATA04DataProcessor.so.1.0.0.0 b/Release/Models/libXNATA04DataProcessor.so.1.0.0.0
new file mode 100644
index 0000000..b867af2
Binary files /dev/null and b/Release/Models/libXNATA04DataProcessor.so.1.0.0.0 differ
diff --git a/Release/Models/libXNAerodynamics.so.1.0.0.0 b/Release/Models/libXNAerodynamics.so.1.0.0.0
new file mode 100644
index 0000000..6fd7fb0
Binary files /dev/null and b/Release/Models/libXNAerodynamics.so.1.0.0.0 differ
diff --git a/Release/Models/libXNGroundHandling.so.1.0.0.0 b/Release/Models/libXNGroundHandling.so.1.0.0.0
new file mode 100644
index 0000000..26cf2bd
Binary files /dev/null and b/Release/Models/libXNGroundHandling.so.1.0.0.0 differ
diff --git a/Release/Models/libXNWeightBalance.so.1.0.0.0 b/Release/Models/libXNWeightBalance.so.1.0.0.0
new file mode 100644
index 0000000..21b7865
Binary files /dev/null and b/Release/Models/libXNWeightBalance.so.1.0.0.0 differ
diff --git a/Release/Scenario/OnlyFlightModel.xml b/Release/Scenario/OnlyFlightModel.xml
index 5169e2b..e632118 100755
--- a/Release/Scenario/OnlyFlightModel.xml
+++ b/Release/Scenario/OnlyFlightModel.xml
@@ -1,15 +1,15 @@
-
+
-
-
-
-
+
+
+
+
-
+
diff --git a/Release/Services/XNUDPService_V1.0.0.0.mcfg b/Release/Services/XNUDPService_V1.0.0.0.mcfg
new file mode 100644
index 0000000..8fa1279
--- /dev/null
+++ b/Release/Services/XNUDPService_V1.0.0.0.mcfg
@@ -0,0 +1,17 @@
+
+
+ XNUDPService
+ UDP通信服务
+ Jin
+ 1.0.0
+ 2025-02-04 10:00:00
+ 2025-02-04 10:00:00
+
+
+
+
+ 12345
+ 127.0.0.1
+ 54321
+
+
diff --git a/Release/Services/libXNUDPService.so.1.0.0.0 b/Release/Services/libXNUDPService.so.1.0.0.0
new file mode 100644
index 0000000..c126e07
Binary files /dev/null and b/Release/Services/libXNUDPService.so.1.0.0.0 differ
diff --git a/Release/XNEngine b/Release/XNEngine
index a5aef0e..c35cdc6 100755
Binary files a/Release/XNEngine and b/Release/XNEngine differ
diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db
index 9440b07..f160d20 100644
Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ
diff --git a/Release/include/XNCore/XNCore_global.h b/Release/include/XNCore/XNCore_global.h
index b4ce4bb..e2cae8a 100644
--- a/Release/include/XNCore/XNCore_global.h
+++ b/Release/include/XNCore/XNCore_global.h
@@ -40,6 +40,8 @@
# include
# include
# include
+# include
+# include
#endif
#include
@@ -53,6 +55,8 @@
#include
#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
+constexpr typename std::underlying_type::type enumValue(T e)
+{
+ return static_cast::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 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(sqlite3_column_text(stmt, column));
+ if (text == nullptr) {
+ return "";
+ }
+ return std::string(text);
+}
+} // namespace XNSim
diff --git a/Release/include/XNCore/XNFramework_p.h b/Release/include/XNCore/XNFramework_p.h
index cb27a74..2d648c4 100644
--- a/Release/include/XNCore/XNFramework_p.h
+++ b/Release/include/XNCore/XNFramework_p.h
@@ -77,4 +77,9 @@ struct XNFrameworkPrivate : public XNObjectPrivate {
* @brief 场景XML
*/
std::string scenarioXml;
+
+ /**
+ * @brief 构型ID
+ */
+ uint32_t configId;
};
diff --git a/Release/include/XNCore/XNModelManager.h b/Release/include/XNCore/XNModelManager.h
index 4c030b6..b1c6a67 100644
--- a/Release/include/XNCore/XNModelManager.h
+++ b/Release/include/XNCore/XNModelManager.h
@@ -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 注册模型信息
diff --git a/Release/include/XNCore/XNModelObject.h b/Release/include/XNCore/XNModelObject.h
index 540781a..2f7153f 100644
--- a/Release/include/XNCore/XNModelObject.h
+++ b/Release/include/XNCore/XNModelObject.h
@@ -238,6 +238,10 @@ public:
public:
virtual void RegisterDDSParticipant();
+
+private:
+ void ParseXml();
+ void ParseConfig();
};
#define XN_MODEL_INITIALIZE(ClassName) \
diff --git a/Release/include/XNCore/XNScenarioManager.h b/Release/include/XNCore/XNScenarioManager.h
index 89a293b..b659e78 100644
--- a/Release/include/XNCore/XNScenarioManager.h
+++ b/Release/include/XNCore/XNScenarioManager.h
@@ -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);
};
diff --git a/Release/include/XNCore/XNServiceManager.h b/Release/include/XNCore/XNServiceManager.h
index eb0a5bb..a736a7f 100644
--- a/Release/include/XNCore/XNServiceManager.h
+++ b/Release/include/XNCore/XNServiceManager.h
@@ -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);
diff --git a/Release/include/XNCore/XNServiceObject.h b/Release/include/XNCore/XNServiceObject.h
index 163be32..c01ff25 100644
--- a/Release/include/XNCore/XNServiceObject.h
+++ b/Release/include/XNCore/XNServiceObject.h
@@ -54,6 +54,10 @@ public:
protected:
XNFrameworkPtr GetFramework() const;
+
+private:
+ void ParseXml();
+ void ParseConfig();
};
XNCLASS_PTR_DECLARE(XNServiceObject)
diff --git a/Release/include/XNCore/XNServiceObject_p.h b/Release/include/XNCore/XNServiceObject_p.h
index a9c4bb4..426dd33 100644
--- a/Release/include/XNCore/XNServiceObject_p.h
+++ b/Release/include/XNCore/XNServiceObject_p.h
@@ -11,4 +11,5 @@ struct XNServiceObjectPrivate : public XNObjectPrivate {
std::unordered_map _dataWriters;
XNFrameworkPtr pFramework;
uint32_t _initialType;
+ XN_JSON _otherParams;
};
diff --git a/XNCore/CMakeLists.txt b/XNCore/CMakeLists.txt
index c0089d9..9d0efd4 100755
--- a/XNCore/CMakeLists.txt
+++ b/XNCore/CMakeLists.txt
@@ -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
)
diff --git a/XNCore/XNCore_Function.cpp b/XNCore/XNCore_Function.cpp
index 0106209..77b3be8 100644
--- a/XNCore/XNCore_Function.cpp
+++ b/XNCore/XNCore_Function.cpp
@@ -1,5 +1,7 @@
#include "XNCore_global.h"
+namespace XNSim
+{
XNTimePoint parseISOTime(const std::string &timeStr)
{
std::tm tm = {};
@@ -7,4 +9,50 @@ XNTimePoint parseISOTime(const std::string &timeStr)
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
return tp;
-}
\ No newline at end of file
+}
+
+// 辅助函数:分割字符串
+std::vector split(const std::string &str, const std::string &delim)
+{
+ std::vector 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
\ No newline at end of file
diff --git a/XNCore/XNCore_global.h b/XNCore/XNCore_global.h
index b4ce4bb..e2cae8a 100755
--- a/XNCore/XNCore_global.h
+++ b/XNCore/XNCore_global.h
@@ -40,6 +40,8 @@
# include
# include
# include
+# include
+# include
#endif
#include
@@ -53,6 +55,8 @@
#include
#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
+constexpr typename std::underlying_type::type enumValue(T e)
+{
+ return static_cast::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 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(sqlite3_column_text(stmt, column));
+ if (text == nullptr) {
+ return "";
+ }
+ return std::string(text);
+}
+} // namespace XNSim
diff --git a/XNCore/XNFramework_p.h b/XNCore/XNFramework_p.h
index cb27a74..2d648c4 100755
--- a/XNCore/XNFramework_p.h
+++ b/XNCore/XNFramework_p.h
@@ -77,4 +77,9 @@ struct XNFrameworkPrivate : public XNObjectPrivate {
* @brief 场景XML
*/
std::string scenarioXml;
+
+ /**
+ * @brief 构型ID
+ */
+ uint32_t configId;
};
diff --git a/XNCore/XNModelManager.cpp b/XNCore/XNModelManager.cpp
index 5d3c2ff..b4008fd 100755
--- a/XNCore/XNModelManager.cpp
+++ b/XNCore/XNModelManager.cpp
@@ -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);
- // 使用std::filesystem处理路径
- std::filesystem::path configPath =
- std::filesystem::path(modelPath).parent_path() / (className + ".mcfg");
- model->SetXmlPath(configPath.string());
+ if (initialType == 0) {
+ // 使用std::filesystem处理路径
+ std::filesystem::path configPath =
+ 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);
diff --git a/XNCore/XNModelManager.h b/XNCore/XNModelManager.h
index 4c030b6..b1c6a67 100755
--- a/XNCore/XNModelManager.h
+++ b/XNCore/XNModelManager.h
@@ -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 注册模型信息
diff --git a/XNCore/XNModelObject.cpp b/XNCore/XNModelObject.cpp
index ccc2409..e697210 100755
--- a/XNCore/XNModelObject.cpp
+++ b/XNCore/XNModelObject.cpp
@@ -195,102 +195,210 @@ void XNModelObject::SetSetFreq(double setFreq)
// 初始化函数
void XNModelObject::Initialize()
{
- // 先尝试调取动态库
T_D();
if (d->_initialType == 0) {
- // 读取配置文件,设置循环执行函数
- std::ifstream file(GetXmlPath());
- if (!file.is_open()) {
- LOG_WARNING("0x2161 Failed to open the model configuration file: %1!", GetXmlPath());
- return;
- }
- tinyxml2::XMLDocument doc;
- doc.LoadFile(GetXmlPath().c_str());
- tinyxml2::XMLElement *rootNode = doc.FirstChildElement("Model");
- if (!rootNode) {
- LOG_WARNING("0x2161 Failed to parse model configuration file: %1!", GetXmlPath());
- return;
- }
- // 读取配置文件的模型参数
- 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 "
- "with the model name in the configuration file of model %2!",
- GetObjectName(), modelName ? modelName : "null");
- return;
- }
- d->_sDescription = rootNode->FirstChildElement("Description")->GetText();
- d->_sAuthor = rootNode->FirstChildElement("Author")->GetText();
- d->_sVersion = rootNode->FirstChildElement("Version")->GetText();
+ ParseXml();
+ } else {
+ ParseConfig();
+ }
+}
- // 使用标准C++时间处理
- std::string createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText();
- std::string changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText();
- d->_cCreatTime = parseISOTime(createTimeStr);
- d->_cChangeTime = parseISOTime(changeTimeStr);
+void XNModelObject::ParseXml()
+{
+ T_D();
+ // 读取配置文件,设置循环执行函数
+ std::ifstream file(GetXmlPath());
+ if (!file.is_open()) {
+ LOG_WARNING("0x2161 Failed to open the model configuration file: %1!", GetXmlPath());
+ return;
+ }
+ tinyxml2::XMLDocument doc;
+ doc.LoadFile(GetXmlPath().c_str());
+ tinyxml2::XMLElement *rootNode = doc.FirstChildElement("Model");
+ if (!rootNode) {
+ LOG_WARNING("0x2161 Failed to parse model configuration file: %1!", GetXmlPath());
+ return;
+ }
+ // 读取配置文件的模型参数
+ 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 "
+ "with the model name in the configuration file of model %2!",
+ GetObjectName(), modelName ? modelName : "null");
+ return;
+ }
+ d->_sDescription = rootNode->FirstChildElement("Description")->GetText();
+ d->_sAuthor = rootNode->FirstChildElement("Author")->GetText();
+ d->_sVersion = rootNode->FirstChildElement("Version")->GetText();
- std::string funcNode = rootNode->FirstChildElement("Node")->GetText();
- d->_runPriority = std::stoi(rootNode->FirstChildElement("Priority")->GetText());
+ // 使用标准C++时间处理
+ std::string createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText();
+ std::string changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText();
+ d->_cCreatTime = XNSim::parseISOTime(createTimeStr);
+ d->_cChangeTime = XNSim::parseISOTime(changeTimeStr);
- // 检查运行节点是否是 "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 "
- "%1 is not in the x-x format, registration not executed!",
- GetObjectName());
- return;
- }
+ std::string funcNode = rootNode->FirstChildElement("Node")->GetText();
+ d->_runPriority = XNSim::safe_stoi(rootNode->FirstChildElement("Priority")->GetText());
- // 使用标准C++字符串处理
- d->_runFreq = std::stoi(funcNode.substr(0, tmp));
- d->_runNode = std::stoi(funcNode.substr(tmp + 1));
+ // 检查运行节点是否是 "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 "
+ "%1 is not in the x-x format, registration not executed!",
+ GetObjectName());
+ return;
+ }
- // 注册周期性函数
- 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);
- }
- }
+ // 使用标准C++字符串处理
+ d->_runFreq = XNSim::safe_stoi(funcNode.substr(0, tmp));
+ d->_runNode = XNSim::safe_stoi(funcNode.substr(tmp + 1));
- // 加载动态库
- const char *mathlib = rootNode->FirstChildElement("MathLib")->GetText();
- if (mathlib && strlen(mathlib) > 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;
- }
- }
-
- // 处理指令列表
- tinyxml2::XMLElement *nodeCmds = rootNode->FirstChildElement("CommandList");
- if (nodeCmds) {
- for (tinyxml2::XMLElement *nodeCmd = nodeCmds->FirstChildElement("Command");
- nodeCmd != nullptr; nodeCmd = nodeCmd->NextSiblingElement("Command")) {
- const char *cmdName = nodeCmd->Attribute("Name");
- const char *cmdDescription = nodeCmd->Attribute("Description");
- const char *cmdCall = nodeCmd->Attribute("Call");
- // TODO: 处理命令列表
- }
+ // 注册周期性函数
+ 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);
}
}
+
+ // 加载动态库
+ const char *mathlib = rootNode->FirstChildElement("MathLib")->GetText();
+ if (mathlib && strlen(mathlib) > 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;
+ }
+ }
+
+ // 处理指令列表
+ tinyxml2::XMLElement *nodeCmds = rootNode->FirstChildElement("CommandList");
+ if (nodeCmds) {
+ for (tinyxml2::XMLElement *nodeCmd = nodeCmds->FirstChildElement("Command");
+ nodeCmd != nullptr; nodeCmd = nodeCmd->NextSiblingElement("Command")) {
+ const char *cmdName = nodeCmd->Attribute("Name");
+ const char *cmdDescription = nodeCmd->Attribute("Description");
+ const char *cmdCall = nodeCmd->Attribute("Call");
+ // TODO: 处理命令列表
+ }
+ }
+}
+
+void XNModelObject::ParseConfig()
+{
+ T_D();
+ std::vector 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);
}
// 单步执行函数
diff --git a/XNCore/XNModelObject.h b/XNCore/XNModelObject.h
index 540781a..2f7153f 100755
--- a/XNCore/XNModelObject.h
+++ b/XNCore/XNModelObject.h
@@ -238,6 +238,10 @@ public:
public:
virtual void RegisterDDSParticipant();
+
+private:
+ void ParseXml();
+ void ParseConfig();
};
#define XN_MODEL_INITIALIZE(ClassName) \
diff --git a/XNCore/XNScenarioManager.cpp b/XNCore/XNScenarioManager.cpp
index 68e1070..468fdbd 100755
--- a/XNCore/XNScenarioManager.cpp
+++ b/XNCore/XNScenarioManager.cpp
@@ -66,35 +66,19 @@ bool XNScenarioManager::PrepareForExecute()
return true;
}
-// 辅助函数:分割字符串
-std::vector split(const std::string &str, const std::string &delim)
-{
- std::vector 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 cpuAffList = split(cpuAff, ",");
+ std::vector 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 modelGroupCPUAffList = split(modelGroupCPUAff, ",");
+ std::vector 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 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 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;
+}
diff --git a/XNCore/XNScenarioManager.h b/XNCore/XNScenarioManager.h
index 89a293b..b659e78 100755
--- a/XNCore/XNScenarioManager.h
+++ b/XNCore/XNScenarioManager.h
@@ -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);
};
diff --git a/XNCore/XNServiceManager.cpp b/XNCore/XNServiceManager.cpp
index 4bdb00e..cdce8a4 100755
--- a/XNCore/XNServiceManager.cpp
+++ b/XNCore/XNServiceManager.cpp
@@ -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());
- // 使用std::filesystem处理路径
- std::filesystem::path configPath =
- std::filesystem::path(servicePath).parent_path() / (serviceName + ".scfg");
- service->SetXmlPath(configPath.string());
+ if (initialType == 0) {
+ // 使用std::filesystem处理路径
+ std::filesystem::path configPath =
+ 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!",
diff --git a/XNCore/XNServiceManager.h b/XNCore/XNServiceManager.h
index eb0a5bb..a736a7f 100755
--- a/XNCore/XNServiceManager.h
+++ b/XNCore/XNServiceManager.h
@@ -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);
diff --git a/XNCore/XNServiceObject.cpp b/XNCore/XNServiceObject.cpp
index 8fd2626..15b6b63 100755
--- a/XNCore/XNServiceObject.cpp
+++ b/XNCore/XNServiceObject.cpp
@@ -139,51 +139,154 @@ void XNServiceObject::Initialize()
{
T_D();
if (d->_initialType == 0) {
- tinyxml2::XMLDocument doc;
- if (doc.LoadFile(GetXmlPath().c_str()) != tinyxml2::XML_SUCCESS) {
- LOG_WARNING("Failed to open the service configuration file: %1!", GetXmlPath());
- return;
- }
-
- tinyxml2::XMLElement *rootNode = doc.RootElement();
- if (!rootNode) {
- LOG_WARNING("Invalid XML file format: %1!", GetXmlPath());
- return;
- }
-
- 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 "
- "with the service name in the configuration file of service %2!",
- GetObjectName(), serviceName);
- return;
- }
-
- d->_sDescription = rootNode->FirstChildElement("Description")->GetText();
- d->_sAuthor = rootNode->FirstChildElement("Author")->GetText();
- d->_sVersion = rootNode->FirstChildElement("Version")->GetText();
-
- // 解析时间
- const char *createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText();
- const char *changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText();
- d->_cCreateTime = parseISOTime(createTimeStr);
- d->_cChangeTime = parseISOTime(changeTimeStr);
-
- tinyxml2::XMLElement *nodeCmds = rootNode->FirstChildElement("CommandList");
- if (nodeCmds) {
- for (tinyxml2::XMLElement *nodeCmd = nodeCmds->FirstChildElement("Command");
- nodeCmd != nullptr; nodeCmd = nodeCmd->NextSiblingElement("Command")) {
- const char *cmdName = nodeCmd->Attribute("Name");
- const char *cmdDescription = nodeCmd->Attribute("Description");
- const char *cmdCall = nodeCmd->Attribute("Call");
- // TODO: 处理命令信息
- }
- }
+ 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());
+ return;
+ }
+
+ tinyxml2::XMLElement *rootNode = doc.RootElement();
+ if (!rootNode) {
+ LOG_WARNING("Invalid XML file format: %1!", GetXmlPath());
+ return;
+ }
+
+ 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 "
+ "with the service name in the configuration file of service %2!",
+ GetObjectName(), serviceName);
+ return;
+ }
+
+ d->_sDescription = rootNode->FirstChildElement("Description")->GetText();
+ d->_sAuthor = rootNode->FirstChildElement("Author")->GetText();
+ d->_sVersion = rootNode->FirstChildElement("Version")->GetText();
+
+ // 解析时间
+ const char *createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText();
+ const char *changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText();
+ d->_cCreateTime = XNSim::parseISOTime(createTimeStr);
+ d->_cChangeTime = XNSim::parseISOTime(changeTimeStr);
+
+ tinyxml2::XMLElement *nodeCmds = rootNode->FirstChildElement("CommandList");
+ if (nodeCmds) {
+ for (tinyxml2::XMLElement *nodeCmd = nodeCmds->FirstChildElement("Command");
+ nodeCmd != nullptr; nodeCmd = nodeCmd->NextSiblingElement("Command")) {
+ const char *cmdName = nodeCmd->Attribute("Name");
+ const char *cmdDescription = nodeCmd->Attribute("Description");
+ const char *cmdCall = nodeCmd->Attribute("Call");
+ // TODO: 处理命令信息
+ }
+ }
+}
+
+void XNServiceObject::ParseConfig()
+{
+ T_D();
+ std::vector 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());
+ // TODO: 处理服务命令信息
+ // d->_commandList.emplace_back(
+ // cmd["Name"].get(),
+ // cmd["Description"].get(),
+ // cmd["Call"].get()
+ // );
+ }
+ }
+ }
+ } 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()
{
T_D();
diff --git a/XNCore/XNServiceObject.h b/XNCore/XNServiceObject.h
index 163be32..c01ff25 100755
--- a/XNCore/XNServiceObject.h
+++ b/XNCore/XNServiceObject.h
@@ -54,6 +54,10 @@ public:
protected:
XNFrameworkPtr GetFramework() const;
+
+private:
+ void ParseXml();
+ void ParseConfig();
};
XNCLASS_PTR_DECLARE(XNServiceObject)
diff --git a/XNCore/XNServiceObject_p.h b/XNCore/XNServiceObject_p.h
index a9c4bb4..426dd33 100755
--- a/XNCore/XNServiceObject_p.h
+++ b/XNCore/XNServiceObject_p.h
@@ -11,4 +11,5 @@ struct XNServiceObjectPrivate : public XNObjectPrivate {
std::unordered_map _dataWriters;
XNFrameworkPtr pFramework;
uint32_t _initialType;
+ XN_JSON _otherParams;
};
diff --git a/XNEngine/XNEngine.cpp b/XNEngine/XNEngine.cpp
index e28c70c..7ec7439 100755
--- a/XNEngine/XNEngine.cpp
+++ b/XNEngine/XNEngine.cpp
@@ -403,24 +403,35 @@ 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;
}
- // 解析配置文件
- bool isReady = ParseConfig(XmlPath);
- // 如果解析配置文件失败
- if (!isReady) {
- // 返回失败
- return false;
+ if (InitializeType == 0) {
+ // 解析配置文件
+ bool isReady = ParseConfig(XmlPath);
+ // 如果解析配置文件失败
+ if (!isReady) {
+ // 返回失败
+ 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(sqlite3_column_text(stmt, 6));
+ std::string CPUAff = XNSim::getStringFromSqlite3(stmt, 6);
+ //std::string CPUAff = reinterpret_cast(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::XNRuntimeControl", 0, func);
- // 触发仿真控制信号
- framework->SimControl(0, SimControlCmd::Start);
- // 注册引擎状态发布者
- engineStatusWriter =
- ddsManager->RegisterPublisher(
- "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)
{
diff --git a/XNEngine/XNEngine.h b/XNEngine/XNEngine.h
index 8c0d66c..30f2a5a 100755
--- a/XNEngine/XNEngine.h
+++ b/XNEngine/XNEngine.h
@@ -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 设置控制台输出
diff --git a/XNEngine/main.cpp b/XNEngine/main.cpp
index d4acff3..38bafd9 100755
--- a/XNEngine/main.cpp
+++ b/XNEngine/main.cpp
@@ -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;
}
diff --git a/XNModels/XNATA04DataProcessor/CMakeLists.txt b/XNModels/XNATA04DataProcessor/CMakeLists.txt
index a2b2903..bb44890 100755
--- a/XNModels/XNATA04DataProcessor/CMakeLists.txt
+++ b/XNModels/XNATA04DataProcessor/CMakeLists.txt
@@ -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"
+)
\ No newline at end of file
diff --git a/XNModels/XNAerodynamics/CMakeLists.txt b/XNModels/XNAerodynamics/CMakeLists.txt
index 6b1e005..ba3848a 100755
--- a/XNModels/XNAerodynamics/CMakeLists.txt
+++ b/XNModels/XNAerodynamics/CMakeLists.txt
@@ -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"
+)
diff --git a/XNModels/XNGroundHandling/CMakeLists.txt b/XNModels/XNGroundHandling/CMakeLists.txt
index a38ba1c..bb5cc98 100755
--- a/XNModels/XNGroundHandling/CMakeLists.txt
+++ b/XNModels/XNGroundHandling/CMakeLists.txt
@@ -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"
+)
\ No newline at end of file
diff --git a/XNModels/XNWeightBalance/CMakeLists.txt b/XNModels/XNWeightBalance/CMakeLists.txt
index 27cf78b..03a0313 100755
--- a/XNModels/XNWeightBalance/CMakeLists.txt
+++ b/XNModels/XNWeightBalance/CMakeLists.txt
@@ -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})
\ No newline at end of file
+install(FILES ${CONFIG_FILE}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}
+ RENAME "XNWeightBalance_V${MODEL_VERSION}.mcfg"
+)
\ No newline at end of file
diff --git a/XNServices/XNUDPService/.vscode/settings.json b/XNServices/XNUDPService/.vscode/settings.json
new file mode 100644
index 0000000..9b6b487
--- /dev/null
+++ b/XNServices/XNUDPService/.vscode/settings.json
@@ -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"
+ }
+}
\ No newline at end of file
diff --git a/XNServices/XNUDPService/CMakeLists.txt b/XNServices/XNUDPService/CMakeLists.txt
index d90b5bb..9c645c2 100755
--- a/XNServices/XNUDPService/CMakeLists.txt
+++ b/XNServices/XNUDPService/CMakeLists.txt
@@ -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})
\ No newline at end of file
+install(FILES ${CONFIG_FILE}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}
+ RENAME "XNUDPService_V${MODEL_VERSION}.mcfg"
+)
\ No newline at end of file
diff --git a/XNServices/XNUDPService/XNUDPService.cpp b/XNServices/XNUDPService/XNUDPService.cpp
index 2f5f7d6..ed97f0b 100755
--- a/XNServices/XNUDPService/XNUDPService.cpp
+++ b/XNServices/XNUDPService/XNUDPService.cpp
@@ -36,43 +36,68 @@ void XNUDPService::Initialize()
{
XNServiceObject::Initialize();
T_D();
- // 读取配置文件
- std::ifstream file(GetXmlPath());
- if (!file.is_open()) {
- LOG_WARNING("无法打开配置文件:%s", GetXmlPath().c_str());
- return;
- }
-
- std::stringstream buffer;
- buffer << file.rdbuf();
- std::string content = buffer.str();
- file.close();
-
- // 简单的XML解析
- size_t udpPos = content.find("");
- if (udpPos != std::string::npos) {
- size_t localPortPos = content.find("", udpPos);
- size_t targetHostPos = content.find("", udpPos);
- size_t targetPortPos = content.find("", udpPos);
-
- if (localPortPos != std::string::npos) {
- size_t endPos = content.find("", localPortPos);
- d->localPort = std::stoi(content.substr(localPortPos + 11, endPos - localPortPos - 11));
+ if (d->_initialType == 0) {
+ // 读取配置文件
+ std::ifstream file(GetXmlPath());
+ if (!file.is_open()) {
+ LOG_WARNING("无法打开配置文件:%1,使用默认值", GetXmlPath().c_str());
+ d->localPort = 12345;
+ d->targetHost = "127.0.0.1";
+ d->targetPort = 54321;
+ return;
}
- if (targetHostPos != std::string::npos) {
- size_t endPos = content.find("", targetHostPos);
- d->targetHost = content.substr(targetHostPos + 12, endPos - targetHostPos - 12);
- }
- if (targetPortPos != std::string::npos) {
- size_t endPos = content.find("", targetPortPos);
- d->targetPort =
- std::stoi(content.substr(targetPortPos + 12, endPos - targetPortPos - 12));
+
+ std::stringstream buffer;
+ buffer << file.rdbuf();
+ std::string content = buffer.str();
+ file.close();
+
+ // 简单的XML解析
+ size_t udpPos = content.find("");
+ if (udpPos != std::string::npos) {
+ size_t localPortPos = content.find("", udpPos);
+ size_t targetHostPos = content.find("", udpPos);
+ size_t targetPortPos = content.find("", udpPos);
+
+ if (localPortPos != std::string::npos) {
+ size_t endPos = content.find("", localPortPos);
+ d->localPort =
+ std::stoi(content.substr(localPortPos + 11, endPos - localPortPos - 11));
+ }
+ if (targetHostPos != std::string::npos) {
+ size_t endPos = content.find("", targetHostPos);
+ d->targetHost = content.substr(targetHostPos + 12, endPos - targetHostPos - 12);
+ }
+ if (targetPortPos != std::string::npos) {
+ size_t endPos = content.find("", targetPortPos);
+ d->targetPort =
+ std::stoi(content.substr(targetPortPos + 12, endPos - targetPortPos - 12));
+ }
+ } else {
+ LOG_WARNING("未找到UDP配置, 使用默认值");
+ d->localPort = 12345;
+ d->targetHost = "127.0.0.1";
+ d->targetPort = 54321;
}
} else {
- LOG_WARNING("未找到UDP配置, 使用默认值");
- d->localPort = 12345;
- d->targetHost = "127.0.0.1";
- d->targetPort = 54321;
+ try {
+ if (d->_otherParams.contains("LocalPort")) {
+ d->localPort = d->_otherParams["LocalPort"].get();
+ }
+ if (d->_otherParams.contains("TargetHost")) {
+ d->targetHost = d->_otherParams["TargetHost"].get();
+ }
+ if (d->_otherParams.contains("TargetPort")) {
+ d->targetPort = d->_otherParams["TargetPort"].get();
+ }
+ 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;
+ }
}
}