From fb2dd9a57a16389157dca056c4c6497f22e5413a Mon Sep 17 00:00:00 2001 From: jinchao <383321154@qq.com> Date: Thu, 15 May 2025 09:15:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=EF=BC=8C=E4=BD=86=E6=9C=89=E4=B8=80=E4=BA=9B?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Release/database/XNSim.db | Bin 200704 -> 200704 bytes XNMonitorServer/ModelInfoMonitor.cpp | 1 + XNSimHtml/components/model-monitor.js | 615 +++++++++++++++++- XNSimHtml/routes/DDSMonitor.js | 2 +- XNSimHtml/routes/ModelMonitor.js | 220 +++++++ XNSimHtml/routes/SystemMonitor.js | 2 +- XNSimHtml/routes/auth.js | 2 +- XNSimHtml/server.js | 4 +- .../cleanup.js => utils/systemMonitor.js} | 63 +- 9 files changed, 883 insertions(+), 26 deletions(-) create mode 100644 XNSimHtml/routes/ModelMonitor.js rename XNSimHtml/{modules/cleanup.js => utils/systemMonitor.js} (76%) diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db index c852265664c6f7e3ae169d621e6146c2208fdd31..12b6811dd1eb907369ad9e9a34c947e95cf19d2c 100644 GIT binary patch delta 88 zcmV-e0H^M$IxsjoGBhqYH!zo44+Ext030{~ delta 88 zcmV-e0H^ +#include using json = nlohmann::json; diff --git a/XNSimHtml/components/model-monitor.js b/XNSimHtml/components/model-monitor.js index 0c97e7a..3d32fe9 100644 --- a/XNSimHtml/components/model-monitor.js +++ b/XNSimHtml/components/model-monitor.js @@ -2,10 +2,236 @@ class ModelMonitor extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); + this.monitorStatus = { + isMonitoring: false, + lastError: null + }; + this.modelInfo = null; + this.statusCheckInterval = null; + this.chart = null; + this.chartInitialized = false; } connectedCallback() { this.render(); + // 等待组件完全加载 + setTimeout(() => { + this.initializeComponent(); + }, 100); + } + + initializeComponent() { + if (this.chartInitialized) return; + + try { + this.initChart(); + this.startStatusCheck(); + this.chartInitialized = true; + } catch (error) { + console.error('初始化组件失败:', error); + } + } + + disconnectedCallback() { + this.stopStatusCheck(); + } + + startStatusCheck() { + this.checkMonitorStatus(); + this.statusCheckInterval = setInterval(() => { + this.checkMonitorStatus(); + }, 1000); + } + + stopStatusCheck() { + if (this.statusCheckInterval) { + clearInterval(this.statusCheckInterval); + this.statusCheckInterval = null; + } + } + + async checkMonitorStatus() { + try { + // 获取监控状态 + const statusResponse = await fetch('/api/model-monitor/status'); + const statusData = await statusResponse.json(); + this.monitorStatus = statusData; + + if (this.monitorStatus.isMonitoring) { + try { + // 获取模型信息 + const modelResponse = await fetch('/api/model-monitor/model-info'); + const modelData = await modelResponse.json(); + + if (!modelResponse.ok) { + console.error('获取模型信息失败:', modelData.error || modelData.message); + this.monitorStatus.lastError = modelData.error || modelData.message; + this.modelInfo = null; + } else { + this.modelInfo = modelData.data; + this.monitorStatus.lastError = null; + } + } catch (error) { + console.error('获取模型信息失败:', error); + this.monitorStatus.lastError = error.message; + this.modelInfo = null; + } + } else { + this.modelInfo = null; + this.monitorStatus.lastError = null; + } + + this.updateUI(); + } catch (error) { + console.error('获取监控状态失败:', error); + this.monitorStatus.lastError = error.message; + this.modelInfo = null; + this.updateUI(); + } + } + + getStatusDisplay(status) { + switch (status) { + case 0: + return { text: '未运行', color: '#999999' }; + case 1: + return { text: '运行中', color: '#4CAF50' }; + case 2: + return { text: '暂停中', color: '#FF9800' }; + case 3: + return { text: '错误', color: '#f44336' }; + default: + return { text: '未知状态', color: '#f44336' }; + } + } + + updateUI() { + const input = this.shadowRoot.querySelector('.domain-input'); + const startButton = this.shadowRoot.querySelector('.start-button'); + const stopButton = this.shadowRoot.querySelector('.stop-button'); + const statusDisplay = this.shadowRoot.querySelector('.status-display'); + const modelTableBody = this.shadowRoot.querySelector('#model-table-body'); + + if (this.monitorStatus.isMonitoring) { + input.disabled = true; + startButton.disabled = true; + stopButton.disabled = false; + } else { + input.disabled = false; + startButton.disabled = false; + stopButton.disabled = true; + } + + // 更新状态显示 + statusDisplay.textContent = `监控状态: ${this.monitorStatus.isMonitoring ? '运行中' : '已停止'}`; + if (this.monitorStatus.lastError) { + statusDisplay.textContent += ` (错误: ${this.monitorStatus.lastError})`; + } + + // 更新模型表格 + if (this.monitorStatus.isMonitoring && this.modelInfo && Array.isArray(this.modelInfo)) { + modelTableBody.innerHTML = this.modelInfo.map(model => { + const statusInfo = this.getStatusDisplay(model.status); + return ` + + ${model.name || '未知'} + ${model.id || '未知'} + ${statusInfo.text} + ${model.threadId || '未知'} + ${model.node} + ${model.priority || '未知'} + ${model.runCount || '0'} + ${(model.setFrequency || 0).toFixed(2)} + ${(model.avgFrequency || 0).toFixed(2)} + ${(model.maxFrequency || 0).toFixed(2)} + ${(model.minFrequency || 0).toFixed(2)} + ${(model.setPeriod || 0).toFixed(2)} + ${(model.avgPeriod || 0).toFixed(2)} + ${(model.maxPeriod || 0).toFixed(2)} + ${(model.minPeriod || 0).toFixed(2)} + + `; + }).join(''); + + // 更新图表数据 + this.updateChartData(); + } else { + modelTableBody.innerHTML = '暂无模型信息'; + // 清空图表数据 + if (this.chart) { + this.chart.data.labels = []; + this.chart.data.datasets = []; + this.chart.update(); + } + } + } + + async startMonitoring() { + const domainId = this.shadowRoot.querySelector('.domain-input').value.trim(); + + // 验证域ID是否为有效的数字字符串 + if (!/^\d+$/.test(domainId)) { + console.error('域ID必须是有效的数字'); + return; + } + + try { + // 首先检查DDS监控状态 + const ddsStatusResponse = await fetch('/api/dds-monitor/status'); + const ddsStatusData = await ddsStatusResponse.json(); + + // 如果DDS监控未初始化,先初始化DDS监控 + if (!ddsStatusData.isInitialized) { + const ddsInitResponse = await fetch('/api/dds-monitor/initialize', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ domainId }) + }); + + if (!ddsInitResponse.ok) { + const errorData = await ddsInitResponse.json(); + console.error('DDS监控初始化失败:', errorData.error); + return; + } + } + + // 启动模型监控 + const response = await fetch('/api/model-monitor/start', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ domainId }) + }); + const data = await response.json(); + if (response.ok) { + this.monitorStatus = data.status; + this.updateUI(); + } else { + console.error('启动监控失败:', data.error); + } + } catch (error) { + console.error('启动监控失败:', error); + } + } + + async stopMonitoring() { + try { + const response = await fetch('/api/model-monitor/stop', { + method: 'POST' + }); + const data = await response.json(); + if (response.ok) { + this.monitorStatus = data.status; + this.updateUI(); + } else { + console.error('停止监控失败:', data.error); + } + } catch (error) { + console.error('停止监控失败:', error); + } } render() { @@ -20,37 +246,392 @@ class ModelMonitor extends HTMLElement { } .monitor-container { - background-color: white; - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0,0,0,0.1); - padding: 16px; + display: flex; + flex-direction: column; + gap: 16px; height: 100%; box-sizing: border-box; } - .monitor-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; - padding-bottom: 10px; - border-bottom: 1px solid #e0e0e0; + .toolbar-section { + background-color: white; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); + padding: 16px; } - .monitor-title { - font-size: 18px; - font-weight: bold; + .content-container { + display: flex; + flex-direction: column; + gap: 16px; + flex: 1; + } + + .panel-section { + background-color: white; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); + padding: 16px; + } + + .toolbar { + display: flex; + gap: 12px; + align-items: center; + justify-content: space-between; + } + + .toolbar-left { + display: flex; + gap: 12px; + align-items: center; + } + + .input-group { + display: flex; + align-items: center; + gap: 8px; + } + + .input-label { + font-size: 14px; color: #333; + white-space: nowrap; + } + + .domain-input { + padding: 8px 12px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 14px; + width: 200px; + } + + .domain-input:disabled { + background-color: #f5f5f5; + cursor: not-allowed; + } + + .control-button { + padding: 8px 16px; + border: none; + border-radius: 4px; + font-size: 14px; + cursor: pointer; + transition: background-color 0.2s; + } + + .control-button:disabled { + opacity: 0.6; + cursor: not-allowed; + } + + .start-button { + background-color: #4CAF50; + color: white; + } + + .start-button:hover:not(:disabled) { + background-color: #45a049; + } + + .stop-button { + background-color: #f44336; + color: white; + } + + .stop-button:hover:not(:disabled) { + background-color: #da190b; + } + + .status-display { + padding: 8px 12px; + background-color: #f5f5f5; + border-radius: 4px; + font-size: 14px; + color: #666; + } + + h3 { + margin: 0 0 12px 0; + color: #333; + font-size: 16px; + } + + .model-table { + width: 100%; + border-collapse: collapse; + margin-top: 8px; + } + + .model-table th, + .model-table td { + padding: 8px; + text-align: left; + border-bottom: 1px solid #e9ecef; + } + + .model-table th { + background-color: #f8f9fa; + font-weight: 500; + color: #333; + } + + .model-table tr:hover { + background-color: #f8f9fa; + } + + .chart-container { + position: relative; + width: 100%; + height: 300px; + margin: 0; + padding: 0; + } + + #model-chart { + width: 100% !important; + height: 100% !important; + display: block; + } + + .chart-controls { + display: flex; + align-items: center; + gap: 8px; + margin-top: 8px; + } + + .switch { + position: relative; + display: inline-block; + width: 60px; + height: 34px; + } + + .switch input { + opacity: 0; + width: 0; + height: 0; + } + + .slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + transition: .4s; + border-radius: 34px; + } + + .slider:before { + position: absolute; + content: ""; + height: 26px; + width: 26px; + left: 4px; + bottom: 4px; + background-color: white; + transition: .4s; + border-radius: 50%; + } + + input:checked + .slider { + background-color: #2196F3; + } + + input:checked + .slider:before { + transform: translateX(26px); }
-
-
模型监控
+
+
+
+
+ + +
+ + +
+
监控状态: 未启动
+
+
+
+
+

模型信息

+ + + + + + + + + + + + + + + + + + + + + +
模型名称模型ID状态线程ID节点优先级运行次数设定频率(Hz)平均频率(Hz)最大频率(Hz)最小频率(Hz)设定周期(ms)平均周期(ms)最大周期(ms)最小周期(ms)
+
+
+

模型监控

+
+ +
+
+ 显示类型: + + 频率 +
+
-
模型监控组件内容(待实现)
`; } + + initChart() { + const chartElement = this.shadowRoot.querySelector('#model-chart'); + if (!chartElement) { + console.error('找不到图表元素'); + return; + } + + // 确保 Chart.js 已加载 + if (typeof Chart === 'undefined') { + console.error('Chart.js 未加载'); + return; + } + + try { + // 创建图表实例 + const ctx = chartElement.getContext('2d'); + if (!ctx) { + console.error('无法获取 canvas 上下文'); + return; + } + + // 销毁已存在的图表实例 + if (this.chart) { + this.chart.destroy(); + } + + // 创建新的图表实例 + this.chart = new Chart(ctx, { + type: 'line', + data: { + labels: [], + datasets: [] + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + beginAtZero: true + } + }, + animation: false, + plugins: { + legend: { + display: true + }, + tooltip: { + enabled: false + } + } + } + }); + + // 监听显示类型切换 + const switchInput = this.shadowRoot.querySelector('#display-type-switch'); + const displayTypeLabel = this.shadowRoot.querySelector('#display-type-label'); + + if (switchInput && displayTypeLabel) { + switchInput.addEventListener('change', (e) => { + const isFrequency = e.target.checked; + displayTypeLabel.textContent = isFrequency ? '频率' : '周期'; + this.updateChartDisplayType(isFrequency); + }); + } + } catch (error) { + console.error('初始化图表失败:', error); + this.chart = null; + } + } + + updateChartData() { + if (!this.chart || !this.modelInfo || !Array.isArray(this.modelInfo)) return; + + const isFrequency = this.shadowRoot.querySelector('#display-type-switch').checked; + const currentTime = new Date().toLocaleTimeString(); + + // 确保图表数据集存在 + if (!this.chart.data.datasets || this.chart.data.datasets.length === 0) { + this.updateChartDisplayType(isFrequency); + } + + // 更新数据 + const newData = { + labels: [...this.chart.data.labels, currentTime].slice(-30), + datasets: this.modelInfo.map((model, index) => { + const dataset = this.chart.data.datasets[index] || { + label: model.name, + data: [], + borderColor: this.getRandomColor(), + fill: false + }; + + const value = isFrequency ? (model.currentFrequency || 0) : (model.currentPeriod || 0); + dataset.data = [...dataset.data, value].slice(-30); + + return dataset; + }) + }; + + // 使用新数据更新图表 + this.chart.data = newData; + this.chart.update('none'); // 使用 'none' 模式更新,避免触发动画和事件 + } + + updateChartDisplayType(isFrequency) { + if (!this.modelInfo) return; + + const datasets = this.modelInfo.map(model => ({ + label: model.name, + data: [], + borderColor: this.getRandomColor(), + fill: false + })); + + this.chart.data.datasets = datasets; + this.chart.update('none'); // 使用 'none' 模式更新 + } + + getRandomColor() { + const letters = '0123456789ABCDEF'; + let color = '#'; + for (let i = 0; i < 6; i++) { + color += letters[Math.floor(Math.random() * 16)]; + } + return color; + } } customElements.define('model-monitor', ModelMonitor); \ No newline at end of file diff --git a/XNSimHtml/routes/DDSMonitor.js b/XNSimHtml/routes/DDSMonitor.js index 8d2526e..a1b0a62 100644 --- a/XNSimHtml/routes/DDSMonitor.js +++ b/XNSimHtml/routes/DDSMonitor.js @@ -1,6 +1,6 @@ const express = require('express'); const router = express.Router(); -const { initializeMonitor, cleanupMonitor } = require('../modules/cleanup'); +const { initializeMonitor, cleanupMonitor } = require('../utils/systemMonitor'); // 存储监控服务的状态 let monitorStatus = { diff --git a/XNSimHtml/routes/ModelMonitor.js b/XNSimHtml/routes/ModelMonitor.js new file mode 100644 index 0000000..79d92bb --- /dev/null +++ b/XNSimHtml/routes/ModelMonitor.js @@ -0,0 +1,220 @@ +const express = require('express'); +const router = express.Router(); +const { startMonitorModelInfo, stopMonitorModelInfo, getModelInfo } = require('../utils/systemMonitor'); + +// 存储监控服务的状态 +let monitorStatus = { + isMonitoring: false, + lastError: null +}; + +// 存储模型频率历史数据 +const modelFrequencyHistory = new Map(); // Map +const MAX_HISTORY_SIZE = 100; + +// 存储模型频率统计 +const modelFrequencyStats = new Map(); // Map + +// 频率转周期(单位:ms) +function frequencyToPeriod(frequency) { + return frequency === 0 ? 0 : (1000 / frequency); +} + +// 更新模型频率统计 +function updateModelFrequencyStats(modelId, currentFrequency, setFrequency) { + // 初始化历史数据 + if (!modelFrequencyHistory.has(modelId)) { + modelFrequencyHistory.set(modelId, []); + } + + // 初始化统计数据 + if (!modelFrequencyStats.has(modelId)) { + modelFrequencyStats.set(modelId, { + max: setFrequency, + min: setFrequency, + avg: setFrequency + }); + } + + const history = modelFrequencyHistory.get(modelId); + const stats = modelFrequencyStats.get(modelId); + + // 更新最大最小值 + stats.max = Math.max(stats.max, currentFrequency); + stats.min = Math.min(stats.min, currentFrequency); + + // 更新历史数据 + history.push(currentFrequency); + if (history.length > MAX_HISTORY_SIZE) { + history.shift(); // 移除最旧的数据 + } + + // 计算平均值 + stats.avg = history.reduce((sum, freq) => sum + freq, 0) / history.length; +} + +// 启动模型监控 +router.post('/start', async (req, res) => { + try { + if (monitorStatus.isMonitoring) { + return res.status(400).json({ error: '模型监控已经在运行' }); + } + + const result = startMonitorModelInfo(); + if (result && result.includes('失败')) { + monitorStatus.lastError = result; + return res.status(500).json({ error: result }); + } + + // 清空历史数据和统计数据 + modelFrequencyHistory.clear(); + modelFrequencyStats.clear(); + + monitorStatus.isMonitoring = true; + monitorStatus.lastError = null; + + res.json({ + message: '模型监控启动成功', + status: monitorStatus + }); + } catch (error) { + console.error('启动模型监控失败:', error); + monitorStatus.lastError = error.message; + res.status(500).json({ error: '启动模型监控失败', message: error.message }); + } +}); + +// 停止模型监控 +router.post('/stop', async (req, res) => { + try { + if (!monitorStatus.isMonitoring) { + return res.status(400).json({ error: '模型监控未在运行' }); + } + + stopMonitorModelInfo(); + monitorStatus.isMonitoring = false; + monitorStatus.lastError = null; + + // 清空历史数据和统计数据 + modelFrequencyHistory.clear(); + modelFrequencyStats.clear(); + + res.json({ + message: '模型监控停止成功', + status: monitorStatus + }); + } catch (error) { + console.error('停止模型监控失败:', error); + monitorStatus.lastError = error.message; + res.status(500).json({ error: '停止模型监控失败', message: error.message }); + } +}); + +// 获取模型信息 +router.get('/model-info', async (req, res) => { + try { + if (!monitorStatus.isMonitoring) { + return res.status(400).json({ error: '模型监控未在运行' }); + } + + const result = getModelInfo(); + if (result && result.includes('失败')) { + monitorStatus.lastError = result; + return res.status(500).json({ error: result }); + } + + // 解析JSON字符串 + let data; + try { + data = JSON.parse(result); + } catch (error) { + console.error('解析模型信息JSON失败:', error); + return res.status(500).json({ error: '解析模型信息失败', message: error.message }); + } + + // 检查数据结构 + if (!data || typeof data !== 'object') { + return res.status(500).json({ error: '模型信息数据格式错误' }); + } + + // 检查顶层modelStatus字段 + if (!data.modelStatus || typeof data.modelStatus !== 'object') { + return res.status(500).json({ error: '模型状态数据缺失' }); + } + + // 构造响应数据 + const responseData = Object.entries(data.modelStatus).map(([modelId, model]) => { + // 检查必要字段 + const requiredFields = [ + 'modelName', 'modelID', 'modelStatus', 'modelThreadID', + 'modelNode', 'modelPriority', 'modelRunCount', + 'modelCurrentFrequency', 'modelSetFrequency' + ]; + + const missingFields = requiredFields.filter(field => + model[field] === undefined || model[field] === null + ); + + if (missingFields.length > 0) { + throw new Error(`模型数据不完整: 缺少 ${missingFields.join(', ')}`); + } + + // 更新频率统计 + updateModelFrequencyStats( + parseInt(modelId), + model.modelCurrentFrequency, + model.modelSetFrequency + ); + + const stats = modelFrequencyStats.get(parseInt(modelId)); + if (!stats) { + throw new Error('模型频率统计数据缺失'); + } + + // 计算周期值 + const currentPeriod = frequencyToPeriod(model.modelCurrentFrequency); + const setPeriod = frequencyToPeriod(model.modelSetFrequency); + const maxPeriod = frequencyToPeriod(stats.min); + const minPeriod = frequencyToPeriod(stats.max); + const avgPeriod = frequencyToPeriod(stats.avg); + + return { + id: parseInt(modelId), + name: model.modelName, + status: model.modelStatus, + threadId: model.modelThreadID, + node: model.modelNode, + priority: model.modelPriority, + runCount: model.modelRunCount, + // 频率值 + currentFrequency: model.modelCurrentFrequency, + setFrequency: model.modelSetFrequency, + maxFrequency: stats.max, + minFrequency: stats.min, + avgFrequency: stats.avg, + // 周期值(单位:ms) + currentPeriod: currentPeriod, + setPeriod: setPeriod, + maxPeriod: maxPeriod, + minPeriod: minPeriod, + avgPeriod: avgPeriod + }; + }); + + res.json({ + data: responseData, + status: monitorStatus + }); + } catch (error) { + console.error('获取模型信息失败:', error); + monitorStatus.lastError = error.message; + res.status(500).json({ error: '获取模型信息失败', message: error.message }); + } +}); + +// 获取监控状态 +router.get('/status', (req, res) => { + res.json(monitorStatus); +}); + +module.exports = router; \ No newline at end of file diff --git a/XNSimHtml/routes/SystemMonitor.js b/XNSimHtml/routes/SystemMonitor.js index 488046f..47ec011 100644 --- a/XNSimHtml/routes/SystemMonitor.js +++ b/XNSimHtml/routes/SystemMonitor.js @@ -1,6 +1,6 @@ const express = require('express'); const router = express.Router(); -const { startMonitorSystemInfo, stopMonitorSystemInfo, getSystemInfo, getAllThreadInfo } = require('../modules/cleanup'); +const { startMonitorSystemInfo, stopMonitorSystemInfo, getSystemInfo, getAllThreadInfo } = require('../utils/systemMonitor'); // 存储监控服务的状态 let monitorStatus = { diff --git a/XNSimHtml/routes/auth.js b/XNSimHtml/routes/auth.js index a541b64..92c39c8 100644 --- a/XNSimHtml/routes/auth.js +++ b/XNSimHtml/routes/auth.js @@ -1,6 +1,6 @@ const express = require('express'); const router = express.Router(); -const { loginLib, stringToBuffer } = require('../modules/cleanup'); +const { loginLib, stringToBuffer } = require('../utils/systemMonitor'); const jwt = require('jsonwebtoken'); // JWT密钥 diff --git a/XNSimHtml/server.js b/XNSimHtml/server.js index 008c24e..74c2842 100644 --- a/XNSimHtml/server.js +++ b/XNSimHtml/server.js @@ -6,7 +6,7 @@ const cookieParser = require('cookie-parser'); const cors = require('cors'); // 导入自定义模块 -const { performCleanup } = require('./modules/cleanup'); +const { performCleanup } = require('./utils/systemMonitor'); const authRoutes = require('./routes/auth'); const versionRoutes = require('./routes/versions'); const filesystemRoutes = require('./routes/filesystem'); @@ -29,6 +29,7 @@ const userRoutes = require('./routes/users'); const systemLogRoutes = require('./routes/system-log'); const ddsMonitorRoutes = require('./routes/DDSMonitor'); const systemMonitorRoutes = require('./routes/SystemMonitor'); +const modelMonitorRoutes = require('./routes/ModelMonitor'); const app = express(); const PORT = process.env.PORT || 3000; @@ -99,6 +100,7 @@ app.use('/api', userRoutes); 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.get('/interface-config', (req, res) => { diff --git a/XNSimHtml/modules/cleanup.js b/XNSimHtml/utils/systemMonitor.js similarity index 76% rename from XNSimHtml/modules/cleanup.js rename to XNSimHtml/utils/systemMonitor.js index f2fa1a7..86208a8 100644 --- a/XNSimHtml/modules/cleanup.js +++ b/XNSimHtml/utils/systemMonitor.js @@ -46,7 +46,10 @@ try { 'XN_StartMonitorSystemInfo': ['int', [StringType, 'int']], 'XN_GetSystemInfo': ['int', [StringType, 'int']], 'XN_GetAllThreadInfo': ['int', [StringType, 'int']], - 'XN_StopMonitorSystemInfo': ['void', []] + 'XN_StopMonitorSystemInfo': ['void', []], + 'XN_StartMonitorModelInfo': ['int', [StringType, 'int']], + 'XN_GetModelInfo': ['int', [StringType, 'int']], + 'XN_StopMonitorModelInfo': ['void', []] }); } catch (error) { console.error(`加载 ${monitorLibName} 失败:`, error); @@ -133,7 +136,7 @@ function getSystemInfo() { return '监控服务器库未加载'; } try { - const infoMsg = Buffer.alloc(4096); + const infoMsg = Buffer.alloc(8192); const result = monitorLib.XN_GetSystemInfo(infoMsg, infoMsg.length); if (result !== 0) { @@ -151,7 +154,7 @@ function getAllThreadInfo() { return '监控服务器库未加载'; } try { - const infoMsg = Buffer.alloc(4096); + const infoMsg = Buffer.alloc(8192); const result = monitorLib.XN_GetAllThreadInfo(infoMsg, infoMsg.length); if (result !== 0) { @@ -175,6 +178,53 @@ function stopMonitorSystemInfo() { } } +// 启动监控模型信息 +function startMonitorModelInfo() { + if (!monitorLib) { + return '监控服务器库未加载'; + } + try { + const errorMsg = Buffer.alloc(1024); + const result = monitorLib.XN_StartMonitorModelInfo(errorMsg, errorMsg.length); + if (result !== 0) { + return `启动失败: ${errorMsg.toString('utf8').replace(/\0/g, '')}`; + } + return '启动成功'; + } catch (error) { + return `启动失败: ${error.message}`; + } +} + +// 获取模型信息 +function getModelInfo() { + if (!monitorLib) { + return '监控服务器库未加载'; + } + try { + const infoMsg = Buffer.alloc(16384); + const result = monitorLib.XN_GetModelInfo(infoMsg, infoMsg.length); + + if (result !== 0) { + return `获取失败: ${infoMsg.toString('utf8').replace(/\0/g, '')}`; + } + return infoMsg.toString('utf8').replace(/\0/g, ''); + } catch (error) { + return `获取失败: ${error.message}`; + } +} + +// 停止监控模型信息 +function stopMonitorModelInfo() { + if (!monitorLib) { + return; + } + try { + monitorLib.XN_StopMonitorModelInfo(); + } catch (error) { + return; + } +} + module.exports = { loginLib, monitorLib, @@ -185,5 +235,8 @@ module.exports = { startMonitorSystemInfo, getSystemInfo, getAllThreadInfo, - stopMonitorSystemInfo -}; \ No newline at end of file + stopMonitorSystemInfo, + startMonitorModelInfo, + getModelInfo, + stopMonitorModelInfo +}; \ No newline at end of file