diff --git a/Release/IDL/C909_V1/ATA04/Aerodynamics_heartbeat.cxx b/Release/IDL/C909_V1/ATA04/Aerodynamics_heartbeat.cxx index e752972..ab2a555 100644 --- a/Release/IDL/C909_V1/ATA04/Aerodynamics_heartbeat.cxx +++ b/Release/IDL/C909_V1/ATA04/Aerodynamics_heartbeat.cxx @@ -1,4 +1,5 @@ #include "Aerodynamics_heartbeat.hpp" +const std::string XNSim::C909::ATA04::Aerodynamics_heartbeat_Interface::topic_name = "XNSim::C909::ATA04::Aerodynamics_heartbeat"; namespace XNSim::C909::ATA04 { Aerodynamics_heartbeat_Interface::Aerodynamics_heartbeat_Interface() diff --git a/Release/IDL/C909_V1/ATA04/Aerodynamics_heartbeat.hpp b/Release/IDL/C909_V1/ATA04/Aerodynamics_heartbeat.hpp index cdec36b..5057ce0 100644 --- a/Release/IDL/C909_V1/ATA04/Aerodynamics_heartbeat.hpp +++ b/Release/IDL/C909_V1/ATA04/Aerodynamics_heartbeat.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class Aerodynamics_heartbeat_Interface final : public XNDDSInterface +class Aerodynamics_heartbeat_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::Aerodynamics_heartbeat; + using DDSPubSubType = XNSim::C909::ATA04::Aerodynamics_heartbeatPubSubType; + static const std::string topic_name; Aerodynamics_heartbeat_Interface(); virtual ~Aerodynamics_heartbeat_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -29,8 +32,8 @@ public: clearOutData(); assign_value_set(data.aero_model_heartbeat(), model_data->aero_model_heartbeat); } -private: - XNSim::C909::ATA04::Aerodynamics_heartbeat data; - XNSim::C909::ATA04::Aerodynamics_heartbeat out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/IDL/C909_V1/ATA04/Aerodynamics_input.cxx b/Release/IDL/C909_V1/ATA04/Aerodynamics_input.cxx index 815dc76..464098a 100644 --- a/Release/IDL/C909_V1/ATA04/Aerodynamics_input.cxx +++ b/Release/IDL/C909_V1/ATA04/Aerodynamics_input.cxx @@ -1,4 +1,5 @@ #include "Aerodynamics_input.hpp" +const std::string XNSim::C909::ATA04::Aerodynamics_input_Interface::topic_name = "XNSim::C909::ATA04::Aerodynamics_input"; namespace XNSim::C909::ATA04 { Aerodynamics_input_Interface::Aerodynamics_input_Interface() diff --git a/Release/IDL/C909_V1/ATA04/Aerodynamics_input.hpp b/Release/IDL/C909_V1/ATA04/Aerodynamics_input.hpp index 9294d99..8b51c5e 100644 --- a/Release/IDL/C909_V1/ATA04/Aerodynamics_input.hpp +++ b/Release/IDL/C909_V1/ATA04/Aerodynamics_input.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class Aerodynamics_input_Interface final : public XNDDSInterface +class Aerodynamics_input_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::Aerodynamics_input; + using DDSPubSubType = XNSim::C909::ATA04::Aerodynamics_inputPubSubType; + static const std::string topic_name; Aerodynamics_input_Interface(); virtual ~Aerodynamics_input_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -81,8 +84,8 @@ public: assign_value_set(data.l_04_i_aerocomac_kice_f8(), model_data->l_04_i_aerocomac_kice_f8); assign_value_set(data.l_04_i_aerocomac_alt_agl_f8(), model_data->l_04_i_aerocomac_alt_agl_f8); } -private: - XNSim::C909::ATA04::Aerodynamics_input data; - XNSim::C909::ATA04::Aerodynamics_input out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/IDL/C909_V1/ATA04/Aerodynamics_output.cxx b/Release/IDL/C909_V1/ATA04/Aerodynamics_output.cxx index b1c2df3..dbba4ad 100644 --- a/Release/IDL/C909_V1/ATA04/Aerodynamics_output.cxx +++ b/Release/IDL/C909_V1/ATA04/Aerodynamics_output.cxx @@ -1,4 +1,5 @@ #include "Aerodynamics_output.hpp" +const std::string XNSim::C909::ATA04::Aerodynamics_output_Interface::topic_name = "XNSim::C909::ATA04::Aerodynamics_output"; namespace XNSim::C909::ATA04 { Aerodynamics_output_Interface::Aerodynamics_output_Interface() diff --git a/Release/IDL/C909_V1/ATA04/Aerodynamics_output.hpp b/Release/IDL/C909_V1/ATA04/Aerodynamics_output.hpp index b8c813e..0fa91c6 100644 --- a/Release/IDL/C909_V1/ATA04/Aerodynamics_output.hpp +++ b/Release/IDL/C909_V1/ATA04/Aerodynamics_output.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class Aerodynamics_output_Interface final : public XNDDSInterface +class Aerodynamics_output_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::Aerodynamics_output; + using DDSPubSubType = XNSim::C909::ATA04::Aerodynamics_outputPubSubType; + static const std::string topic_name; Aerodynamics_output_Interface(); virtual ~Aerodynamics_output_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -53,8 +56,8 @@ public: assign_value_set(data.l_04_o_aerocomac_cy_f8(), model_data->l_04_o_aerocomac_cy_f8); assign_value_set(data.l_04_o_aerocomac_cn_f8(), model_data->l_04_o_aerocomac_cn_f8); } -private: - XNSim::C909::ATA04::Aerodynamics_output data; - XNSim::C909::ATA04::Aerodynamics_output out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/IDL/C909_V1/ATA04/GroundHandling_heartbeat.cxx b/Release/IDL/C909_V1/ATA04/GroundHandling_heartbeat.cxx index 76df9ba..d659ecb 100644 --- a/Release/IDL/C909_V1/ATA04/GroundHandling_heartbeat.cxx +++ b/Release/IDL/C909_V1/ATA04/GroundHandling_heartbeat.cxx @@ -1,4 +1,5 @@ #include "GroundHandling_heartbeat.hpp" +const std::string XNSim::C909::ATA04::GroundHandling_heartbeat_Interface::topic_name = "XNSim::C909::ATA04::GroundHandling_heartbeat"; namespace XNSim::C909::ATA04 { GroundHandling_heartbeat_Interface::GroundHandling_heartbeat_Interface() diff --git a/Release/IDL/C909_V1/ATA04/GroundHandling_heartbeat.hpp b/Release/IDL/C909_V1/ATA04/GroundHandling_heartbeat.hpp index 87cdf70..c55294c 100644 --- a/Release/IDL/C909_V1/ATA04/GroundHandling_heartbeat.hpp +++ b/Release/IDL/C909_V1/ATA04/GroundHandling_heartbeat.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class GroundHandling_heartbeat_Interface final : public XNDDSInterface +class GroundHandling_heartbeat_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::GroundHandling_heartbeat; + using DDSPubSubType = XNSim::C909::ATA04::GroundHandling_heartbeatPubSubType; + static const std::string topic_name; GroundHandling_heartbeat_Interface(); virtual ~GroundHandling_heartbeat_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -29,8 +32,8 @@ public: clearOutData(); assign_value_set(data.groundhandling_model_heartbeat(), model_data->groundhandling_model_heartbeat); } -private: - XNSim::C909::ATA04::GroundHandling_heartbeat data; - XNSim::C909::ATA04::GroundHandling_heartbeat out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/IDL/C909_V1/ATA04/GroundHandling_input.cxx b/Release/IDL/C909_V1/ATA04/GroundHandling_input.cxx index a4ffced..f7061c9 100644 --- a/Release/IDL/C909_V1/ATA04/GroundHandling_input.cxx +++ b/Release/IDL/C909_V1/ATA04/GroundHandling_input.cxx @@ -1,4 +1,5 @@ #include "GroundHandling_input.hpp" +const std::string XNSim::C909::ATA04::GroundHandling_input_Interface::topic_name = "XNSim::C909::ATA04::GroundHandling_input"; namespace XNSim::C909::ATA04 { GroundHandling_input_Interface::GroundHandling_input_Interface() diff --git a/Release/IDL/C909_V1/ATA04/GroundHandling_input.hpp b/Release/IDL/C909_V1/ATA04/GroundHandling_input.hpp index d94cf0b..cc6cc10 100644 --- a/Release/IDL/C909_V1/ATA04/GroundHandling_input.hpp +++ b/Release/IDL/C909_V1/ATA04/GroundHandling_input.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class GroundHandling_input_Interface final : public XNDDSInterface +class GroundHandling_input_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::GroundHandling_input; + using DDSPubSubType = XNSim::C909::ATA04::GroundHandling_inputPubSubType; + static const std::string topic_name; GroundHandling_input_Interface(); virtual ~GroundHandling_input_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -105,8 +108,8 @@ public: assign_value_set(data.l_04_i_gdcomac_psi_deg_f8(), model_data->l_04_i_gdcomac_psi_deg_f8); assign_value_set(data.l_04_i_gdcomac_resetint_l1(), model_data->l_04_i_gdcomac_resetint_l1); } -private: - XNSim::C909::ATA04::GroundHandling_input data; - XNSim::C909::ATA04::GroundHandling_input out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/IDL/C909_V1/ATA04/GroundHandling_output.cxx b/Release/IDL/C909_V1/ATA04/GroundHandling_output.cxx index dac051e..4ed4219 100644 --- a/Release/IDL/C909_V1/ATA04/GroundHandling_output.cxx +++ b/Release/IDL/C909_V1/ATA04/GroundHandling_output.cxx @@ -1,4 +1,5 @@ #include "GroundHandling_output.hpp" +const std::string XNSim::C909::ATA04::GroundHandling_output_Interface::topic_name = "XNSim::C909::ATA04::GroundHandling_output"; namespace XNSim::C909::ATA04 { GroundHandling_output_Interface::GroundHandling_output_Interface() diff --git a/Release/IDL/C909_V1/ATA04/GroundHandling_output.hpp b/Release/IDL/C909_V1/ATA04/GroundHandling_output.hpp index 8b5aefa..e3e78cd 100644 --- a/Release/IDL/C909_V1/ATA04/GroundHandling_output.hpp +++ b/Release/IDL/C909_V1/ATA04/GroundHandling_output.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class GroundHandling_output_Interface final : public XNDDSInterface +class GroundHandling_output_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::GroundHandling_output; + using DDSPubSubType = XNSim::C909::ATA04::GroundHandling_outputPubSubType; + static const std::string topic_name; GroundHandling_output_Interface(); virtual ~GroundHandling_output_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -95,8 +98,8 @@ public: assign_value_set(data.l_04_o_gdcomac_wor_par_f8(), model_data->l_04_o_gdcomac_wor_par_f8); assign_value_set(data.l_04_o_gdcomac_nd_f8(), model_data->l_04_o_gdcomac_nd_f8); } -private: - XNSim::C909::ATA04::GroundHandling_output data; - XNSim::C909::ATA04::GroundHandling_output out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/IDL/C909_V1/ATA04/WeightBalance_heartbeat.cxx b/Release/IDL/C909_V1/ATA04/WeightBalance_heartbeat.cxx index a344d46..b40f815 100644 --- a/Release/IDL/C909_V1/ATA04/WeightBalance_heartbeat.cxx +++ b/Release/IDL/C909_V1/ATA04/WeightBalance_heartbeat.cxx @@ -1,4 +1,5 @@ #include "WeightBalance_heartbeat.hpp" +const std::string XNSim::C909::ATA04::WeightBalance_heartbeat_Interface::topic_name = "XNSim::C909::ATA04::WeightBalance_heartbeat"; namespace XNSim::C909::ATA04 { WeightBalance_heartbeat_Interface::WeightBalance_heartbeat_Interface() diff --git a/Release/IDL/C909_V1/ATA04/WeightBalance_heartbeat.hpp b/Release/IDL/C909_V1/ATA04/WeightBalance_heartbeat.hpp index 81c23b6..833306c 100644 --- a/Release/IDL/C909_V1/ATA04/WeightBalance_heartbeat.hpp +++ b/Release/IDL/C909_V1/ATA04/WeightBalance_heartbeat.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class WeightBalance_heartbeat_Interface final : public XNDDSInterface +class WeightBalance_heartbeat_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::WeightBalance_heartbeat; + using DDSPubSubType = XNSim::C909::ATA04::WeightBalance_heartbeatPubSubType; + static const std::string topic_name; WeightBalance_heartbeat_Interface(); virtual ~WeightBalance_heartbeat_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -29,8 +32,8 @@ public: clearOutData(); assign_value_set(data.weightbody_model_heartbeat(), model_data->weightbody_model_heartbeat); } -private: - XNSim::C909::ATA04::WeightBalance_heartbeat data; - XNSim::C909::ATA04::WeightBalance_heartbeat out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/IDL/C909_V1/ATA04/WeightBalance_input.cxx b/Release/IDL/C909_V1/ATA04/WeightBalance_input.cxx index 95c883f..c3af0d0 100644 --- a/Release/IDL/C909_V1/ATA04/WeightBalance_input.cxx +++ b/Release/IDL/C909_V1/ATA04/WeightBalance_input.cxx @@ -1,4 +1,5 @@ #include "WeightBalance_input.hpp" +const std::string XNSim::C909::ATA04::WeightBalance_input_Interface::topic_name = "XNSim::C909::ATA04::WeightBalance_input"; namespace XNSim::C909::ATA04 { WeightBalance_input_Interface::WeightBalance_input_Interface() diff --git a/Release/IDL/C909_V1/ATA04/WeightBalance_input.hpp b/Release/IDL/C909_V1/ATA04/WeightBalance_input.hpp index 48d27fe..4848025 100644 --- a/Release/IDL/C909_V1/ATA04/WeightBalance_input.hpp +++ b/Release/IDL/C909_V1/ATA04/WeightBalance_input.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class WeightBalance_input_Interface final : public XNDDSInterface +class WeightBalance_input_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::WeightBalance_input; + using DDSPubSubType = XNSim::C909::ATA04::WeightBalance_inputPubSubType; + static const std::string topic_name; WeightBalance_input_Interface(); virtual ~WeightBalance_input_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -73,8 +76,8 @@ public: assign_value_set(data.l_04_i_wbcomac_phi_deg_f8(), model_data->l_04_i_wbcomac_phi_deg_f8); assign_value_set(data.l_04_i_wbcomac_psi_deg_f8(), model_data->l_04_i_wbcomac_psi_deg_f8); } -private: - XNSim::C909::ATA04::WeightBalance_input data; - XNSim::C909::ATA04::WeightBalance_input out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/IDL/C909_V1/ATA04/WeightBalance_output.cxx b/Release/IDL/C909_V1/ATA04/WeightBalance_output.cxx index 2f76b3c..a6772cc 100644 --- a/Release/IDL/C909_V1/ATA04/WeightBalance_output.cxx +++ b/Release/IDL/C909_V1/ATA04/WeightBalance_output.cxx @@ -1,4 +1,5 @@ #include "WeightBalance_output.hpp" +const std::string XNSim::C909::ATA04::WeightBalance_output_Interface::topic_name = "XNSim::C909::ATA04::WeightBalance_output"; namespace XNSim::C909::ATA04 { WeightBalance_output_Interface::WeightBalance_output_Interface() diff --git a/Release/IDL/C909_V1/ATA04/WeightBalance_output.hpp b/Release/IDL/C909_V1/ATA04/WeightBalance_output.hpp index 4aab68b..1f9a580 100644 --- a/Release/IDL/C909_V1/ATA04/WeightBalance_output.hpp +++ b/Release/IDL/C909_V1/ATA04/WeightBalance_output.hpp @@ -3,9 +3,12 @@ #include "XNCore/XNDDSInterface.h" namespace XNSim::C909::ATA04 { -class WeightBalance_output_Interface final : public XNDDSInterface +class WeightBalance_output_Interface : public XNDDSInterface { public: + using DDSType = XNSim::C909::ATA04::WeightBalance_output; + using DDSPubSubType = XNSim::C909::ATA04::WeightBalance_outputPubSubType; + static const std::string topic_name; WeightBalance_output_Interface(); virtual ~WeightBalance_output_Interface(); virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override; @@ -139,8 +142,8 @@ public: assign_value_set(data.l_04_o_wbcomac_max_zfw_f4(), model_data->l_04_o_wbcomac_max_zfw_f4); assign_value_set(data.l_04_o_wbcomac_max_zfwcg_f4(), model_data->l_04_o_wbcomac_max_zfwcg_f4); } -private: - XNSim::C909::ATA04::WeightBalance_output data; - XNSim::C909::ATA04::WeightBalance_output out_data; +protected: + DDSType data; + DDSType out_data; }; } diff --git a/Release/Models/libXNGroundHandling.so.1.0.0.0 b/Release/Models/libXNGroundHandling.so.1.0.0.0 index 26cf2bd..3cf8e1d 100644 Binary files a/Release/Models/libXNGroundHandling.so.1.0.0.0 and b/Release/Models/libXNGroundHandling.so.1.0.0.0 differ diff --git a/Release/XNEngine b/Release/XNEngine index c35cdc6..da256f9 100755 Binary files a/Release/XNEngine and b/Release/XNEngine differ diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db index 5ee22e7..fb6ee21 100644 Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ diff --git a/XNCore/CMakeLists.txt b/XNCore/CMakeLists.txt index 9d0efd4..d07579b 100755 --- a/XNCore/CMakeLists.txt +++ b/XNCore/CMakeLists.txt @@ -79,6 +79,7 @@ target_link_libraries(XNCore PRIVATE OpenSSL::SSL OpenSSL::Crypto nlohmann_json + sqlite3 dl ) diff --git a/XNInterfaceGenServer/DDSInterfaceGen.cpp b/XNInterfaceGenServer/DDSInterfaceGen.cpp index aaecfd5..142aa1a 100644 --- a/XNInterfaceGenServer/DDSInterfaceGen.cpp +++ b/XNInterfaceGenServer/DDSInterfaceGen.cpp @@ -44,9 +44,12 @@ bool DDSInterfaceGen::generateDDSInterfaceHpp(const std::string &nameSpace, hppFile << "namespace " << nameSpace << std::endl; hppFile << "{" << std::endl; // 3. 写入类声明 - hppFile << "class " << className << " final : public XNDDSInterface" << std::endl; + hppFile << "class " << className << " : public XNDDSInterface" << std::endl; hppFile << "{" << std::endl; hppFile << "public:" << std::endl; + hppFile << "\t" << "using DDSType = " << topicType << ";" << std::endl; + hppFile << "\t" << "using DDSPubSubType = " << topicType << "PubSubType;" << std::endl; + hppFile << "\t" << "static const std::string topic_name;" << std::endl; // 4. 写入构造函数和析构函数 hppFile << "\t" << className << "();" << std::endl; hppFile << "\t" << "virtual ~" << className << "();" << std::endl; @@ -87,9 +90,9 @@ bool DDSInterfaceGen::generateDDSInterfaceHpp(const std::string &nameSpace, } hppFile << "\t" << "}" << std::endl; // 11. 写入私有成员变量 - hppFile << "" << "private:" << std::endl; - hppFile << "\t" << topicType << " data;" << std::endl; - hppFile << "\t" << topicType << " out_data;" << std::endl; + hppFile << "" << "protected:" << std::endl; + hppFile << "\t" << "DDSType data;" << std::endl; + hppFile << "\t" << "DDSType out_data;" << std::endl; // 12. 写入类声明结束 hppFile << "};" << std::endl; // 13. 写入命名空间结束 @@ -110,6 +113,8 @@ bool DDSInterfaceGen::generateDDSInterfaceCxx(const std::string &nameSpace, // 1. 写入引用头文件 cxxFile << "#include \"" << structName << ".hpp\"" << std::endl; // 2. 写入命名空间 + cxxFile << "const std::string " << nameSpace << "::" << className << "::topic_name = \"" + << topicType << "\";" << std::endl; cxxFile << "namespace " << nameSpace << std::endl; cxxFile << "{" << std::endl; // 3. 写入类构造函数实现 diff --git a/XNMonitorServer/.vscode/settings.json b/XNMonitorServer/.vscode/settings.json index 1f9ba80..fc63933 100644 --- a/XNMonitorServer/.vscode/settings.json +++ b/XNMonitorServer/.vscode/settings.json @@ -69,6 +69,10 @@ "thread": "cpp", "cinttypes": "cpp", "typeindex": "cpp", - "typeinfo": "cpp" + "typeinfo": "cpp", + "any": "cpp", + "forward_list": "cpp", + "fstream": "cpp", + "valarray": "cpp" } } diff --git a/XNMonitorServer/CMakeLists.txt b/XNMonitorServer/CMakeLists.txt index 640907a..68d2658 100644 --- a/XNMonitorServer/CMakeLists.txt +++ b/XNMonitorServer/CMakeLists.txt @@ -20,7 +20,9 @@ else() message(FATAL_ERROR "Environment variable XNCore is not set.") endif() -file(GLOB DDS_XNIDL_SOURCES_CXX "../XNCore/XNIDL/*.cxx") +# file(GLOB DDS_XNIDL_SOURCES_CXX "../XNCore/XNIDL/*.cxx") +include_directories(${XNCore_PATH}/include) +include_directories(${XNCore_PATH}/IDL) find_package(OpenSSL REQUIRED) find_package(nlohmann_json 3.9.1 REQUIRED) @@ -29,7 +31,7 @@ add_library(XNMonitorServer SHARED XNMonitorServer_global.h TopicManager.h TopicManager.cpp - DataReaderListenerImpl.h + XNDataReaderListenerImpl.h TypeDefine.h XNMonitorInterface.h XNMonitorInterface.cpp @@ -39,7 +41,11 @@ add_library(XNMonitorServer SHARED ModelInfoMonitor.cpp SystemControl.h SystemControl.cpp - ${DDS_XNIDL_SOURCES_CXX} + DataMonitor.h + DataMonitorFactory.h + DataMonitorFactory.cpp + DataInjectThread.h + DataInjectThread.cpp ) # 添加头文件搜索路径 @@ -51,6 +57,8 @@ target_link_libraries(XNMonitorServer PRIVATE fastdds OpenSSL::SSL OpenSSL::Crypto + ${XNCore_PATH}/lib/libXNCore.so + ${XNCore_PATH}/lib/libC909_V1_Interface.so ) target_compile_definitions(XNMonitorServer PRIVATE XNMONITOR_SERVER_LIBRARY) diff --git a/XNMonitorServer/DataInjectThread.cpp b/XNMonitorServer/DataInjectThread.cpp new file mode 100644 index 0000000..11ff55b --- /dev/null +++ b/XNMonitorServer/DataInjectThread.cpp @@ -0,0 +1,72 @@ +#include "DataInjectThread.h" + +DataInjectThread::DataInjectThread(DataMonitorBasePtr dataMonitor, + std::unordered_map data, + double frequency) + : m_dataMonitor(dataMonitor), m_data(data), m_frequency(frequency), m_running(false) +{ +} + +DataInjectThread::~DataInjectThread() +{ + stop(); +} + +void DataInjectThread::start() +{ + std::lock_guard lock(m_mutex); + if (!m_running) { + m_running = true; + m_thread = std::thread(&DataInjectThread::threadFunc, this); + } +} + +void DataInjectThread::stop() +{ + { + std::lock_guard lock(m_mutex); + if (m_running) { + m_running = false; + m_cv.notify_all(); + } + } + + if (m_thread.joinable()) { + m_thread.join(); + } +} + +void DataInjectThread::updateData(const std::unordered_map &data) +{ + std::lock_guard lock(m_mutex); + m_data = data; +} + +void DataInjectThread::updateFrequency(double frequency) +{ + m_frequency = frequency; +} + +void DataInjectThread::threadFunc() +{ + while (m_running) { + std::unordered_map currentData; + { + std::lock_guard lock(m_mutex); + currentData = m_data; + } + + if (m_dataMonitor) { + m_dataMonitor->setDataByString(currentData); + } + + // 使用当前频率计算睡眠时间 + double currentFreq = m_frequency; + std::this_thread::sleep_for( + std::chrono::milliseconds(static_cast(1000 / currentFreq))); + + // 使用条件变量等待,避免CPU空转 + std::unique_lock lock(m_mutex); + m_cv.wait_for(lock, std::chrono::milliseconds(100), [this] { return !m_running; }); + } +} \ No newline at end of file diff --git a/XNMonitorServer/DataInjectThread.h b/XNMonitorServer/DataInjectThread.h new file mode 100644 index 0000000..e592505 --- /dev/null +++ b/XNMonitorServer/DataInjectThread.h @@ -0,0 +1,67 @@ +#pragma once + +#include "DataMonitor.h" +#include +#include +#include +#include + +/** + * @brief 数据注入线程类,用于持续向数据监控器注入数据 + */ +class DataInjectThread +{ +public: + /** + * @brief 构造函数 + * @param dataMonitor 数据监控器指针 + * @param data 要注入的数据 + * @param frequency 注入频率(Hz) + */ + DataInjectThread(DataMonitorBasePtr dataMonitor, + std::unordered_map data, double frequency); + + /** + * @brief 析构函数 + */ + ~DataInjectThread(); + + /** + * @brief 启动数据注入线程 + */ + void start(); + + /** + * @brief 停止数据注入线程 + */ + void stop(); + + /** + * @brief 更新要注入的数据 + * @param data 新的数据 + */ + void updateData(const std::unordered_map &data); + + /** + * @brief 更新注入频率 + * @param frequency 新的频率(Hz) + */ + void updateFrequency(double frequency); + +private: + /** + * @brief 线程执行函数 + */ + void threadFunc(); + +private: + std::thread m_thread; ///< 数据注入线程 + std::atomic m_running; ///< 线程运行标志 + std::mutex m_mutex; ///< 互斥锁 + std::condition_variable m_cv; ///< 条件变量 + DataMonitorBasePtr m_dataMonitor; ///< 数据监控器指针 + std::unordered_map m_data; ///< 要注入的数据 + std::atomic m_frequency; ///< 注入频率 +}; + +using DataInjectThreadPtr = std::shared_ptr; \ No newline at end of file diff --git a/XNMonitorServer/DataMonitor.h b/XNMonitorServer/DataMonitor.h new file mode 100644 index 0000000..68d82bb --- /dev/null +++ b/XNMonitorServer/DataMonitor.h @@ -0,0 +1,80 @@ +#pragma once + +#include "XNMonitorServer_global.h" +#include "TypeDefine.h" +#include "TopicManager.h" + +#define THISUNUSED(x) (void)(x) + +class XNFramework; +using XNFrameworkPtr = std::shared_ptr; + +class XNMONITORSERVER_EXPORT DataMonitorBase +{ +public: + virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) = 0; + virtual std::unordered_map + getStringData(std::vector varNames) = 0; + virtual void setDataByString(std::unordered_map data) = 0; + virtual bool isInitialized() { return _isInitialized; } + +protected: + bool _isInitialized = false; +}; + +template +class XNMONITORSERVER_EXPORT DataMonitorProduct : public T, public DataMonitorBase +{ +public: + DataMonitorProduct() : T() {}; + virtual ~DataMonitorProduct() + { + try { + if (auto topicManager = TopicManager::Instance()) { + topicManager->unregisterSubscriber(T::topic_name); + topicManager->unregisterPublisher(T::topic_name); + } + } catch (...) { + return; + } + _isInitialized = false; + }; + + virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override + { + THISUNUSED(framework); + THISUNUSED(modelId); + THISUNUSED(DDS_type); + XNDDSErrorCode ret = + TopicManager::Instance()->registerSubscriber( + T::topic_name, + std::bind(&DataMonitorProduct::inputDataListener, this, std::placeholders::_1)); + if (ret != XNDDSErrorCode::SUCCESS) { + return; + } + ret = TopicManager::Instance()->registerPublisher( + T::topic_name, this->dataWriter); + if (ret != XNDDSErrorCode::SUCCESS || this->dataWriter == nullptr) { + return; + } + _isInitialized = true; + }; + + virtual std::unordered_map + getStringData(std::vector varNames) override + { + if (!isInitialized()) { + return {}; + } + return T::getStringData(varNames); + } + virtual void setDataByString(std::unordered_map data) override + { + if (!isInitialized()) { + return; + } + T::setDataByString(data); + } +}; + +using DataMonitorBasePtr = std::shared_ptr; diff --git a/XNMonitorServer/DataMonitorFactory.cpp b/XNMonitorServer/DataMonitorFactory.cpp new file mode 100644 index 0000000..d142fe0 --- /dev/null +++ b/XNMonitorServer/DataMonitorFactory.cpp @@ -0,0 +1,6 @@ +#include "DataMonitorFactory.h" + +// 静态成员初始化 +std::mutex DataMonitorFactory::mutex_; + +std::unordered_map DataMonitorFactory::instances_; \ No newline at end of file diff --git a/XNMonitorServer/DataMonitorFactory.h b/XNMonitorServer/DataMonitorFactory.h new file mode 100644 index 0000000..6749777 --- /dev/null +++ b/XNMonitorServer/DataMonitorFactory.h @@ -0,0 +1,118 @@ +#pragma once + +#include "XNMonitorServer_global.h" +#include "DataMonitor.h" + +//接口头文件 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief DataMonitor工厂类,用于创建不同类型的DataMonitor实例 + */ +class XNMONITORSERVER_EXPORT DataMonitorFactory +{ +public: + static DataMonitorBasePtr GetInstance(const std::string &interfaceName) + { + if (interfaceName == "Aerodynamics_heartbeat") { + return GetInstance(); + } else if (interfaceName == "Aerodynamics_input") { + return GetInstance(); + } else if (interfaceName == "Aerodynamics_output") { + return GetInstance(); + } else if (interfaceName == "GroundHandling_heartbeat") { + return GetInstance(); + } else if (interfaceName == "GroundHandling_input") { + return GetInstance(); + } else if (interfaceName == "GroundHandling_output") { + return GetInstance(); + } else if (interfaceName == "WeightBalance_heartbeat") { + return GetInstance(); + } else if (interfaceName == "WeightBalance_input") { + return GetInstance(); + } else if (interfaceName == "WeightBalance_output") { + return GetInstance(); + } + return nullptr; + } + + static void ReleaseInstance(const std::string &interfaceName) + { + if (interfaceName == "Aerodynamics_heartbeat") { + ReleaseInstance(); + } else if (interfaceName == "Aerodynamics_input") { + ReleaseInstance(); + } else if (interfaceName == "Aerodynamics_output") { + ReleaseInstance(); + } else if (interfaceName == "GroundHandling_heartbeat") { + ReleaseInstance(); + } else if (interfaceName == "GroundHandling_input") { + ReleaseInstance(); + } else if (interfaceName == "GroundHandling_output") { + ReleaseInstance(); + } else if (interfaceName == "WeightBalance_heartbeat") { + ReleaseInstance(); + } else if (interfaceName == "WeightBalance_input") { + ReleaseInstance(); + } else if (interfaceName == "WeightBalance_output") { + ReleaseInstance(); + } + } + +private: + /** + * @brief 创建DataMonitor实例 + * @param framework 框架指针 + * @param modelId 模型ID + * @param DDS_type DDS类型 + * @return 返回创建的DataMonitor实例的智能指针 + */ + template + static DataMonitorBasePtr GetInstance() + { + std::lock_guard lock(mutex_); + + // 使用type_index作为键,更可靠的类型标识 + std::type_index typeIndex(typeid(T)); + + // 检查是否已存在实例 + auto it = instances_.find(typeIndex); + if (it != instances_.end()) { + return it->second; + } + + // 创建新实例 + auto monitor = std::make_shared>(); + instances_[typeIndex] = monitor; + return monitor; + } + + /** + * @brief 释放指定类型的实例 + */ + template + static void ReleaseInstance() + { + std::lock_guard lock(mutex_); + std::type_index typeIndex(typeid(T)); + if (instances_.find(typeIndex) == instances_.end()) { + return; + } + instances_.erase(typeIndex); + } + +private: + DataMonitorFactory() = delete; + ~DataMonitorFactory() = delete; + + static std::mutex mutex_; + static std::unordered_map instances_; +}; diff --git a/XNMonitorServer/ModelInfoMonitor.h b/XNMonitorServer/ModelInfoMonitor.h index 6b13493..7c9a4fb 100644 --- a/XNMonitorServer/ModelInfoMonitor.h +++ b/XNMonitorServer/ModelInfoMonitor.h @@ -1,7 +1,7 @@ #pragma once #include "TopicManager.h" -#include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp" +#include class XNMONITORSERVER_EXPORT ModelInfoMonitor { diff --git a/XNMonitorServer/SystemControl.h b/XNMonitorServer/SystemControl.h index eb946fc..0694d43 100644 --- a/XNMonitorServer/SystemControl.h +++ b/XNMonitorServer/SystemControl.h @@ -3,7 +3,7 @@ #include "XNMonitorServer_global.h" #include "TypeDefine.h" #include "TopicManager.h" -#include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp" +#include class XNMONITORSERVER_EXPORT SystemControl { diff --git a/XNMonitorServer/SystemInfoMonitor.h b/XNMonitorServer/SystemInfoMonitor.h index 1ea2684..defa515 100644 --- a/XNMonitorServer/SystemInfoMonitor.h +++ b/XNMonitorServer/SystemInfoMonitor.h @@ -1,7 +1,7 @@ #pragma once #include "TopicManager.h" -#include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp" +#include class XNMONITORSERVER_EXPORT SystemInfoMonitor { diff --git a/XNMonitorServer/TopicManager.h b/XNMonitorServer/TopicManager.h index e5db60b..822d870 100755 --- a/XNMonitorServer/TopicManager.h +++ b/XNMonitorServer/TopicManager.h @@ -11,7 +11,7 @@ #pragma once #include "XNMonitorServer_global.h" -#include "DataReaderListenerImpl.h" +#include "XNDataReaderListenerImpl.h" /** * @brief 主题管理类 @@ -101,10 +101,10 @@ public: { std::lock_guard locker(m_Mutex); if (topics_.find(topicName) == topics_.end()) { - topics_[topicName] = TopicInfo(); // 创建主题信息 - TopicInfo &tmp = topics_[topicName]; // 获取主题信息 - XNTypeSupport typeSupport(new T()); // 创建类型支持 - typeSupport.register_type(m_Participant); // 注册类型 + topics_[topicName] = MonitorTopicInfo(); // 创建主题信息 + MonitorTopicInfo &tmp = topics_[topicName]; // 获取主题信息 + XNTypeSupport typeSupport(new T()); // 创建类型支持 + typeSupport.register_type(m_Participant); // 注册类型 tmp.topic = m_Participant->create_topic(topicName.c_str(), typeSupport.get_type_name(), eprosima::fastdds::dds::TOPIC_QOS_DEFAULT); // 创建主题 @@ -113,7 +113,7 @@ public: return XNDDSErrorCode::TOPIC_CREATE_FAILED; } } - TopicInfo &topicInfo = topics_[topicName]; // 获取主题信息 + MonitorTopicInfo &topicInfo = topics_[topicName]; // 获取主题信息 if (topicInfo.publisher == nullptr) { topicInfo.publisher = m_Participant->create_publisher( eprosima::fastdds::dds::PUBLISHER_QOS_DEFAULT); // 创建发布者 @@ -147,7 +147,7 @@ public: std::lock_guard locker(m_Mutex); auto it = topics_.find(topicName); if (it != topics_.end()) { - TopicInfo &topicInfo = it->second; // 获取主题信息 + MonitorTopicInfo &topicInfo = it->second; // 获取主题信息 if (topicInfo.dataWriter != nullptr) { topicInfo.publisher->delete_datawriter(topicInfo.dataWriter); // 删除数据写入器 topicInfo.dataWriter = nullptr; // 设置数据写入器为空 @@ -177,10 +177,10 @@ public: { std::lock_guard locker(m_Mutex); if (topics_.find(topicName) == topics_.end()) { - topics_[topicName] = TopicInfo(); // 创建主题信息 - TopicInfo &tmp = topics_[topicName]; // 获取主题信息 - XNTypeSupport typeSupport(new T()); // 创建类型支持 - typeSupport.register_type(m_Participant); // 注册类型 + topics_[topicName] = MonitorTopicInfo(); // 创建主题信息 + MonitorTopicInfo &tmp = topics_[topicName]; // 获取主题信息 + XNTypeSupport typeSupport(new T()); // 创建类型支持 + typeSupport.register_type(m_Participant); // 注册类型 tmp.topic = m_Participant->create_topic(topicName.c_str(), typeSupport.get_type_name(), eprosima::fastdds::dds::TOPIC_QOS_DEFAULT); // 创建主题 @@ -189,7 +189,7 @@ public: return XNDDSErrorCode::TOPIC_CREATE_FAILED; // 返回 } } - TopicInfo &topicInfo = topics_[topicName]; // 获取主题信息 + MonitorTopicInfo &topicInfo = topics_[topicName]; // 获取主题信息 if (topicInfo.subscriber == nullptr) { topicInfo.subscriber = m_Participant->create_subscriber( eprosima::fastdds::dds::SUBSCRIBER_QOS_DEFAULT); // 创建订阅者 @@ -202,7 +202,7 @@ public: dataReaderQos.durability().kind = eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS; // 设置数据读取器的持久性策略 topicInfo.listener = - new DataReaderListenerImpl(fun); // 创建数据读取器监听器 + new XNDataReaderListenerImpl(fun); // 创建数据读取器监听器 topicInfo.dataReader = topicInfo.subscriber->create_datareader( topicInfo.topic, dataReaderQos, topicInfo.listener); // 创建数据读取器 if (topicInfo.dataReader == nullptr) { @@ -211,7 +211,7 @@ public: } else { auto oldListener = topicInfo.dataReader->get_listener(); // 获取旧的监听器 topicInfo.listener = - new DataReaderListenerImpl(fun); // 创建新的监听器 + new XNDataReaderListenerImpl(fun); // 创建新的监听器 topicInfo.dataReader->set_listener( topicInfo.listener, eprosima::fastdds::dds::StatusMask::all()); // 设置新的监听器 @@ -229,7 +229,7 @@ public: std::lock_guard locker(m_Mutex); auto it = topics_.find(topicName); if (it != topics_.end()) { - TopicInfo &topicInfo = it->second; // 获取主题信息 + MonitorTopicInfo &topicInfo = it->second; // 获取主题信息 if (topicInfo.dataReader != nullptr) { topicInfo.subscriber->delete_datareader(topicInfo.dataReader); // 删除数据读取器 topicInfo.dataReader = nullptr; // 设置数据读取器为空 @@ -285,7 +285,7 @@ private: /** * @brief 主题映射 */ - std::map topics_; + std::map topics_; /** * @brief 主题访问互斥锁 diff --git a/XNMonitorServer/TypeDefine.h b/XNMonitorServer/TypeDefine.h index b118e0f..eb55a78 100755 --- a/XNMonitorServer/TypeDefine.h +++ b/XNMonitorServer/TypeDefine.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -92,7 +94,7 @@ using json = nlohmann::json; /** * @brief 主题信息 */ -struct TopicInfo { +struct MonitorTopicInfo { /** * @brief 主题 */ diff --git a/XNMonitorServer/DataReaderListenerImpl.h b/XNMonitorServer/XNDataReaderListenerImpl.h similarity index 80% rename from XNMonitorServer/DataReaderListenerImpl.h rename to XNMonitorServer/XNDataReaderListenerImpl.h index 5e3240e..59aaa0d 100755 --- a/XNMonitorServer/DataReaderListenerImpl.h +++ b/XNMonitorServer/XNDataReaderListenerImpl.h @@ -1,5 +1,5 @@ /** - * @file DataReaderListenerImpl.h + * @file XNDataReaderListenerImpl.h * @author jinchao * @brief 数据读取器监听器模板类 * @version 1.0 @@ -17,14 +17,14 @@ * @tparam T 数据类型 */ template -class DataReaderListenerImpl : public XNDataReaderListener +class XNDataReaderListenerImpl : public XNDataReaderListener { public: /** * @brief 构造函数 * @param callback 回调函数 */ - DataReaderListenerImpl(std::function callback) : callback_(callback) {} + XNDataReaderListenerImpl(std::function callback) : callback_(callback) {} /** * @brief 数据可用回调函数 diff --git a/XNMonitorServer/XNMonitorInterface.cpp b/XNMonitorServer/XNMonitorInterface.cpp index 8ba3f74..a9c8acc 100644 --- a/XNMonitorServer/XNMonitorInterface.cpp +++ b/XNMonitorServer/XNMonitorInterface.cpp @@ -6,6 +6,8 @@ #include "SystemInfoMonitor.h" #include "ModelInfoMonitor.h" #include "SystemControl.h" +#include "DataMonitorFactory.h" +#include "DataInjectThread.h" // 全局变量 static bool g_initialized = false; @@ -353,186 +355,252 @@ void XN_StopEngine(char *errorMsg, int errorMsgSize) systemControl->Stop(); } -// // 注册发布者实现 -// XNDDSErrorCode XN_RegisterPublisher(const char *topicName, void **dataWriter) -// { -// if (!g_initialized) { -// SetLastError("Not initialized"); -// return XNDDSErrorCode::NOT_INITIALIZED; -// } +int XN_StartDataMonitor(const char *structName, const int structNameLen, char *errorMsg, + int errorMsgSize) +{ + if (!g_initialized) { + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "DDSMonitor Not Initialized", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return -1; + } + std::string structNameStr(structName, structNameLen); + auto dataMonitor = DataMonitorFactory::GetInstance(structNameStr); + if (dataMonitor == nullptr) { + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "Invalid struct name", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return -1; + } + if (!dataMonitor->isInitialized()) { + dataMonitor->Initialize(nullptr, 0, 0); + } + return 0; +} -// if (!topicName || !dataWriter) { -// SetLastError("Invalid parameters"); -// return XNDDSErrorCode::INVALID_PARAM; -// } +void XN_StopDataMonitor(const char *structName, const int structNameLen, char *errorMsg, + int errorMsgSize) +{ + if (!g_initialized) { + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "DDSMonitor Not Initialized", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return; + } + std::string structNameStr(structName, structNameLen); + DataMonitorFactory::ReleaseInstance(structNameStr); + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "Data Monitor Stopped Successfully", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return; +} -// try { -// auto *writer = -// TopicManager::Instance()->registerPublisher(topicName); -// if (!writer) { -// SetLastError("Failed to create publisher"); -// return XNDDSErrorCode::PUBLISHER_CREATE_FAILED; -// } -// *dataWriter = writer; -// return XNDDSErrorCode::SUCCESS; -// } catch (const std::exception &e) { -// SetLastError(e.what()); -// return XNDDSErrorCode::PUBLISHER_CREATE_FAILED; -// } -// } +int XN_GetDataMonitorInfo(const char *structName, const int structNameLen, + const char *interfaceName, const int interfaceNameLen, char *data, + int dataLen, char *infoMsg, int infoMsgSize) +{ + if (!g_initialized) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "DDSMonitor Not Initialized", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + std::string structNameStr(structName, structNameLen); + auto dataMonitor = DataMonitorFactory::GetInstance(structNameStr); + if (dataMonitor == nullptr) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Invalid interface name", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + if (!dataMonitor->isInitialized()) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Data Monitor Not Initialized", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + std::string interfaceNameStr(interfaceName, interfaceNameLen); + try { + nlohmann::json interfaceNamesJson = nlohmann::json::parse(interfaceNameStr); + if (!interfaceNamesJson.is_array()) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Interface name must be a JSON array", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } -// // 注销发布者实现 -// XNDDSErrorCode XN_UnregisterPublisher(const char *topicName) -// { -// if (!g_initialized) { -// SetLastError("Not initialized"); -// return XNDDSErrorCode::NOT_INITIALIZED; -// } + std::vector interfaceNames; + for (const auto &name : interfaceNamesJson) { + if (!name.is_string()) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Interface name must be a string", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + interfaceNames.push_back(name.get()); + } -// if (!topicName) { -// SetLastError("Invalid parameters"); -// return XNDDSErrorCode::INVALID_PARAM; -// } + std::unordered_map resultData = + dataMonitor->getStringData(interfaceNames); -// try { -// TopicManager::Instance()->unregisterPublisher(topicName); -// return XNDDSErrorCode::SUCCESS; -// } catch (const std::exception &e) { -// SetLastError(e.what()); -// return XNDDSErrorCode::INVALID_PARAM; -// } -// } + nlohmann::json resultJson; + for (const auto &pair : resultData) { + resultJson[pair.first] = pair.second; + } + std::string resultStr = resultJson.dump(); + if (data && dataLen > 0) { + strncpy(data, resultStr.c_str(), dataLen - 1); + data[dataLen - 1] = '\0'; + } + } catch (const nlohmann::json::parse_error &e) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Invalid JSON format", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + return 0; +} -// // 数据写入实现 -// XNDDSErrorCode XN_WriteData(void *dataWriter, const void *data, size_t dataSize) -// { -// if (!g_initialized) { -// SetLastError("Not initialized"); -// return XNDDSErrorCode::NOT_INITIALIZED; -// } +int XN_InjectDataInterface(const char *structName, const int structNameLen, + const char *interfaceNameAndData, const int interfaceNameAndDataLen, + char *infoMsg, int infoMsgSize) +{ + if (!g_initialized) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "DDSMonitor Not Initialized", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + std::string structNameStr(structName, structNameLen); + auto dataMonitor = DataMonitorFactory::GetInstance(structNameStr); + if (dataMonitor == nullptr) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Invalid interface name", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + if (!dataMonitor->isInitialized()) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Data Monitor Not Initialized", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + std::string interfaceNameStr(interfaceNameAndData, interfaceNameAndDataLen); + try { + nlohmann::json interfaceNames = nlohmann::json::parse(interfaceNameStr); + std::unordered_map dataMap; + for (const auto &[key, value] : interfaceNames.items()) { + dataMap[key] = value.get(); + } + dataMonitor->setDataByString(dataMap); + } catch (const nlohmann::json::parse_error &e) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Invalid JSON format", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + return 0; +} -// if (!dataWriter || !data || dataSize != sizeof(XNRuntimeData)) { -// SetLastError("Invalid parameters"); -// return XNDDSErrorCode::INVALID_PARAM; -// } +std::unordered_map g_dataInjectThreads; -// try { -// auto *writer = static_cast(dataWriter); -// if (writer->write(data) != eprosima::fastdds::dds::RETCODE_OK) { -// SetLastError("Failed to write data"); -// return XNDDSErrorCode::INVALID_PARAM; -// } -// return XNDDSErrorCode::SUCCESS; -// } catch (const std::exception &e) { -// SetLastError(e.what()); -// return XNDDSErrorCode::INVALID_PARAM; -// } -// } +int XN_StartInjectContinuous(const char *structName, const int structNameLen, + const char *interfaceNameAndData, const int interfaceNameAndDataLen, + double frequency, char *infoMsg, int infoMsgSize) +{ + if (!g_initialized) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "DDSMonitor Not Initialized", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + std::string structNameStr(structName, structNameLen); + auto dataMonitor = DataMonitorFactory::GetInstance(structNameStr); + if (dataMonitor == nullptr) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Invalid Struct Name", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + if (!dataMonitor->isInitialized()) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Data Monitor Not Initialized", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + std::string interfaceNameStr(interfaceNameAndData, interfaceNameAndDataLen); + try { + nlohmann::json interfaceNames = nlohmann::json::parse(interfaceNameStr); + std::unordered_map dataMap; + for (const auto &[key, value] : interfaceNames.items()) { + dataMap[key] = value.get(); + } + auto it = g_dataInjectThreads.find(structNameStr); + if (it != g_dataInjectThreads.end()) { + it->second->updateData(dataMap); + it->second->updateFrequency(frequency); + } else { + DataInjectThreadPtr dataInjectThread = + std::make_shared(dataMonitor, dataMap, frequency); + dataInjectThread->start(); + g_dataInjectThreads[structNameStr] = dataInjectThread; + } + } catch (const nlohmann::json::parse_error &e) { + if (infoMsg && infoMsgSize > 0) { + strncpy(infoMsg, "Invalid JSON format", infoMsgSize - 1); + infoMsg[infoMsgSize - 1] = '\0'; + } + return -1; + } + return 0; +} -// // 订阅回调包装器 -// class SubscriberCallbackWrapper -// { -// public: -// SubscriberCallbackWrapper(XNDataCallback callback, void *userData) -// : callback_(callback), userData_(userData) -// { -// } +int XN_StopInjectContinuous(const char *structName, const int structNameLen, char *infoMsg, + int infoMsgSize) +{ + std::string structNameStr(structName, structNameLen); + auto it = g_dataInjectThreads.find(structNameStr); + if (it != g_dataInjectThreads.end()) { + it->second->stop(); + g_dataInjectThreads.erase(it); + } + return 0; +} -// void operator()(const XNRuntimeData &data) -// { -// if (callback_) { -// callback_(&data, sizeof(XNRuntimeData), userData_); -// } -// } +// 从csv文件中注入数据接口 +int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv(const char *structName, + const int structNameLen, + const char *csvFilePath, + const int csvFilePathLen, char *infoMsg, + int infoMsgSize) +{ + // TODO: 从csv文件中注入数据接口 + return -1; +} -// private: -// XNDataCallback callback_; -// void *userData_; -// }; - -// // 注册订阅者实现 -// XNDDSErrorCode XN_RegisterSubscriber(const char *topicName, XNDataCallback callback, void *userData) -// { -// if (!g_initialized) { -// SetLastError("Not initialized"); -// return XNDDSErrorCode::NOT_INITIALIZED; -// } - -// if (!topicName || !callback) { -// SetLastError("Invalid parameters"); -// return XNDDSErrorCode::INVALID_PARAM; -// } - -// try { -// // auto wrapper = std::make_shared(callback, userData); -// // TopicManager::Instance()->registerSubscriber( -// // topicName, [wrapper](const XNRuntimeData &data) { (*wrapper)(data); }); -// return XNDDSErrorCode::SUCCESS; -// } catch (const std::exception &e) { -// SetLastError(e.what()); -// return XNDDSErrorCode::SUBSCRIBER_CREATE_FAILED; -// } -// } - -// // 注销订阅者实现 -// XNDDSErrorCode XN_UnregisterSubscriber(const char *topicName) -// { -// if (!g_initialized) { -// SetLastError("Not initialized"); -// return XNDDSErrorCode::NOT_INITIALIZED; -// } - -// if (!topicName) { -// SetLastError("Invalid parameters"); -// return XNDDSErrorCode::INVALID_PARAM; -// } - -// try { -// TopicManager::Instance()->unregisterSubscriber(topicName); -// return XNDDSErrorCode::SUCCESS; -// } catch (const std::exception &e) { -// SetLastError(e.what()); -// return XNDDSErrorCode::INVALID_PARAM; -// } -// } - -// // 获取运行时数据实现 -// XNDDSErrorCode XN_GetRuntimeData(const char *name, XNRuntimeData *data) -// { -// if (!g_initialized) { -// SetLastError("Not initialized"); -// return XNDDSErrorCode::NOT_INITIALIZED; -// } - -// if (!name || !data) { -// SetLastError("Invalid parameters"); -// return XNDDSErrorCode::INVALID_PARAM; -// } - -// // TODO: 实现从数据存储中获取运行时数据 -// return XNDDSErrorCode::SUCCESS; -// } - -// // 设置运行时数据实现 -// XNDDSErrorCode XN_SetRuntimeData(const char *name, const XNRuntimeData *data) -// { -// if (!g_initialized) { -// SetLastError("Not initialized"); -// return XNDDSErrorCode::NOT_INITIALIZED; -// } - -// if (!name || !data) { -// SetLastError("Invalid parameters"); -// return XNDDSErrorCode::INVALID_PARAM; -// } - -// // TODO: 实现将运行时数据保存到数据存储中 -// return XNDDSErrorCode::SUCCESS; -// } - -// // 获取最后错误信息实现 -// const char *XN_GetLastError() -// { -// std::lock_guard lock(g_errorMutex); -// return g_lastError.c_str(); -// } \ No newline at end of file +int XNMONITORSERVER_EXPORT XN_StartCollectData(const char *structName, const int structNameLen, + const char *interfaceName, + const int interfaceNameLen, const char *csvFilePath, + const int csvFilePathLen, char *infoMsg, + int infoMsgSize) +{ + // TODO: 持续采集数据并保存到csv文件接口 + return -1; +} \ No newline at end of file diff --git a/XNMonitorServer/XNMonitorInterface.h b/XNMonitorServer/XNMonitorInterface.h index 07ba335..f72faaf 100644 --- a/XNMonitorServer/XNMonitorInterface.h +++ b/XNMonitorServer/XNMonitorInterface.h @@ -12,67 +12,234 @@ extern "C" { #endif - // 初始化函数 + /** + * @brief 初始化DDS监控服务器 + * @param domainId 域ID + * @param domainIdLen 域ID长度 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ int XNMONITORSERVER_EXPORT XN_Initialize(const char *domainId, int domainIdLen, char *errorMsg, int errorMsgSize); - // 清理函数 + /** + * @brief 清理DDS监控服务器 + */ void XNMONITORSERVER_EXPORT XN_Cleanup(); - // 启动监控系统信息 + //******************** 系统信息监控 ********************* + + /** + * @brief 启动监控系统信息 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ int XNMONITORSERVER_EXPORT XN_StartMonitorSystemInfo(char *errorMsg, int errorMsgSize); - // 获取系统信息 + /** + * @brief 获取系统信息 + * @param infoMsg 系统信息 + * @param infoMsgSize 系统信息大小 + * @return 0: 成功, -1: 失败 + */ int XNMONITORSERVER_EXPORT XN_GetSystemInfo(char *infoMsg, int infoMsgSize); - // 获取所有线程信息 - int XNMONITORSERVER_EXPORT XN_GetAllThreadInfo(char *infoMsg, int infoMsgSize); - - // 停止监控系统信息 + /** + * @brief 停止监控系统信息 + */ void XNMONITORSERVER_EXPORT XN_StopMonitorSystemInfo(); - // 启动监控模型信息 + //******************** 线程信息监控 ********************* + + /** + * @brief 获取所有线程信息 + * @param infoMsg 线程信息 + * @param infoMsgSize 线程信息大小 + * @return 0: 成功, -1: 失败 + */ + int XNMONITORSERVER_EXPORT XN_GetAllThreadInfo(char *infoMsg, int infoMsgSize); + + //******************** 模型信息监控 ********************* + + /** + * @brief 启动监控模型信息 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ int XNMONITORSERVER_EXPORT XN_StartMonitorModelInfo(char *errorMsg, int errorMsgSize); - // 获取模型信息 + /** + * @brief 获取模型信息 + * @param infoMsg 模型信息 + * @param infoMsgSize 模型信息大小 + * @return 0: 成功, -1: 失败 + */ int XNMONITORSERVER_EXPORT XN_GetModelInfo(char *infoMsg, int infoMsgSize); - // 停止监控模型信息 + /** + * @brief 停止监控模型信息 + */ void XNMONITORSERVER_EXPORT XN_StopMonitorModelInfo(); - // 初始化引擎控制 + //******************** 引擎控制 ********************* + + /** + * @brief 初始化引擎控制 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ int XNMONITORSERVER_EXPORT XN_InitializeEngineControl(char *errorMsg, int errorMsgSize); - // 暂停引擎 + /** + * @brief 暂停引擎 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + */ void XNMONITORSERVER_EXPORT XN_PauseEngine(char *errorMsg, int errorMsgSize); - // 恢复引擎 + /** + * @brief 恢复引擎 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ void XNMONITORSERVER_EXPORT XN_ResumeEngine(char *errorMsg, int errorMsgSize); - // 停止引擎 + /** + * @brief 停止引擎 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + */ void XNMONITORSERVER_EXPORT XN_StopEngine(char *errorMsg, int errorMsgSize); - // // 主题管理接口 - // XNDDSErrorCode XN_RegisterPublisher(const char *topicName, void **dataWriter); - // XNDDSErrorCode XN_UnregisterPublisher(const char *topicName); + //******************** 数据监控 ********************* - // // 数据写入接口 - // XNDDSErrorCode XN_WriteData(void *dataWriter, const void *data, size_t dataSize); + /** + * @brief 启动数据监控 + * @param structName 结构体名称 + * @param structNameLen 结构体名称长度 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ + int XNMONITORSERVER_EXPORT XN_StartDataMonitor(const char *structName, const int structNameLen, + char *errorMsg, int errorMsgSize); - // // 订阅回调函数类型 - // typedef void (*XNDataCallback)(const void *data, size_t dataSize, void *userData); + /** + * @brief 停止数据监控 + * @param structName 结构体名称 + * @param structNameLen 结构体名称长度 + * @param errorMsg 错误信息 + * @param errorMsgSize 错误信息大小 + */ + void XNMONITORSERVER_EXPORT XN_StopDataMonitor(const char *structName, const int structNameLen, + char *errorMsg, int errorMsgSize); - // // 订阅接口 - // XNDDSErrorCode XN_RegisterSubscriber(const char *topicName, XNDataCallback callback, - // void *userData); - // XNDDSErrorCode XN_UnregisterSubscriber(const char *topicName); + //******************** 数据注入 ********************* - // // 运行时数据接口 - // XNDDSErrorCode XN_GetRuntimeData(const char *name, XNRuntimeData *data); - // XNDDSErrorCode XN_SetRuntimeData(const char *name, const XNRuntimeData *data); + /** + * @brief 获取数据监控信息 + * @param structName 结构体名称 + * @param structNameLen 结构体名称长度 + * @param interfaceName 接口名称JSON数组字符串 + * @param interfaceNameLen 接口名称JSON数组字符串长度 + * @param data 数据JSON字符串 + * @param dataLen 数据JSON字符串长度 + * @param infoMsg 错误信息 + * @param infoMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ + int XNMONITORSERVER_EXPORT XN_GetDataMonitorInfo(const char *structName, + const int structNameLen, + const char *interfaceName, + const int interfaceNameLen, char *data, + int dataLen, char *infoMsg, int infoMsgSize); - // 错误信息获取 - //const char *MONITOR_EXPORT XN_GetLastError(); + /** + * @brief 注入数据接口 + * @param structName 结构体名称 + * @param structNameLen 结构体名称长度 + * @param interfaceNameAndData 接口名称和数据JSON字符串 + * @param interfaceNameAndDataLen 接口名称和数据JSON字符串长度 + * @param infoMsg 错误信息 + * @param infoMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ + int XNMONITORSERVER_EXPORT XN_InjectDataInterface(const char *structName, + const int structNameLen, + const char *interfaceNameAndData, + const int interfaceNameAndDataLen, + char *infoMsg, int infoMsgSize); + + /** + * @brief 持续注入数据接口 + * @param structName 结构体名称 + * @param structNameLen 结构体名称长度 + * @param interfaceNameAndData 接口名称和数据JSON字符串 + * @param interfaceNameAndDataLen 接口名称和数据JSON字符串长度 + * @param frequency 注入频率 + * @param infoMsg 错误信息 + * @param infoMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ + int XNMONITORSERVER_EXPORT XN_StartInjectContinuous( + const char *structName, const int structNameLen, const char *interfaceNameAndData, + const int interfaceNameAndDataLen, double frequency, char *infoMsg, int infoMsgSize); + + /** + * @brief 停止持续注入数据接口 + * @param structName 结构体名称 + * @param structNameLen 结构体名称长度 + * @param infoMsg 错误信息 + * @param infoMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ + int XNMONITORSERVER_EXPORT XN_StopInjectContinuous(const char *structName, + const int structNameLen, char *infoMsg, + int infoMsgSize); + + //******************** csv数据注入 ********************* + + /** + * @brief 从csv文件中注入数据接口 + * @param structName 结构体名称 + * @param structNameLen 结构体名称长度 + * @param csvFilePath csv文件路径 + * @param csvFilePathLen csv文件路径长度 + * @param injectTimes 注入次数 + * @param infoMsg 错误信息 + * @param infoMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ + int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv( + const char *structName, const int structNameLen, const char *csvFilePath, + const int csvFilePathLen, int injectTimes, char *infoMsg, int infoMsgSize); + + //******************** csv数据采集 ********************* + + /** + * @brief 持续采集数据并保存到csv文件接口 + * @param structName 结构体名称 + * @param structNameLen 结构体名称长度 + * @param interfaceName 接口名称JSON数组字符串 + * @param interfaceNameLen 接口名称JSON数组字符串长度 + * @param csvFilePath csv文件路径 + * @param csvFilePathLen csv文件路径长度 + * @param frequency 采集频率 + * @param infoMsg 错误信息 + * @param infoMsgSize 错误信息大小 + * @return 0: 成功, -1: 失败 + */ + int XNMONITORSERVER_EXPORT XN_StartCollectData(const char *structName, const int structNameLen, + const char *interfaceName, + const int interfaceNameLen, + const char *csvFilePath, + const int csvFilePathLen, char *infoMsg, + int infoMsgSize); #ifdef __cplusplus }