diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db index f435023..49cba17 100644 Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ diff --git a/XNMonitorServer/CMakeLists.txt b/XNMonitorServer/CMakeLists.txt index 6fb1877..640907a 100644 --- a/XNMonitorServer/CMakeLists.txt +++ b/XNMonitorServer/CMakeLists.txt @@ -37,6 +37,8 @@ add_library(XNMonitorServer SHARED SystemInfoMonitor.cpp ModelInfoMonitor.h ModelInfoMonitor.cpp + SystemControl.h + SystemControl.cpp ${DDS_XNIDL_SOURCES_CXX} ) diff --git a/XNMonitorServer/ModelInfoMonitor.cpp b/XNMonitorServer/ModelInfoMonitor.cpp index 6b4d7c2..c2ed5d1 100644 --- a/XNMonitorServer/ModelInfoMonitor.cpp +++ b/XNMonitorServer/ModelInfoMonitor.cpp @@ -1,8 +1,4 @@ #include "ModelInfoMonitor.h" -#include -#include - -using json = nlohmann::json; ModelInfoMonitor::~ModelInfoMonitor() { diff --git a/XNMonitorServer/ModelInfoMonitor.h b/XNMonitorServer/ModelInfoMonitor.h index 7ed2b09..6b13493 100644 --- a/XNMonitorServer/ModelInfoMonitor.h +++ b/XNMonitorServer/ModelInfoMonitor.h @@ -1,9 +1,5 @@ #pragma once -#include "XNMonitorServer_global.h" -#include -#include -#include "TypeDefine.h" #include "TopicManager.h" #include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp" diff --git a/XNMonitorServer/SystemControl.cpp b/XNMonitorServer/SystemControl.cpp new file mode 100644 index 0000000..7722d6b --- /dev/null +++ b/XNMonitorServer/SystemControl.cpp @@ -0,0 +1,58 @@ +#include "SystemControl.h" +#include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp" + +SystemControl::~SystemControl() +{ + //注销引擎控制发布者 + TopicManager::Instance()->unregisterPublisher("XNSim::XNSimControl::XNRuntimeControl"); + m_EngineControlWriter = nullptr; +} + +std::string SystemControl::Initialize() +{ + m_EngineControlWriter = nullptr; + XNDDSErrorCode ret = TopicManager::Instance() + ->registerPublisher( + "XNSim::XNSimControl::XNRuntimeControl", m_EngineControlWriter); + if (ret != XNDDSErrorCode::SUCCESS || m_EngineControlWriter == nullptr) { + return "Failed to register engine control publisher, error code: " + + std::to_string(static_cast(ret)); + } + return "Success"; +} + +void SystemControl::Pause() +{ + // 暂停引擎 + if (m_EngineControlWriter == nullptr) { + return; + } + XNSim::XNSimControl::XNRuntimeControl cmd; + cmd.XNSimCmd(1); + cmd.XNThrCmd(0); + m_EngineControlWriter->write(&cmd); +} + +void SystemControl::Resume() +{ + // 恢复引擎 + if (m_EngineControlWriter == nullptr) { + return; + } + XNSim::XNSimControl::XNRuntimeControl cmd; + cmd.XNSimCmd(2); + cmd.XNThrCmd(0); + m_EngineControlWriter->write(&cmd); +} + +void SystemControl::Stop() +{ + // 停止引擎 + if (m_EngineControlWriter == nullptr) { + return; + } + XNSim::XNSimControl::XNRuntimeControl cmd; + cmd.XNSimCmd(3); + cmd.XNThrCmd(0); + m_EngineControlWriter->write(&cmd); +} \ No newline at end of file diff --git a/XNMonitorServer/SystemControl.h b/XNMonitorServer/SystemControl.h new file mode 100644 index 0000000..eb946fc --- /dev/null +++ b/XNMonitorServer/SystemControl.h @@ -0,0 +1,22 @@ +#pragma once + +#include "XNMonitorServer_global.h" +#include "TypeDefine.h" +#include "TopicManager.h" +#include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp" + +class XNMONITORSERVER_EXPORT SystemControl +{ +public: + SystemControl() {}; + virtual ~SystemControl(); + +public: + std::string Initialize(); + void Pause(); + void Resume(); + void Stop(); + +private: + XNDataWriter *m_EngineControlWriter; +}; diff --git a/XNMonitorServer/SystemInfoMonitor.cpp b/XNMonitorServer/SystemInfoMonitor.cpp index ee0c6f8..fcc94fe 100644 --- a/XNMonitorServer/SystemInfoMonitor.cpp +++ b/XNMonitorServer/SystemInfoMonitor.cpp @@ -1,7 +1,4 @@ #include "SystemInfoMonitor.h" -#include - -using json = nlohmann::json; SystemInfoMonitor::~SystemInfoMonitor() { diff --git a/XNMonitorServer/SystemInfoMonitor.h b/XNMonitorServer/SystemInfoMonitor.h index 31ab863..1ea2684 100644 --- a/XNMonitorServer/SystemInfoMonitor.h +++ b/XNMonitorServer/SystemInfoMonitor.h @@ -1,10 +1,5 @@ -#ifndef SYSTEMINFOMONITOR_H -#define SYSTEMINFOMONITOR_H +#pragma once -#include "XNMonitorServer_global.h" -#include -#include -#include "TypeDefine.h" #include "TopicManager.h" #include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp" @@ -55,5 +50,3 @@ private: */ std::map m_ThreadCycleCount; }; - -#endif // SYSTEMINFOMONITOR_H diff --git a/XNMonitorServer/TopicManager.h b/XNMonitorServer/TopicManager.h index 17eae46..e5db60b 100755 --- a/XNMonitorServer/TopicManager.h +++ b/XNMonitorServer/TopicManager.h @@ -10,12 +10,8 @@ */ #pragma once -#include -#include -#include -#include +#include "XNMonitorServer_global.h" #include "DataReaderListenerImpl.h" -#include /** * @brief 主题管理类 @@ -101,8 +97,7 @@ public: * @return XNDataWriter*: 数据写入器 */ template - XNDDSErrorCode registerPublisher(const std::string &topicName, - XNDataWriter *dataWriter = nullptr) + XNDDSErrorCode registerPublisher(const std::string &topicName, XNDataWriter *&dataWriter) { std::lock_guard locker(m_Mutex); if (topics_.find(topicName) == topics_.end()) { diff --git a/XNMonitorServer/TypeDefine.h b/XNMonitorServer/TypeDefine.h index 2d0a830..b118e0f 100755 --- a/XNMonitorServer/TypeDefine.h +++ b/XNMonitorServer/TypeDefine.h @@ -6,6 +6,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -21,6 +25,7 @@ #include #include #include +#include /** * @brief 域参与者 @@ -83,6 +88,7 @@ using XNTopic = eprosima::fastdds::dds::Topic; */ using XNTopicDataType = eprosima::fastdds::dds::TopicDataType; +using json = nlohmann::json; /** * @brief 主题信息 */ diff --git a/XNMonitorServer/XNMonitorInterface.cpp b/XNMonitorServer/XNMonitorInterface.cpp index 6c110a3..8ba3f74 100644 --- a/XNMonitorServer/XNMonitorInterface.cpp +++ b/XNMonitorServer/XNMonitorInterface.cpp @@ -3,11 +3,9 @@ * @brief 监控服务器接口实现 */ #include "XNMonitorInterface.h" -#include "TopicManager.h" -#include -#include #include "SystemInfoMonitor.h" #include "ModelInfoMonitor.h" +#include "SystemControl.h" // 全局变量 static bool g_initialized = false; @@ -16,6 +14,8 @@ SystemInfoMonitor *systemInfoMonitor = nullptr; bool g_systemInfoMonitorStarted = false; ModelInfoMonitor *modelInfoMonitor = nullptr; bool g_modelInfoMonitorStarted = false; +SystemControl *systemControl = nullptr; +bool g_systemControlStarted = false; // 初始化函数实现 int XN_Initialize(const char *domainId, int domainIdLen, char *errorMsg, int errorMsgSize) @@ -288,6 +288,71 @@ void XN_Cleanup() } } +int XN_InitializeEngineControl(char *errorMsg, int errorMsgSize) +{ + if (g_systemControlStarted) { + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "Engine Control Already Started", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return 0; + } + systemControl = new SystemControl(); + std::string ret = systemControl->Initialize(); + if (ret == "Success") { + g_systemControlStarted = true; + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "Engine Control Initialized Successfully", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return 0; + } else { + delete systemControl; + systemControl = nullptr; + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, ret.c_str(), errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return -1; + } +} + +void XN_PauseEngine(char *errorMsg, int errorMsgSize) +{ + if (!g_systemControlStarted) { + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "Engine Control Not Started", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return; + } + systemControl->Pause(); +} + +void XN_ResumeEngine(char *errorMsg, int errorMsgSize) +{ + if (!g_systemControlStarted) { + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "Engine Control Not Started", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return; + } + systemControl->Resume(); +} + +void XN_StopEngine(char *errorMsg, int errorMsgSize) +{ + if (!g_systemControlStarted) { + if (errorMsg && errorMsgSize > 0) { + strncpy(errorMsg, "Engine Control Not Started", errorMsgSize - 1); + errorMsg[errorMsgSize - 1] = '\0'; + } + return; + } + systemControl->Stop(); +} + // // 注册发布者实现 // XNDDSErrorCode XN_RegisterPublisher(const char *topicName, void **dataWriter) // { diff --git a/XNMonitorServer/XNMonitorInterface.h b/XNMonitorServer/XNMonitorInterface.h index be2f36c..07ba335 100644 --- a/XNMonitorServer/XNMonitorInterface.h +++ b/XNMonitorServer/XNMonitorInterface.h @@ -40,6 +40,18 @@ extern "C" // 停止监控模型信息 void XNMONITORSERVER_EXPORT XN_StopMonitorModelInfo(); + // 初始化引擎控制 + int XNMONITORSERVER_EXPORT XN_InitializeEngineControl(char *errorMsg, int errorMsgSize); + + // 暂停引擎 + void XNMONITORSERVER_EXPORT XN_PauseEngine(char *errorMsg, int errorMsgSize); + + // 恢复引擎 + void XNMONITORSERVER_EXPORT XN_ResumeEngine(char *errorMsg, int errorMsgSize); + + // 停止引擎 + void XNMONITORSERVER_EXPORT XN_StopEngine(char *errorMsg, int errorMsgSize); + // // 主题管理接口 // XNDDSErrorCode XN_RegisterPublisher(const char *topicName, void **dataWriter); // XNDDSErrorCode XN_UnregisterPublisher(const char *topicName); diff --git a/XNSimHtml/components/run-sim.js b/XNSimHtml/components/run-sim.js index c355d33..585b1ad 100644 --- a/XNSimHtml/components/run-sim.js +++ b/XNSimHtml/components/run-sim.js @@ -10,6 +10,7 @@ class RunSim extends HTMLElement { this.currentSimulationId = null; this.reconnectAttempts = 0; this.maxReconnectAttempts = 3; + this.isPaused = false; } connectedCallback() { @@ -286,10 +287,68 @@ class RunSim extends HTMLElement { } // 连接到SSE事件源获取实时输出 + async checkAndConnectToExistingSimulation() { + try { + const response = await fetch('/api/check-xnengine'); + const data = await response.json(); + + if (data.running) { + this.showMessage('检测到正在运行的仿真,正在重新连接...'); + + // 更新UI以反映运行状态 + const runButton = this.shadowRoot.querySelector('#run-simulation-button'); + const pauseButton = this.shadowRoot.querySelector('#pause-simulation-button'); + const stopButton = this.shadowRoot.querySelector('#stop-simulation-button'); + + if (runButton) { + runButton.disabled = true; + runButton.textContent = '运行中...'; + } + + if (pauseButton) { + pauseButton.disabled = false; + } + + if (stopButton) { + stopButton.disabled = false; + } + + // 使用进程ID作为仿真ID + this.currentSimulationId = data.pid.toString(); + + // 清空并初始化输出框 + const outputContent = this.shadowRoot.querySelector('#output-content'); + outputContent.innerHTML = '重新连接到运行中的仿真...\n'; + + // 检查现有SSE连接是否有效 + if (!this.eventSource || this.eventSource.readyState === 2) { // 2表示CLOSED + // 只有在没有有效连接时才创建新连接 + this.connectToEventSource(this.currentSimulationId); + } + + // 检查引擎的暂停状态 + pauseButton.textContent = this.isPaused ? '继续仿真' : '暂停仿真'; + + // 更新状态为已连接 + this.showSuccess('已连接到运行中的仿真'); + + // 重置重连尝试次数 + this.reconnectAttempts = 0; + } else { + // 如果没有运行中的仿真,重置UI + this.resetSimulationButtons(); + } + } catch (error) { + console.error('检查XNEngine进程失败:', error); + this.showError('检查仿真状态失败: ' + error.message); + this.resetSimulationButtons(); + } + } + connectToEventSource(simulationId) { - // 关闭之前的连接 - if (this.eventSource) { - this.eventSource.close(); + // 只有在没有有效连接时才创建新连接 + if (this.eventSource && this.eventSource.readyState !== 2) { // 2表示CLOSED + return; // 如果连接有效,直接返回 } // 创建新的SSE连接 @@ -452,6 +511,57 @@ class RunSim extends HTMLElement { const outputContent = this.shadowRoot.querySelector('#output-content'); outputContent.innerHTML = '开始执行仿真...\n'; + // 获取构型参数 + const configResponse = await fetch(`/api/configurations/${confID}`); + if (!configResponse.ok) { + throw new Error('获取构型参数失败'); + } + const configData = await configResponse.json(); + + // 从构型参数中提取域ID + const domainId = configData.DomainID; + if (!domainId) { + throw new Error('构型参数中未找到有效的域ID'); + } + + // 生成唯一的监控器ID + const monitorId = `sim_${Date.now()}`; + + // 初始化DDS监控 + const ddsInitResponse = await fetch('/api/dds-monitor/initialize', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ domainId, monitorId }) + }); + + if (!ddsInitResponse.ok) { + throw new Error('初始化DDS监控失败'); + } + + const ddsInitResult = await ddsInitResponse.json(); + if (ddsInitResult.error) { + throw new Error(ddsInitResult.error); + } + + // 初始化引擎控制 + const initResponse = await fetch('/api/system-control/initialize', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }); + + if (!initResponse.ok) { + throw new Error('初始化引擎控制失败'); + } + + const initResult = await initResponse.json(); + if (!initResult.success) { + throw new Error(initResult.message || '初始化引擎控制失败'); + } + // 准备启动参数 const simulationArgs = ['-id', confID]; @@ -506,59 +616,6 @@ class RunSim extends HTMLElement { } } - // 添加新方法:检查并连接到已有的仿真 - async checkAndConnectToExistingSimulation() { - try { - const response = await fetch('/api/check-xnengine'); - const data = await response.json(); - - if (data.running) { - this.showMessage('检测到正在运行的仿真,正在重新连接...'); - - // 更新UI以反映运行状态 - const runButton = this.shadowRoot.querySelector('#run-simulation-button'); - const pauseButton = this.shadowRoot.querySelector('#pause-simulation-button'); - const stopButton = this.shadowRoot.querySelector('#stop-simulation-button'); - - if (runButton) { - runButton.disabled = true; - runButton.textContent = '运行中...'; - } - - if (pauseButton) { - pauseButton.disabled = false; - } - - if (stopButton) { - stopButton.disabled = false; - } - - // 使用进程ID作为仿真ID重新连接 - this.currentSimulationId = data.pid.toString(); - - // 清空并初始化输出框 - const outputContent = this.shadowRoot.querySelector('#output-content'); - outputContent.innerHTML = '重新连接到运行中的仿真...\n'; - - // 连接到SSE获取输出 - this.connectToEventSource(this.currentSimulationId); - - // 更新状态为已连接 - this.showSuccess('已连接到运行中的仿真'); - - // 重置重连尝试次数 - this.reconnectAttempts = 0; - } else { - // 如果没有运行中的仿真,重置UI - this.resetSimulationButtons(); - } - } catch (error) { - console.error('检查XNEngine进程失败:', error); - this.showError('检查仿真状态失败: ' + error.message); - this.resetSimulationButtons(); - } - } - // 添加reactivate方法,用于从缓存中恢复时检查仿真状态 async reactivate() { // 检查是否有XNEngine进程在运行 @@ -971,27 +1028,41 @@ class RunSim extends HTMLElement { try { const button = this.shadowRoot.querySelector('#pause-simulation-button'); - const isPaused = button.textContent === '继续仿真'; - // 调用后端API暂停/继续仿真 - const response = await fetch('/api/pause-simulation', { + // 检查DDS状态 + const ddsStatusResponse = await fetch('/api/dds-monitor/status'); + if (!ddsStatusResponse.ok) { + throw new Error('获取DDS状态失败'); + } + + const ddsStatus = await ddsStatusResponse.json(); + if (!ddsStatus.isInitialized) { + throw new Error('DDS监控未初始化'); + } + + // 根据当前暂停状态调用不同的接口 + const apiEndpoint = this.isPaused ? '/api/system-control/resume' : '/api/system-control/pause'; + const response = await fetch(apiEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - id: simulationId, - pause: !isPaused - }) + } }); if (!response.ok) { throw new Error('操作失败'); } + const result = await response.json(); + if (!result.success) { + throw new Error(result.message || '操作失败'); + } + + // 更新暂停状态 + this.isPaused = !this.isPaused; // 更新按钮状态 - button.textContent = isPaused ? '暂停仿真' : '继续仿真'; - this.showMessage(isPaused ? '仿真已继续' : '仿真已暂停'); + button.textContent = this.isPaused ? '继续仿真' : '暂停仿真'; + this.showMessage(this.isPaused ? '仿真已暂停' : '仿真已继续'); } catch (error) { console.error('暂停/继续仿真失败:', error); this.showError('操作失败: ' + error.message); @@ -1003,8 +1074,39 @@ class RunSim extends HTMLElement { if (!simulationId) return; try { - // 调用后端API停止仿真 - const response = await fetch('/api/stop-simulation', { + // 检查DDS状态 + const ddsStatusResponse = await fetch('/api/dds-monitor/status'); + if (!ddsStatusResponse.ok) { + throw new Error('获取DDS状态失败'); + } + + const ddsStatus = await ddsStatusResponse.json(); + if (!ddsStatus.isInitialized) { + throw new Error('DDS监控未初始化'); + } + + // 首先使用新的引擎控制接口 + const response = await fetch('/api/system-control/stop', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + throw new Error('停止引擎失败'); + } + + const result = await response.json(); + if (!result.success) { + throw new Error(result.message || '停止引擎失败'); + } + + // 等待5秒 + await new Promise(resolve => setTimeout(resolve, 5000)); + + // 调用老接口确保完全停止 + const fallbackResponse = await fetch('/api/stop-simulation', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -1014,8 +1116,8 @@ class RunSim extends HTMLElement { }) }); - if (!response.ok) { - throw new Error('停止仿真失败'); + if (!fallbackResponse.ok) { + console.warn('调用老接口停止仿真失败,但引擎已停止'); } // 关闭SSE连接 @@ -1044,6 +1146,7 @@ class RunSim extends HTMLElement { pauseButton.disabled = true; stopButton.disabled = true; pauseButton.textContent = '暂停仿真'; + this.isPaused = false; } } diff --git a/XNSimHtml/routes/SystemControl.js b/XNSimHtml/routes/SystemControl.js new file mode 100644 index 0000000..a537588 --- /dev/null +++ b/XNSimHtml/routes/SystemControl.js @@ -0,0 +1,99 @@ +const express = require('express'); +const router = express.Router(); +const { + initializeEngineControl, + pauseEngine, + resumeEngine, + stopEngine +} = require('../utils/systemMonitor'); + +/** + * @brief 初始化引擎控制 + * @route POST /api/system-control/initialize + * @returns {Object} 返回初始化结果 + */ +router.post('/initialize', async (req, res) => { + try { + const result = initializeEngineControl(); + + if (result.includes('失败')) { + res.status(500).json({ + success: false, + message: result + }); + return; + } + + res.json({ + success: true, + message: result + }); + } catch (error) { + res.status(500).json({ + success: false, + message: `初始化引擎控制失败: ${error.message}` + }); + } +}); + +/** + * @brief 暂停引擎 + * @route POST /api/system-control/pause + * @returns {Object} 返回暂停操作结果 + */ +router.post('/pause', async (req, res) => { + try { + const result = pauseEngine(); + res.json({ + success: !result.includes('失败'), + message: result + }); + } catch (error) { + res.status(500).json({ + success: false, + message: `暂停引擎失败: ${error.message}` + }); + } +}); + +/** + * @brief 恢复引擎 + * @route POST /api/system-control/resume + * @returns {Object} 返回恢复操作结果 + */ +router.post('/resume', async (req, res) => { + try { + const result = resumeEngine(); + res.json({ + success: !result.includes('失败'), + message: result + }); + } catch (error) { + res.status(500).json({ + success: false, + message: `恢复引擎失败: ${error.message}` + }); + } +}); + +/** + * @brief 停止引擎 + * @route POST /api/system-control/stop + * @returns {Object} 返回停止操作结果 + */ +router.post('/stop', async (req, res) => { + try { + const result = stopEngine(); + res.json({ + success: !result.includes('失败'), + message: result + }); + } catch (error) { + res.status(500).json({ + success: false, + message: `停止引擎失败: ${error.message}` + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/XNSimHtml/server.js b/XNSimHtml/server.js index 67f2b01..cbb1277 100644 --- a/XNSimHtml/server.js +++ b/XNSimHtml/server.js @@ -29,6 +29,7 @@ const systemLogRoutes = require('./routes/system-log'); const ddsMonitorRoutes = require('./routes/DDSMonitor'); const systemMonitorRoutes = require('./routes/SystemMonitor'); const modelMonitorRoutes = require('./routes/ModelMonitor'); +const systemControlRoutes = require('./routes/SystemControl'); const app = express(); const PORT = process.env.PORT || 3000; @@ -99,6 +100,7 @@ app.use('/api/system-log', systemLogRoutes); app.use('/api/dds-monitor', ddsMonitorRoutes); app.use('/api/system-monitor', systemMonitorRoutes); app.use('/api/model-monitor', modelMonitorRoutes); +app.use('/api/system-control', systemControlRoutes); // 接口配置页面路由 app.get('/interface-config', (req, res) => { diff --git a/XNSimHtml/utils/systemMonitor.js b/XNSimHtml/utils/systemMonitor.js index 86208a8..af7a6ec 100644 --- a/XNSimHtml/utils/systemMonitor.js +++ b/XNSimHtml/utils/systemMonitor.js @@ -49,7 +49,11 @@ try { 'XN_StopMonitorSystemInfo': ['void', []], 'XN_StartMonitorModelInfo': ['int', [StringType, 'int']], 'XN_GetModelInfo': ['int', [StringType, 'int']], - 'XN_StopMonitorModelInfo': ['void', []] + 'XN_StopMonitorModelInfo': ['void', []], + 'XN_InitializeEngineControl': ['int', [StringType, 'int']], + 'XN_PauseEngine': ['void', [StringType, 'int']], + 'XN_ResumeEngine': ['void', [StringType, 'int']], + 'XN_StopEngine': ['void', [StringType, 'int']] }); } catch (error) { console.error(`加载 ${monitorLibName} 失败:`, error); @@ -225,6 +229,68 @@ function stopMonitorModelInfo() { } } +// 初始化引擎控制 +function initializeEngineControl() { + if (!monitorLib) { + return '监控服务器库未加载'; + } + try { + const errorMsg = Buffer.alloc(1024); + const result = monitorLib.XN_InitializeEngineControl(errorMsg, errorMsg.length); + if (result !== 0) { + return `初始化引擎控制失败: ${errorMsg.toString('utf8').replace(/\0/g, '')}`; + } + return '初始化引擎控制成功'; + } catch (error) { + return `初始化引擎控制失败: ${error.message}`; + } +} + +// 暂停引擎 +function pauseEngine() { + if (!monitorLib) { + return '监控服务器库未加载'; + } + try { + const errorMsg = Buffer.alloc(1024); + monitorLib.XN_PauseEngine(errorMsg, errorMsg.length); + const error = errorMsg.toString('utf8').replace(/\0/g, ''); + return error ? `暂停引擎失败: ${error}` : '暂停引擎成功'; + } catch (error) { + return `暂停引擎失败: ${error.message}`; + } +} + +// 恢复引擎 +function resumeEngine() { + if (!monitorLib) { + return '监控服务器库未加载'; + } + try { + const errorMsg = Buffer.alloc(1024); + monitorLib.XN_ResumeEngine(errorMsg, errorMsg.length); + const error = errorMsg.toString('utf8').replace(/\0/g, ''); + return error ? `恢复引擎失败: ${error}` : '恢复引擎成功'; + } catch (error) { + return `恢复引擎失败: ${error.message}`; + } +} + +// 停止引擎 +function stopEngine() { + if (!monitorLib) { + return '监控服务器库未加载'; + } + try { + const errorMsg = Buffer.alloc(1024); + monitorLib.XN_StopEngine(errorMsg, errorMsg.length); + const error = errorMsg.toString('utf8').replace(/\0/g, ''); + return error ? `停止引擎失败: ${error}` : '停止引擎成功'; + } catch (error) { + return `停止引擎失败: ${error.message}`; + } +} + module.exports = { loginLib, monitorLib, @@ -238,5 +304,9 @@ module.exports = { stopMonitorSystemInfo, startMonitorModelInfo, getModelInfo, - stopMonitorModelInfo + stopMonitorModelInfo, + initializeEngineControl, + pauseEngine, + resumeEngine, + stopEngine }; \ No newline at end of file