diff --git a/Release/Configuration/C909_V1/Services/XNUDPService_V1.0.0.0.mcfg b/Release/Configuration/C909_V1/Services/XNUDPService_V1.0.0.0.mcfg
deleted file mode 100644
index 8fa1279..0000000
--- a/Release/Configuration/C909_V1/Services/XNUDPService_V1.0.0.0.mcfg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- 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/Configuration/C909_V1/Services/XNUDPTestService.scfg b/Release/Configuration/C909_V1/Services/XNUDPTestService.scfg
deleted file mode 100644
index d80e723..0000000
--- a/Release/Configuration/C909_V1/Services/XNUDPTestService.scfg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- XNUDPTestService
- UDP通信服务
- Jin
- 1.0.0
- 2025-02-04 10:00:00
- 2025-02-04 10:00:00
-
-
-
-
- 54321
- 127.0.0.1
- 12345
-
-
diff --git a/Release/ServiceProjects/XNTCPService_1.0.0.0.zip b/Release/ServiceProjects/XNTCPService_1.0.0.0.zip
new file mode 100644
index 0000000..d26ecba
Binary files /dev/null and b/Release/ServiceProjects/XNTCPService_1.0.0.0.zip differ
diff --git a/Release/ServiceProjects/XNTCPService_1.0.0.0/CMakeLists.txt b/Release/ServiceProjects/XNTCPService_1.0.0.0/CMakeLists.txt
new file mode 100644
index 0000000..dfa86d4
--- /dev/null
+++ b/Release/ServiceProjects/XNTCPService_1.0.0.0/CMakeLists.txt
@@ -0,0 +1,49 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(XNTCPService LANGUAGES CXX)
+
+set(SERVICE_VERSION "1.0.0.0")
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+if(DEFINED ENV{XNCore})
+ set(XNCore_PATH $ENV{XNCore})
+else()
+ message(FATAL_ERROR "Environment variable XNCore is not set.")
+endif()
+
+include_directories(${XNCore_PATH}/include)
+
+add_library(XNTCPService SHARED
+ XNTCPService_global.h
+ XNTCPService.cpp
+ XNTCPService.h
+ XNTCPService_p.h
+)
+
+set_target_properties(XNTCPService PROPERTIES
+ LIBRARY_OUTPUT_NAME "libXNTCPService.so.1.0.0.0"
+ PREFIX ""
+ SUFFIX ""
+ SKIP_BUILD_RPATH TRUE
+ BUILD_WITH_INSTALL_RPATH TRUE
+)
+
+target_link_libraries(XNTCPService PRIVATE
+ ${XNCore_PATH}/lib/libXNCore.so
+)
+
+target_compile_definitions(XNTCPService PRIVATE XNTCPSERVICE_LIBRARY)
+
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}/Services" CACHE PATH "Install path prefix" FORCE)
+endif()
+
+install(TARGETS XNTCPService BUNDLE DESTINATION . LIBRARY DESTINATION . RUNTIME DESTINATION .)
+
+file(GLOB CONFIG_FILE "*.scfg")
+
+install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME "${CMAKE_PROJECT_NAME}_V${SERVICE_VERSION}.scfg")
+
diff --git a/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.cpp b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.cpp
new file mode 100644
index 0000000..131476b
--- /dev/null
+++ b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.cpp
@@ -0,0 +1,29 @@
+#include "XNTCPService.h"
+#include "XNTCPService_p.h"
+#include
+
+XN_SERVICE_INITIALIZE(XNTCPService)
+
+XNTCPService::XNTCPService() : XNServiceObject(new XNTCPServicePrivate())
+{
+}
+
+XNTCPService::~XNTCPService() {
+}
+
+XNTCPService::XNTCPService(PrivateType *p) : XNServiceObject(p)
+{
+}
+
+void XNTCPService::Initialize() {
+ T_D();
+ SuperType::Initialize();
+ /* 在这里进行其它初始化 */
+}
+
+void XNTCPService::PrepareForExecute() {
+ T_D();
+ SuperType::PrepareForExecute();
+ /* 在这里进行其它运行前准备工作 */
+}
+
diff --git a/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.h b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.h
new file mode 100644
index 0000000..905e7ce
--- /dev/null
+++ b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "XNTCPService_global.h"
+#include
+
+struct XNTCPServicePrivate;
+
+class XNTCPSERVICE_EXPORT XNTCPService : public XNServiceObject
+{
+XN_METATYPE(XNTCPService, XNServiceObject)
+XN_DECLARE_PRIVATE(XNTCPService)
+public:
+ XNTCPService();
+ virtual ~XNTCPService();
+
+protected:
+ XNTCPService(PrivateType *p);
+
+public:
+ virtual void Initialize() override;
+ virtual void PrepareForExecute() override;
+
+};
+
+XNCLASS_PTR_DECLARE(XNTCPService)
+
diff --git a/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.scfg b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.scfg
new file mode 100644
index 0000000..70e9890
--- /dev/null
+++ b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService.scfg
@@ -0,0 +1,10 @@
+
+
+ XNTCPService
+ TCP通信服务
+ Jin
+ 1.0.0.0
+ 2025-06-25 09:16:45
+ 2025-06-25 09:16:26
+
+
diff --git a/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService_global.h b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService_global.h
new file mode 100644
index 0000000..9526fc3
--- /dev/null
+++ b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService_global.h
@@ -0,0 +1,11 @@
+#ifndef XNTCPSERVICE_GLOBAL_H
+#define XNTCPSERVICE_GLOBAL_H
+
+#if defined(XNTCPSERVICE_LIBRARY)
+#define XNTCPSERVICE_EXPORT __attribute__((visibility("default")))
+#else
+#define XNTCPSERVICE_EXPORT __attribute__((visibility("default")))
+#endif
+
+#endif // XNTCPSERVICE_GLOBAL_H
+
diff --git a/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService_p.h b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService_p.h
new file mode 100644
index 0000000..9df1708
--- /dev/null
+++ b/Release/ServiceProjects/XNTCPService_1.0.0.0/XNTCPService_p.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include
+
+struct XNTCPServicePrivate : public XNServiceObjectPrivate{
+};
+
diff --git a/Release/ServiceProjects/XNUDPService_1.0.0.0.zip b/Release/ServiceProjects/XNUDPService_1.0.0.0.zip
new file mode 100644
index 0000000..ad37f12
Binary files /dev/null and b/Release/ServiceProjects/XNUDPService_1.0.0.0.zip differ
diff --git a/XNServices/XNUDPService/CMakeLists.txt b/Release/ServiceProjects/XNUDPService_1.0.0.0/CMakeLists.txt
old mode 100755
new mode 100644
similarity index 54%
rename from XNServices/XNUDPService/CMakeLists.txt
rename to Release/ServiceProjects/XNUDPService_1.0.0.0/CMakeLists.txt
index 9c645c2..5f27f0f
--- a/XNServices/XNUDPService/CMakeLists.txt
+++ b/Release/ServiceProjects/XNUDPService_1.0.0.0/CMakeLists.txt
@@ -2,37 +2,36 @@ cmake_minimum_required(VERSION 3.16)
project(XNUDPService LANGUAGES CXX)
-set(MODEL_VERSION "1.0.0.0")
+set(SERVICE_VERSION "1.0.0.0")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-# 获取环境变量
if(DEFINED ENV{XNCore})
set(XNCore_PATH $ENV{XNCore})
else()
message(FATAL_ERROR "Environment variable XNCore is not set.")
endif()
-# 添加 XNCore_PATH 下的 include 目录为包含目录
include_directories(${XNCore_PATH}/include)
add_library(XNUDPService SHARED
- XNUDPService_global.h
- XNUDPService.cpp
- XNUDPService.h
- XNUDPService_p.h
+ XNUDPService_global.h
+ XNUDPService.cpp
+ XNUDPService.h
+ XNUDPService_p.h
)
set_target_properties(XNUDPService PROPERTIES
- LIBRARY_OUTPUT_NAME "libXNUDPService.so.${MODEL_VERSION}"
+ LIBRARY_OUTPUT_NAME "libXNUDPService.so.1.0.0.0"
PREFIX ""
SUFFIX ""
SKIP_BUILD_RPATH TRUE
BUILD_WITH_INSTALL_RPATH TRUE
)
-target_link_libraries(XNUDPService PRIVATE
+target_link_libraries(XNUDPService PRIVATE
${XNCore_PATH}/lib/libXNCore.so
)
@@ -42,18 +41,9 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}/Services" CACHE PATH "Install path prefix" FORCE)
endif()
-include(GNUInstallDirs)
-install(TARGETS XNUDPService
- BUNDLE DESTINATION .
- LIBRARY DESTINATION .
- RUNTIME DESTINATION .
-)
+install(TARGETS XNUDPService BUNDLE DESTINATION . LIBRARY DESTINATION . RUNTIME DESTINATION .)
-# 添加自定义命令和目标以拷贝配置文件
file(GLOB CONFIG_FILE "*.scfg")
-# 使用 install 命令在安装时拷贝配置文件
-install(FILES ${CONFIG_FILE}
- DESTINATION ${CMAKE_INSTALL_PREFIX}
- RENAME "XNUDPService_V${MODEL_VERSION}.mcfg"
-)
\ No newline at end of file
+install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME "${CMAKE_PROJECT_NAME}_V${SERVICE_VERSION}.scfg")
+
diff --git a/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.cpp b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.cpp
new file mode 100644
index 0000000..e8e9da5
--- /dev/null
+++ b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.cpp
@@ -0,0 +1,29 @@
+#include "XNUDPService.h"
+#include "XNUDPService_p.h"
+#include
+
+XN_SERVICE_INITIALIZE(XNUDPService)
+
+XNUDPService::XNUDPService() : XNServiceObject(new XNUDPServicePrivate())
+{
+}
+
+XNUDPService::~XNUDPService() {
+}
+
+XNUDPService::XNUDPService(PrivateType *p) : XNServiceObject(p)
+{
+}
+
+void XNUDPService::Initialize() {
+ T_D();
+ SuperType::Initialize();
+ /* 在这里进行其它初始化 */
+}
+
+void XNUDPService::PrepareForExecute() {
+ T_D();
+ SuperType::PrepareForExecute();
+ /* 在这里进行其它运行前准备工作 */
+}
+
diff --git a/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.h b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.h
new file mode 100644
index 0000000..ec9b764
--- /dev/null
+++ b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "XNUDPService_global.h"
+#include
+
+struct XNUDPServicePrivate;
+
+class XNUDPSERVICE_EXPORT XNUDPService : public XNServiceObject
+{
+XN_METATYPE(XNUDPService, XNServiceObject)
+XN_DECLARE_PRIVATE(XNUDPService)
+public:
+ XNUDPService();
+ virtual ~XNUDPService();
+
+protected:
+ XNUDPService(PrivateType *p);
+
+public:
+ virtual void Initialize() override;
+ virtual void PrepareForExecute() override;
+
+};
+
+XNCLASS_PTR_DECLARE(XNUDPService)
+
diff --git a/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.scfg b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.scfg
new file mode 100644
index 0000000..c9921b5
--- /dev/null
+++ b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService.scfg
@@ -0,0 +1,10 @@
+
+
+ XNUDPService
+ UDP通信服务,提供UDP数据的发送与接收接口
+ Jin
+ 1.0.0.0
+ 2025-02-04 10:00:00
+ 2025-02-04 10:00:00
+
+
diff --git a/XNServices/XNUDPService/XNUDPService_global.h b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService_global.h
old mode 100755
new mode 100644
similarity index 50%
rename from XNServices/XNUDPService/XNUDPService_global.h
rename to Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService_global.h
index 2b3bdb0..6ea4ab6
--- a/XNServices/XNUDPService/XNUDPService_global.h
+++ b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService_global.h
@@ -2,9 +2,10 @@
#define XNUDPSERVICE_GLOBAL_H
#if defined(XNUDPSERVICE_LIBRARY)
-# define XNUDPSERVICE_EXPORT __attribute__((visibility("default")))
+#define XNUDPSERVICE_EXPORT __attribute__((visibility("default")))
#else
-# define XNUDPSERVICE_EXPORT __attribute__((visibility("default")))
+#define XNUDPSERVICE_EXPORT __attribute__((visibility("default")))
#endif
#endif // XNUDPSERVICE_GLOBAL_H
+
diff --git a/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService_p.h b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService_p.h
new file mode 100644
index 0000000..b94d4f2
--- /dev/null
+++ b/Release/ServiceProjects/XNUDPService_1.0.0.0/XNUDPService_p.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include
+
+struct XNUDPServicePrivate : public XNServiceObjectPrivate{
+};
+
diff --git a/Release/Services/XNTCPService_V1.0.0.0.scfg b/Release/Services/XNTCPService_V1.0.0.0.scfg
new file mode 100644
index 0000000..70e9890
--- /dev/null
+++ b/Release/Services/XNTCPService_V1.0.0.0.scfg
@@ -0,0 +1,10 @@
+
+
+ XNTCPService
+ TCP通信服务
+ Jin
+ 1.0.0.0
+ 2025-06-25 09:16:45
+ 2025-06-25 09:16:26
+
+
diff --git a/Release/Configuration/C909_V1/Services/XNUDPService.scfg b/Release/Services/XNUDPService_V1.0.0.0.scfg
similarity index 100%
rename from Release/Configuration/C909_V1/Services/XNUDPService.scfg
rename to Release/Services/XNUDPService_V1.0.0.0.scfg
diff --git a/Release/Services/libXNTCPService.so.1.0.0.0 b/Release/Services/libXNTCPService.so.1.0.0.0
new file mode 100644
index 0000000..0406020
Binary files /dev/null and b/Release/Services/libXNTCPService.so.1.0.0.0 differ
diff --git a/Release/Configuration/C909_V1/Services/libXNUDPService.so.1.0.0.0 b/Release/Services/libXNUDPService.so.1.0.0.0
similarity index 100%
rename from Release/Configuration/C909_V1/Services/libXNUDPService.so.1.0.0.0
rename to Release/Services/libXNUDPService.so.1.0.0.0
diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db
index 22cda0b..086175b 100644
Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ
diff --git a/XNCore/XNScenarioManager.cpp b/XNCore/XNScenarioManager.cpp
index 285a786..1f07ecb 100755
--- a/XNCore/XNScenarioManager.cpp
+++ b/XNCore/XNScenarioManager.cpp
@@ -245,7 +245,7 @@ bool XNScenarioManager::ParseConfig(const std::string &ConfigID)
std::string modelPath = rootPath + "/Models";
GetFramework()->SetModelPath(modelPath);
// 设置服务库目录
- std::string servicePath = rootPath + "/Services";
+ std::string servicePath = XNCorePath + "/Services";
GetFramework()->SetServicePath(servicePath);
// 设置域ID
uint32_t domainID = std::stoul(XNSim::getStringFromSqlite3(stmt, 7));
diff --git a/XNServiceGenServer/XNServiceGen.cpp b/XNServiceGenServer/XNServiceGen.cpp
index 2ca830a..2d2ba0f 100644
--- a/XNServiceGenServer/XNServiceGen.cpp
+++ b/XNServiceGenServer/XNServiceGen.cpp
@@ -250,7 +250,7 @@ bool XNServiceGen::GenerateSourceFile()
bool XNServiceGen::GenerateConfigFile()
{
- std::string configPath = m_codePath + "/" + m_className + ".mcfg";
+ std::string configPath = m_codePath + "/" + m_className + ".scfg";
std::ofstream configFile(configPath);
if (!configFile.is_open()) {
return false;
diff --git a/XNServiceGenServer/test/CMakeLists.txt b/XNServiceGenServer/test/CMakeLists.txt
index 5e2dc7d..41182b5 100644
--- a/XNServiceGenServer/test/CMakeLists.txt
+++ b/XNServiceGenServer/test/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
-project(XNModelGenTest)
+project(XNServiceGenTest)
# 设置C++标准
set(CMAKE_CXX_STANDARD 11)
@@ -9,13 +9,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_library(DL_LIBRARY dl)
# 创建测试可执行文件
-add_executable(test_xnmodel test_xnmodel.cpp)
+add_executable(test_xnservice test_xnservice.cpp)
# 链接动态库
-target_link_libraries(test_xnmodel ${DL_LIBRARY})
+target_link_libraries(test_xnservice ${DL_LIBRARY})
# 设置运行时库路径
-set_target_properties(test_xnmodel PROPERTIES
+set_target_properties(test_xnservice PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "${CMAKE_SOURCE_DIR}/.."
)
\ No newline at end of file
diff --git a/XNServiceGenServer/test/test_xnmodel.cpp b/XNServiceGenServer/test/test_xnmodel.cpp
deleted file mode 100644
index 0d46c44..0000000
--- a/XNServiceGenServer/test/test_xnmodel.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-#include
-#include
-#include
-
-// 函数指针类型定义
-typedef int (*XNModelCodeGenFunc)(const char *className, int classNameLen, const char *version,
- int versionLen, const char *planeName, int planeNameLen,
- char *errorMsg, int errorMsgLen);
-
-typedef int (*XNModelCodeZipFunc)(const char *className, int classNameLen, const char *version,
- int versionLen, const char *planeName, int planeNameLen,
- char *dstPath, int dstPathLen, char *errorMsg, int errorMsgLen);
-
-typedef int (*XNModelCodeUnzipFunc)(const char *className, int classNameLen, const char *version,
- int versionLen, const char *planeName, int planeNameLen,
- const char *srcPath, int srcPathLen, char *errorMsg,
- int errorMsgLen);
-
-typedef int (*XNModelCodeCompileFunc)(const char *className, int classNameLen, const char *version,
- int versionLen, const char *planeName, int planeNameLen,
- char *errorMsg, int errorMsgLen);
-
-// 测试参数
-const char *className = "XNAerodynamics";
-const char *version = "2.0.3.5";
-const char *planeName = "C909";
-
-void printResult(const std::string &testName, int result, const char *errorMsg)
-{
- std::cout << testName << " 结果: " << result << std::endl;
- if (result == 0) {
- std::cout << "✓ " << testName << " 成功!" << std::endl;
- } else {
- std::cout << "✗ " << testName << " 失败!" << std::endl;
- }
-
- if (strlen(errorMsg) > 0) {
- std::cout << "错误信息: " << errorMsg << std::endl;
- }
- std::cout << std::endl;
-}
-
-int main()
-{
- // 动态加载.so库 - 修改路径指向build目录
- void *handle = dlopen("../../build/libXNModelGenServer.so", RTLD_LAZY);
- if (!handle) {
- std::cerr << "无法加载库文件: " << dlerror() << std::endl;
- return -1;
- }
-
- // 获取函数指针
- XNModelCodeGenFunc XNModelCodeGen = (XNModelCodeGenFunc)dlsym(handle, "XNModelCodeGen");
- XNModelCodeZipFunc XNModelCodeZip = (XNModelCodeZipFunc)dlsym(handle, "XNModelCodeZip");
- XNModelCodeUnzipFunc XNModelCodeUnzip = (XNModelCodeUnzipFunc)dlsym(handle, "XNModelCodeUnzip");
- XNModelCodeCompileFunc XNModelCodeCompile =
- (XNModelCodeCompileFunc)dlsym(handle, "XNModelCodeCompile");
-
- if (!XNModelCodeGen || !XNModelCodeZip || !XNModelCodeUnzip || !XNModelCodeCompile) {
- std::cerr << "无法找到函数: " << dlerror() << std::endl;
- dlclose(handle);
- return -1;
- }
-
- int classNameLen = strlen(className);
- int versionLen = strlen(version);
- int planeNameLen = strlen(planeName);
-
- // 错误消息缓冲区
- char errorMsg[1024];
- int errorMsgLen = sizeof(errorMsg);
-
- std::cout << "开始测试XNModelGen函数..." << std::endl;
- std::cout << "参数:" << std::endl;
- std::cout << " className: " << className << " (长度: " << classNameLen << ")" << std::endl;
- std::cout << " version: " << version << " (长度: " << versionLen << ")" << std::endl;
- std::cout << " planeName: " << planeName << " (长度: " << planeNameLen << ")" << std::endl;
- std::cout << std::endl;
-
- // 测试1: XNModelCodeGen
- std::cout << "=== 测试1: XNModelCodeGen ===" << std::endl;
- memset(errorMsg, 0, sizeof(errorMsg));
- int result1 = XNModelCodeGen(className, classNameLen, version, versionLen, planeName,
- planeNameLen, errorMsg, errorMsgLen);
- printResult("XNModelCodeGen", result1, errorMsg);
-
- // 测试2: XNModelCodeZip
- std::cout << "=== 测试2: XNModelCodeZip ===" << std::endl;
- char dstPath[1024];
- int dstPathLen = sizeof(dstPath);
- memset(errorMsg, 0, sizeof(errorMsg));
- memset(dstPath, 0, sizeof(dstPath));
-
- int result2 = XNModelCodeZip(className, classNameLen, version, versionLen, planeName,
- planeNameLen, dstPath, dstPathLen, errorMsg, errorMsgLen);
- printResult("XNModelCodeZip", result2, errorMsg);
-
- if (result2 == 0 && strlen(dstPath) > 0) {
- std::cout << "生成的zip文件路径: " << dstPath << std::endl;
- }
-
- // 测试3: XNModelCodeUnzip
- std::cout << "=== 测试3: XNModelCodeUnzip ===" << std::endl;
- const char *srcZipPath = dstPath; // 使用上面生成的zip文件路径
- int srcZipPathLen = strlen(srcZipPath);
- memset(errorMsg, 0, sizeof(errorMsg));
-
- int result3 = XNModelCodeUnzip(className, classNameLen, version, versionLen, planeName,
- planeNameLen, srcZipPath, srcZipPathLen, errorMsg, errorMsgLen);
- printResult("XNModelCodeUnzip", result3, errorMsg);
-
- // 测试4: XNModelCodeCompile
- std::cout << "=== 测试4: XNModelCodeCompile ===" << std::endl;
- memset(errorMsg, 0, sizeof(errorMsg));
- int result4 = XNModelCodeCompile(className, classNameLen, version, versionLen, planeName,
- planeNameLen, errorMsg, errorMsgLen);
- printResult("XNModelCodeCompile", result4, errorMsg);
-
- // 清理资源
- dlclose(handle);
-
- std::cout << "=== 测试总结 ===" << std::endl;
- std::cout << "XNModelCodeGen: " << (result1 == 0 ? "成功" : "失败") << std::endl;
- std::cout << "XNModelCodeZip: " << (result2 == 0 ? "成功" : "失败") << std::endl;
- std::cout << "XNModelCodeUnzip: " << (result3 == 0 ? "成功" : "失败") << std::endl;
- std::cout << "XNModelCodeCompile: " << (result4 == 0 ? "成功" : "失败") << std::endl;
-
- return (result1 == 0 && result2 == 0 && result3 == 0 && result4 == 0) ? 0 : -1;
-}
\ No newline at end of file
diff --git a/XNServiceGenServer/test/test_xnservice.cpp b/XNServiceGenServer/test/test_xnservice.cpp
new file mode 100644
index 0000000..9fa2b0c
--- /dev/null
+++ b/XNServiceGenServer/test/test_xnservice.cpp
@@ -0,0 +1,126 @@
+#include
+#include
+#include
+
+// 函数指针类型定义
+typedef int (*XNServiceCodeGenFunc)(const char *className, int classNameLen, const char *version,
+ int versionLen, char *errorMsg, int errorMsgLen);
+
+typedef int (*XNServiceCodeZipFunc)(const char *className, int classNameLen, const char *version,
+ int versionLen, char *dstPath, int dstPathLen, char *errorMsg,
+ int errorMsgLen);
+
+typedef int (*XNServiceCodeUnzipFunc)(const char *className, int classNameLen, const char *version,
+ int versionLen, const char *srcPath, int srcPathLen,
+ char *errorMsg, int errorMsgLen);
+
+typedef int (*XNServiceCodeCompileFunc)(const char *className, int classNameLen,
+ const char *version, int versionLen, char *errorMsg,
+ int errorMsgLen);
+
+// 测试参数
+const char *className = "XNUDPService";
+const char *version = "1.0.0.0";
+const char *planeName = "XNUDPServer";
+
+void printResult(const std::string &testName, int result, const char *errorMsg)
+{
+ std::cout << testName << " 结果: " << result << std::endl;
+ if (result == 0) {
+ std::cout << "✓ " << testName << " 成功!" << std::endl;
+ } else {
+ std::cout << "✗ " << testName << " 失败!" << std::endl;
+ }
+
+ if (strlen(errorMsg) > 0) {
+ std::cout << "错误信息: " << errorMsg << std::endl;
+ }
+ std::cout << std::endl;
+}
+
+int main()
+{
+ // 动态加载.so库 - 修改路径指向build目录
+ void *handle = dlopen("../../build/libXNServiceGenServer.so", RTLD_LAZY);
+ if (!handle) {
+ std::cerr << "无法加载库文件: " << dlerror() << std::endl;
+ return -1;
+ }
+
+ // 获取函数指针
+ XNServiceCodeGenFunc XNServiceCodeGen = (XNServiceCodeGenFunc)dlsym(handle, "XNServiceCodeGen");
+ XNServiceCodeZipFunc XNServiceCodeZip = (XNServiceCodeZipFunc)dlsym(handle, "XNServiceCodeZip");
+ XNServiceCodeUnzipFunc XNServiceCodeUnzip =
+ (XNServiceCodeUnzipFunc)dlsym(handle, "XNServiceCodeUnzip");
+ XNServiceCodeCompileFunc XNServiceCodeCompile =
+ (XNServiceCodeCompileFunc)dlsym(handle, "XNServiceCodeCompile");
+
+ if (!XNServiceCodeGen || !XNServiceCodeZip || !XNServiceCodeUnzip || !XNServiceCodeCompile) {
+ std::cerr << "无法找到函数: " << dlerror() << std::endl;
+ dlclose(handle);
+ return -1;
+ }
+
+ int classNameLen = strlen(className);
+ int versionLen = strlen(version);
+
+ // 错误消息缓冲区
+ char errorMsg[1024];
+ int errorMsgLen = sizeof(errorMsg);
+
+ std::cout << "开始测试XNModelGen函数..." << std::endl;
+ std::cout << "参数:" << std::endl;
+ std::cout << " className: " << className << " (长度: " << classNameLen << ")" << std::endl;
+ std::cout << " version: " << version << " (长度: " << versionLen << ")" << std::endl;
+ std::cout << std::endl;
+
+ // 测试1: XNModelCodeGen
+ std::cout << "=== 测试1: XNModelCodeGen ===" << std::endl;
+ memset(errorMsg, 0, sizeof(errorMsg));
+ int result1 =
+ XNServiceCodeGen(className, classNameLen, version, versionLen, errorMsg, errorMsgLen);
+ printResult("XNServiceCodeGen", result1, errorMsg);
+
+ // 测试2: XNModelCodeZip
+ std::cout << "=== 测试2: XNModelCodeZip ===" << std::endl;
+ char dstPath[1024];
+ int dstPathLen = sizeof(dstPath);
+ memset(errorMsg, 0, sizeof(errorMsg));
+ memset(dstPath, 0, sizeof(dstPath));
+
+ int result2 = XNServiceCodeZip(className, classNameLen, version, versionLen, dstPath,
+ dstPathLen, errorMsg, errorMsgLen);
+ printResult("XNServiceCodeZip", result2, errorMsg);
+
+ if (result2 == 0 && strlen(dstPath) > 0) {
+ std::cout << "生成的zip文件路径: " << dstPath << std::endl;
+ }
+
+ // 测试3: XNModelCodeUnzip
+ std::cout << "=== 测试3: XNModelCodeUnzip ===" << std::endl;
+ const char *srcZipPath = dstPath; // 使用上面生成的zip文件路径
+ int srcZipPathLen = strlen(srcZipPath);
+ memset(errorMsg, 0, sizeof(errorMsg));
+
+ int result3 = XNServiceCodeUnzip(className, classNameLen, version, versionLen, srcZipPath,
+ srcZipPathLen, errorMsg, errorMsgLen);
+ printResult("XNServiceCodeUnzip", result3, errorMsg);
+
+ // 测试4: XNModelCodeCompile
+ std::cout << "=== 测试4: XNModelCodeCompile ===" << std::endl;
+ memset(errorMsg, 0, sizeof(errorMsg));
+ int result4 =
+ XNServiceCodeCompile(className, classNameLen, version, versionLen, errorMsg, errorMsgLen);
+ printResult("XNServiceCodeCompile", result4, errorMsg);
+
+ // 清理资源
+ dlclose(handle);
+
+ std::cout << "=== 测试总结 ===" << std::endl;
+ std::cout << "XNServiceCodeGen: " << (result1 == 0 ? "成功" : "失败") << std::endl;
+ std::cout << "XNServiceCodeZip: " << (result2 == 0 ? "成功" : "失败") << std::endl;
+ std::cout << "XNServiceCodeUnzip: " << (result3 == 0 ? "成功" : "失败") << std::endl;
+ std::cout << "XNServiceCodeCompile: " << (result4 == 0 ? "成功" : "失败") << std::endl;
+
+ return (result1 == 0 && result2 == 0 && result3 == 0 && result4 == 0) ? 0 : -1;
+}
\ No newline at end of file
diff --git a/XNServices/XNUDPService/.vscode/c_cpp_properties.json b/XNServices/XNUDPService/.vscode/c_cpp_properties.json
deleted file mode 100755
index 0b3cbd5..0000000
--- a/XNServices/XNUDPService/.vscode/c_cpp_properties.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "configurations": [
- {
- "compileCommands": "${workspaceFolder}/build/compile_commands.json",
- "configurationProvider": "ms-vscode.cmake-tools"
- }
- ],
- "version": 4
-}
\ No newline at end of file
diff --git a/XNServices/XNUDPService/.vscode/settings.json b/XNServices/XNUDPService/.vscode/settings.json
deleted file mode 100644
index 9b6b487..0000000
--- a/XNServices/XNUDPService/.vscode/settings.json
+++ /dev/null
@@ -1,77 +0,0 @@
-{
- "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.user b/XNServices/XNUDPService/CMakeLists.txt.user
deleted file mode 100755
index 3432be7..0000000
--- a/XNServices/XNUDPService/CMakeLists.txt.user
+++ /dev/null
@@ -1,424 +0,0 @@
-
-
-
-
-
- EnvironmentId
- {5b958118-2d32-49ab-8eab-9018ac74c7d6}
-
-
- ProjectExplorer.Project.ActiveTarget
- 0
-
-
- ProjectExplorer.Project.EditorSettings
-
- true
- false
- true
-
- Cpp
-
- CppGlobal
-
-
-
- QmlJS
-
- QmlJSGlobal
-
-
- 2
- UTF-8
- false
- 4
- false
- 80
- true
- true
- 1
- 0
- false
- true
- false
- 2
- true
- true
- 0
- 8
- true
- false
- 1
- true
- true
- true
- *.md, *.MD, Makefile
- false
- true
- true
-
-
-
- ProjectExplorer.Project.PluginSettings
-
-
- true
- false
- true
- true
- true
- true
-
- false
-
-
- 0
- true
-
- true
- true
- Builtin.DefaultTidyAndClazy
- 5
- true
-
-
-
- true
-
-
- true
- true
-
-
-
-
- ProjectExplorer.Project.Target.0
-
- Desktop
- Desktop Qt 6.7.2
- Desktop Qt 6.7.2
- qt.qt6.672.linux_gcc_64_kit
- 0
- 0
- 0
-
- Debug
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=Debug
- 0
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Debug
-
-
-
-
- all
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Debug
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- Release
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=Release
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Release
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-RelWithDebInfo
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release with Debug Information
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
- 0
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Profile
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Profile
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- MinSizeRel
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=MinSizeRel
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-MinSizeRel
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Minimum Size Release
- CMakeProjectManager.CMakeBuildConfiguration
-
- 5
-
-
- 0
- 部署
- 部署
- ProjectExplorer.BuildSteps.Deploy
-
- 1
-
- false
- ProjectExplorer.DefaultDeployConfiguration
-
- 1
-
- true
- true
- 0
- true
-
- 2
-
- false
- -e cpu-cycles --call-graph dwarf,4096 -F 250
-
- ProjectExplorer.CustomExecutableRunConfiguration
-
- false
- true
- true
-
- 1
-
-
-
- ProjectExplorer.Project.TargetCount
- 1
-
-
- ProjectExplorer.Project.Updater.FileVersion
- 22
-
-
- Version
- 22
-
-
diff --git a/XNServices/XNUDPService/XNUDPService.cpp b/XNServices/XNUDPService/XNUDPService.cpp
deleted file mode 100755
index ed97f0b..0000000
--- a/XNServices/XNUDPService/XNUDPService.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-#include "XNUDPService.h"
-#include "XNUDPService_p.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-XN_SERVICE_INITIALIZE(XNUDPService)
-
-XNUDPService::XNUDPService() : XNServiceObject(new XNUDPServicePrivate())
-{
-}
-
-XNUDPService::~XNUDPService()
-{
- T_D();
- if (d->udpSocket >= 0) {
- close(d->udpSocket);
- d->udpSocket = -1;
- }
-};
-
-XNUDPService::XNUDPService(PrivateType *p) : XNServiceObject(p)
-{
-}
-
-void XNUDPService::Initialize()
-{
- XNServiceObject::Initialize();
- T_D();
- 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;
- }
-
- 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 {
- 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;
- }
- }
-}
-
-void XNUDPService::PrepareForExecute()
-{
- XNServiceObject::PrepareForExecute();
- T_D();
- // 初始化UDP socket
- d->udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
- if (d->udpSocket < 0) {
- LOG_WARNING("无法创建UDP socket");
- return;
- }
-
- // 设置非阻塞模式
- int flags = fcntl(d->udpSocket, F_GETFL, 0);
- fcntl(d->udpSocket, F_SETFL, flags | O_NONBLOCK);
-
- // 绑定本地端口
- struct sockaddr_in localAddr;
- memset(&localAddr, 0, sizeof(localAddr));
- localAddr.sin_family = AF_INET;
- localAddr.sin_addr.s_addr = INADDR_ANY;
- localAddr.sin_port = htons(d->localPort);
-
- if (bind(d->udpSocket, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) {
- LOG_WARNING("UDP socket 绑定失败, 端口:%d", d->localPort);
- close(d->udpSocket);
- d->udpSocket = -1;
- return;
- }
-
- RegisterRTEventHandler("SendUDPData",
- std::bind(&XNUDPService::SendData, this, std::placeholders::_1));
-}
-
-void XNUDPService::HandleIncomingData()
-{
- T_D();
- if (d->udpSocket < 0)
- return;
-
- char buffer[65536];
- struct sockaddr_in senderAddr;
- socklen_t senderLen = sizeof(senderAddr);
-
- while (true) {
- ssize_t bytesRead = recvfrom(d->udpSocket, buffer, sizeof(buffer), 0,
- (struct sockaddr *)&senderAddr, &senderLen);
-
- if (bytesRead <= 0) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- break; // 没有更多数据
- }
- LOG_WARNING("读取UDP socket失败");
- break;
- }
-
- if (bytesRead <= 8) {
- LOG_WARNING("UDP 数据包小于8字节");
- continue;
- }
-
- // 将数据转换为XNByteArray
- XNByteArray datagram;
- datagram.resize(bytesRead);
- memcpy(datagram.data(), buffer, bytesRead);
- if (datagram[0] != 0xa6) {
- LOG_WARNING("UDP 数据包头无效, 头:%1", datagram[0]);
- continue;
- }
-
- if (datagram[5] != 0x00) {
- LOG_WARNING("UDP 数据包传输方向错误, 方向:%1", datagram[5]);
- continue;
- }
-
- uint16_t dataSize = ((uint16_t)datagram[6] << 8) | (uint16_t)datagram[7];
- if (dataSize != bytesRead) {
- LOG_WARNING("UDP 数据包大小无效, 大小:%d, 实际大小:%zd", dataSize, bytesRead - 8);
- continue;
- }
-
- uint8_t planeHeader = datagram[1];
- uint8_t ataHeader = datagram[2];
- uint8_t modelHeader = datagram[3];
- uint8_t structHeader = datagram[4];
-
- if (planeHeader == 0xc0) { //C909数据
- if (ataHeader == 0x04) { //ATA04章节数据
- if (modelHeader == 0x00 && structHeader == 0x00) { //气动输入数据
- TriggerRTEvent("C909::ATA04::AeroInput", datagram);
- continue;
- } else if (modelHeader == 0x01 && structHeader == 0x00) { //地操输入数据
- TriggerRTEvent("C909::ATA04::GhInput", datagram);
- continue;
- } else if (modelHeader == 0x02 && structHeader == 0x00) { //质量输入数据
- TriggerRTEvent("C909::ATA04::WbInput", datagram);
- continue;
- }
- }
- } else {
- TriggerRTEvent("ReceiveUDPData", datagram);
- }
- }
-}
-
-void XNUDPService::SendData(const std::any &data)
-{
- T_D();
- if (d->udpSocket < 0) {
- LOG_WARNING("UDP socket not initialized");
- return;
- }
-
- struct sockaddr_in targetAddr;
- memset(&targetAddr, 0, sizeof(targetAddr));
- targetAddr.sin_family = AF_INET;
- targetAddr.sin_port = htons(d->targetPort);
- inet_pton(AF_INET, d->targetHost.c_str(), &targetAddr.sin_addr);
-
- XNByteArray packet = std::any_cast(data);
- ssize_t bytesSent = sendto(d->udpSocket, packet.data(), packet.size(), 0,
- (struct sockaddr *)&targetAddr, sizeof(targetAddr));
-
- if (bytesSent < 0) {
- LOG_WARNING("Failed to send UDP datagram: %s", strerror(errno));
- }
-}
diff --git a/XNServices/XNUDPService/XNUDPService.h b/XNServices/XNUDPService/XNUDPService.h
deleted file mode 100755
index 5c9a44a..0000000
--- a/XNServices/XNUDPService/XNUDPService.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-#include "XNUDPService_global.h"
-#include
-#include
-#include
-
-struct XNUDPServicePrivate;
-
-class XNUDPSERVICE_EXPORT XNUDPService : public XNServiceObject
-{
- XN_METATYPE(XNUDPService, XNServiceObject)
- XN_DECLARE_PRIVATE(XNUDPService)
-public:
- explicit XNUDPService();
- virtual ~XNUDPService();
-
-protected:
- XNUDPService(PrivateType *p);
-
-public:
- virtual void Initialize() override;
- virtual void PrepareForExecute() override;
- void HandleIncomingData();
- void SendData(const std::any &data);
-};
-
-XNCLASS_PTR_DECLARE(XNUDPService)
diff --git a/XNServices/XNUDPService/XNUDPService.scfg b/XNServices/XNUDPService/XNUDPService.scfg
deleted file mode 100755
index 8fa1279..0000000
--- a/XNServices/XNUDPService/XNUDPService.scfg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- 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/XNServices/XNUDPService/XNUDPService_p.h b/XNServices/XNUDPService/XNUDPService_p.h
deleted file mode 100755
index 1a2a6df..0000000
--- a/XNServices/XNUDPService/XNUDPService_p.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-struct XNUDPServicePrivate : public XNServiceObjectPrivate {
- int udpSocket{-1};
- std::string targetHost;
- uint16_t targetPort{0};
- uint16_t localPort{0};
-};
diff --git a/XNServices/XNUDPTestService/.vscode/c_cpp_properties.json b/XNServices/XNUDPTestService/.vscode/c_cpp_properties.json
deleted file mode 100755
index 0b3cbd5..0000000
--- a/XNServices/XNUDPTestService/.vscode/c_cpp_properties.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "configurations": [
- {
- "compileCommands": "${workspaceFolder}/build/compile_commands.json",
- "configurationProvider": "ms-vscode.cmake-tools"
- }
- ],
- "version": 4
-}
\ No newline at end of file
diff --git a/XNServices/XNUDPTestService/.vscode/settings.json b/XNServices/XNUDPTestService/.vscode/settings.json
deleted file mode 100644
index 1507357..0000000
--- a/XNServices/XNUDPTestService/.vscode/settings.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "files.associations": {
- "functional": "cpp"
- }
-}
\ No newline at end of file
diff --git a/XNServices/XNUDPTestService/CMakeLists.txt b/XNServices/XNUDPTestService/CMakeLists.txt
deleted file mode 100755
index 61ba363..0000000
--- a/XNServices/XNUDPTestService/CMakeLists.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-cmake_minimum_required(VERSION 3.16)
-
-project(XNUDPTestService LANGUAGES CXX)
-
-set(CMAKE_AUTOUIC ON)
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
-# 获取环境变量
-if(DEFINED ENV{XNCore})
- set(XNCore_PATH $ENV{XNCore})
-else()
- message(FATAL_ERROR "Environment variable XNCore is not set.")
-endif()
-
-# 添加 XNCore_PATH 下的 include 目录为包含目录
-include_directories(${XNCore_PATH}/include)
-
-find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Network Xml)
-find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Network Xml)
-
-add_library(XNUDPTestService SHARED
- XNUDPTestService_global.h
- XNUDPTestService.cpp
- XNUDPTestService.h
- XNUDPTestService_p.h
-)
-
-target_link_libraries(XNUDPTestService PRIVATE
- Qt${QT_VERSION_MAJOR}::Core
- Qt${QT_VERSION_MAJOR}::Network
- Qt${QT_VERSION_MAJOR}::Xml
- ${XNCore_PATH}/lib/libXNCore.so
- )
-
-# 获取Qt库的安装路径
-get_target_property(QT_LIB_DIR Qt${QT_VERSION_MAJOR}::Core LOCATION)
-get_filename_component(QT_LIB_DIR ${QT_LIB_DIR} DIRECTORY)
-
-# 设置rpath
-set_target_properties(XNUDPTestService PROPERTIES
- BUILD_WITH_INSTALL_RPATH TRUE
- INSTALL_RPATH "${QT_LIB_DIR}"
-)
-
-target_compile_definitions(XNUDPTestService PRIVATE XNUDPSERVICE_LIBRARY)
-
-if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
- set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}/Services" CACHE PATH "Install path prefix" FORCE)
-endif()
-
-include(GNUInstallDirs)
-install(TARGETS XNUDPTestService
- BUNDLE DESTINATION .
- LIBRARY DESTINATION .
- RUNTIME DESTINATION .
-)
-
-# 添加自定义命令和目标以拷贝配置文件
-file(GLOB CONFIG_FILE "*.scfg")
-
-# 使用 install 命令在安装时拷贝配置文件
-install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX})
diff --git a/XNServices/XNUDPTestService/CMakeLists.txt.user b/XNServices/XNUDPTestService/CMakeLists.txt.user
deleted file mode 100755
index 3432be7..0000000
--- a/XNServices/XNUDPTestService/CMakeLists.txt.user
+++ /dev/null
@@ -1,424 +0,0 @@
-
-
-
-
-
- EnvironmentId
- {5b958118-2d32-49ab-8eab-9018ac74c7d6}
-
-
- ProjectExplorer.Project.ActiveTarget
- 0
-
-
- ProjectExplorer.Project.EditorSettings
-
- true
- false
- true
-
- Cpp
-
- CppGlobal
-
-
-
- QmlJS
-
- QmlJSGlobal
-
-
- 2
- UTF-8
- false
- 4
- false
- 80
- true
- true
- 1
- 0
- false
- true
- false
- 2
- true
- true
- 0
- 8
- true
- false
- 1
- true
- true
- true
- *.md, *.MD, Makefile
- false
- true
- true
-
-
-
- ProjectExplorer.Project.PluginSettings
-
-
- true
- false
- true
- true
- true
- true
-
- false
-
-
- 0
- true
-
- true
- true
- Builtin.DefaultTidyAndClazy
- 5
- true
-
-
-
- true
-
-
- true
- true
-
-
-
-
- ProjectExplorer.Project.Target.0
-
- Desktop
- Desktop Qt 6.7.2
- Desktop Qt 6.7.2
- qt.qt6.672.linux_gcc_64_kit
- 0
- 0
- 0
-
- Debug
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=Debug
- 0
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Debug
-
-
-
-
- all
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Debug
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- Release
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=Release
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Release
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-RelWithDebInfo
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release with Debug Information
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
- 0
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-Profile
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Profile
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- MinSizeRel
- 2
- false
-
- -DCMAKE_GENERATOR:STRING=Unix Makefiles
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_BUILD_TYPE:STRING=MinSizeRel
- /media/jin/E/MyCode/xnsim/XNModels/XNAerodynamics/build/Desktop_Qt_6_7_2-MinSizeRel
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Minimum Size Release
- CMakeProjectManager.CMakeBuildConfiguration
-
- 5
-
-
- 0
- 部署
- 部署
- ProjectExplorer.BuildSteps.Deploy
-
- 1
-
- false
- ProjectExplorer.DefaultDeployConfiguration
-
- 1
-
- true
- true
- 0
- true
-
- 2
-
- false
- -e cpu-cycles --call-graph dwarf,4096 -F 250
-
- ProjectExplorer.CustomExecutableRunConfiguration
-
- false
- true
- true
-
- 1
-
-
-
- ProjectExplorer.Project.TargetCount
- 1
-
-
- ProjectExplorer.Project.Updater.FileVersion
- 22
-
-
- Version
- 22
-
-
diff --git a/XNServices/XNUDPTestService/XNUDPTestService.cpp b/XNServices/XNUDPTestService/XNUDPTestService.cpp
deleted file mode 100755
index 72a533a..0000000
--- a/XNServices/XNUDPTestService/XNUDPTestService.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "XNUDPTestService.h"
-#include "XNUDPTestService_p.h"
-#include
-#include
-#include
-#include
-
-XN_DLL_INITIALIZE(XNUDPTestService)
-
-XN_REGISTER_SERVICE_BEGIN_SERVICE(XNUDPTestService)
-XN_REGISTER_SERVICE_END_SERVICE(XNUDPTestService)
-
-XNUDPTestService::XNUDPTestService(QObject *parent)
- : XNServiceObject(*new XNUDPTestServicePrivate(this), parent)
-{
-}
-
-XNUDPTestService::~XNUDPTestService()
-{
-}
-
-XNUDPTestService::XNUDPTestService(XNUDPTestServicePrivate &dd, QObject *parent)
- : XNServiceObject(dd, parent)
-{
-}
-
-void XNUDPTestService::OnInitialize()
-{
- Q_D(XNUDPTestService);
- XNServiceObject::OnInitialize();
-
- // 读取配置文件
- QFile file(GetXmlPath());
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- LOG_WARNING("Failed to open config file:%1", GetXmlPath());
- return;
- }
-
- QDomDocument doc;
- if (!doc.setContent(&file)) {
- file.close();
- LOG_WARNING("Failed to parse config file:%1", GetXmlPath());
- return;
- }
- file.close();
-
- // 读取UDP配置
- QDomElement udpElement = doc.documentElement().firstChildElement("UDP");
- if (!udpElement.isNull()) {
- d->localPort = udpElement.firstChildElement("LocalPort").text().toUInt();
- d->targetHost = udpElement.firstChildElement("TargetHost").text();
- d->targetPort = udpElement.firstChildElement("TargetPort").text().toUInt();
- } else {
- LOG_WARNING("UDP configuration not found, using default values");
- d->localPort = 12345;
- d->targetHost = "127.0.0.1";
- d->targetPort = 54321;
- }
-}
-
-void XNUDPTestService::OnPrepareForExecute()
-{
- Q_D(XNUDPTestService);
- XNServiceObject::OnPrepareForExecute();
-
- // 初始化UDP socket
- d->udpSocket = new QUdpSocket(this);
-
- // 绑定本地端口
- if (!d->udpSocket->bind(QHostAddress::Any, d->localPort)) {
- LOG_WARNING("UDP socket bind failed on port:%1", d->localPort);
- return;
- }
-
- // 连接UDP socket的信号
- //connect(d->udpSocket, &QUdpSocket::readyRead, this, &XNUDPTestService::HandleIncomingData);
-
- RegisterRTEventHandler("SendTestUDPData",
- std::bind(&XNUDPTestService::SendData, this, std::placeholders::_1));
-}
-
-void XNUDPTestService::HandleIncomingData()
-{
- Q_D(XNUDPTestService);
- return;
- while (d->udpSocket->hasPendingDatagrams()) {
- QByteArray datagram;
- datagram.resize(d->udpSocket->pendingDatagramSize());
- QHostAddress sender;
- quint16 senderPort;
-
- d->udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
-
- // 处理接收到的数据
- if (datagram.size() <= 5 || datagram[0] != 0x0b || datagram[4] != datagram.size()) {
- LOG_WARNING("Invalid UDP datagram received");
- continue;
- }
- if (datagram[1] == 0x04) {
- if (datagram[2] == 0x00 && datagram[3] == 0x00) {
- TriggerRTEvent("ATA04AeroInput", datagram);
- continue;
- } else if (datagram[2] == 0x01 && datagram[3] == 0x00) {
- TriggerRTEvent("ATA04GhInput", datagram);
- continue;
- } else if (datagram[2] == 0x02 && datagram[3] == 0x00) {
- TriggerRTEvent("ATA04WbInput", datagram);
- continue;
- }
- }
- // TODO: 根据具体需求处理其它数据
- //TriggerRTEvent("ReceiveUDPData", datagram);
- }
-}
-
-void XNUDPTestService::SendData(const QVariant &data)
-{
- Q_D(XNUDPTestService);
- if (!d->udpSocket) {
- LOG_WARNING("UDP socket not initialized");
- return;
- }
-
- // 将QVariant转换为字节数组
- QByteArray datagram = data.toByteArray();
-
- // 发送数据
- qint64 bytesSent =
- d->udpSocket->writeDatagram(datagram, QHostAddress(d->targetHost), d->targetPort);
- if (bytesSent == -1) {
- LOG_WARNING("Failed to send UDP datagram:%1", d->udpSocket->errorString());
- }
-}
diff --git a/XNServices/XNUDPTestService/XNUDPTestService.h b/XNServices/XNUDPTestService/XNUDPTestService.h
deleted file mode 100755
index 0ca8f22..0000000
--- a/XNServices/XNUDPTestService/XNUDPTestService.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-#include "XNUDPTestService_global.h"
-#include
-#include
-class XNUDPTestServicePrivate;
-
-class XNUDPTESTSERVICE_EXPORT XNUDPTestService : public XNServiceObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(XNUDPTestService)
- Q_DECLARE_PRIVATE(XNUDPTestService)
- XN_DECLARE_DDS_SERVICE()
-public:
- explicit XNUDPTestService(QObject *parent = nullptr);
- virtual ~XNUDPTestService();
-
-protected:
- XNUDPTestService(XNUDPTestServicePrivate &dd, QObject *parent = nullptr);
-
-public slots:
- virtual void OnInitialize() override;
- virtual void OnPrepareForExecute() override;
- void HandleIncomingData();
-
-public:
- void SendData(const QVariant &data);
-};
-
-Q_DECLARE_METATYPE(XNUDPTestService)
diff --git a/XNServices/XNUDPTestService/XNUDPTestService.scfg b/XNServices/XNUDPTestService/XNUDPTestService.scfg
deleted file mode 100755
index d80e723..0000000
--- a/XNServices/XNUDPTestService/XNUDPTestService.scfg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- XNUDPTestService
- UDP通信服务
- Jin
- 1.0.0
- 2025-02-04 10:00:00
- 2025-02-04 10:00:00
-
-
-
-
- 54321
- 127.0.0.1
- 12345
-
-
diff --git a/XNServices/XNUDPTestService/XNUDPTestService_global.h b/XNServices/XNUDPTestService/XNUDPTestService_global.h
deleted file mode 100755
index ad16e20..0000000
--- a/XNServices/XNUDPTestService/XNUDPTestService_global.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef XNUDPTESTSERVICE_GLOBAL_H
-#define XNUDPTESTSERVICE_GLOBAL_H
-
-#include
-
-#if defined(XNUDPTESTSERVICE_LIBRARY)
-# define XNUDPTESTSERVICE_EXPORT Q_DECL_EXPORT
-#else
-# define XNUDPTESTSERVICE_EXPORT Q_DECL_IMPORT
-#endif
-
-#endif // XNUDPTESTSERVICE_GLOBAL_H
diff --git a/XNServices/XNUDPTestService/XNUDPTestService_p.h b/XNServices/XNUDPTestService/XNUDPTestService_p.h
deleted file mode 100755
index 636b0bb..0000000
--- a/XNServices/XNUDPTestService/XNUDPTestService_p.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-#include
-#include
-#include
-
-class XNUDPTestServicePrivate : public XNServiceObjectPrivate
-{
-public:
- Q_DECLARE_PUBLIC(XNUDPTestService)
-
- XNUDPTestServicePrivate(XNUDPTestService *q) : XNServiceObjectPrivate(q) {}
-
- QUdpSocket *udpSocket{nullptr};
- QString targetHost;
- quint16 targetPort{0};
- quint16 localPort{0};
-};
diff --git a/XNSimPortal/components/service-development.js b/XNSimPortal/components/service-development.js
index e78abe7..ad58c3b 100644
--- a/XNSimPortal/components/service-development.js
+++ b/XNSimPortal/components/service-development.js
@@ -407,7 +407,7 @@ class ServiceDevelopment extends HTMLElement {
async init() {
try {
- const response = await fetch('/api/services');
+ const response = await fetch('/api/service-dev/services');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
@@ -421,7 +421,7 @@ class ServiceDevelopment extends HTMLElement {
async fetchServiceVersions(className, serviceName) {
try {
- const response = await fetch(`/api/service-versions/${encodeURIComponent(className)}`);
+ const response = await fetch(`/api/service-dev/service-versions/${encodeURIComponent(className)}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
@@ -466,7 +466,7 @@ class ServiceDevelopment extends HTMLElement {
versionData.OtherParam = '{}';
}
- const response = await fetch('/api/service-versions', {
+ const response = await fetch('/api/service-dev/service-versions', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -1758,7 +1758,7 @@ class ServiceDevelopment extends HTMLElement {
Description: serviceData.Description || ''
};
- const response = await fetch('/api/services', {
+ const response = await fetch('/api/service-dev/services', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -1779,31 +1779,376 @@ class ServiceDevelopment extends HTMLElement {
}
// 生成模板代码
- generateTemplateCode() {
- console.log('生成模板代码功能');
- // TODO: 实现生成模板代码的具体功能
- alert('生成模板代码功能即将上线');
+ async generateTemplateCode() {
+ try {
+ // 检查是否有当前版本数据
+ if (!this.currentVersion || !this.currentVersion.ClassName || !this.currentVersion.Version) {
+ alert('请先保存版本信息,然后再生成模板代码');
+ return;
+ }
+
+ // 找到对应的按钮并更新状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('生成模板代码') ||
+ btn.onclick && btn.onclick.toString().includes('generateTemplateCode')
+ );
+ const originalText = button ? button.textContent : '生成模板代码';
+
+ if (button) {
+ button.textContent = '正在生成...';
+ button.disabled = true;
+ }
+
+ // 调用生成代码API
+ const response = await fetch('/api/service-dev/generate-code', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ className: this.currentVersion.ClassName,
+ version: this.currentVersion.Version
+ })
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json();
+ throw new Error(errorData.error || `HTTP错误! 状态码: ${response.status}`);
+ }
+
+ const result = await response.json();
+
+ if (result.success) {
+ alert(`模板代码生成成功!\n${result.message}`);
+ } else {
+ throw new Error(result.error || '生成失败');
+ }
+ } catch (error) {
+ console.error('生成模板代码失败:', error);
+ alert(`生成模板代码失败: ${error.message}`);
+ } finally {
+ // 恢复按钮状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('正在生成...') ||
+ btn.textContent.includes('生成模板代码')
+ );
+ if (button) {
+ button.textContent = '生成模板代码';
+ button.disabled = false;
+ }
+ }
}
// 下载模板代码
- downloadTemplateCode() {
- console.log('下载模板代码功能');
- // TODO: 实现下载模板代码的具体功能
- alert('下载模板代码功能即将上线');
+ async downloadTemplateCode() {
+ try {
+ // 检查是否有当前版本数据
+ if (!this.currentVersion || !this.currentVersion.ClassName || !this.currentVersion.Version) {
+ alert('请先保存版本信息,然后再下载模板代码');
+ return;
+ }
+
+ // 找到对应的按钮并更新状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('下载模板代码') ||
+ btn.onclick && btn.onclick.toString().includes('downloadTemplateCode')
+ );
+ const originalText = button ? button.textContent : '下载模板代码';
+
+ if (button) {
+ button.textContent = '正在打包...';
+ button.disabled = true;
+ }
+
+ // 第一步:调用打包API
+ const zipResponse = await fetch('/api/service-dev/zip-code', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ className: this.currentVersion.ClassName,
+ version: this.currentVersion.Version
+ })
+ });
+
+ if (!zipResponse.ok) {
+ const errorData = await zipResponse.json();
+ throw new Error(errorData.error || `打包失败! 状态码: ${zipResponse.status}`);
+ }
+
+ const zipResult = await zipResponse.json();
+
+ if (!zipResult.success) {
+ throw new Error(zipResult.error || '打包失败');
+ }
+
+ // 更新按钮状态为下载中
+ if (button) {
+ button.textContent = '正在下载...';
+ }
+
+ // 第二步:调用下载API
+ const downloadResponse = await fetch('/api/service-dev/download-zip', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ filePath: zipResult.dstPath
+ })
+ });
+
+ if (!downloadResponse.ok) {
+ const errorData = await downloadResponse.json();
+ throw new Error(errorData.error || `下载失败! 状态码: ${downloadResponse.status}`);
+ }
+
+ // 获取文件名
+ const fileName = `${this.currentVersion.ClassName}_${this.currentVersion.Version}.zip`;
+
+ // 创建下载链接
+ const blob = await downloadResponse.blob();
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = fileName;
+ document.body.appendChild(a);
+ a.click();
+ window.URL.revokeObjectURL(url);
+ document.body.removeChild(a);
+
+ alert(`模板代码下载成功!\n文件路径: ${zipResult.dstPath}\n文件名: ${fileName}`);
+ } catch (error) {
+ console.error('下载模板代码失败:', error);
+ alert(`下载模板代码失败: ${error.message}`);
+ } finally {
+ // 恢复按钮状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('正在下载...') ||
+ btn.textContent.includes('正在打包...') ||
+ btn.textContent.includes('下载模板代码')
+ );
+ if (button) {
+ button.textContent = '下载模板代码';
+ button.disabled = false;
+ }
+ }
}
// 上传服务代码
- uploadServiceCode() {
- console.log('上传服务代码功能');
- // TODO: 实现上传服务代码的具体功能
- alert('上传服务代码功能即将上线');
+ async uploadServiceCode() {
+ try {
+ // 检查是否有当前版本数据
+ if (!this.currentVersion || !this.currentVersion.ClassName || !this.currentVersion.Version) {
+ alert('请先保存版本信息,然后再上传服务代码');
+ return;
+ }
+
+ // 找到对应的按钮并更新状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('上传服务代码') ||
+ btn.onclick && btn.onclick.toString().includes('uploadServiceCode')
+ );
+ const originalText = button ? button.textContent : '上传服务代码';
+
+ if (button) {
+ button.textContent = '选择文件中...';
+ button.disabled = true;
+ }
+
+ // 创建文件输入元素
+ const fileInput = document.createElement('input');
+ fileInput.type = 'file';
+ fileInput.accept = '.zip';
+ fileInput.style.display = 'none';
+
+ // 添加到DOM
+ document.body.appendChild(fileInput);
+
+ // 监听文件选择
+ fileInput.addEventListener('change', async (event) => {
+ const file = event.target.files[0];
+ if (!file) {
+ // 恢复按钮状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('选择文件中...') ||
+ btn.textContent.includes('上传服务代码')
+ );
+ if (button) {
+ button.textContent = '上传服务代码';
+ button.disabled = false;
+ }
+ document.body.removeChild(fileInput);
+ return;
+ }
+
+ try {
+ // 验证文件类型
+ if (!file.name.toLowerCase().endsWith('.zip')) {
+ throw new Error('请选择ZIP格式的压缩包文件');
+ }
+
+ // 更新按钮状态为上传中
+ if (button) {
+ button.textContent = '正在上传...';
+ }
+
+ // 第一步:上传文件
+ const formData = new FormData();
+ formData.append('file', file);
+ formData.append('className', this.currentVersion.ClassName);
+ formData.append('version', this.currentVersion.Version);
+
+ const uploadResponse = await fetch('/api/service-dev/upload-zip', {
+ method: 'POST',
+ body: formData
+ });
+
+ if (!uploadResponse.ok) {
+ const errorData = await uploadResponse.json();
+ throw new Error(errorData.error || `上传失败! 状态码: ${uploadResponse.status}`);
+ }
+
+ const uploadResult = await uploadResponse.json();
+
+ if (!uploadResult.success) {
+ throw new Error(uploadResult.error || '上传失败');
+ }
+
+ // 更新按钮状态为解压中
+ if (button) {
+ button.textContent = '正在解压...';
+ }
+
+ // 第二步:解压文件
+ const unzipResponse = await fetch('/api/service-dev/unzip-code', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ className: this.currentVersion.ClassName,
+ version: this.currentVersion.Version,
+ srcPath: uploadResult.filePath
+ })
+ });
+
+ if (!unzipResponse.ok) {
+ const errorData = await unzipResponse.json();
+ throw new Error(errorData.error || `解压失败! 状态码: ${unzipResponse.status}`);
+ }
+
+ const unzipResult = await unzipResponse.json();
+
+ if (unzipResult.success) {
+ alert(`服务代码上传并解压成功!\n原始文件名: ${uploadResult.originalName}\n保存路径: ${uploadResult.filePath}\n${unzipResult.message}`);
+ } else {
+ throw new Error(unzipResult.error || '解压失败');
+ }
+
+ } catch (error) {
+ console.error('上传服务代码失败:', error);
+ alert(`上传服务代码失败: ${error.message}`);
+ } finally {
+ // 恢复按钮状态
+ if (button) {
+ button.textContent = '上传服务代码';
+ button.disabled = false;
+ }
+ // 清理文件输入元素
+ document.body.removeChild(fileInput);
+ }
+ });
+
+ // 触发文件选择对话框
+ fileInput.click();
+
+ } catch (error) {
+ console.error('上传服务代码失败:', error);
+ alert(`上传服务代码失败: ${error.message}`);
+ // 恢复按钮状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('选择文件中...') ||
+ btn.textContent.includes('正在上传...') ||
+ btn.textContent.includes('正在解压...') ||
+ btn.textContent.includes('上传服务代码')
+ );
+ if (button) {
+ button.textContent = '上传服务代码';
+ button.disabled = false;
+ }
+ }
}
// 服务编译发布
- compileAndPublishService() {
- console.log('服务编译发布功能');
- // TODO: 实现服务编译发布的具体功能
- alert('服务编译发布功能即将上线');
+ async compileAndPublishService() {
+ try {
+ // 检查是否有当前版本数据
+ if (!this.currentVersion || !this.currentVersion.ClassName || !this.currentVersion.Version) {
+ alert('请先保存版本信息,然后再编译发布服务');
+ return;
+ }
+
+ // 找到对应的按钮并更新状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('服务编译发布') ||
+ btn.onclick && btn.onclick.toString().includes('compileAndPublishService')
+ );
+ const originalText = button ? button.textContent : '服务编译发布';
+
+ if (button) {
+ button.textContent = '正在编译...';
+ button.disabled = true;
+ }
+
+ // 调用编译API
+ const response = await fetch('/api/service-dev/compile-code', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ className: this.currentVersion.ClassName,
+ version: this.currentVersion.Version
+ })
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json();
+ throw new Error(errorData.error || `HTTP错误! 状态码: ${response.status}`);
+ }
+
+ const result = await response.json();
+
+ if (result.success) {
+ alert(`服务编译发布成功!\n${result.message}`);
+ } else {
+ throw new Error(result.error || '编译失败');
+ }
+ } catch (error) {
+ console.error('服务编译发布失败:', error);
+ alert(`服务编译发布失败: ${error.message}`);
+ } finally {
+ // 恢复按钮状态
+ const buttons = this.shadowRoot.querySelectorAll('button');
+ const button = Array.from(buttons).find(btn =>
+ btn.textContent.includes('正在编译...') ||
+ btn.textContent.includes('服务编译发布')
+ );
+ if (button) {
+ button.textContent = '服务编译发布';
+ button.disabled = false;
+ }
+ }
}
}
diff --git a/XNSimPortal/routes/service-dev.js b/XNSimPortal/routes/service-dev.js
index 1c5a731..333e90b 100644
--- a/XNSimPortal/routes/service-dev.js
+++ b/XNSimPortal/routes/service-dev.js
@@ -1,11 +1,20 @@
const express = require('express');
const router = express.Router();
+const multer = require('multer');
+const path = require('path');
+const fs = require('fs');
const {
getServices,
getServiceVersionsByClassName,
saveServiceVersion,
createService
} = require('../utils/service-utils');
+const {
+ serviceCodeGen,
+ serviceCodeZip,
+ serviceCodeUnzip,
+ serviceCodeCompile
+} = require('../utils/xnCoreService');
// 获取所有服务列表
router.get('/services', (req, res) => {
@@ -105,4 +114,222 @@ router.post('/services', (req, res) => {
}
});
+// 生成服务代码
+router.post('/generate-code', (req, res) => {
+ try {
+ const { className, version } = req.body;
+
+ if (!className || !version) {
+ return res.status(400).json({ error: '缺少必要的参数:className 和 version' });
+ }
+
+ const result = serviceCodeGen(className, version);
+
+ if (result.includes('成功')) {
+ res.json({ success: true, message: result });
+ } else {
+ res.status(500).json({ success: false, error: result });
+ }
+ } catch (error) {
+ console.error(`生成服务代码失败: ${error.message}`);
+ res.status(500).json({ error: '生成服务代码失败', details: error.message });
+ }
+});
+
+// 压缩服务代码
+router.post('/zip-code', (req, res) => {
+ try {
+ const { className, version } = req.body;
+
+ if (!className || !version) {
+ return res.status(400).json({ error: '缺少必要的参数:className 和 version' });
+ }
+
+ const result = serviceCodeZip(className, version);
+
+ if (result.success) {
+ res.json({
+ success: true,
+ message: result.message,
+ dstPath: result.dstPath
+ });
+ } else {
+ res.status(500).json({ success: false, error: result.message });
+ }
+ } catch (error) {
+ console.error(`压缩服务代码失败: ${error.message}`);
+ res.status(500).json({ error: '压缩服务代码失败', details: error.message });
+ }
+});
+
+// 解压服务代码
+router.post('/unzip-code', (req, res) => {
+ try {
+ const { className, version, srcPath } = req.body;
+
+ if (!className || !version || !srcPath) {
+ return res.status(400).json({ error: '缺少必要的参数:className、version 和 srcPath' });
+ }
+
+ const result = serviceCodeUnzip(className, version, srcPath);
+
+ if (result.includes('成功')) {
+ res.json({ success: true, message: result });
+ } else {
+ res.status(500).json({ success: false, error: result });
+ }
+ } catch (error) {
+ console.error(`解压服务代码失败: ${error.message}`);
+ res.status(500).json({ error: '解压服务代码失败', details: error.message });
+ }
+});
+
+// 编译服务代码
+router.post('/compile-code', (req, res) => {
+ try {
+ const { className, version } = req.body;
+
+ if (!className || !version) {
+ return res.status(400).json({ error: '缺少必要的参数:className 和 version' });
+ }
+
+ const result = serviceCodeCompile(className, version);
+
+ if (result.includes('成功')) {
+ res.json({ success: true, message: result });
+ } else {
+ res.status(500).json({ success: false, error: result });
+ }
+ } catch (error) {
+ console.error(`编译服务代码失败: ${error.message}`);
+ res.status(500).json({ error: '编译服务代码失败', details: error.message });
+ }
+});
+
+// 下载ZIP文件
+router.post('/download-zip', (req, res) => {
+ try {
+ const { filePath } = req.body;
+
+ if (!filePath) {
+ return res.status(400).json({ error: '缺少文件路径参数' });
+ }
+
+ // 检查文件是否存在
+ if (!fs.existsSync(filePath)) {
+ return res.status(404).json({ error: '文件不存在' });
+ }
+
+ // 检查文件是否为ZIP格式
+ if (!filePath.toLowerCase().endsWith('.zip')) {
+ return res.status(400).json({ error: '只能下载ZIP格式的文件' });
+ }
+
+ // 获取文件名
+ const fileName = path.basename(filePath);
+
+ // 设置响应头
+ res.setHeader('Content-Type', 'application/zip');
+ res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
+
+ // 发送文件
+ res.sendFile(filePath);
+ } catch (error) {
+ console.error(`下载ZIP文件失败: ${error.message}`);
+ res.status(500).json({ error: '下载ZIP文件失败', details: error.message });
+ }
+});
+
+// 配置multer用于文件上传
+const storage = multer.diskStorage({
+ destination: function (req, file, cb) {
+ // 获取XNCore环境变量
+ const xnCorePath = process.env.XNCore || '';
+ if (!xnCorePath) {
+ return cb(new Error('XNCore环境变量未设置'));
+ }
+
+ // 创建ServiceProjects目录
+ const serviceProjectsDir = path.join(xnCorePath, 'ServiceProjects');
+ if (!fs.existsSync(serviceProjectsDir)) {
+ fs.mkdirSync(serviceProjectsDir, { recursive: true });
+ }
+ cb(null, serviceProjectsDir);
+ },
+ filename: function (req, file, cb) {
+ cb(null, file.originalname);
+ }
+});
+
+const upload = multer({
+ storage: storage,
+ fileFilter: function (req, file, cb) {
+ // 只允许ZIP文件
+ if (file.mimetype === 'application/zip' || file.originalname.toLowerCase().endsWith('.zip')) {
+ cb(null, true);
+ } else {
+ cb(new Error('只允许上传ZIP格式的文件'), false);
+ }
+ },
+ limits: {
+ fileSize: 100 * 1024 * 1024 // 限制100MB
+ }
+});
+
+// 上传ZIP文件
+router.post('/upload-zip', upload.single('file'), (req, res) => {
+ try {
+ // 检查XNCore环境变量
+ const xnCorePath = process.env.XNCore || '';
+ if (!xnCorePath) {
+ return res.status(500).json({ error: 'XNCore环境变量未设置' });
+ }
+
+ if (!req.file) {
+ return res.status(400).json({ error: '没有选择文件' });
+ }
+
+ const filePath = req.file.path;
+ const fileName = req.file.filename;
+
+ // 验证文件是否成功保存到ServiceProjects目录
+ if (!fs.existsSync(filePath)) {
+ return res.status(500).json({ error: '文件上传失败,文件未保存到目标目录' });
+ }
+
+ res.json({
+ success: true,
+ message: '文件上传成功',
+ filePath: filePath,
+ fileName: fileName,
+ originalName: req.file.originalname,
+ uploadDir: path.dirname(filePath)
+ });
+ } catch (error) {
+ console.error(`上传ZIP文件失败: ${error.message}`);
+ res.status(500).json({ error: '上传ZIP文件失败', details: error.message });
+ }
+});
+
+// 处理multer错误
+router.use('/upload-zip', (error, req, res, next) => {
+ if (error instanceof multer.MulterError) {
+ if (error.code === 'LIMIT_FILE_SIZE') {
+ return res.status(400).json({ error: '文件大小超过限制(最大100MB)' });
+ }
+ return res.status(400).json({ error: `文件上传错误: ${error.message}` });
+ }
+
+ if (error.message === 'XNCore环境变量未设置') {
+ return res.status(500).json({ error: 'XNCore环境变量未设置,无法上传文件' });
+ }
+
+ if (error.message.includes('只允许上传ZIP格式的文件')) {
+ return res.status(400).json({ error: '只允许上传ZIP格式的文件' });
+ }
+
+ console.error('文件上传错误:', error);
+ res.status(500).json({ error: '文件上传失败', details: error.message });
+});
+
module.exports = router;
\ No newline at end of file
diff --git a/XNSimPortal/server.js b/XNSimPortal/server.js
index 61225a1..24ecb65 100644
--- a/XNSimPortal/server.js
+++ b/XNSimPortal/server.js
@@ -94,7 +94,7 @@ app.use('/api', authRoutes);
app.use('/api', versionRoutes);
app.use('/api/filesystem', filesystemRoutes);
app.use('/api', systemInfoRoutes);
-app.use('/api', serviceApiRoutes);
+app.use('/api/service-dev', serviceApiRoutes);
app.use('/api', ataChaptersRoutes);
app.use('/api', simulationRoutes);
app.use('/api/udp-monitor', udpMonitorRoutes);
diff --git a/XNSimPortal/utils/xnCoreService.js b/XNSimPortal/utils/xnCoreService.js
index 3bfe521..253e8b5 100644
--- a/XNSimPortal/utils/xnCoreService.js
+++ b/XNSimPortal/utils/xnCoreService.js
@@ -27,6 +27,10 @@ const interfaceGenLibPath = path.join(xnCorePath, 'lib', interfaceGenLibName);
const modelGenLibName = `${libPrefix}XNModelGenServer${libExtension}`;
const modelGenLibPath = path.join(xnCorePath, 'lib', modelGenLibName);
+// ServiceGenServer库配置
+const serviceGenLibName = `${libPrefix}XNServiceGenServer${libExtension}`;
+const serviceGenLibPath = path.join(xnCorePath, 'lib', serviceGenLibName);
+
// 定义Buffer类型
const BufferType = ref.refType(ref.types.void);
const StringType = ref.types.CString;
@@ -37,6 +41,7 @@ let loginLib;
let monitorLib;
let interfaceGenLib;
let modelGenLib;
+let serviceGenLib;
try {
loginLib = ffi.Library(loginLibPath, {
@@ -115,6 +120,17 @@ try {
console.error(`加载 ${modelGenLibName} 失败:`, error);
}
+try {
+ serviceGenLib = ffi.Library(serviceGenLibPath, {
+ 'XNServiceCodeGen': ['int', [StringType, 'int', StringType, 'int', StringType, 'int']],
+ 'XNServiceCodeZip': ['int', [StringType, 'int', StringType, 'int', StringType, 'int', StringType, 'int']],
+ 'XNServiceCodeUnzip': ['int', [StringType, 'int', StringType, 'int', StringType, 'int', StringType, 'int']],
+ 'XNServiceCodeCompile': ['int', [StringType, 'int', StringType, 'int', StringType, 'int']]
+ });
+} catch (error) {
+ console.error(`加载 ${serviceGenLibName} 失败:`, error);
+}
+
// 注册进程退出时的清理函数
function performCleanup() {
console.log('正在执行清理操作...');
@@ -907,11 +923,108 @@ function modelCodeCompile(className, version, planeName) {
}
}
+// ========== XNServiceGenServer 封装函数 ==========
+
+// 生成服务代码
+function serviceCodeGen(className, version) {
+ if (!serviceGenLib) {
+ return '服务生成库未加载';
+ }
+ try {
+ const errorMsg = Buffer.alloc(1024);
+ const result = serviceGenLib.XNServiceCodeGen(
+ className, className.length,
+ version, version.length,
+ errorMsg, errorMsg.length
+ );
+ if (result !== 0) {
+ return `生成服务代码失败: ${errorMsg.toString('utf8').replace(/\0/g, '')}`;
+ }
+ return '生成服务代码成功';
+ } catch (error) {
+ return `生成服务代码失败: ${error.message}`;
+ }
+}
+
+// 压缩服务代码
+function serviceCodeZip(className, version) {
+ if (!serviceGenLib) {
+ return '服务生成库未加载';
+ }
+ try {
+ const dstPath = Buffer.alloc(1024);
+ const errorMsg = Buffer.alloc(1024);
+ const result = serviceGenLib.XNServiceCodeZip(
+ className, className.length,
+ version, version.length,
+ dstPath, dstPath.length,
+ errorMsg, errorMsg.length
+ );
+ if (result !== 0) {
+ return `压缩服务代码失败: ${errorMsg.toString('utf8').replace(/\0/g, '')}`;
+ }
+ return {
+ success: true,
+ dstPath: dstPath.toString('utf8').replace(/\0/g, ''),
+ message: '压缩服务代码成功'
+ };
+ } catch (error) {
+ return {
+ success: false,
+ message: `压缩服务代码失败: ${error.message}`
+ };
+ }
+}
+
+// 解压服务代码
+function serviceCodeUnzip(className, version, srcPath) {
+ if (!serviceGenLib) {
+ return '服务生成库未加载';
+ }
+ try {
+ const errorMsg = Buffer.alloc(1024);
+ const result = serviceGenLib.XNServiceCodeUnzip(
+ className, className.length,
+ version, version.length,
+ srcPath, srcPath.length,
+ errorMsg, errorMsg.length
+ );
+ if (result !== 0) {
+ return `解压服务代码失败: ${errorMsg.toString('utf8').replace(/\0/g, '')}`;
+ }
+ return '解压服务代码成功';
+ } catch (error) {
+ return `解压服务代码失败: ${error.message}`;
+ }
+}
+
+// 编译服务代码
+function serviceCodeCompile(className, version) {
+ if (!serviceGenLib) {
+ return '服务生成库未加载';
+ }
+ try {
+ const errorMsg = Buffer.alloc(1024);
+ const result = serviceGenLib.XNServiceCodeCompile(
+ className, className.length,
+ version, version.length,
+ errorMsg, errorMsg.length
+ );
+ if (result !== 0) {
+ return `编译服务代码失败: ${errorMsg.toString('utf8').replace(/\0/g, '')}`;
+ }
+ return '编译服务代码成功';
+ } catch (error) {
+ return `编译服务代码失败: ${error.message}`;
+ }
+}
+
module.exports = {
loginLib,
monitorLib,
interfaceGenLib,
modelGenLib,
+ serviceGenLib,
performCleanup,
stringToBuffer,
initializeMonitor,
@@ -954,5 +1067,9 @@ module.exports = {
modelCodeGen,
modelCodeZip,
modelCodeUnzip,
- modelCodeCompile
+ modelCodeCompile,
+ serviceCodeGen,
+ serviceCodeZip,
+ serviceCodeUnzip,
+ serviceCodeCompile
};
\ No newline at end of file