V0.34.0.250624_alpha:更改了监控后端C++服务
This commit is contained in:
parent
63442f0e27
commit
a78e1bb85f
Binary file not shown.
@ -0,0 +1,52 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(XNGroundHandling LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(MODEL_VERSION "2.0.143.1")
|
||||||
|
|
||||||
|
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)
|
||||||
|
include_directories(${XNCore_PATH}/IDL)
|
||||||
|
|
||||||
|
add_library(XNGroundHandling SHARED
|
||||||
|
XNGroundHandling_global.h
|
||||||
|
XNGroundHandling.cpp
|
||||||
|
XNGroundHandling.h
|
||||||
|
XNGroundHandling_p.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(XNGroundHandling PROPERTIES
|
||||||
|
LIBRARY_OUTPUT_NAME "libXNGroundHandling.so.2.0.143.1"
|
||||||
|
PREFIX ""
|
||||||
|
SUFFIX ""
|
||||||
|
SKIP_BUILD_RPATH TRUE
|
||||||
|
BUILD_WITH_INSTALL_RPATH TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(XNGroundHandling PRIVATE
|
||||||
|
${XNCore_PATH}/lib/libXNCore.so
|
||||||
|
${XNCore_PATH}/lib/libC909_V1_Interface.so
|
||||||
|
dl
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(XNGroundHandling PRIVATE XNGROUNDHANDLING_LIBRARY)
|
||||||
|
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}/Configuration/C909_V1/Models" CACHE PATH "Install path prefix" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS XNGroundHandling BUNDLE DESTINATION . LIBRARY DESTINATION . RUNTIME DESTINATION .)
|
||||||
|
|
||||||
|
file(GLOB CONFIG_FILE "*.mcfg")
|
||||||
|
|
||||||
|
install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME "${CMAKE_PROJECT_NAME}_V${MODEL_VERSION}.mcfg")
|
||||||
|
|
@ -0,0 +1,319 @@
|
|||||||
|
#include "XNGroundHandling.h"
|
||||||
|
#include "XNGroundHandling_p.h"
|
||||||
|
#include <XNCore/XNModelManager.h>
|
||||||
|
|
||||||
|
XN_MODEL_INITIALIZE(XNGroundHandling)
|
||||||
|
|
||||||
|
XNGroundHandling::XNGroundHandling() : XNModelObject(new XNGroundHandlingPrivate())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
XNGroundHandling::~XNGroundHandling()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
XNGroundHandling::XNGroundHandling(PrivateType *p) : XNModelObject(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNGroundHandling::Initialize()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
SuperType::Initialize();
|
||||||
|
if (d->_dynamicLib) {
|
||||||
|
d->_fun = (FunctionType)dlsym(d->_dynamicLib, d->_entryPointName.c_str());
|
||||||
|
if (!d->_fun) {
|
||||||
|
LOG_WARNING(
|
||||||
|
"Failed to resolve _Z29SACSCGroundHandlingEntryPointP20ComacDataStructure_S");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 在这里进行其它初始化 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNGroundHandling::PrepareForExecute()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
SuperType::PrepareForExecute();
|
||||||
|
InitializeData();
|
||||||
|
d->_inputInterface.Initialize(GetFramework(), GetUniqueId(), 1);
|
||||||
|
d->_outputInterface.Initialize(GetFramework(), GetUniqueId(), 2);
|
||||||
|
d->_heartbeatInterface.Initialize(GetFramework(), GetUniqueId(), 2);
|
||||||
|
/* 在这里进行其它运行前准备工作 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNGroundHandling::StepUpdate()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
SuperType::StepUpdate();
|
||||||
|
if (d->_fun) {
|
||||||
|
d->_inputInterface.getData(d->_data.input_ground);
|
||||||
|
d->_fun(&d->_data);
|
||||||
|
d->_outputInterface.setData(d->_data.output_ground);
|
||||||
|
d->_heartbeatInterface.setData(&d->_data);
|
||||||
|
}
|
||||||
|
/* 在这里进行其它运行时计算 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNGroundHandling::InitializeData()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
d->_data.input_ground = new input_ground_S;
|
||||||
|
// TODO: 在这里初始化输入数据
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_brake_torq_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_brake_torq_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_gear_f8 = new double[3];
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_gsteer_f8 = new double[3];
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_tire_pres_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_tire_pres_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_contdep_f8 = new double[7];
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_brake_temp_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_brake_temp_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_tire_tburst_l1 = new unsigned char *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_tire_tburst_l1[i] = new unsigned char[2];
|
||||||
|
}
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_tire_tflat_l1 = new unsigned char *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_tire_tflat_l1[i] = new unsigned char[2];
|
||||||
|
}
|
||||||
|
d->_data.input_ground->l_04_i_gdcomac_rcon_ci_f8 = new double[14];
|
||||||
|
|
||||||
|
d->_data.output_ground = new output_ground_S;
|
||||||
|
// TODO: 在这里初始化输出数据
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_fygs_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_mzgs_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_mu_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_dstroke_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_sr_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_sr_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_sy_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_sy_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_sx_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_sx_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_xft_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_yft_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_zft_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_tire_vel_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_tire_vel_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_tire_temp_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_tire_temp_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_tire_burst_l1 = new unsigned char *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_tire_burst_l1[i] = new unsigned char[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_utirew_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_utirew_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_vtirew_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_vtirew_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_whl_omega_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_whl_omega_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_dstruc_f8 = new double[6];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_nd_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_wor_par_f8 = new double[3];
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_vczt_f8 = new double *[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
d->_data.output_ground->l_04_o_gdcomac_vczt_f8[i] = new double[2];
|
||||||
|
}
|
||||||
|
d->_data.groundhandling_model_heartbeat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNGroundHandling::ReleaseData()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
// TODO: 在这里释放输入数据
|
||||||
|
|
||||||
|
if (d->_data.input_ground) {
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_brake_torq_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_brake_torq_f8[i]) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_brake_torq_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_brake_torq_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_gear_f8) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_gear_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_gsteer_f8) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_gsteer_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_tire_pres_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_tire_pres_f8[i]) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_tire_pres_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_tire_pres_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_contdep_f8) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_contdep_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_brake_temp_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_brake_temp_f8[i]) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_brake_temp_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_brake_temp_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_tire_tburst_l1) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_tire_tburst_l1[i]) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_tire_tburst_l1[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_tire_tburst_l1;
|
||||||
|
}
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_tire_tflat_l1) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_tire_tflat_l1[i]) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_tire_tflat_l1[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_tire_tflat_l1;
|
||||||
|
}
|
||||||
|
if (d->_data.input_ground->l_04_i_gdcomac_rcon_ci_f8) {
|
||||||
|
delete[] d->_data.input_ground->l_04_i_gdcomac_rcon_ci_f8;
|
||||||
|
}
|
||||||
|
delete d->_data.input_ground;
|
||||||
|
d->_data.input_ground = nullptr;
|
||||||
|
}
|
||||||
|
// TODO: 在这里释放输出数据
|
||||||
|
|
||||||
|
if (d->_data.output_ground) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_fygs_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_fygs_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_mzgs_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_mzgs_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_mu_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_mu_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_dstroke_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_dstroke_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_sr_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_sr_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_sr_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_sr_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_sy_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_sy_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_sy_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_sy_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_sx_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_sx_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_sx_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_sx_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_xft_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_xft_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_yft_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_yft_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_zft_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_zft_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_tire_vel_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_tire_vel_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_tire_vel_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_tire_vel_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_tire_temp_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_tire_temp_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_tire_temp_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_tire_temp_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_tire_burst_l1) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_tire_burst_l1[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_tire_burst_l1[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_tire_burst_l1;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_utirew_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_utirew_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_utirew_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_utirew_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_vtirew_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_vtirew_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_vtirew_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_vtirew_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_whl_omega_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_whl_omega_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_whl_omega_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_whl_omega_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_dstruc_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_dstruc_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_nd_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_nd_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_wor_par_f8) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_wor_par_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_vczt_f8) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (d->_data.output_ground->l_04_o_gdcomac_vczt_f8[i]) {
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_vczt_f8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] d->_data.output_ground->l_04_o_gdcomac_vczt_f8;
|
||||||
|
}
|
||||||
|
delete d->_data.output_ground;
|
||||||
|
d->_data.output_ground = nullptr;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNGroundHandling_global.h"
|
||||||
|
#include <XNCore/XNModelObject.h>
|
||||||
|
|
||||||
|
struct XNGroundHandlingPrivate;
|
||||||
|
|
||||||
|
class XNGROUNDHANDLING_EXPORT XNGroundHandling : public XNModelObject
|
||||||
|
{
|
||||||
|
XN_METATYPE(XNGroundHandling, XNModelObject)
|
||||||
|
XN_DECLARE_PRIVATE(XNGroundHandling)
|
||||||
|
public:
|
||||||
|
XNGroundHandling();
|
||||||
|
virtual ~XNGroundHandling();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
XNGroundHandling(PrivateType *p);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void Initialize() override;
|
||||||
|
virtual void PrepareForExecute() override;
|
||||||
|
virtual void StepUpdate() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void InitializeData();
|
||||||
|
void ReleaseData();
|
||||||
|
};
|
||||||
|
|
||||||
|
XNCLASS_PTR_DECLARE(XNGroundHandling)
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Model>
|
||||||
|
<Name>XNGroundHandling</Name>
|
||||||
|
<Description>ATA04GroundHandling</Description>
|
||||||
|
<Author>Jin</Author>
|
||||||
|
<Version>2.0.143.1</Version>
|
||||||
|
<CreateTime>2025-04-03 14:47:42</CreateTime>
|
||||||
|
<ChangeTime>2025-04-03 14:47:42</ChangeTime>
|
||||||
|
<Node>0</Node>
|
||||||
|
<Priority>99</Priority>
|
||||||
|
<MathLib>ATA04_SACSCGroundHandling_2.0.143.1H_20250506/libSACSCGroundHandling.so.2.0.143.1H</MathLib>
|
||||||
|
<CommandList/>
|
||||||
|
</Model>
|
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef XNGROUNDHANDLING_GLOBAL_H
|
||||||
|
#define XNGROUNDHANDLING_GLOBAL_H
|
||||||
|
|
||||||
|
#if defined(XNGROUNDHANDLING_LIBRARY)
|
||||||
|
#define XNGROUNDHANDLING_EXPORT __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define XNGROUNDHANDLING_EXPORT __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // XNGROUNDHANDLING_GLOBAL_H
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XNCore/XNModelObject_p.h>
|
||||||
|
#include "../../Packages/ATA04_SACSCGroundHandling_2.0.143.1H_20250506/std_04_dll.h"
|
||||||
|
#include "../../IDL/C909_V1_Interface.h"
|
||||||
|
|
||||||
|
using InterfaceType = ComacDataStructure_S;
|
||||||
|
typedef void (*FunctionType)(InterfaceType *);
|
||||||
|
|
||||||
|
struct XNGroundHandlingPrivate : public XNModelObjectPrivate{
|
||||||
|
FunctionType _fun = nullptr;
|
||||||
|
InterfaceType _data;
|
||||||
|
std::string _entryPointName = "_Z29SACSCGroundHandlingEntryPointP20ComacDataStructure_S";
|
||||||
|
std::mutex _mutex;
|
||||||
|
XNSim::C909::ATA04::GroundHandling_input_Interface _inputInterface;
|
||||||
|
XNSim::C909::ATA04::GroundHandling_output_Interface _outputInterface;
|
||||||
|
XNSim::C909::ATA04::GroundHandling_heartbeat_Interface _heartbeatInterface;
|
||||||
|
};
|
||||||
|
|
Binary file not shown.
@ -0,0 +1,52 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(XNWeightBalance LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(MODEL_VERSION "2.0.14.6")
|
||||||
|
|
||||||
|
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)
|
||||||
|
include_directories(${XNCore_PATH}/IDL)
|
||||||
|
|
||||||
|
add_library(XNWeightBalance SHARED
|
||||||
|
XNWeightBalance_global.h
|
||||||
|
XNWeightBalance.cpp
|
||||||
|
XNWeightBalance.h
|
||||||
|
XNWeightBalance_p.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(XNWeightBalance PROPERTIES
|
||||||
|
LIBRARY_OUTPUT_NAME "libXNWeightBalance.so.2.0.14.6"
|
||||||
|
PREFIX ""
|
||||||
|
SUFFIX ""
|
||||||
|
SKIP_BUILD_RPATH TRUE
|
||||||
|
BUILD_WITH_INSTALL_RPATH TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(XNWeightBalance PRIVATE
|
||||||
|
${XNCore_PATH}/lib/libXNCore.so
|
||||||
|
${XNCore_PATH}/lib/libC909_V1_Interface.so
|
||||||
|
dl
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(XNWeightBalance PRIVATE XNWEIGHTBALANCE_LIBRARY)
|
||||||
|
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}/Configuration/C909_V1/Models" CACHE PATH "Install path prefix" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS XNWeightBalance BUNDLE DESTINATION . LIBRARY DESTINATION . RUNTIME DESTINATION .)
|
||||||
|
|
||||||
|
file(GLOB CONFIG_FILE "*.mcfg")
|
||||||
|
|
||||||
|
install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME "${CMAKE_PROJECT_NAME}_V${MODEL_VERSION}.mcfg")
|
||||||
|
|
@ -0,0 +1,106 @@
|
|||||||
|
#include "XNWeightBalance.h"
|
||||||
|
#include "XNWeightBalance_p.h"
|
||||||
|
#include <XNCore/XNModelManager.h>
|
||||||
|
|
||||||
|
XN_MODEL_INITIALIZE(XNWeightBalance)
|
||||||
|
|
||||||
|
XNWeightBalance::XNWeightBalance() : XNModelObject(new XNWeightBalancePrivate())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
XNWeightBalance::~XNWeightBalance()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
XNWeightBalance::XNWeightBalance(PrivateType *p) : XNModelObject(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNWeightBalance::Initialize()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
SuperType::Initialize();
|
||||||
|
if (d->_dynamicLib) {
|
||||||
|
d->_fun = (FunctionType)dlsym(d->_dynamicLib, d->_entryPointName.c_str());
|
||||||
|
if (!d->_fun) {
|
||||||
|
LOG_WARNING(
|
||||||
|
"Failed to resolve _Z28SACSCWeightBalanceEntryPointP20ComacDataStructure_S");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 在这里进行其它初始化 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNWeightBalance::PrepareForExecute()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
SuperType::PrepareForExecute();
|
||||||
|
InitializeData();
|
||||||
|
d->_inputInterface.Initialize(GetFramework(), GetUniqueId(), 1);
|
||||||
|
d->_outputInterface.Initialize(GetFramework(), GetUniqueId(), 2);
|
||||||
|
d->_heartbeatInterface.Initialize(GetFramework(), GetUniqueId(), 2);
|
||||||
|
/* 在这里进行其它运行前准备工作 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNWeightBalance::StepUpdate()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
SuperType::StepUpdate();
|
||||||
|
if (d->_fun) {
|
||||||
|
d->_inputInterface.getData(d->_data.input_weight);
|
||||||
|
d->_fun(&d->_data);
|
||||||
|
d->_outputInterface.setData(d->_data.output_weight);
|
||||||
|
d->_heartbeatInterface.setData(&d->_data);
|
||||||
|
}
|
||||||
|
/* 在这里进行其它运行时计算 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNWeightBalance::InitializeData()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
d->_data.input_weight = new input_weight_S;
|
||||||
|
// TODO: 在这里初始化输入数据
|
||||||
|
d->_data.input_weight->l_04_i_wbcomac_acset_tankfuel_f4 = new float[20];
|
||||||
|
d->_data.input_weight->l_04_i_wbcomac_eng_efsep_l1 = new unsigned char[4];
|
||||||
|
d->_data.input_weight->l_04_i_wbcomac_fuel_f8 = new double[20];
|
||||||
|
d->_data.input_weight->l_04_i_wbcomac_kice_f8 = new double[20];
|
||||||
|
|
||||||
|
d->_data.output_weight = new output_weight_S;
|
||||||
|
// TODO: 在这里初始化输出数据
|
||||||
|
d->_data.output_weight->l_04_o_wbcomac_fuel_cmd_f8 = new double[20];
|
||||||
|
d->_data.output_weight->l_04_o_wbcomac_ice_eng_f8 = new double[4];
|
||||||
|
|
||||||
|
d->_data.weightbody_model_heartbeat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNWeightBalance::ReleaseData()
|
||||||
|
{
|
||||||
|
T_D();
|
||||||
|
if (d->_data.input_weight) {
|
||||||
|
// TODO: 在这里释放输入数据
|
||||||
|
if (d->_data.input_weight->l_04_i_wbcomac_acset_tankfuel_f4) {
|
||||||
|
delete[] d->_data.input_weight->l_04_i_wbcomac_acset_tankfuel_f4;
|
||||||
|
}
|
||||||
|
if (d->_data.input_weight->l_04_i_wbcomac_eng_efsep_l1) {
|
||||||
|
delete[] d->_data.input_weight->l_04_i_wbcomac_eng_efsep_l1;
|
||||||
|
}
|
||||||
|
if (d->_data.input_weight->l_04_i_wbcomac_fuel_f8) {
|
||||||
|
delete[] d->_data.input_weight->l_04_i_wbcomac_fuel_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.input_weight->l_04_i_wbcomac_kice_f8) {
|
||||||
|
delete[] d->_data.input_weight->l_04_i_wbcomac_kice_f8;
|
||||||
|
}
|
||||||
|
delete d->_data.input_weight;
|
||||||
|
d->_data.input_weight = nullptr;
|
||||||
|
}
|
||||||
|
if (d->_data.output_weight) {
|
||||||
|
// TODO: 在这里释放输出数据
|
||||||
|
if (d->_data.output_weight->l_04_o_wbcomac_fuel_cmd_f8) {
|
||||||
|
delete[] d->_data.output_weight->l_04_o_wbcomac_fuel_cmd_f8;
|
||||||
|
}
|
||||||
|
if (d->_data.output_weight->l_04_o_wbcomac_ice_eng_f8) {
|
||||||
|
delete[] d->_data.output_weight->l_04_o_wbcomac_ice_eng_f8;
|
||||||
|
}
|
||||||
|
delete d->_data.output_weight;
|
||||||
|
d->_data.output_weight = nullptr;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNWeightBalance_global.h"
|
||||||
|
#include <XNCore/XNModelObject.h>
|
||||||
|
|
||||||
|
struct XNWeightBalancePrivate;
|
||||||
|
|
||||||
|
class XNWEIGHTBALANCE_EXPORT XNWeightBalance : public XNModelObject
|
||||||
|
{
|
||||||
|
XN_METATYPE(XNWeightBalance, XNModelObject)
|
||||||
|
XN_DECLARE_PRIVATE(XNWeightBalance)
|
||||||
|
public:
|
||||||
|
XNWeightBalance();
|
||||||
|
virtual ~XNWeightBalance();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
XNWeightBalance(PrivateType *p);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void Initialize() override;
|
||||||
|
virtual void PrepareForExecute() override;
|
||||||
|
virtual void StepUpdate() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void InitializeData();
|
||||||
|
void ReleaseData();
|
||||||
|
};
|
||||||
|
|
||||||
|
XNCLASS_PTR_DECLARE(XNWeightBalance)
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Model>
|
||||||
|
<Name>XNWeightBalance</Name>
|
||||||
|
<Description>ATA04WeightBalance</Description>
|
||||||
|
<Author>Jin</Author>
|
||||||
|
<Version>2.0.14.6</Version>
|
||||||
|
<CreateTime>2025-04-27 13:57:50</CreateTime>
|
||||||
|
<ChangeTime>2025-04-27 13:57:50</ChangeTime>
|
||||||
|
<Node>0</Node>
|
||||||
|
<Priority>99</Priority>
|
||||||
|
<MathLib>ATA04_WeightBalance_2.0.14.6H_20241106/libSACSCWeightBalance.so</MathLib>
|
||||||
|
<CommandList/>
|
||||||
|
</Model>
|
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef XNWEIGHTBALANCE_GLOBAL_H
|
||||||
|
#define XNWEIGHTBALANCE_GLOBAL_H
|
||||||
|
|
||||||
|
#if defined(XNWEIGHTBALANCE_LIBRARY)
|
||||||
|
#define XNWEIGHTBALANCE_EXPORT __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define XNWEIGHTBALANCE_EXPORT __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // XNWEIGHTBALANCE_GLOBAL_H
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XNCore/XNModelObject_p.h>
|
||||||
|
#include "../../Packages/ATA04_WeightBalance_2.0.14.6H_20241106/std_04_dll.h"
|
||||||
|
#include "../../IDL/C909_V1_Interface.h"
|
||||||
|
|
||||||
|
using InterfaceType = ComacDataStructure_S;
|
||||||
|
typedef void (*FunctionType)(InterfaceType *);
|
||||||
|
|
||||||
|
struct XNWeightBalancePrivate : public XNModelObjectPrivate{
|
||||||
|
FunctionType _fun = nullptr;
|
||||||
|
InterfaceType _data;
|
||||||
|
std::string _entryPointName = "_Z28SACSCWeightBalanceEntryPointP20ComacDataStructure_S";
|
||||||
|
std::mutex _mutex;
|
||||||
|
XNSim::C909::ATA04::WeightBalance_input_Interface _inputInterface;
|
||||||
|
XNSim::C909::ATA04::WeightBalance_output_Interface _outputInterface;
|
||||||
|
XNSim::C909::ATA04::WeightBalance_heartbeat_Interface _heartbeatInterface;
|
||||||
|
};
|
||||||
|
|
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Model>
|
|
||||||
<Name>XNGroundHandling</Name>
|
|
||||||
<Description>ATA04地面操纵模型</Description>
|
|
||||||
<Author>Jin</Author>
|
|
||||||
<Version>1.0.0</Version>
|
|
||||||
<CreateTime>2025-02-19 16:22:17</CreateTime>
|
|
||||||
<ChangeTime>2025-02-19 16:22:19</ChangeTime>
|
|
||||||
<Node>0-0</Node>
|
|
||||||
<Priority>99</Priority>
|
|
||||||
<MathLib>ATA04_SACSCGroundHandling_2.0.143.1H_20250506/libSACSCGroundHandling.so.2.0.143.1H</MathLib>
|
|
||||||
<CommandList/>
|
|
||||||
</Model>
|
|
@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Model>
|
<Model>
|
||||||
<Name>XNGroundHandling</Name>
|
<Name>XNGroundHandling</Name>
|
||||||
<Description>ATA04地面操纵模型</Description>
|
<Description>ATA04GroundHandling</Description>
|
||||||
<Author>Jin</Author>
|
<Author>Jin</Author>
|
||||||
<Version>1.0.0</Version>
|
<Version>2.0.143.1</Version>
|
||||||
<CreateTime>2025-02-19 16:22:17</CreateTime>
|
<CreateTime>2025-04-03 14:47:42</CreateTime>
|
||||||
<ChangeTime>2025-02-19 16:22:19</ChangeTime>
|
<ChangeTime>2025-04-03 14:47:42</ChangeTime>
|
||||||
<Node>0-0</Node>
|
<Node>0</Node>
|
||||||
<Priority>99</Priority>
|
<Priority>99</Priority>
|
||||||
<MathLib>ATA04_SACSCGroundHandling_2.0.143.1H_20250506/libSACSCGroundHandling.so.2.0.143.1H</MathLib>
|
<MathLib>ATA04_SACSCGroundHandling_2.0.143.1H_20250506/libSACSCGroundHandling.so.2.0.143.1H</MathLib>
|
||||||
<CommandList/>
|
<CommandList/>
|
||||||
</Model>
|
</Model>
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Model>
|
|
||||||
<Name>XNWeightBalance</Name>
|
|
||||||
<Description>ATA04质量模型</Description>
|
|
||||||
<Author>Jin</Author>
|
|
||||||
<Version>1.0.0</Version>
|
|
||||||
<CreateTime>2025-02-20 09:29:18</CreateTime>
|
|
||||||
<ChangeTime>2025-02-20 09:29:20</ChangeTime>
|
|
||||||
<Node>0-0</Node>
|
|
||||||
<Priority>99</Priority>
|
|
||||||
<MathLib>ATA04_WeightBalance_2.0.14.6H_20241106/libSACSCWeightBalance.so</MathLib>
|
|
||||||
<CommandList/>
|
|
||||||
</Model>
|
|
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Model>
|
||||||
|
<Name>XNWeightBalance</Name>
|
||||||
|
<Description>ATA04WeightBalance</Description>
|
||||||
|
<Author>Jin</Author>
|
||||||
|
<Version>2.0.14.6</Version>
|
||||||
|
<CreateTime>2025-04-27 13:57:50</CreateTime>
|
||||||
|
<ChangeTime>2025-04-27 13:57:50</ChangeTime>
|
||||||
|
<Node>0</Node>
|
||||||
|
<Priority>99</Priority>
|
||||||
|
<MathLib>ATA04_WeightBalance_2.0.14.6H_20241106/libSACSCWeightBalance.so</MathLib>
|
||||||
|
<CommandList/>
|
||||||
|
</Model>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
84
Release/Configuration/C909_V1/PluginCode/C909_V1_plugin.cpp
Normal file
84
Release/Configuration/C909_V1/PluginCode/C909_V1_plugin.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include <XNMonitor/PluginInterface.h>
|
||||||
|
#include <XNMonitor/DataMonitor.h>
|
||||||
|
// C909_V1接口头文件 - 只在插件中包含
|
||||||
|
#include "../IDL/C909_V1_Interface.h"
|
||||||
|
|
||||||
|
// 插件信息
|
||||||
|
static PluginInfo plugin_info = {"C909_V1", "", DATAMONITOR_PLUGIN_INTERFACE_VERSION};
|
||||||
|
|
||||||
|
// 支持的接口列表
|
||||||
|
static const char *supported_interfaces[] = {
|
||||||
|
"Aerodynamics_input",
|
||||||
|
"GroundHandling_input",
|
||||||
|
"GroundHandling_output",
|
||||||
|
"Aerodynamics_output",
|
||||||
|
"WeightBalance_input",
|
||||||
|
"WeightBalance_output",
|
||||||
|
"GroundHandling_heartbeat",
|
||||||
|
"WeightBalance_heartbeat",
|
||||||
|
"Aerodynamics_heartbeat"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int interface_count = sizeof(supported_interfaces) / sizeof(supported_interfaces[0]);
|
||||||
|
|
||||||
|
// 导出的插件函数
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
PluginInfo *get_plugin_info()
|
||||||
|
{
|
||||||
|
return &plugin_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataMonitorBasePtr create_monitor(const char *interfaceName)
|
||||||
|
{
|
||||||
|
std::string name(interfaceName);
|
||||||
|
|
||||||
|
if (name == "Aerodynamics_input") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::Aerodynamics_input_Interface>>();
|
||||||
|
} else
|
||||||
|
if (name == "GroundHandling_input") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::GroundHandling_input_Interface>>();
|
||||||
|
} else
|
||||||
|
if (name == "GroundHandling_output") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::GroundHandling_output_Interface>>();
|
||||||
|
} else
|
||||||
|
if (name == "Aerodynamics_output") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::Aerodynamics_output_Interface>>();
|
||||||
|
} else
|
||||||
|
if (name == "WeightBalance_input") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::WeightBalance_input_Interface>>();
|
||||||
|
} else
|
||||||
|
if (name == "WeightBalance_output") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::WeightBalance_output_Interface>>();
|
||||||
|
} else
|
||||||
|
if (name == "GroundHandling_heartbeat") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::GroundHandling_heartbeat_Interface>>();
|
||||||
|
} else
|
||||||
|
if (name == "WeightBalance_heartbeat") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::WeightBalance_heartbeat_Interface>>();
|
||||||
|
} else
|
||||||
|
if (name == "Aerodynamics_heartbeat") {
|
||||||
|
return std::make_shared<DataMonitorProduct<XNSim::C909::ATA04::Aerodynamics_heartbeat_Interface>>();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_monitor(const char *interfaceName)
|
||||||
|
{
|
||||||
|
// 智能指针会自动管理内存,这里可以添加额外的清理逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
const char **get_supported_interfaces(int *count)
|
||||||
|
{
|
||||||
|
if (count) {
|
||||||
|
*count = interface_count;
|
||||||
|
}
|
||||||
|
return const_cast<const char **>(supported_interfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_string_array(const char **array)
|
||||||
|
{
|
||||||
|
// 这里不需要释放,因为使用的是静态数组
|
||||||
|
}
|
||||||
|
}
|
44
Release/Configuration/C909_V1/PluginCode/CMakeLists.txt
Normal file
44
Release/Configuration/C909_V1/PluginCode/CMakeLists.txt
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# CMakeLists.txt for C909_V1_Monitor plugin
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
# 设置项目名称
|
||||||
|
project(C909_V1_Monitor_plugin)
|
||||||
|
|
||||||
|
# 设置C++标准
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# 查找必要的包
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
find_package(FastDDS REQUIRED)
|
||||||
|
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(C909_V1_Monitor SHARED
|
||||||
|
C909_V1_plugin.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# 链接库
|
||||||
|
target_link_libraries(C909_V1_Monitor
|
||||||
|
fastcdr
|
||||||
|
fastdds
|
||||||
|
OpenSSL::SSL
|
||||||
|
OpenSSL::Crypto
|
||||||
|
${XNCore_PATH}/lib/libC909_V1_Interface.so
|
||||||
|
${XNCore_PATH}/lib/libXNMonitorServer.so
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(C909_V1_Monitor PRIVATE C909_V1_Monitor_LIBRARY)
|
||||||
|
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}/Configuration/C909_V1/Plugins" CACHE PATH "Install path prefix" FORCE)
|
||||||
|
endif()
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
install(TARGETS C909_V1_Monitor
|
||||||
|
BUNDLE DESTINATION .
|
||||||
|
LIBRARY DESTINATION .
|
||||||
|
RUNTIME DESTINATION .
|
||||||
|
)
|
Binary file not shown.
66
Release/include/XNMonitor/CSVDataInjectThread.h
Normal file
66
Release/include/XNMonitor/CSVDataInjectThread.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DataMonitor.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 数据注入线程类,用于持续向数据监控器注入数据
|
||||||
|
*/
|
||||||
|
class CSVDataInjectThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 构造函数
|
||||||
|
* @param csvFilePath CSV文件路径
|
||||||
|
*/
|
||||||
|
CSVDataInjectThread(std::string csvFilePath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 析构函数
|
||||||
|
*/
|
||||||
|
~CSVDataInjectThread();
|
||||||
|
|
||||||
|
bool Initialize(std::vector<MonitorDataInfo> injectDataInfos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 启动数据注入线程
|
||||||
|
*/
|
||||||
|
void start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 停止数据注入线程
|
||||||
|
*/
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从CSV文件读取下一行数据并更新执行时间
|
||||||
|
* 如果文件读取完毕,将停止线程
|
||||||
|
*/
|
||||||
|
void updateData();
|
||||||
|
|
||||||
|
bool isRunning() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 线程执行函数
|
||||||
|
*/
|
||||||
|
void threadFunc();
|
||||||
|
|
||||||
|
void parseHeaderField(const std::string &headerField);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_csvFilePath;
|
||||||
|
std::ifstream m_csvFile;
|
||||||
|
std::vector<MonitorDataInfo> m_injectDataInfos;
|
||||||
|
std::vector<CSVHeaderField> m_headerFields;
|
||||||
|
std::thread m_thread; ///< 数据注入线程
|
||||||
|
std::atomic<bool> m_running; ///< 线程运行标志
|
||||||
|
std::mutex m_mutex; ///< 互斥锁
|
||||||
|
std::condition_variable m_cv; ///< 条件变量
|
||||||
|
std::unordered_map<std::string, DataMonitorBasePtr>
|
||||||
|
m_alreadyStartedMonitors; ///< 已经启动的数据监控器
|
||||||
|
std::unordered_map<std::string, DataMonitorBasePtr>
|
||||||
|
m_notStartedMonitors; ///< 未启动的数据监控器
|
||||||
|
std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
|
||||||
|
m_data; ///< 要注入的数据
|
||||||
|
std::atomic<int64_t> m_nextExecuteTime; ///< 下一次执行的时间点
|
||||||
|
};
|
52
Release/include/XNMonitor/DataCollect.h
Normal file
52
Release/include/XNMonitor/DataCollect.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DataMonitor.h"
|
||||||
|
|
||||||
|
class DataCollect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DataCollect();
|
||||||
|
~DataCollect();
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool Initialize(std::vector<MonitorDataInfo> collectDataInfos, std::string dcsFilePath);
|
||||||
|
|
||||||
|
void start();
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从CSV文件读取下一行数据并更新执行时间
|
||||||
|
* 如果文件读取完毕,将停止线程
|
||||||
|
*/
|
||||||
|
void updateData();
|
||||||
|
|
||||||
|
bool isRunning() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 线程执行函数
|
||||||
|
*/
|
||||||
|
void threadFunc();
|
||||||
|
|
||||||
|
void parseHeaderField(const std::string &headerField);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_outputFileName;
|
||||||
|
std::ofstream m_outputFile;
|
||||||
|
std::vector<MonitorDataInfo> m_collectDataInfos;
|
||||||
|
std::vector<CSVHeaderField> m_headerFields;
|
||||||
|
std::thread m_thread; ///< 数据采集线程
|
||||||
|
std::atomic<bool> m_running; ///< 线程运行标志
|
||||||
|
std::mutex m_mutex; ///< 互斥锁
|
||||||
|
std::condition_variable m_cv; ///< 条件变量
|
||||||
|
std::unordered_map<std::string, DataMonitorBasePtr>
|
||||||
|
m_alreadyStartedMonitors; ///< 已经启动的数据监控器
|
||||||
|
std::unordered_map<std::string, DataMonitorBasePtr>
|
||||||
|
m_notStartedMonitors; ///< 未启动的数据监控器
|
||||||
|
std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
|
||||||
|
m_data; ///< 采集到的数据
|
||||||
|
std::atomic<int64_t> m_nextExecuteTime; ///< 下一次执行的时间点
|
||||||
|
int m_collectDuration; ///< 采集时长(秒)
|
||||||
|
int m_collectFrequency; ///< 采集频率(Hz)
|
||||||
|
};
|
63
Release/include/XNMonitor/DataInjectThread.h
Normal file
63
Release/include/XNMonitor/DataInjectThread.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DataMonitor.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 数据注入线程类,用于持续向数据监控器注入数据
|
||||||
|
*/
|
||||||
|
class DataInjectThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 构造函数
|
||||||
|
* @param dataMonitor 数据监控器指针
|
||||||
|
* @param data 要注入的数据
|
||||||
|
* @param frequency 注入频率(Hz)
|
||||||
|
*/
|
||||||
|
DataInjectThread(DataMonitorBasePtr dataMonitor,
|
||||||
|
std::unordered_map<std::string, std::string> data, double frequency);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 析构函数
|
||||||
|
*/
|
||||||
|
~DataInjectThread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 启动数据注入线程
|
||||||
|
*/
|
||||||
|
void start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 停止数据注入线程
|
||||||
|
*/
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新要注入的数据
|
||||||
|
* @param data 新的数据
|
||||||
|
*/
|
||||||
|
void updateData(const std::unordered_map<std::string, std::string> &data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新注入频率
|
||||||
|
* @param frequency 新的频率(Hz)
|
||||||
|
*/
|
||||||
|
void updateFrequency(double frequency);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 线程执行函数
|
||||||
|
*/
|
||||||
|
void threadFunc();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::thread m_thread; ///< 数据注入线程
|
||||||
|
std::atomic<bool> m_running; ///< 线程运行标志
|
||||||
|
std::mutex m_mutex; ///< 互斥锁
|
||||||
|
std::condition_variable m_cv; ///< 条件变量
|
||||||
|
DataMonitorBasePtr m_dataMonitor; ///< 数据监控器指针
|
||||||
|
std::unordered_map<std::string, std::string> m_data; ///< 要注入的数据
|
||||||
|
std::atomic<double> m_frequency; ///< 注入频率
|
||||||
|
};
|
||||||
|
|
||||||
|
using DataInjectThreadPtr = std::shared_ptr<DataInjectThread>;
|
80
Release/include/XNMonitor/DataMonitor.h
Normal file
80
Release/include/XNMonitor/DataMonitor.h
Normal file
@ -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<XNFramework>;
|
||||||
|
|
||||||
|
class XNMONITORSERVER_EXPORT DataMonitorBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) = 0;
|
||||||
|
virtual std::unordered_map<std::string, std::string>
|
||||||
|
getStringData(std::vector<std::string> varNames) = 0;
|
||||||
|
virtual void setDataByString(std::unordered_map<std::string, std::string> data) = 0;
|
||||||
|
virtual bool isInitialized() { return _isInitialized; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool _isInitialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
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<typename T::DDSPubSubType>(
|
||||||
|
T::topic_name,
|
||||||
|
std::bind(&DataMonitorProduct::inputDataListener, this, std::placeholders::_1));
|
||||||
|
if (ret != XNDDSErrorCode::SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = TopicManager::Instance()->registerPublisher<typename T::DDSPubSubType>(
|
||||||
|
T::topic_name, this->dataWriter);
|
||||||
|
if (ret != XNDDSErrorCode::SUCCESS || this->dataWriter == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_isInitialized = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual std::unordered_map<std::string, std::string>
|
||||||
|
getStringData(std::vector<std::string> varNames) override
|
||||||
|
{
|
||||||
|
if (!isInitialized()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return T::getStringData(varNames);
|
||||||
|
}
|
||||||
|
virtual void setDataByString(std::unordered_map<std::string, std::string> data) override
|
||||||
|
{
|
||||||
|
if (!isInitialized()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
T::setDataByString(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using DataMonitorBasePtr = std::shared_ptr<DataMonitorBase>;
|
25
Release/include/XNMonitor/DataMonitorFactory.h
Normal file
25
Release/include/XNMonitor/DataMonitorFactory.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNMonitorServer_global.h"
|
||||||
|
#include "DataMonitor.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DataMonitor工厂类,用于创建不同类型的DataMonitor实例
|
||||||
|
*/
|
||||||
|
class XNMONITORSERVER_EXPORT DataMonitorFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static DataMonitorBasePtr GetInstance(const std::string &interfaceName);
|
||||||
|
|
||||||
|
static void ReleaseInstance(const std::string &interfaceName);
|
||||||
|
|
||||||
|
// 检查接口是否存在
|
||||||
|
static bool HasInterface(const std::string &interfaceName);
|
||||||
|
|
||||||
|
// 获取所有已注册的接口名称
|
||||||
|
static std::vector<std::string> GetRegisteredInterfaces();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DataMonitorFactory() = delete;
|
||||||
|
~DataMonitorFactory() = delete;
|
||||||
|
};
|
37
Release/include/XNMonitor/ModelInfoMonitor.h
Normal file
37
Release/include/XNMonitor/ModelInfoMonitor.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TopicManager.h"
|
||||||
|
#include <XNIDL/XNSimStatusPubSubTypes.hpp>
|
||||||
|
|
||||||
|
class XNMONITORSERVER_EXPORT ModelInfoMonitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ModelInfoMonitor() {}
|
||||||
|
virtual ~ModelInfoMonitor();
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string Initialize();
|
||||||
|
|
||||||
|
std::string GetAllModelInfo();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 模型状态监听
|
||||||
|
* @param status 模型状态
|
||||||
|
*/
|
||||||
|
void ModelStatusListener(const XNSim::XNSimStatus::XNModelStatus &status);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 互斥锁
|
||||||
|
*/
|
||||||
|
std::mutex m_ModelStatusMutex;
|
||||||
|
/**
|
||||||
|
* @brief 模型状态
|
||||||
|
*/
|
||||||
|
std::map<uint32_t, XNSim::XNSimStatus::XNModelStatus> m_ModelStatus;
|
||||||
|
/**
|
||||||
|
* @brief 模型周期计数
|
||||||
|
*/
|
||||||
|
std::map<uint32_t, uint64_t> m_ModelCycleCount;
|
||||||
|
};
|
66
Release/include/XNMonitor/PluginGenerator.h
Normal file
66
Release/include/XNMonitor/PluginGenerator.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* @file PluginGenerator.h
|
||||||
|
* @brief 简化的插件生成器 - 从数据库生成插件cpp文件和CMakeLists
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
|
||||||
|
// 接口信息结构
|
||||||
|
struct InterfaceInfo {
|
||||||
|
std::string interfaceName; // 接口名称(如:Aerodynamics_heartbeat)
|
||||||
|
std::string
|
||||||
|
templateType; // 模板类型(如:XNSim::C909::ATA04::Aerodynamics_heartbeat_Interface)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 插件信息
|
||||||
|
struct GenPluginInfo {
|
||||||
|
std::string pluginName; // 插件名称(如:C909_V1)
|
||||||
|
std::string pluginDescription; // 插件描述
|
||||||
|
std::string interfaceHeaderPath; // 接口头文件路径(如:IDL/C909_V1_Interface.h)
|
||||||
|
std::vector<InterfaceInfo> interfaces; // 接口列表
|
||||||
|
std::string outputDirectory; // 输出目录
|
||||||
|
};
|
||||||
|
|
||||||
|
class PluginGenerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PluginGenerator();
|
||||||
|
~PluginGenerator();
|
||||||
|
|
||||||
|
// 从数据库加载插件信息
|
||||||
|
bool loadPluginFromDatabase(const int confID);
|
||||||
|
|
||||||
|
// 生成插件cpp文件
|
||||||
|
bool generatePluginCpp();
|
||||||
|
|
||||||
|
// 生成CMakeLists.txt
|
||||||
|
bool generateCMakeLists();
|
||||||
|
|
||||||
|
// 编译插件
|
||||||
|
bool compilePlugin();
|
||||||
|
|
||||||
|
// 获取错误信息
|
||||||
|
std::string getLastError() const;
|
||||||
|
|
||||||
|
// 获取插件信息
|
||||||
|
const GenPluginInfo &getPluginInfo() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 生成插件cpp文件内容
|
||||||
|
std::string generatePluginCppContent();
|
||||||
|
|
||||||
|
// 生成CMakeLists.txt内容
|
||||||
|
std::string generateCMakeListsContent();
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
bool writeFile(const std::string &filePath, const std::string &content);
|
||||||
|
|
||||||
|
// 创建目录
|
||||||
|
bool createDirectory(const std::string &dirPath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_lastError;
|
||||||
|
|
||||||
|
GenPluginInfo m_pluginInfo;
|
||||||
|
};
|
34
Release/include/XNMonitor/PluginInterface.h
Normal file
34
Release/include/XNMonitor/PluginInterface.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNMonitorServer_global.h"
|
||||||
|
#include "DataMonitor.h"
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
|
||||||
|
// 插件信息结构
|
||||||
|
struct PluginInfo {
|
||||||
|
const char *name; // 插件名称,如 "C909_V1"
|
||||||
|
const char *description; // 描述信息
|
||||||
|
const char *interface_version; // 接口版本,必须与主项目兼容
|
||||||
|
};
|
||||||
|
|
||||||
|
// C风格插件接口 - 确保ABI兼容性
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
// 获取插件信息
|
||||||
|
typedef PluginInfo *(*GetPluginInfoFunc)();
|
||||||
|
|
||||||
|
// 创建监控器实例
|
||||||
|
typedef DataMonitorBasePtr (*CreateMonitorFunc)(const char *interfaceName);
|
||||||
|
|
||||||
|
// 销毁监控器实例
|
||||||
|
typedef void (*DestroyMonitorFunc)(const char *interfaceName);
|
||||||
|
|
||||||
|
// 获取支持的接口列表
|
||||||
|
typedef const char **(*GetSupportedInterfacesFunc)(int *count);
|
||||||
|
|
||||||
|
// 释放字符串数组
|
||||||
|
typedef void (*FreeStringArrayFunc)(const char **array);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插件接口版本 - 主项目一旦发布就不再修改
|
||||||
|
#define DATAMONITOR_PLUGIN_INTERFACE_VERSION "1.0.0"
|
51
Release/include/XNMonitor/PluginManager.h
Normal file
51
Release/include/XNMonitor/PluginManager.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNMonitorServer_global.h"
|
||||||
|
#include "PluginInterface.h"
|
||||||
|
#include "PluginGenerator.h"
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
|
||||||
|
class XNMONITORSERVER_EXPORT PluginManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static PluginManager &Instance();
|
||||||
|
|
||||||
|
// 设置生成的插件信息
|
||||||
|
void SetGeneratedPluginInfo(const GenPluginInfo &pluginInfo);
|
||||||
|
|
||||||
|
// 从生成器加载插件
|
||||||
|
bool LoadPluginFromGenerator();
|
||||||
|
|
||||||
|
// 卸载当前插件
|
||||||
|
void UnloadCurrentPlugin();
|
||||||
|
|
||||||
|
// 获取监控器实例
|
||||||
|
DataMonitorBasePtr GetMonitor(const std::string &interfaceName);
|
||||||
|
|
||||||
|
// 获取所有支持的接口
|
||||||
|
std::vector<std::string> GetSupportedInterfaces();
|
||||||
|
|
||||||
|
// 检查插件是否已加载
|
||||||
|
bool IsPluginLoaded() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PluginManager() = default;
|
||||||
|
~PluginManager();
|
||||||
|
PluginManager(const PluginManager &) = delete;
|
||||||
|
PluginManager &operator=(const PluginManager &) = delete;
|
||||||
|
|
||||||
|
// 当前加载的插件信息
|
||||||
|
void *m_pluginHandle = nullptr;
|
||||||
|
PluginInfo *m_pluginInfo = nullptr;
|
||||||
|
GetPluginInfoFunc m_getPluginInfoFunc = nullptr;
|
||||||
|
CreateMonitorFunc m_createMonitorFunc = nullptr;
|
||||||
|
DestroyMonitorFunc m_destroyMonitorFunc = nullptr;
|
||||||
|
GetSupportedInterfacesFunc m_getSupportedInterfacesFunc = nullptr;
|
||||||
|
FreeStringArrayFunc m_freeStringArrayFunc = nullptr;
|
||||||
|
|
||||||
|
// 生成的插件信息
|
||||||
|
GenPluginInfo m_generatedPluginInfo;
|
||||||
|
|
||||||
|
// 监控器实例缓存
|
||||||
|
std::unordered_map<std::string, DataMonitorBasePtr> m_monitorCache;
|
||||||
|
};
|
24
Release/include/XNMonitor/SystemControl.h
Normal file
24
Release/include/XNMonitor/SystemControl.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNMonitorServer_global.h"
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
#include "TopicManager.h"
|
||||||
|
#include <XNIDL/XNSimStatusPubSubTypes.hpp>
|
||||||
|
|
||||||
|
class XNMONITORSERVER_EXPORT SystemControl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SystemControl() {};
|
||||||
|
virtual ~SystemControl();
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string Initialize();
|
||||||
|
void Pause();
|
||||||
|
void Resume();
|
||||||
|
void Stop();
|
||||||
|
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
private:
|
||||||
|
XNDataWriter *m_EngineControlWriter;
|
||||||
|
};
|
52
Release/include/XNMonitor/SystemInfoMonitor.h
Normal file
52
Release/include/XNMonitor/SystemInfoMonitor.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TopicManager.h"
|
||||||
|
#include <XNIDL/XNSimStatusPubSubTypes.hpp>
|
||||||
|
|
||||||
|
class XNMONITORSERVER_EXPORT SystemInfoMonitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SystemInfoMonitor() {}
|
||||||
|
virtual ~SystemInfoMonitor();
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string Initialize();
|
||||||
|
|
||||||
|
std::string GetSystemInfo();
|
||||||
|
std::string GetAllThreadInfo();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 引擎状态监听器
|
||||||
|
* @param status 引擎状态
|
||||||
|
*/
|
||||||
|
void EngineStatusListener(const XNSim::XNSimStatus::XNEngineStatus &status);
|
||||||
|
/**
|
||||||
|
* @brief 线程状态监听器
|
||||||
|
* @param status 线程状态
|
||||||
|
*/
|
||||||
|
void ThreadStatusListener(const XNSim::XNSimStatus::XNThreadStatus &status);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 互斥锁
|
||||||
|
*/
|
||||||
|
std::mutex m_EngineStatusMutex;
|
||||||
|
std::mutex m_ThreadStatusMutex;
|
||||||
|
/**
|
||||||
|
* @brief 引擎状态
|
||||||
|
*/
|
||||||
|
XNSim::XNSimStatus::XNEngineStatus m_EngineStatus;
|
||||||
|
/**
|
||||||
|
* @brief 引擎状态更新
|
||||||
|
*/
|
||||||
|
bool m_EngineStatusUpdate = false;
|
||||||
|
/**
|
||||||
|
* @brief 线程状态
|
||||||
|
*/
|
||||||
|
std::map<uint32_t, XNSim::XNSimStatus::XNThreadStatus> m_ThreadStatus;
|
||||||
|
/**
|
||||||
|
* @brief 线程周期计数
|
||||||
|
*/
|
||||||
|
std::map<uint32_t, uint64_t> m_ThreadCycleCount;
|
||||||
|
};
|
310
Release/include/XNMonitor/TopicManager.h
Normal file
310
Release/include/XNMonitor/TopicManager.h
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
/**
|
||||||
|
* @file TopicManager.h
|
||||||
|
* @author jinchao
|
||||||
|
* @brief 主题管理类
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2025-03-10
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2025 COMAC
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNMonitorServer_global.h"
|
||||||
|
#include "XNDataReaderListenerImpl.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 主题管理类
|
||||||
|
*/
|
||||||
|
class TopicManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 删除拷贝构造
|
||||||
|
*/
|
||||||
|
TopicManager(const TopicManager &) = delete;
|
||||||
|
/**
|
||||||
|
* @brief 删除赋值操作
|
||||||
|
*/
|
||||||
|
TopicManager &operator=(const TopicManager &) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取单例
|
||||||
|
* @return TopicManager*: 主题管理类实例
|
||||||
|
*/
|
||||||
|
static TopicManager *Instance()
|
||||||
|
{
|
||||||
|
if (instance == nullptr) {
|
||||||
|
std::lock_guard<std::mutex> locker(instanceMutex);
|
||||||
|
if (instance == nullptr) { // 双重检查锁定
|
||||||
|
instance = new TopicManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 清理参与者
|
||||||
|
*/
|
||||||
|
static void cleanupParticipant()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(instanceMutex);
|
||||||
|
if (instance != nullptr) {
|
||||||
|
instance->clearAllTopic(); // 清理所有主题
|
||||||
|
if (instance->m_Participant != nullptr) {
|
||||||
|
eprosima::fastdds::dds::DomainParticipantFactory::get_instance()
|
||||||
|
->delete_participant(instance->m_Participant); // 删除参与者
|
||||||
|
instance->m_Participant = nullptr; // 设置参与者为空
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 显式构造函数
|
||||||
|
*/
|
||||||
|
explicit TopicManager() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 析构函数
|
||||||
|
*/
|
||||||
|
virtual ~TopicManager() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 初始化参与者
|
||||||
|
* @param domainId: 域ID
|
||||||
|
*/
|
||||||
|
XNDDSErrorCode initializeParticipant(int domainId)
|
||||||
|
{
|
||||||
|
XNParticipantQos participantQos = eprosima::fastdds::dds::PARTICIPANT_QOS_DEFAULT;
|
||||||
|
participantQos.name("XNMonitor"); // 设置参与者名称
|
||||||
|
m_Participant =
|
||||||
|
eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->create_participant(
|
||||||
|
domainId, participantQos); // 创建参与者
|
||||||
|
if (m_Participant == nullptr) {
|
||||||
|
return XNDDSErrorCode::INIT_FAILED;
|
||||||
|
}
|
||||||
|
return XNDDSErrorCode::SUCCESS;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 注册发布者模板函数
|
||||||
|
* @tparam T: 类型
|
||||||
|
* @param topicName: 主题名称
|
||||||
|
* @return XNDataWriter*: 数据写入器
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
XNDDSErrorCode registerPublisher(const std::string &topicName, XNDataWriter *&dataWriter)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(m_Mutex);
|
||||||
|
if (topics_.find(topicName) == topics_.end()) {
|
||||||
|
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); // 创建主题
|
||||||
|
if (tmp.topic == nullptr) {
|
||||||
|
topics_.erase(topicName); // 移除主题
|
||||||
|
return XNDDSErrorCode::TOPIC_CREATE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MonitorTopicInfo &topicInfo = topics_[topicName]; // 获取主题信息
|
||||||
|
if (topicInfo.publisher == nullptr) {
|
||||||
|
topicInfo.publisher = m_Participant->create_publisher(
|
||||||
|
eprosima::fastdds::dds::PUBLISHER_QOS_DEFAULT); // 创建发布者
|
||||||
|
if (topicInfo.publisher == nullptr) {
|
||||||
|
return XNDDSErrorCode::PUBLISHER_CREATE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topicInfo.dataWriter == nullptr) {
|
||||||
|
XNDataWriterQos dataWriterQos;
|
||||||
|
// 设置数据写入器的持久性策略, 使用瞬态本地持久性
|
||||||
|
dataWriterQos.durability().kind = eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS;
|
||||||
|
// 设置数据写入器的生命周期策略, 设置为5秒
|
||||||
|
dataWriterQos.lifespan().duration = eprosima::fastdds::dds::Duration_t(5, 0);
|
||||||
|
topicInfo.dataWriter = topicInfo.publisher->create_datawriter(
|
||||||
|
topicInfo.topic, dataWriterQos); // 创建数据写入器
|
||||||
|
if (topicInfo.dataWriter == nullptr) {
|
||||||
|
return XNDDSErrorCode::DATAWRITER_CREATE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataWriter = topicInfo.dataWriter;
|
||||||
|
return XNDDSErrorCode::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 注销发布者
|
||||||
|
* @param topicName: 主题名称
|
||||||
|
*/
|
||||||
|
void unregisterPublisher(const std::string &topicName)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(m_Mutex);
|
||||||
|
unregisterPublisherWithoutLock(topicName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 注销发布者, 不带锁
|
||||||
|
* @param topicName: 主题名称
|
||||||
|
*/
|
||||||
|
void unregisterPublisherWithoutLock(const std::string &topicName)
|
||||||
|
{
|
||||||
|
auto it = topics_.find(topicName);
|
||||||
|
if (it != topics_.end()) {
|
||||||
|
MonitorTopicInfo &topicInfo = it->second; // 获取主题信息
|
||||||
|
if (topicInfo.dataWriter != nullptr) {
|
||||||
|
topicInfo.publisher->delete_datawriter(topicInfo.dataWriter); // 删除数据写入器
|
||||||
|
topicInfo.dataWriter = nullptr; // 设置数据写入器为空
|
||||||
|
}
|
||||||
|
if (topicInfo.publisher != nullptr) {
|
||||||
|
m_Participant->delete_publisher(topicInfo.publisher); // 删除发布者
|
||||||
|
topicInfo.publisher = nullptr; // 设置发布者为空
|
||||||
|
}
|
||||||
|
if (topicInfo.publisher == nullptr && topicInfo.subscriber == nullptr
|
||||||
|
&& topicInfo.topic != nullptr) {
|
||||||
|
m_Participant->delete_topic(topicInfo.topic); // 删除主题
|
||||||
|
topicInfo.topic = nullptr; // 设置主题为空
|
||||||
|
topics_.erase(it); // 移除主题
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 注册订阅者模板函数
|
||||||
|
* @tparam T: 类型
|
||||||
|
* @param topicName: 主题名称
|
||||||
|
* @param fun: 回调函数
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
XNDDSErrorCode registerSubscriber(const std::string &topicName,
|
||||||
|
std::function<void(const typename T::type &)> fun)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(m_Mutex);
|
||||||
|
if (topics_.find(topicName) == topics_.end()) {
|
||||||
|
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); // 创建主题
|
||||||
|
if (tmp.topic == nullptr) {
|
||||||
|
topics_.erase(topicName); // 移除主题
|
||||||
|
return XNDDSErrorCode::TOPIC_CREATE_FAILED; // 返回
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MonitorTopicInfo &topicInfo = topics_[topicName]; // 获取主题信息
|
||||||
|
if (topicInfo.subscriber == nullptr) {
|
||||||
|
topicInfo.subscriber = m_Participant->create_subscriber(
|
||||||
|
eprosima::fastdds::dds::SUBSCRIBER_QOS_DEFAULT); // 创建订阅者
|
||||||
|
if (topicInfo.subscriber == nullptr) {
|
||||||
|
return XNDDSErrorCode::SUBSCRIBER_CREATE_FAILED; // 返回
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (topicInfo.dataReader == nullptr) {
|
||||||
|
XNDataReaderQos dataReaderQos;
|
||||||
|
dataReaderQos.durability().kind =
|
||||||
|
eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS; // 设置数据读取器的持久性策略
|
||||||
|
topicInfo.listener =
|
||||||
|
new XNDataReaderListenerImpl<typename T::type>(fun); // 创建数据读取器监听器
|
||||||
|
topicInfo.dataReader = topicInfo.subscriber->create_datareader(
|
||||||
|
topicInfo.topic, dataReaderQos, topicInfo.listener); // 创建数据读取器
|
||||||
|
if (topicInfo.dataReader == nullptr) {
|
||||||
|
return XNDDSErrorCode::DATAREADER_CREATE_FAILED; // 返回
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto oldListener = topicInfo.dataReader->get_listener(); // 获取旧的监听器
|
||||||
|
topicInfo.listener =
|
||||||
|
new XNDataReaderListenerImpl<typename T::type>(fun); // 创建新的监听器
|
||||||
|
topicInfo.dataReader->set_listener(
|
||||||
|
topicInfo.listener,
|
||||||
|
eprosima::fastdds::dds::StatusMask::all()); // 设置新的监听器
|
||||||
|
delete oldListener; // 删除旧的监听器
|
||||||
|
}
|
||||||
|
return XNDDSErrorCode::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 注销订阅者, 带锁
|
||||||
|
* @param topicName: 主题名称
|
||||||
|
*/
|
||||||
|
void unregisterSubscriber(const std::string &topicName)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(m_Mutex);
|
||||||
|
unregisterSubscriberWithoutLock(topicName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 注销订阅者, 不带锁
|
||||||
|
* @param topicName: 主题名称
|
||||||
|
*/
|
||||||
|
void unregisterSubscriberWithoutLock(const std::string &topicName)
|
||||||
|
{
|
||||||
|
auto it = topics_.find(topicName);
|
||||||
|
if (it != topics_.end()) {
|
||||||
|
MonitorTopicInfo &topicInfo = it->second; // 获取主题信息
|
||||||
|
if (topicInfo.dataReader != nullptr) {
|
||||||
|
topicInfo.subscriber->delete_datareader(topicInfo.dataReader); // 删除数据读取器
|
||||||
|
topicInfo.dataReader = nullptr; // 设置数据读取器为空
|
||||||
|
}
|
||||||
|
if (topicInfo.listener != nullptr) {
|
||||||
|
delete topicInfo.listener; // 删除监听器
|
||||||
|
topicInfo.listener = nullptr; // 设置监听器为空
|
||||||
|
}
|
||||||
|
if (topicInfo.subscriber != nullptr) {
|
||||||
|
m_Participant->delete_subscriber(topicInfo.subscriber); // 删除订阅者
|
||||||
|
topicInfo.subscriber = nullptr; // 设置订阅者为空
|
||||||
|
}
|
||||||
|
if (topicInfo.subscriber == nullptr && topicInfo.publisher == nullptr
|
||||||
|
&& topicInfo.topic != nullptr) {
|
||||||
|
m_Participant->delete_topic(topicInfo.topic); // 删除主题
|
||||||
|
topicInfo.topic = nullptr; // 设置主题为空
|
||||||
|
topics_.erase(it); // 移除主题
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 清除所有主题
|
||||||
|
*/
|
||||||
|
void clearAllTopic()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(m_Mutex);
|
||||||
|
if (m_Participant != nullptr) {
|
||||||
|
while (!topics_.empty()) {
|
||||||
|
unregisterPublisherWithoutLock(topics_.begin()->first); // 注销发布者
|
||||||
|
unregisterSubscriberWithoutLock(topics_.begin()->first); // 注销订阅者
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 单例指针
|
||||||
|
*/
|
||||||
|
static TopicManager *instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 单例互斥锁
|
||||||
|
*/
|
||||||
|
static std::mutex instanceMutex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 参与者
|
||||||
|
*/
|
||||||
|
XNParticipant *m_Participant = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 主题映射
|
||||||
|
*/
|
||||||
|
std::map<std::string, MonitorTopicInfo> topics_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 主题访问互斥锁
|
||||||
|
*/
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
};
|
270
Release/include/XNMonitor/TypeDefine.h
Normal file
270
Release/include/XNMonitor/TypeDefine.h
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
/**
|
||||||
|
* @file TypeDefine.h
|
||||||
|
* @brief 类型定义头文件
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <typeindex>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include <fastdds/dds/domain/DomainParticipant.hpp>
|
||||||
|
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
|
||||||
|
#include <fastdds/dds/topic/TypeSupport.hpp>
|
||||||
|
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
|
||||||
|
#include <fastdds/dds/subscriber/DataReader.hpp>
|
||||||
|
#include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>
|
||||||
|
#include <fastdds/dds/subscriber/SampleInfo.hpp>
|
||||||
|
#include <fastdds/dds/subscriber/Subscriber.hpp>
|
||||||
|
#include <fastdds/dds/topic/TypeSupport.hpp>
|
||||||
|
#include <fastdds/dds/topic/Topic.hpp>
|
||||||
|
#include <fastdds/dds/topic/TopicDataType.hpp>
|
||||||
|
#include <fastdds/dds/publisher/Publisher.hpp>
|
||||||
|
#include <fastdds/dds/publisher/qos/PublisherQos.hpp>
|
||||||
|
#include <fastdds/dds/publisher/DataWriter.hpp>
|
||||||
|
#include <fastdds/dds/publisher/qos/DataWriterQos.hpp>
|
||||||
|
#include <fastdds/dds/core/status/StatusMask.hpp>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 域参与者
|
||||||
|
*/
|
||||||
|
using XNParticipant = eprosima::fastdds::dds::DomainParticipant;
|
||||||
|
/**
|
||||||
|
* @brief 域参与者Qos
|
||||||
|
*/
|
||||||
|
using XNParticipantQos = eprosima::fastdds::dds::DomainParticipantQos;
|
||||||
|
/**
|
||||||
|
* @brief 域参与者工厂
|
||||||
|
*/
|
||||||
|
using XNParticipantFactory = eprosima::fastdds::dds::DomainParticipantFactory;
|
||||||
|
/**
|
||||||
|
* @brief 数据读取器监听器
|
||||||
|
*/
|
||||||
|
using XNDataReaderListener = eprosima::fastdds::dds::DataReaderListener;
|
||||||
|
/**
|
||||||
|
* @brief 数据读取器
|
||||||
|
*/
|
||||||
|
using XNDataReader = eprosima::fastdds::dds::DataReader;
|
||||||
|
/**
|
||||||
|
* @brief 数据读取器Qos
|
||||||
|
*/
|
||||||
|
using XNDataReaderQos = eprosima::fastdds::dds::DataReaderQos;
|
||||||
|
/**
|
||||||
|
* @brief 样本信息
|
||||||
|
*/
|
||||||
|
using XNSampleInfo = eprosima::fastdds::dds::SampleInfo;
|
||||||
|
/**
|
||||||
|
* @brief 订阅者
|
||||||
|
*/
|
||||||
|
using XNSubscriber = eprosima::fastdds::dds::Subscriber;
|
||||||
|
/**
|
||||||
|
* @brief 类型支持
|
||||||
|
*/
|
||||||
|
using XNTypeSupport = eprosima::fastdds::dds::TypeSupport;
|
||||||
|
/**
|
||||||
|
* @brief 数据写入器
|
||||||
|
*/
|
||||||
|
using XNDataWriter = eprosima::fastdds::dds::DataWriter;
|
||||||
|
/**
|
||||||
|
* @brief 数据写入器Qos
|
||||||
|
*/
|
||||||
|
using XNDataWriterQos = eprosima::fastdds::dds::DataWriterQos;
|
||||||
|
/**
|
||||||
|
* @brief 发布者
|
||||||
|
*/
|
||||||
|
using XNPublisher = eprosima::fastdds::dds::Publisher;
|
||||||
|
/**
|
||||||
|
* @brief 发布者Qos
|
||||||
|
*/
|
||||||
|
using XNPublisherQos = eprosima::fastdds::dds::PublisherQos;
|
||||||
|
/**
|
||||||
|
* @brief 主题
|
||||||
|
*/
|
||||||
|
using XNTopic = eprosima::fastdds::dds::Topic;
|
||||||
|
/**
|
||||||
|
* @brief 主题数据类型
|
||||||
|
*/
|
||||||
|
using XNTopicDataType = eprosima::fastdds::dds::TopicDataType;
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
/**
|
||||||
|
* @brief 主题信息
|
||||||
|
*/
|
||||||
|
struct MonitorTopicInfo {
|
||||||
|
/**
|
||||||
|
* @brief 主题
|
||||||
|
*/
|
||||||
|
XNTopic *topic;
|
||||||
|
/**
|
||||||
|
* @brief 发布者
|
||||||
|
*/
|
||||||
|
XNPublisher *publisher;
|
||||||
|
/**
|
||||||
|
* @brief 数据写入器
|
||||||
|
*/
|
||||||
|
XNDataWriter *dataWriter;
|
||||||
|
/**
|
||||||
|
* @brief 订阅者
|
||||||
|
*/
|
||||||
|
XNSubscriber *subscriber;
|
||||||
|
/**
|
||||||
|
* @brief 数据读取器
|
||||||
|
*/
|
||||||
|
XNDataReader *dataReader;
|
||||||
|
/**
|
||||||
|
* @brief 数据读取器监听器
|
||||||
|
*/
|
||||||
|
XNDataReaderListener *listener;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 错误码定义
|
||||||
|
enum class XNDDSErrorCode {
|
||||||
|
SUCCESS = 0,
|
||||||
|
INIT_FAILED = -1,
|
||||||
|
TOPIC_CREATE_FAILED = -2,
|
||||||
|
PUBLISHER_CREATE_FAILED = -3,
|
||||||
|
SUBSCRIBER_CREATE_FAILED = -4,
|
||||||
|
DATAWRITER_CREATE_FAILED = -5,
|
||||||
|
DATAREADER_CREATE_FAILED = -6,
|
||||||
|
INVALID_PARAM = -7,
|
||||||
|
NOT_INITIALIZED = -8
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 成员变量定义结构体
|
||||||
|
* @note 成员变量包含数据类型、变量名、是否为数组、数组大小、描述
|
||||||
|
*/
|
||||||
|
struct MemberVariable {
|
||||||
|
/**
|
||||||
|
* @brief 数据类型
|
||||||
|
*/
|
||||||
|
std::string dataType;
|
||||||
|
/**
|
||||||
|
* @brief 变量名
|
||||||
|
*/
|
||||||
|
std::string variableName;
|
||||||
|
/**
|
||||||
|
* @brief 是否为数组
|
||||||
|
*/
|
||||||
|
bool isArray;
|
||||||
|
/**
|
||||||
|
* @brief 数组大小
|
||||||
|
*/
|
||||||
|
std::vector<int> arraySizes;
|
||||||
|
/**
|
||||||
|
* @brief 描述
|
||||||
|
*/
|
||||||
|
std::string description;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 接口结构体定义结构体
|
||||||
|
* @note 接口结构体定义包含结构体名称、成员变量
|
||||||
|
*/
|
||||||
|
struct StructDefinition {
|
||||||
|
/**
|
||||||
|
* @brief 结构体名称
|
||||||
|
*/
|
||||||
|
std::string structName;
|
||||||
|
/**
|
||||||
|
* @brief 成员变量
|
||||||
|
*/
|
||||||
|
std::vector<std::shared_ptr<MemberVariable>> memberVariables;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 命名空间定义结构体
|
||||||
|
* @note 命名空间定义包含命名空间名称、接口结构体定义、子命名空间定义
|
||||||
|
*/
|
||||||
|
struct NamespaceDefinition {
|
||||||
|
/**
|
||||||
|
* @brief 命名空间名称
|
||||||
|
*/
|
||||||
|
std::string namespaceName;
|
||||||
|
/**
|
||||||
|
* @brief 结构体定义
|
||||||
|
*/
|
||||||
|
std::vector<std::shared_ptr<StructDefinition>> structDefinitions;
|
||||||
|
/**
|
||||||
|
* @brief 子命名空间
|
||||||
|
*/
|
||||||
|
std::vector<std::shared_ptr<NamespaceDefinition>> childNamespaces;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 模型接口定义
|
||||||
|
* @note 模型接口定义包含模型名称和接口命名空间定义
|
||||||
|
*/
|
||||||
|
struct ModelDefinition {
|
||||||
|
/**
|
||||||
|
* @brief 模型名称
|
||||||
|
*/
|
||||||
|
std::string modelName;
|
||||||
|
/**
|
||||||
|
* @brief 命名空间定义
|
||||||
|
*/
|
||||||
|
std::vector<std::shared_ptr<NamespaceDefinition>> namespaceDefinitions;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MonitorDataInfo {
|
||||||
|
/**
|
||||||
|
* @brief 结构体名称
|
||||||
|
*/
|
||||||
|
std::string structName;
|
||||||
|
/**
|
||||||
|
* @brief 接口名称
|
||||||
|
*/
|
||||||
|
std::vector<std::string> interfaceNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 数组大小
|
||||||
|
*/
|
||||||
|
std::vector<std::pair<int, int>> arraySizes;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CSVHeaderField {
|
||||||
|
/**
|
||||||
|
* @brief 字段名
|
||||||
|
*/
|
||||||
|
std::string fieldName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 结构体名称
|
||||||
|
*/
|
||||||
|
std::string structName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 数组维度
|
||||||
|
*/
|
||||||
|
int arrayDim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 数组索引1
|
||||||
|
*/
|
||||||
|
int arrayIndex1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 数组索引2
|
||||||
|
*/
|
||||||
|
int arrayIndex2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 列大小
|
||||||
|
*/
|
||||||
|
int arraySize2;
|
||||||
|
};
|
51
Release/include/XNMonitor/XNDataReaderListenerImpl.h
Normal file
51
Release/include/XNMonitor/XNDataReaderListenerImpl.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* @file XNDataReaderListenerImpl.h
|
||||||
|
* @author jinchao
|
||||||
|
* @brief 数据读取器监听器模板类
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2025-03-10
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2025 COMAC
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 数据读取器监听器模板类
|
||||||
|
* @tparam T 数据类型
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class XNDataReaderListenerImpl : public XNDataReaderListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 构造函数
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
|
XNDataReaderListenerImpl(std::function<void(const T &)> callback) : callback_(callback) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 数据可用回调函数
|
||||||
|
* @param reader 数据读取器
|
||||||
|
*/
|
||||||
|
void on_data_available(XNDataReader *reader) override
|
||||||
|
{
|
||||||
|
XNSampleInfo info;
|
||||||
|
if (reader->take_next_sample(&data_, &info) == eprosima::fastdds::dds::RETCODE_OK
|
||||||
|
&& info.valid_data) {
|
||||||
|
callback_(data_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 数据
|
||||||
|
*/
|
||||||
|
T data_;
|
||||||
|
/**
|
||||||
|
* @brief 回调函数
|
||||||
|
*/
|
||||||
|
std::function<void(const T &)> callback_;
|
||||||
|
};
|
281
Release/include/XNMonitor/XNMonitorInterface.h
Normal file
281
Release/include/XNMonitor/XNMonitorInterface.h
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
/**
|
||||||
|
* @file XNMonitorInterface.h
|
||||||
|
* @brief 监控服务器接口定义
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
#include "XNMonitorServer_global.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief 初始化DDS监控服务器
|
||||||
|
* @param domainId 域ID
|
||||||
|
* @param domainIdLen 域ID长度
|
||||||
|
* @param confID 构型ID
|
||||||
|
* @param errorMsg 错误信息
|
||||||
|
* @param errorMsgSize 错误信息大小
|
||||||
|
* @return 0: 成功, -1: 失败
|
||||||
|
*/
|
||||||
|
int XNMONITORSERVER_EXPORT XN_Initialize(const char *domainId, int domainIdLen, int confID,
|
||||||
|
int forceGen, 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
//******************** 数据监控 *********************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 停止数据监控
|
||||||
|
* @param structName 结构体名称
|
||||||
|
* @param structNameLen 结构体名称长度
|
||||||
|
* @param errorMsg 错误信息
|
||||||
|
* @param errorMsgSize 错误信息大小
|
||||||
|
*/
|
||||||
|
void XNMONITORSERVER_EXPORT XN_StopDataMonitor(const char *structName, const int structNameLen,
|
||||||
|
char *errorMsg, int errorMsgSize);
|
||||||
|
|
||||||
|
//******************** 数据注入 *********************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 infoMsg 错误信息
|
||||||
|
* @param infoMsgSize 错误信息大小
|
||||||
|
* @return 0: 成功, -1: 失败
|
||||||
|
*/
|
||||||
|
int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv(const char *InjectDataInfo,
|
||||||
|
const int InjectDataInfoLen,
|
||||||
|
const char *csvFilePath,
|
||||||
|
const int csvFilePathLen,
|
||||||
|
char *infoMsg, int infoMsgSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取csv数据注入状态
|
||||||
|
* @param infoMsg 错误信息
|
||||||
|
* @param infoMsgSize 错误信息大小
|
||||||
|
* @return 0: 成功, -1: 失败, 1: 正在注入
|
||||||
|
*/
|
||||||
|
int XNMONITORSERVER_EXPORT XN_GetCsvDataInjectStatus(char *infoMsg, int infoMsgSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 停止csv数据注入
|
||||||
|
* @param infoMsg 错误信息
|
||||||
|
* @param infoMsgSize 错误信息大小
|
||||||
|
* @return 0: 成功, -1: 失败
|
||||||
|
*/
|
||||||
|
int XNMONITORSERVER_EXPORT XN_StopCsvDataInject(char *infoMsg, int infoMsgSize);
|
||||||
|
|
||||||
|
//******************** csv数据采集 *********************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取dcs采集脚本并将数据保存到csv文件接口
|
||||||
|
* @param CollectDataInfo 采集数据信息JSON数组字符串
|
||||||
|
* @param CollectDataInfoLen 采集数据信息JSON数组字符串长度
|
||||||
|
* @param dcsFilePath dcs文件路径
|
||||||
|
* @param dcsFilePathLen dcs文件路径长度
|
||||||
|
* @param infoMsg 错误信息
|
||||||
|
* @param infoMsgSize 错误信息大小
|
||||||
|
* @return 0: 成功, -1: 失败
|
||||||
|
*/
|
||||||
|
int XNMONITORSERVER_EXPORT XN_StartCollectData(const char *CollectDataInfo,
|
||||||
|
const int CollectDataInfoLen,
|
||||||
|
const char *dcsFilePath,
|
||||||
|
const int dcsFilePathLen, char *infoMsg,
|
||||||
|
int infoMsgSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取csv数据采集状态
|
||||||
|
* @param infoMsg 错误信息
|
||||||
|
* @param infoMsgSize 错误信息大小
|
||||||
|
* @return 0: 成功, -1: 失败, 1: 正在采集
|
||||||
|
*/
|
||||||
|
int XNMONITORSERVER_EXPORT XN_GetCollectDataStatus(char *infoMsg, int infoMsgSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 停止采集数据
|
||||||
|
* @param infoMsg 错误信息
|
||||||
|
* @param infoMsgSize 错误信息大小
|
||||||
|
* @return 0: 成功, -1: 失败
|
||||||
|
*/
|
||||||
|
int XNMONITORSERVER_EXPORT XN_StopCollectData(char *infoMsg, int infoMsgSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 清理所有资源
|
||||||
|
*/
|
||||||
|
void XNMONITORSERVER_EXPORT XN_Cleanup();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
7
Release/include/XNMonitor/XNMonitorServer_global.h
Normal file
7
Release/include/XNMonitor/XNMonitorServer_global.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef XNMonitorServer_EXPORTS
|
||||||
|
# define XNMONITORSERVER_EXPORT __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define XNMONITORSERVER_EXPORT __attribute__((visibility("default")))
|
||||||
|
#endif
|
@ -439,10 +439,11 @@ bool XNModelGen::GenerateSourceFile()
|
|||||||
sourceFile << "void " << m_className << "::ReleaseData() {" << std::endl;
|
sourceFile << "void " << m_className << "::ReleaseData() {" << std::endl;
|
||||||
sourceFile << " T_D();" << std::endl;
|
sourceFile << " T_D();" << std::endl;
|
||||||
if (!m_inputStructName.structName.empty()) {
|
if (!m_inputStructName.structName.empty()) {
|
||||||
sourceFile << " // TODO: 在这里释放输入数据" << std::endl;
|
|
||||||
sourceFile << std::endl;
|
|
||||||
if (m_inputStructName.isPointer) {
|
if (m_inputStructName.isPointer) {
|
||||||
sourceFile << " if (d->_data." << m_inputStructName.structName << ") {" << std::endl;
|
sourceFile << " if (d->_data." << m_inputStructName.structName << ") {" << std::endl;
|
||||||
|
sourceFile << " // TODO: 在这里释放输入数据" << std::endl;
|
||||||
|
sourceFile << std::endl;
|
||||||
sourceFile << " delete d->_data." << m_inputStructName.structName << ";"
|
sourceFile << " delete d->_data." << m_inputStructName.structName << ";"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
sourceFile << " d->_data." << m_inputStructName.structName << " = nullptr;"
|
sourceFile << " d->_data." << m_inputStructName.structName << " = nullptr;"
|
||||||
@ -451,11 +452,11 @@ bool XNModelGen::GenerateSourceFile()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!m_outputStructName.structName.empty()) {
|
if (!m_outputStructName.structName.empty()) {
|
||||||
sourceFile << " // TODO: 在这里释放输出数据" << std::endl;
|
|
||||||
sourceFile << std::endl;
|
|
||||||
if (m_outputStructName.isPointer) {
|
if (m_outputStructName.isPointer) {
|
||||||
sourceFile << " if (d->_data." << m_outputStructName.structName << ") {"
|
sourceFile << " if (d->_data." << m_outputStructName.structName << ") {"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
sourceFile << " // TODO: 在这里释放输出数据" << std::endl;
|
||||||
|
sourceFile << std::endl;
|
||||||
sourceFile << " delete d->_data." << m_outputStructName.structName << ";"
|
sourceFile << " delete d->_data." << m_outputStructName.structName << ";"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
sourceFile << " d->_data." << m_outputStructName.structName << " = nullptr;"
|
sourceFile << " d->_data." << m_outputStructName.structName << " = nullptr;"
|
||||||
|
3
XNMonitorServer/.vscode/settings.json
vendored
3
XNMonitorServer/.vscode/settings.json
vendored
@ -73,6 +73,7 @@
|
|||||||
"any": "cpp",
|
"any": "cpp",
|
||||||
"forward_list": "cpp",
|
"forward_list": "cpp",
|
||||||
"fstream": "cpp",
|
"fstream": "cpp",
|
||||||
"valarray": "cpp"
|
"valarray": "cpp",
|
||||||
|
"*.ipp": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,11 @@ else()
|
|||||||
message(FATAL_ERROR "Environment variable XNCore is not set.")
|
message(FATAL_ERROR "Environment variable XNCore is not set.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# file(GLOB DDS_XNIDL_SOURCES_CXX "../XNCore/XNIDL/*.cxx")
|
|
||||||
include_directories(${XNCore_PATH}/include)
|
include_directories(${XNCore_PATH}/include)
|
||||||
include_directories(${XNCore_PATH}/Configuration/C909_V1)
|
|
||||||
|
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
find_package(nlohmann_json 3.9.1 REQUIRED)
|
find_package(nlohmann_json 3.9.1 REQUIRED)
|
||||||
|
find_package(SQLite3 REQUIRED)
|
||||||
|
|
||||||
add_library(XNMonitorServer SHARED
|
add_library(XNMonitorServer SHARED
|
||||||
XNMonitorServer_global.h
|
XNMonitorServer_global.h
|
||||||
@ -50,6 +49,11 @@ add_library(XNMonitorServer SHARED
|
|||||||
CSVDataInjectThread.cpp
|
CSVDataInjectThread.cpp
|
||||||
DataCollect.h
|
DataCollect.h
|
||||||
DataCollect.cpp
|
DataCollect.cpp
|
||||||
|
PluginManager.h
|
||||||
|
PluginManager.cpp
|
||||||
|
PluginInterface.h
|
||||||
|
PluginGenerator.h
|
||||||
|
PluginGenerator.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# 添加头文件搜索路径
|
# 添加头文件搜索路径
|
||||||
@ -61,8 +65,9 @@ target_link_libraries(XNMonitorServer PRIVATE
|
|||||||
fastdds
|
fastdds
|
||||||
OpenSSL::SSL
|
OpenSSL::SSL
|
||||||
OpenSSL::Crypto
|
OpenSSL::Crypto
|
||||||
|
SQLite::SQLite3
|
||||||
${XNCore_PATH}/lib/libXNCore.so
|
${XNCore_PATH}/lib/libXNCore.so
|
||||||
${XNCore_PATH}/lib/libC909_V1_Interface.so
|
dl
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(XNMonitorServer PRIVATE XNMONITOR_SERVER_LIBRARY)
|
target_compile_definitions(XNMonitorServer PRIVATE XNMONITOR_SERVER_LIBRARY)
|
||||||
@ -77,3 +82,9 @@ install(TARGETS XNMonitorServer
|
|||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
RUNTIME DESTINATION .
|
RUNTIME DESTINATION .
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#添加自定义命令和目标以拷贝所有头文件
|
||||||
|
file(GLOB HEADER_FILES "*.h")
|
||||||
|
|
||||||
|
# 使用 install 命令在安装时拷贝头文件
|
||||||
|
install(FILES ${HEADER_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/XNMonitor)
|
||||||
|
@ -1,6 +1,24 @@
|
|||||||
#include "DataMonitorFactory.h"
|
#include "DataMonitorFactory.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
|
||||||
// 静态成员初始化
|
DataMonitorBasePtr DataMonitorFactory::GetInstance(const std::string &interfaceName)
|
||||||
std::mutex DataMonitorFactory::mutex_;
|
{
|
||||||
|
return PluginManager::Instance().GetMonitor(interfaceName);
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<std::type_index, DataMonitorBasePtr> DataMonitorFactory::instances_;
|
void DataMonitorFactory::ReleaseInstance(const std::string &interfaceName)
|
||||||
|
{
|
||||||
|
// 插件管理器会自动管理实例生命周期
|
||||||
|
// 这里可以添加额外的清理逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataMonitorFactory::HasInterface(const std::string &interfaceName)
|
||||||
|
{
|
||||||
|
auto interfaces = PluginManager::Instance().GetSupportedInterfaces();
|
||||||
|
return std::find(interfaces.begin(), interfaces.end(), interfaceName) != interfaces.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> DataMonitorFactory::GetRegisteredInterfaces()
|
||||||
|
{
|
||||||
|
return PluginManager::Instance().GetSupportedInterfaces();
|
||||||
|
}
|
@ -3,108 +3,23 @@
|
|||||||
#include "XNMonitorServer_global.h"
|
#include "XNMonitorServer_global.h"
|
||||||
#include "DataMonitor.h"
|
#include "DataMonitor.h"
|
||||||
|
|
||||||
//接口头文件
|
|
||||||
#include <IDL/C909_V1_Interface.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief DataMonitor工厂类,用于创建不同类型的DataMonitor实例
|
* @brief DataMonitor工厂类,用于创建不同类型的DataMonitor实例
|
||||||
*/
|
*/
|
||||||
class XNMONITORSERVER_EXPORT DataMonitorFactory
|
class XNMONITORSERVER_EXPORT DataMonitorFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static DataMonitorBasePtr GetInstance(const std::string &interfaceName)
|
static DataMonitorBasePtr GetInstance(const std::string &interfaceName);
|
||||||
{
|
|
||||||
if (interfaceName == "Aerodynamics_heartbeat") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::Aerodynamics_heartbeat_Interface>();
|
|
||||||
} else if (interfaceName == "Aerodynamics_input") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::Aerodynamics_input_Interface>();
|
|
||||||
} else if (interfaceName == "Aerodynamics_output") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::Aerodynamics_output_Interface>();
|
|
||||||
} else if (interfaceName == "GroundHandling_heartbeat") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::GroundHandling_heartbeat_Interface>();
|
|
||||||
} else if (interfaceName == "GroundHandling_input") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::GroundHandling_input_Interface>();
|
|
||||||
} else if (interfaceName == "GroundHandling_output") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::GroundHandling_output_Interface>();
|
|
||||||
} else if (interfaceName == "WeightBalance_heartbeat") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::WeightBalance_heartbeat_Interface>();
|
|
||||||
} else if (interfaceName == "WeightBalance_input") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::WeightBalance_input_Interface>();
|
|
||||||
} else if (interfaceName == "WeightBalance_output") {
|
|
||||||
return GetInstance<XNSim::C909::ATA04::WeightBalance_output_Interface>();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ReleaseInstance(const std::string &interfaceName)
|
static void ReleaseInstance(const std::string &interfaceName);
|
||||||
{
|
|
||||||
if (interfaceName == "Aerodynamics_heartbeat") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::Aerodynamics_heartbeat_Interface>();
|
|
||||||
} else if (interfaceName == "Aerodynamics_input") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::Aerodynamics_input_Interface>();
|
|
||||||
} else if (interfaceName == "Aerodynamics_output") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::Aerodynamics_output_Interface>();
|
|
||||||
} else if (interfaceName == "GroundHandling_heartbeat") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::GroundHandling_heartbeat_Interface>();
|
|
||||||
} else if (interfaceName == "GroundHandling_input") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::GroundHandling_input_Interface>();
|
|
||||||
} else if (interfaceName == "GroundHandling_output") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::GroundHandling_output_Interface>();
|
|
||||||
} else if (interfaceName == "WeightBalance_heartbeat") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::WeightBalance_heartbeat_Interface>();
|
|
||||||
} else if (interfaceName == "WeightBalance_input") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::WeightBalance_input_Interface>();
|
|
||||||
} else if (interfaceName == "WeightBalance_output") {
|
|
||||||
ReleaseInstance<XNSim::C909::ATA04::WeightBalance_output_Interface>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
// 检查接口是否存在
|
||||||
/**
|
static bool HasInterface(const std::string &interfaceName);
|
||||||
* @brief 创建DataMonitor实例
|
|
||||||
* @param framework 框架指针
|
|
||||||
* @param modelId 模型ID
|
|
||||||
* @param DDS_type DDS类型
|
|
||||||
* @return 返回创建的DataMonitor实例的智能指针
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
static DataMonitorBasePtr GetInstance()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
|
|
||||||
// 使用type_index作为键,更可靠的类型标识
|
// 获取所有已注册的接口名称
|
||||||
std::type_index typeIndex(typeid(T));
|
static std::vector<std::string> GetRegisteredInterfaces();
|
||||||
|
|
||||||
// 检查是否已存在实例
|
|
||||||
auto it = instances_.find(typeIndex);
|
|
||||||
if (it != instances_.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建新实例
|
|
||||||
auto monitor = std::make_shared<DataMonitorProduct<T>>();
|
|
||||||
instances_[typeIndex] = monitor;
|
|
||||||
return monitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 释放指定类型的实例
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
static void ReleaseInstance()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
std::type_index typeIndex(typeid(T));
|
|
||||||
if (instances_.find(typeIndex) == instances_.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
instances_.erase(typeIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataMonitorFactory() = delete;
|
DataMonitorFactory() = delete;
|
||||||
~DataMonitorFactory() = delete;
|
~DataMonitorFactory() = delete;
|
||||||
|
|
||||||
static std::mutex mutex_;
|
|
||||||
static std::unordered_map<std::type_index, DataMonitorBasePtr> instances_;
|
|
||||||
};
|
};
|
||||||
|
379
XNMonitorServer/PluginGenerator.cpp
Normal file
379
XNMonitorServer/PluginGenerator.cpp
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
/**
|
||||||
|
* @file PluginGenerator.cpp
|
||||||
|
* @brief 简化的插件生成器实现
|
||||||
|
*/
|
||||||
|
#include "PluginGenerator.h"
|
||||||
|
|
||||||
|
std::string GetXNCorePath()
|
||||||
|
{
|
||||||
|
const char *xnCorePath = std::getenv("XNCore");
|
||||||
|
if (xnCorePath != nullptr) {
|
||||||
|
return std::string(xnCorePath);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginGenerator::PluginGenerator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginGenerator::~PluginGenerator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginGenerator::loadPluginFromDatabase(const int confID)
|
||||||
|
{
|
||||||
|
std::string xncorePath = GetXNCorePath();
|
||||||
|
if (xncorePath.empty()) {
|
||||||
|
m_lastError = "无法获取XNCore环境变量的值!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dbPath = xncorePath + "/database/XNSim.db";
|
||||||
|
if (!std::filesystem::exists(dbPath)) {
|
||||||
|
m_lastError = "数据库文件不存在!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3 *db = nullptr;
|
||||||
|
int rc = sqlite3_open(dbPath.c_str(), &db);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
m_lastError = "无法打开数据库: " + std::string(sqlite3_errmsg(db));
|
||||||
|
sqlite3_close(db);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 准备SQL语句查询Configuration表
|
||||||
|
const char *sql = "SELECT ConfName FROM Configuration WHERE ConfID = ?";
|
||||||
|
sqlite3_stmt *stmt = nullptr;
|
||||||
|
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
m_lastError = "SQL准备失败: " + std::string(sqlite3_errmsg(db));
|
||||||
|
sqlite3_close(db);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绑定参数
|
||||||
|
sqlite3_bind_int(stmt, 1, confID);
|
||||||
|
|
||||||
|
// 执行查询
|
||||||
|
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||||
|
const char *text = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0));
|
||||||
|
m_pluginInfo.pluginName = text ? text : "";
|
||||||
|
m_pluginInfo.interfaceHeaderPath = "../IDL/" + m_pluginInfo.pluginName + "_Interface.h";
|
||||||
|
m_pluginInfo.outputDirectory =
|
||||||
|
xncorePath + "/Configuration/" + m_pluginInfo.pluginName + "/PluginCode";
|
||||||
|
} else {
|
||||||
|
m_lastError = "未找到ConfID为 " + std::to_string(confID) + " 的配置";
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
sqlite3_close(db);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理资源
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
|
||||||
|
// 查询DataInterface_{ConfID}表获取接口信息
|
||||||
|
std::string dataInterfaceTableName = "DataInterface_" + std::to_string(confID);
|
||||||
|
std::string dataInterfaceSql =
|
||||||
|
"SELECT DISTINCT ModelStructName, SystemName, PlaneName, ATAName FROM "
|
||||||
|
+ dataInterfaceTableName;
|
||||||
|
|
||||||
|
sqlite3_stmt *dataInterfaceStmt = nullptr;
|
||||||
|
rc = sqlite3_prepare_v2(db, dataInterfaceSql.c_str(), -1, &dataInterfaceStmt, nullptr);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
m_lastError = "DataInterface表SQL准备失败: " + std::string(sqlite3_errmsg(db));
|
||||||
|
sqlite3_close(db);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行查询并收集接口信息
|
||||||
|
while (sqlite3_step(dataInterfaceStmt) == SQLITE_ROW) {
|
||||||
|
InterfaceInfo interface;
|
||||||
|
interface.interfaceName =
|
||||||
|
reinterpret_cast<const char *>(sqlite3_column_text(dataInterfaceStmt, 0));
|
||||||
|
std::string systemName =
|
||||||
|
reinterpret_cast<const char *>(sqlite3_column_text(dataInterfaceStmt, 1));
|
||||||
|
std::string planeName =
|
||||||
|
reinterpret_cast<const char *>(sqlite3_column_text(dataInterfaceStmt, 2));
|
||||||
|
std::string ataName =
|
||||||
|
reinterpret_cast<const char *>(sqlite3_column_text(dataInterfaceStmt, 3));
|
||||||
|
interface.templateType = systemName + "::" + planeName + "::" + ataName
|
||||||
|
+ "::" + interface.interfaceName + "_Interface";
|
||||||
|
|
||||||
|
// 使用ModelStructName去重
|
||||||
|
bool isDuplicate = false;
|
||||||
|
for (const auto &existingInterface : m_pluginInfo.interfaces) {
|
||||||
|
if (existingInterface.interfaceName == interface.interfaceName) {
|
||||||
|
isDuplicate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isDuplicate) {
|
||||||
|
m_pluginInfo.interfaces.push_back(interface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理DataInterface查询资源
|
||||||
|
sqlite3_finalize(dataInterfaceStmt);
|
||||||
|
sqlite3_close(db);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginGenerator::generatePluginCpp()
|
||||||
|
{
|
||||||
|
std::string content = generatePluginCppContent();
|
||||||
|
std::string filePath =
|
||||||
|
m_pluginInfo.outputDirectory + "/" + m_pluginInfo.pluginName + "_plugin.cpp";
|
||||||
|
return writeFile(filePath, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginGenerator::generateCMakeLists()
|
||||||
|
{
|
||||||
|
std::string content = generateCMakeListsContent();
|
||||||
|
std::string filePath = m_pluginInfo.outputDirectory + "/CMakeLists.txt";
|
||||||
|
return writeFile(filePath, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginGenerator::compilePlugin()
|
||||||
|
{
|
||||||
|
std::string buildDir = m_pluginInfo.outputDirectory + "/build";
|
||||||
|
// 如果build目录已存在则删除
|
||||||
|
if (std::filesystem::exists(buildDir)) {
|
||||||
|
try {
|
||||||
|
std::filesystem::remove_all(buildDir);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
m_lastError = "Failed to remove existing build directory: " + std::string(e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 创建build目录
|
||||||
|
if (!createDirectory(buildDir)) {
|
||||||
|
m_lastError = "Failed to create build directory: " + buildDir;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建命令
|
||||||
|
std::string cmakeCmd = "cd " + buildDir + " && cmake ..";
|
||||||
|
std::string makeCmd = "cd " + buildDir + " && make";
|
||||||
|
std::string installCmd = "cd " + buildDir + " && make install";
|
||||||
|
|
||||||
|
// 执行cmake
|
||||||
|
int cmakeResult = system(cmakeCmd.c_str());
|
||||||
|
if (cmakeResult != 0) {
|
||||||
|
m_lastError = "CMake failed with exit code: " + std::to_string(cmakeResult);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行make
|
||||||
|
int makeResult = system(makeCmd.c_str());
|
||||||
|
if (makeResult != 0) {
|
||||||
|
m_lastError = "Make failed with exit code: " + std::to_string(makeResult);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行make install
|
||||||
|
int installResult = system(installCmd.c_str());
|
||||||
|
if (installResult != 0) {
|
||||||
|
m_lastError = "Make install failed with exit code: " + std::to_string(installResult);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PluginGenerator::getLastError() const
|
||||||
|
{
|
||||||
|
return m_lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PluginGenerator::generatePluginCppContent()
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
// 生成头文件包含
|
||||||
|
ss << "#include <XNMonitor/PluginInterface.h>\n";
|
||||||
|
ss << "#include <XNMonitor/DataMonitor.h>\n";
|
||||||
|
ss << "// " << m_pluginInfo.pluginName << "接口头文件 - 只在插件中包含\n";
|
||||||
|
ss << "#include \"" << m_pluginInfo.interfaceHeaderPath << "\"\n\n";
|
||||||
|
|
||||||
|
// 生成插件信息
|
||||||
|
ss << "// 插件信息\n";
|
||||||
|
ss << "static PluginInfo plugin_info = {\"" << m_pluginInfo.pluginName << "\", \""
|
||||||
|
<< "" << "\", DATAMONITOR_PLUGIN_INTERFACE_VERSION};\n\n";
|
||||||
|
|
||||||
|
// 生成支持的接口列表
|
||||||
|
ss << "// 支持的接口列表\n";
|
||||||
|
ss << "static const char *supported_interfaces[] = {\n";
|
||||||
|
for (size_t i = 0; i < m_pluginInfo.interfaces.size(); ++i) {
|
||||||
|
ss << " \"" << m_pluginInfo.interfaces[i].interfaceName << "\"";
|
||||||
|
if (i < m_pluginInfo.interfaces.size() - 1) {
|
||||||
|
ss << ",";
|
||||||
|
}
|
||||||
|
ss << "\n";
|
||||||
|
}
|
||||||
|
ss << "};\n\n";
|
||||||
|
|
||||||
|
ss << "static const int interface_count = sizeof(supported_interfaces) / "
|
||||||
|
"sizeof(supported_interfaces[0]);\n\n";
|
||||||
|
|
||||||
|
// 生成导出的插件函数
|
||||||
|
ss << "// 导出的插件函数\n";
|
||||||
|
ss << "extern \"C\"\n";
|
||||||
|
ss << "{\n\n";
|
||||||
|
|
||||||
|
// get_plugin_info函数
|
||||||
|
ss << " PluginInfo *get_plugin_info()\n";
|
||||||
|
ss << " {\n";
|
||||||
|
ss << " return &plugin_info;\n";
|
||||||
|
ss << " }\n\n";
|
||||||
|
|
||||||
|
// create_monitor函数
|
||||||
|
ss << " DataMonitorBasePtr create_monitor(const char *interfaceName)\n";
|
||||||
|
ss << " {\n";
|
||||||
|
ss << " std::string name(interfaceName);\n\n";
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_pluginInfo.interfaces.size(); ++i) {
|
||||||
|
const auto &interface = m_pluginInfo.interfaces[i];
|
||||||
|
ss << " if (name == \"" << interface.interfaceName << "\") {\n";
|
||||||
|
ss << " return std::make_shared<DataMonitorProduct<" << interface.templateType
|
||||||
|
<< ">>();\n";
|
||||||
|
ss << " }";
|
||||||
|
if (i < m_pluginInfo.interfaces.size() - 1) {
|
||||||
|
ss << " else";
|
||||||
|
}
|
||||||
|
ss << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << " return nullptr;\n";
|
||||||
|
ss << " }\n\n";
|
||||||
|
|
||||||
|
// destroy_monitor函数
|
||||||
|
ss << " void destroy_monitor(const char *interfaceName)\n";
|
||||||
|
ss << " {\n";
|
||||||
|
ss << " // 智能指针会自动管理内存,这里可以添加额外的清理逻辑\n";
|
||||||
|
ss << " }\n\n";
|
||||||
|
|
||||||
|
// get_supported_interfaces函数
|
||||||
|
ss << " const char **get_supported_interfaces(int *count)\n";
|
||||||
|
ss << " {\n";
|
||||||
|
ss << " if (count) {\n";
|
||||||
|
ss << " *count = interface_count;\n";
|
||||||
|
ss << " }\n";
|
||||||
|
ss << " return const_cast<const char **>(supported_interfaces);\n";
|
||||||
|
ss << " }\n\n";
|
||||||
|
|
||||||
|
// free_string_array函数
|
||||||
|
ss << " void free_string_array(const char **array)\n";
|
||||||
|
ss << " {\n";
|
||||||
|
ss << " // 这里不需要释放,因为使用的是静态数组\n";
|
||||||
|
ss << " }\n";
|
||||||
|
ss << "}\n";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PluginGenerator::generateCMakeListsContent()
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
std::string projectName = m_pluginInfo.pluginName + "_Monitor";
|
||||||
|
|
||||||
|
ss << "# CMakeLists.txt for " << projectName << " plugin\n";
|
||||||
|
ss << "cmake_minimum_required(VERSION 3.10)\n\n";
|
||||||
|
|
||||||
|
ss << "# 设置项目名称\n";
|
||||||
|
ss << "project(" << projectName << "_plugin)\n\n";
|
||||||
|
|
||||||
|
ss << "# 设置C++标准\n";
|
||||||
|
ss << "set(CMAKE_CXX_STANDARD 17)\n";
|
||||||
|
ss << "set(CMAKE_CXX_STANDARD_REQUIRED ON)\n\n";
|
||||||
|
|
||||||
|
ss << "# 查找必要的包\n";
|
||||||
|
ss << "find_package(PkgConfig REQUIRED)\n";
|
||||||
|
ss << "find_package(FastDDS REQUIRED)\n";
|
||||||
|
|
||||||
|
ss << "if(DEFINED ENV{XNCore})\n";
|
||||||
|
ss << " set(XNCore_PATH $ENV{XNCore})\n";
|
||||||
|
ss << "else()\n";
|
||||||
|
ss << " message(FATAL_ERROR \"Environment variable XNCore is not set.\")\n";
|
||||||
|
ss << "endif()\n";
|
||||||
|
|
||||||
|
ss << "include_directories(${XNCore_PATH}/include)\n";
|
||||||
|
|
||||||
|
ss << "# 创建插件库\n";
|
||||||
|
ss << "add_library(" << projectName << " SHARED\n";
|
||||||
|
ss << " " << m_pluginInfo.pluginName << "_plugin.cpp\n";
|
||||||
|
ss << ")\n\n";
|
||||||
|
|
||||||
|
ss << "# 链接库\n";
|
||||||
|
ss << "target_link_libraries(" << projectName << "\n";
|
||||||
|
ss << " fastcdr\n";
|
||||||
|
ss << " fastdds\n";
|
||||||
|
ss << " OpenSSL::SSL\n";
|
||||||
|
ss << " OpenSSL::Crypto\n";
|
||||||
|
ss << " ${XNCore_PATH}/lib/lib" << m_pluginInfo.pluginName << "_Interface.so\n";
|
||||||
|
ss << " ${XNCore_PATH}/lib/libXNMonitorServer.so\n";
|
||||||
|
ss << ")\n\n";
|
||||||
|
|
||||||
|
ss << "target_compile_definitions(" << projectName << " PRIVATE " << projectName
|
||||||
|
<< "_LIBRARY)\n";
|
||||||
|
|
||||||
|
ss << "if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)\n";
|
||||||
|
ss << " set(CMAKE_INSTALL_PREFIX \"${XNCore_PATH}/Configuration/" << m_pluginInfo.pluginName
|
||||||
|
<< "/Plugins\" CACHE PATH \"Install path prefix\" "
|
||||||
|
"FORCE)\n";
|
||||||
|
ss << "endif()\n";
|
||||||
|
|
||||||
|
ss << "include(GNUInstallDirs)\n";
|
||||||
|
ss << "install(TARGETS " << projectName << "\n";
|
||||||
|
ss << " BUNDLE DESTINATION .\n";
|
||||||
|
ss << " LIBRARY DESTINATION .\n";
|
||||||
|
ss << " RUNTIME DESTINATION .\n";
|
||||||
|
ss << ")\n";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginGenerator::writeFile(const std::string &filePath, const std::string &content)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 确保目录存在
|
||||||
|
std::filesystem::path path(filePath);
|
||||||
|
if (path.has_parent_path()) {
|
||||||
|
createDirectory(path.parent_path().string());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream file(filePath);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
m_lastError = "无法创建文件: " + filePath;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file << content;
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
m_lastError = "写入文件错误: " + std::string(e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginGenerator::createDirectory(const std::string &dirPath)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (!std::filesystem::exists(dirPath)) {
|
||||||
|
return std::filesystem::create_directories(dirPath);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
m_lastError = "创建目录错误: " + std::string(e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const GenPluginInfo &PluginGenerator::getPluginInfo() const
|
||||||
|
{
|
||||||
|
return m_pluginInfo;
|
||||||
|
}
|
66
XNMonitorServer/PluginGenerator.h
Normal file
66
XNMonitorServer/PluginGenerator.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* @file PluginGenerator.h
|
||||||
|
* @brief 简化的插件生成器 - 从数据库生成插件cpp文件和CMakeLists
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
|
||||||
|
// 接口信息结构
|
||||||
|
struct InterfaceInfo {
|
||||||
|
std::string interfaceName; // 接口名称(如:Aerodynamics_heartbeat)
|
||||||
|
std::string
|
||||||
|
templateType; // 模板类型(如:XNSim::C909::ATA04::Aerodynamics_heartbeat_Interface)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 插件信息
|
||||||
|
struct GenPluginInfo {
|
||||||
|
std::string pluginName; // 插件名称(如:C909_V1)
|
||||||
|
std::string pluginDescription; // 插件描述
|
||||||
|
std::string interfaceHeaderPath; // 接口头文件路径(如:IDL/C909_V1_Interface.h)
|
||||||
|
std::vector<InterfaceInfo> interfaces; // 接口列表
|
||||||
|
std::string outputDirectory; // 输出目录
|
||||||
|
};
|
||||||
|
|
||||||
|
class PluginGenerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PluginGenerator();
|
||||||
|
~PluginGenerator();
|
||||||
|
|
||||||
|
// 从数据库加载插件信息
|
||||||
|
bool loadPluginFromDatabase(const int confID);
|
||||||
|
|
||||||
|
// 生成插件cpp文件
|
||||||
|
bool generatePluginCpp();
|
||||||
|
|
||||||
|
// 生成CMakeLists.txt
|
||||||
|
bool generateCMakeLists();
|
||||||
|
|
||||||
|
// 编译插件
|
||||||
|
bool compilePlugin();
|
||||||
|
|
||||||
|
// 获取错误信息
|
||||||
|
std::string getLastError() const;
|
||||||
|
|
||||||
|
// 获取插件信息
|
||||||
|
const GenPluginInfo &getPluginInfo() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 生成插件cpp文件内容
|
||||||
|
std::string generatePluginCppContent();
|
||||||
|
|
||||||
|
// 生成CMakeLists.txt内容
|
||||||
|
std::string generateCMakeListsContent();
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
bool writeFile(const std::string &filePath, const std::string &content);
|
||||||
|
|
||||||
|
// 创建目录
|
||||||
|
bool createDirectory(const std::string &dirPath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_lastError;
|
||||||
|
|
||||||
|
GenPluginInfo m_pluginInfo;
|
||||||
|
};
|
34
XNMonitorServer/PluginInterface.h
Normal file
34
XNMonitorServer/PluginInterface.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNMonitorServer_global.h"
|
||||||
|
#include "DataMonitor.h"
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
|
||||||
|
// 插件信息结构
|
||||||
|
struct PluginInfo {
|
||||||
|
const char *name; // 插件名称,如 "C909_V1"
|
||||||
|
const char *description; // 描述信息
|
||||||
|
const char *interface_version; // 接口版本,必须与主项目兼容
|
||||||
|
};
|
||||||
|
|
||||||
|
// C风格插件接口 - 确保ABI兼容性
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
// 获取插件信息
|
||||||
|
typedef PluginInfo *(*GetPluginInfoFunc)();
|
||||||
|
|
||||||
|
// 创建监控器实例
|
||||||
|
typedef DataMonitorBasePtr (*CreateMonitorFunc)(const char *interfaceName);
|
||||||
|
|
||||||
|
// 销毁监控器实例
|
||||||
|
typedef void (*DestroyMonitorFunc)(const char *interfaceName);
|
||||||
|
|
||||||
|
// 获取支持的接口列表
|
||||||
|
typedef const char **(*GetSupportedInterfacesFunc)(int *count);
|
||||||
|
|
||||||
|
// 释放字符串数组
|
||||||
|
typedef void (*FreeStringArrayFunc)(const char **array);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插件接口版本 - 主项目一旦发布就不再修改
|
||||||
|
#define DATAMONITOR_PLUGIN_INTERFACE_VERSION "1.0.0"
|
126
XNMonitorServer/PluginManager.cpp
Normal file
126
XNMonitorServer/PluginManager.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#include "PluginManager.h"
|
||||||
|
|
||||||
|
PluginManager &PluginManager::Instance()
|
||||||
|
{
|
||||||
|
static PluginManager instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginManager::~PluginManager()
|
||||||
|
{
|
||||||
|
UnloadCurrentPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PluginManager::SetGeneratedPluginInfo(const GenPluginInfo &pluginInfo)
|
||||||
|
{
|
||||||
|
m_generatedPluginInfo = pluginInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginManager::LoadPluginFromGenerator()
|
||||||
|
{
|
||||||
|
if (m_generatedPluginInfo.pluginName.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建插件路径 - 安装到outputDirectory上级目录的Plugins下
|
||||||
|
std::filesystem::path outputPath(m_generatedPluginInfo.outputDirectory);
|
||||||
|
std::string pluginPath = outputPath.parent_path().string() + "/Plugins/lib"
|
||||||
|
+ m_generatedPluginInfo.pluginName + "_Monitor.so";
|
||||||
|
|
||||||
|
// 卸载当前插件
|
||||||
|
UnloadCurrentPlugin();
|
||||||
|
|
||||||
|
// 加载插件库
|
||||||
|
m_pluginHandle = dlopen(pluginPath.c_str(), RTLD_LAZY);
|
||||||
|
if (!m_pluginHandle) {
|
||||||
|
std::cerr << "Failed to load plugin: " << dlerror() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取插件函数
|
||||||
|
m_getPluginInfoFunc =
|
||||||
|
reinterpret_cast<GetPluginInfoFunc>(dlsym(m_pluginHandle, "get_plugin_info"));
|
||||||
|
m_createMonitorFunc =
|
||||||
|
reinterpret_cast<CreateMonitorFunc>(dlsym(m_pluginHandle, "create_monitor"));
|
||||||
|
m_destroyMonitorFunc =
|
||||||
|
reinterpret_cast<DestroyMonitorFunc>(dlsym(m_pluginHandle, "destroy_monitor"));
|
||||||
|
m_getSupportedInterfacesFunc = reinterpret_cast<GetSupportedInterfacesFunc>(
|
||||||
|
dlsym(m_pluginHandle, "get_supported_interfaces"));
|
||||||
|
m_freeStringArrayFunc =
|
||||||
|
reinterpret_cast<FreeStringArrayFunc>(dlsym(m_pluginHandle, "free_string_array"));
|
||||||
|
|
||||||
|
// 检查函数是否都加载成功
|
||||||
|
if (!m_getPluginInfoFunc || !m_createMonitorFunc || !m_getSupportedInterfacesFunc) {
|
||||||
|
std::cerr << "Failed to load plugin functions" << std::endl;
|
||||||
|
UnloadCurrentPlugin();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取插件信息
|
||||||
|
m_pluginInfo = m_getPluginInfoFunc();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PluginManager::UnloadCurrentPlugin()
|
||||||
|
{
|
||||||
|
// 先清理监控器缓存(这会触发DataMonitorProduct的析构函数)
|
||||||
|
m_monitorCache.clear();
|
||||||
|
|
||||||
|
if (m_pluginHandle) {
|
||||||
|
dlclose(m_pluginHandle);
|
||||||
|
m_pluginHandle = nullptr;
|
||||||
|
}
|
||||||
|
m_pluginInfo = nullptr;
|
||||||
|
m_getPluginInfoFunc = nullptr;
|
||||||
|
m_createMonitorFunc = nullptr;
|
||||||
|
m_destroyMonitorFunc = nullptr;
|
||||||
|
m_getSupportedInterfacesFunc = nullptr;
|
||||||
|
m_freeStringArrayFunc = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataMonitorBasePtr PluginManager::GetMonitor(const std::string &interfaceName)
|
||||||
|
{
|
||||||
|
if (!m_createMonitorFunc) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查缓存中是否已有实例
|
||||||
|
auto it = m_monitorCache.find(interfaceName);
|
||||||
|
if (it != m_monitorCache.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新实例(不自动初始化)
|
||||||
|
auto monitor = m_createMonitorFunc(interfaceName.c_str());
|
||||||
|
|
||||||
|
// 缓存实例
|
||||||
|
if (monitor) {
|
||||||
|
m_monitorCache[interfaceName] = monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> PluginManager::GetSupportedInterfaces()
|
||||||
|
{
|
||||||
|
std::vector<std::string> interfaces;
|
||||||
|
|
||||||
|
if (!m_getSupportedInterfacesFunc) {
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
const char **interfaceNames = m_getSupportedInterfacesFunc(&count);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
interfaces.push_back(interfaceNames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginManager::IsPluginLoaded() const
|
||||||
|
{
|
||||||
|
return m_pluginHandle != nullptr && m_createMonitorFunc != nullptr;
|
||||||
|
}
|
51
XNMonitorServer/PluginManager.h
Normal file
51
XNMonitorServer/PluginManager.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XNMonitorServer_global.h"
|
||||||
|
#include "PluginInterface.h"
|
||||||
|
#include "PluginGenerator.h"
|
||||||
|
#include "TypeDefine.h"
|
||||||
|
|
||||||
|
class XNMONITORSERVER_EXPORT PluginManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static PluginManager &Instance();
|
||||||
|
|
||||||
|
// 设置生成的插件信息
|
||||||
|
void SetGeneratedPluginInfo(const GenPluginInfo &pluginInfo);
|
||||||
|
|
||||||
|
// 从生成器加载插件
|
||||||
|
bool LoadPluginFromGenerator();
|
||||||
|
|
||||||
|
// 卸载当前插件
|
||||||
|
void UnloadCurrentPlugin();
|
||||||
|
|
||||||
|
// 获取监控器实例
|
||||||
|
DataMonitorBasePtr GetMonitor(const std::string &interfaceName);
|
||||||
|
|
||||||
|
// 获取所有支持的接口
|
||||||
|
std::vector<std::string> GetSupportedInterfaces();
|
||||||
|
|
||||||
|
// 检查插件是否已加载
|
||||||
|
bool IsPluginLoaded() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PluginManager() = default;
|
||||||
|
~PluginManager();
|
||||||
|
PluginManager(const PluginManager &) = delete;
|
||||||
|
PluginManager &operator=(const PluginManager &) = delete;
|
||||||
|
|
||||||
|
// 当前加载的插件信息
|
||||||
|
void *m_pluginHandle = nullptr;
|
||||||
|
PluginInfo *m_pluginInfo = nullptr;
|
||||||
|
GetPluginInfoFunc m_getPluginInfoFunc = nullptr;
|
||||||
|
CreateMonitorFunc m_createMonitorFunc = nullptr;
|
||||||
|
DestroyMonitorFunc m_destroyMonitorFunc = nullptr;
|
||||||
|
GetSupportedInterfacesFunc m_getSupportedInterfacesFunc = nullptr;
|
||||||
|
FreeStringArrayFunc m_freeStringArrayFunc = nullptr;
|
||||||
|
|
||||||
|
// 生成的插件信息
|
||||||
|
GenPluginInfo m_generatedPluginInfo;
|
||||||
|
|
||||||
|
// 监控器实例缓存
|
||||||
|
std::unordered_map<std::string, DataMonitorBasePtr> m_monitorCache;
|
||||||
|
};
|
@ -1,5 +1,5 @@
|
|||||||
#include "SystemControl.h"
|
#include "SystemControl.h"
|
||||||
#include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp"
|
#include "XNIDL/XNSimStatusPubSubTypes.hpp"
|
||||||
|
|
||||||
SystemControl::~SystemControl()
|
SystemControl::~SystemControl()
|
||||||
{
|
{
|
||||||
|
@ -16,6 +16,13 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <sqlite3.h>
|
||||||
#include <fastdds/dds/domain/DomainParticipant.hpp>
|
#include <fastdds/dds/domain/DomainParticipant.hpp>
|
||||||
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
|
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
|
||||||
#include <fastdds/dds/topic/TypeSupport.hpp>
|
#include <fastdds/dds/topic/TypeSupport.hpp>
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "DataInjectThread.h"
|
#include "DataInjectThread.h"
|
||||||
#include "CSVDataInjectThread.h"
|
#include "CSVDataInjectThread.h"
|
||||||
#include "DataCollect.h"
|
#include "DataCollect.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
#include "PluginGenerator.h"
|
||||||
|
|
||||||
// 全局变量
|
// 全局变量
|
||||||
static bool g_initialized = false;
|
static bool g_initialized = false;
|
||||||
@ -25,10 +27,19 @@ std::unordered_map<std::string, DataInjectThreadPtr> g_dataInjectThreads;
|
|||||||
CSVDataInjectThread *g_csvDataInjectThread = nullptr;
|
CSVDataInjectThread *g_csvDataInjectThread = nullptr;
|
||||||
DataCollect *g_dataCollect = nullptr;
|
DataCollect *g_dataCollect = nullptr;
|
||||||
|
|
||||||
// 初始化函数实现
|
/**
|
||||||
int XN_Initialize(const char *domainId, int domainIdLen, char *errorMsg, int errorMsgSize)
|
* @brief 生成插件
|
||||||
{
|
* @param confID 构型ID
|
||||||
|
* @param errorMsg 错误信息
|
||||||
|
* @param errorMsgSize 错误信息大小
|
||||||
|
* @return 0: 成功, -1: 失败
|
||||||
|
*/
|
||||||
|
int XN_GenPlugin(int confID, int forceGen, char *errorMsg, int errorMsgSize);
|
||||||
|
|
||||||
|
// 初始化函数实现
|
||||||
|
int XN_Initialize(const char *domainId, int domainIdLen, int confID, int forceGen, char *errorMsg,
|
||||||
|
int errorMsgSize)
|
||||||
|
{
|
||||||
if (g_initialized) {
|
if (g_initialized) {
|
||||||
if (errorMsg && errorMsgSize > 0) {
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
strncpy(errorMsg, "DDSMonitor Initialized Successfully", errorMsgSize - 1);
|
strncpy(errorMsg, "DDSMonitor Initialized Successfully", errorMsgSize - 1);
|
||||||
@ -56,6 +67,12 @@ int XN_Initialize(const char *domainId, int domainIdLen, char *errorMsg, int err
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成插件
|
||||||
|
if (XN_GenPlugin(confID, forceGen, errorMsg, errorMsgSize) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先初始化DDS参与者
|
||||||
XNDDSErrorCode ret = TopicManager::Instance()->initializeParticipant(domainIdInt);
|
XNDDSErrorCode ret = TopicManager::Instance()->initializeParticipant(domainIdInt);
|
||||||
if (ret != XNDDSErrorCode::SUCCESS) {
|
if (ret != XNDDSErrorCode::SUCCESS) {
|
||||||
if (errorMsg && errorMsgSize > 0) {
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
@ -67,6 +84,19 @@ int XN_Initialize(const char *domainId, int domainIdLen, char *errorMsg, int err
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化插件管理器
|
||||||
|
auto &pluginManager = PluginManager::Instance();
|
||||||
|
|
||||||
|
// 加载生成的插件
|
||||||
|
if (!pluginManager.LoadPluginFromGenerator()) {
|
||||||
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
|
std::string error = "Failed to load generated plugin";
|
||||||
|
strncpy(errorMsg, error.c_str(), errorMsgSize - 1);
|
||||||
|
errorMsg[errorMsgSize - 1] = '\0';
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
g_initialized = true;
|
g_initialized = true;
|
||||||
if (errorMsg && errorMsgSize > 0) {
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
strncpy(errorMsg, "DDSMonitor Initialized Successfully", errorMsgSize - 1);
|
strncpy(errorMsg, "DDSMonitor Initialized Successfully", errorMsgSize - 1);
|
||||||
@ -855,8 +885,6 @@ int XN_StopCollectData(char *infoMsg, int infoMsgSize)
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
g_dataCollect->stop();
|
g_dataCollect->stop();
|
||||||
delete g_dataCollect;
|
|
||||||
g_dataCollect = nullptr;
|
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
if (infoMsg && infoMsgSize > 0) {
|
if (infoMsg && infoMsgSize > 0) {
|
||||||
strncpy(infoMsg, e.what(), infoMsgSize - 1);
|
strncpy(infoMsg, e.what(), infoMsgSize - 1);
|
||||||
@ -876,6 +904,75 @@ void XN_CleanupDataCollect()
|
|||||||
g_dataCollect = nullptr;
|
g_dataCollect = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成插件函数实现
|
||||||
|
int XN_GenPlugin(int confID, int forceGen, char *errorMsg, int errorMsgSize)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 创建插件生成器
|
||||||
|
PluginGenerator generator;
|
||||||
|
|
||||||
|
// 从数据库加载插件信息
|
||||||
|
if (!generator.loadPluginFromDatabase(confID)) {
|
||||||
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
|
std::string error =
|
||||||
|
"Failed to load plugin info from database: " + generator.getLastError();
|
||||||
|
strncpy(errorMsg, error.c_str(), errorMsgSize - 1);
|
||||||
|
errorMsg[errorMsgSize - 1] = '\0';
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (forceGen == 1) {
|
||||||
|
// 生成插件cpp文件
|
||||||
|
if (!generator.generatePluginCpp()) {
|
||||||
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
|
std::string error =
|
||||||
|
"Failed to generate plugin cpp: " + generator.getLastError();
|
||||||
|
strncpy(errorMsg, error.c_str(), errorMsgSize - 1);
|
||||||
|
errorMsg[errorMsgSize - 1] = '\0';
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成CMakeLists.txt
|
||||||
|
if (!generator.generateCMakeLists()) {
|
||||||
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
|
std::string error =
|
||||||
|
"Failed to generate CMakeLists: " + generator.getLastError();
|
||||||
|
strncpy(errorMsg, error.c_str(), errorMsgSize - 1);
|
||||||
|
errorMsg[errorMsgSize - 1] = '\0';
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编译插件
|
||||||
|
if (!generator.compilePlugin()) {
|
||||||
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
|
std::string error = "Failed to compile plugin: " + generator.getLastError();
|
||||||
|
strncpy(errorMsg, error.c_str(), errorMsgSize - 1);
|
||||||
|
errorMsg[errorMsgSize - 1] = '\0';
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存插件信息到插件管理器
|
||||||
|
PluginManager::Instance().SetGeneratedPluginInfo(generator.getPluginInfo());
|
||||||
|
|
||||||
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
|
strncpy(errorMsg, "Plugin generated and compiled successfully", errorMsgSize - 1);
|
||||||
|
errorMsg[errorMsgSize - 1] = '\0';
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
if (errorMsg && errorMsgSize > 0) {
|
||||||
|
strncpy(errorMsg, e.what(), errorMsgSize - 1);
|
||||||
|
errorMsg[errorMsgSize - 1] = '\0';
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 清理函数实现
|
// 清理函数实现
|
||||||
void XN_Cleanup()
|
void XN_Cleanup()
|
||||||
{
|
{
|
||||||
@ -892,15 +989,19 @@ void XN_Cleanup()
|
|||||||
if (g_systemControlStarted) {
|
if (g_systemControlStarted) {
|
||||||
XN_CleanupEngineControl();
|
XN_CleanupEngineControl();
|
||||||
}
|
}
|
||||||
// 停止并清理数据采集
|
|
||||||
XN_CleanupDataCollect();
|
|
||||||
// 停止并清理CSV数据注入
|
|
||||||
XN_CleanupCsvDataInject();
|
|
||||||
// 停止并清理数据注入
|
// 停止并清理数据注入
|
||||||
XN_CleanupInjectContinuous();
|
XN_CleanupInjectContinuous();
|
||||||
|
// 停止并清理CSV数据注入
|
||||||
|
XN_CleanupCsvDataInject();
|
||||||
|
// 停止并清理数据采集
|
||||||
|
XN_CleanupDataCollect();
|
||||||
|
|
||||||
// 清理DDS参与者
|
// 先清理DDS参与者,再卸载插件
|
||||||
TopicManager::cleanupParticipant();
|
TopicManager::cleanupParticipant();
|
||||||
|
|
||||||
|
// 卸载动态加载的插件
|
||||||
|
PluginManager::Instance().UnloadCurrentPlugin();
|
||||||
|
|
||||||
g_initialized = false;
|
g_initialized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,12 +16,13 @@ extern "C"
|
|||||||
* @brief 初始化DDS监控服务器
|
* @brief 初始化DDS监控服务器
|
||||||
* @param domainId 域ID
|
* @param domainId 域ID
|
||||||
* @param domainIdLen 域ID长度
|
* @param domainIdLen 域ID长度
|
||||||
|
* @param confID 构型ID
|
||||||
* @param errorMsg 错误信息
|
* @param errorMsg 错误信息
|
||||||
* @param errorMsgSize 错误信息大小
|
* @param errorMsgSize 错误信息大小
|
||||||
* @return 0: 成功, -1: 失败
|
* @return 0: 成功, -1: 失败
|
||||||
*/
|
*/
|
||||||
int XNMONITORSERVER_EXPORT XN_Initialize(const char *domainId, int domainIdLen, char *errorMsg,
|
int XNMONITORSERVER_EXPORT XN_Initialize(const char *domainId, int domainIdLen, int confID,
|
||||||
int errorMsgSize);
|
int forceGen, char *errorMsg, int errorMsgSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 清理DDS监控服务器
|
* @brief 清理DDS监控服务器
|
||||||
@ -270,6 +271,11 @@ extern "C"
|
|||||||
*/
|
*/
|
||||||
int XNMONITORSERVER_EXPORT XN_StopCollectData(char *infoMsg, int infoMsgSize);
|
int XNMONITORSERVER_EXPORT XN_StopCollectData(char *infoMsg, int infoMsgSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 清理所有资源
|
||||||
|
*/
|
||||||
|
void XNMONITORSERVER_EXPORT XN_Cleanup();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
56
XNMonitorServer/test/CMakeLists.txt
Normal file
56
XNMonitorServer/test/CMakeLists.txt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# 测试程序的CMakeLists.txt
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
# 设置项目名称
|
||||||
|
project(XNMonitorServer_Test)
|
||||||
|
|
||||||
|
# 设置C++标准
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# 查找必要的包
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
find_package(FastDDS REQUIRED)
|
||||||
|
|
||||||
|
# 设置XNCore路径
|
||||||
|
if(DEFINED ENV{XNCore})
|
||||||
|
set(XNCore_PATH $ENV{XNCore})
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Environment variable XNCore is not set.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 包含目录
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
|
${XNCore_PATH}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
# 创建测试可执行文件
|
||||||
|
add_executable(test_initialize test_initialize.cpp)
|
||||||
|
|
||||||
|
# 链接库
|
||||||
|
target_link_libraries(test_initialize
|
||||||
|
fastcdr
|
||||||
|
fastdds
|
||||||
|
OpenSSL::SSL
|
||||||
|
OpenSSL::Crypto
|
||||||
|
pthread
|
||||||
|
dl
|
||||||
|
${XNCore_PATH}/lib/libXNMonitorServer.so
|
||||||
|
)
|
||||||
|
|
||||||
|
# 链接主项目的库(如果存在)
|
||||||
|
if(TARGET XNMonitorServer)
|
||||||
|
target_link_libraries(test_initialize XNMonitorServer)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 设置运行时库路径
|
||||||
|
set_target_properties(test_initialize PROPERTIES
|
||||||
|
INSTALL_RPATH "${XNCore_PATH}/lib"
|
||||||
|
BUILD_WITH_INSTALL_RPATH TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
# 安装目标
|
||||||
|
install(TARGETS test_initialize
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
)
|
96
XNMonitorServer/test/test_initialize.cpp
Normal file
96
XNMonitorServer/test/test_initialize.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
#include "../XNMonitorInterface.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << "=== XNMonitorServer 初始化测试 ===" << std::endl;
|
||||||
|
|
||||||
|
// 测试参数
|
||||||
|
const char *domainId = "10";
|
||||||
|
int domainIdLen = strlen(domainId);
|
||||||
|
int confID = 1;
|
||||||
|
int forceGen = 0;
|
||||||
|
|
||||||
|
char errorMsg[1024];
|
||||||
|
int errorMsgSize = sizeof(errorMsg);
|
||||||
|
|
||||||
|
std::cout << "测试参数:" << std::endl;
|
||||||
|
std::cout << " domainId: " << domainId << std::endl;
|
||||||
|
std::cout << " confID: " << confID << std::endl;
|
||||||
|
std::cout << " forceGen: " << forceGen << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// 调用XN_Initialize
|
||||||
|
std::cout << "正在调用 XN_Initialize..." << std::endl;
|
||||||
|
int result = XN_Initialize(domainId, domainIdLen, confID, forceGen, errorMsg, errorMsgSize);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
std::cout << "✓ XN_Initialize 调用成功!" << std::endl;
|
||||||
|
std::cout << "返回信息: " << errorMsg << std::endl;
|
||||||
|
|
||||||
|
// 测试其他功能
|
||||||
|
std::cout << std::endl << "=== 测试其他功能 ===" << std::endl;
|
||||||
|
|
||||||
|
// 测试系统信息监控
|
||||||
|
std::cout << "正在启动系统信息监控..." << std::endl;
|
||||||
|
int sysResult = XN_StartMonitorSystemInfo(errorMsg, errorMsgSize);
|
||||||
|
if (sysResult == 0) {
|
||||||
|
std::cout << "✓ 系统信息监控启动成功" << std::endl;
|
||||||
|
|
||||||
|
// 获取系统信息
|
||||||
|
char sysInfo[2048];
|
||||||
|
int sysInfoSize = sizeof(sysInfo);
|
||||||
|
int getSysResult = XN_GetSystemInfo(sysInfo, sysInfoSize);
|
||||||
|
if (getSysResult == 0) {
|
||||||
|
std::cout << "✓ 获取系统信息成功" << std::endl;
|
||||||
|
std::cout << "系统信息: " << sysInfo << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "✗ 获取系统信息失败: " << sysInfo << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 停止系统信息监控
|
||||||
|
XN_StopMonitorSystemInfo();
|
||||||
|
std::cout << "✓ 系统信息监控已停止" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "✗ 系统信息监控启动失败: " << errorMsg << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试模型信息监控
|
||||||
|
std::cout << std::endl << "正在启动模型信息监控..." << std::endl;
|
||||||
|
int modelResult = XN_StartMonitorModelInfo(errorMsg, errorMsgSize);
|
||||||
|
if (modelResult == 0) {
|
||||||
|
std::cout << "✓ 模型信息监控启动成功" << std::endl;
|
||||||
|
|
||||||
|
// 获取模型信息
|
||||||
|
char modelInfo[2048];
|
||||||
|
int modelInfoSize = sizeof(modelInfo);
|
||||||
|
int getModelResult = XN_GetModelInfo(modelInfo, modelInfoSize);
|
||||||
|
if (getModelResult == 0) {
|
||||||
|
std::cout << "✓ 获取模型信息成功" << std::endl;
|
||||||
|
std::cout << "模型信息: " << modelInfo << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "✗ 获取模型信息失败: " << modelInfo << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 停止模型信息监控
|
||||||
|
XN_StopMonitorModelInfo();
|
||||||
|
std::cout << "✓ 模型信息监控已停止" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "✗ 模型信息监控启动失败: " << errorMsg << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理资源
|
||||||
|
std::cout << std::endl << "=== 清理资源 ===" << std::endl;
|
||||||
|
XN_Cleanup();
|
||||||
|
std::cout << "✓ 资源清理完成" << std::endl;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::cout << "✗ XN_Initialize 调用失败!" << std::endl;
|
||||||
|
std::cout << "错误信息: " << errorMsg << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl << "=== 测试完成 ===" << std::endl;
|
||||||
|
return result;
|
||||||
|
}
|
@ -341,7 +341,8 @@ class RunSim extends HTMLElement {
|
|||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
domainId: domainId,
|
domainId: domainId,
|
||||||
|
confID: confID
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -569,7 +570,11 @@ class RunSim extends HTMLElement {
|
|||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ domainId })
|
body: JSON.stringify({
|
||||||
|
domainId: domainId,
|
||||||
|
confID: confID,
|
||||||
|
forceGen : 1
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!ddsInitResponse.ok) {
|
if (!ddsInitResponse.ok) {
|
||||||
|
@ -6,22 +6,24 @@ const { initializeMonitor, cleanupMonitor } = require('../utils/xnCoreService');
|
|||||||
let monitorStatus = {
|
let monitorStatus = {
|
||||||
isInitialized: false,
|
isInitialized: false,
|
||||||
domainId: null,
|
domainId: null,
|
||||||
|
confID: null,
|
||||||
|
forceGen: 0,
|
||||||
lastError: null
|
lastError: null
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化监控服务
|
// 初始化监控服务
|
||||||
router.post('/initialize', async (req, res) => {
|
router.post('/initialize', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { domainId } = req.body;
|
const { domainId, confID, forceGen = 0 } = req.body;
|
||||||
|
|
||||||
if (!domainId) {
|
if (!domainId || confID === undefined) {
|
||||||
return res.status(400).json({ error: '缺少必要的参数' });
|
return res.status(400).json({ error: '缺少必要的参数: domainId 和 confID' });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果已经初始化,检查域ID是否匹配
|
// 如果已经初始化,检查域ID和配置ID是否匹配
|
||||||
if (monitorStatus.isInitialized) {
|
if (monitorStatus.isInitialized) {
|
||||||
if (monitorStatus.domainId !== domainId) {
|
if (monitorStatus.domainId !== domainId || monitorStatus.confID !== confID) {
|
||||||
return res.status(400).json({ error: 'DDS域ID不匹配' });
|
return res.status(400).json({ error: 'DDS域ID或配置ID不匹配' });
|
||||||
}
|
}
|
||||||
return res.json({
|
return res.json({
|
||||||
message: '监控服务已初始化',
|
message: '监控服务已初始化',
|
||||||
@ -30,7 +32,7 @@ router.post('/initialize', async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 首次初始化
|
// 首次初始化
|
||||||
const result = initializeMonitor(domainId);
|
const result = initializeMonitor(domainId, confID, forceGen);
|
||||||
if (result && result.includes('失败')) {
|
if (result && result.includes('失败')) {
|
||||||
monitorStatus.lastError = result;
|
monitorStatus.lastError = result;
|
||||||
return res.status(500).json({ error: result });
|
return res.status(500).json({ error: result });
|
||||||
@ -38,6 +40,8 @@ router.post('/initialize', async (req, res) => {
|
|||||||
|
|
||||||
monitorStatus.isInitialized = true;
|
monitorStatus.isInitialized = true;
|
||||||
monitorStatus.domainId = domainId;
|
monitorStatus.domainId = domainId;
|
||||||
|
monitorStatus.confID = confID;
|
||||||
|
monitorStatus.forceGen = forceGen;
|
||||||
monitorStatus.lastError = null;
|
monitorStatus.lastError = null;
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
@ -59,6 +63,8 @@ router.post('/unregister', async (req, res) => {
|
|||||||
monitorStatus = {
|
monitorStatus = {
|
||||||
isInitialized: false,
|
isInitialized: false,
|
||||||
domainId: null,
|
domainId: null,
|
||||||
|
confID: null,
|
||||||
|
forceGen: 0,
|
||||||
lastError: null
|
lastError: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ try {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
monitorLib = ffi.Library(monitorLibPath, {
|
monitorLib = ffi.Library(monitorLibPath, {
|
||||||
'XN_Initialize': ['int', [StringType, 'int', StringType, 'int']],
|
'XN_Initialize': ['int', [StringType, 'int', 'int', 'int', StringType, 'int']],
|
||||||
'XN_Cleanup': ['void', []],
|
'XN_Cleanup': ['void', []],
|
||||||
'XN_StartMonitorSystemInfo': ['int', [StringType, 'int']],
|
'XN_StartMonitorSystemInfo': ['int', [StringType, 'int']],
|
||||||
'XN_GetSystemInfo': ['int', [StringType, 'int']],
|
'XN_GetSystemInfo': ['int', [StringType, 'int']],
|
||||||
@ -156,14 +156,14 @@ function stringToBuffer(str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化监控服务器
|
// 初始化监控服务器
|
||||||
function initializeMonitor(domainId) {
|
function initializeMonitor(domainId, confID, forceGen = 0) {
|
||||||
if (!monitorLib) {
|
if (!monitorLib) {
|
||||||
return '监控服务器库未加载';
|
return '监控服务器库未加载';
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 创建错误消息缓冲区
|
// 创建错误消息缓冲区
|
||||||
const errorMsg = Buffer.alloc(1024);
|
const errorMsg = Buffer.alloc(1024);
|
||||||
const result = monitorLib.XN_Initialize(domainId, domainId.length, errorMsg, errorMsg.length);
|
const result = monitorLib.XN_Initialize(domainId, domainId.length, confID, forceGen, errorMsg, errorMsg.length);
|
||||||
|
|
||||||
if (result !== 0) {
|
if (result !== 0) {
|
||||||
return `初始化失败: ${errorMsg.toString('utf8').replace(/\0/g, '')}`;
|
return `初始化失败: ${errorMsg.toString('utf8').replace(/\0/g, '')}`;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user