V0.28.2.250618_alpha:修复了运行仿真第二次会导致崩溃的问题
This commit is contained in:
parent
346b34ee40
commit
9c3326eeda
Binary file not shown.
@ -3,7 +3,13 @@
|
||||
|
||||
SystemControl::~SystemControl()
|
||||
{
|
||||
//注销引擎控制发布者
|
||||
if (m_EngineControlWriter != nullptr) {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void SystemControl::cleanup()
|
||||
{
|
||||
TopicManager::Instance()->unregisterPublisher("XNSim::XNSimControl::XNRuntimeControl");
|
||||
m_EngineControlWriter = nullptr;
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ public:
|
||||
void Resume();
|
||||
void Stop();
|
||||
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
XNDataWriter *m_EngineControlWriter;
|
||||
};
|
||||
|
@ -56,8 +56,6 @@ public:
|
||||
->delete_participant(instance->m_Participant); // 删除参与者
|
||||
instance->m_Participant = nullptr; // 设置参与者为空
|
||||
}
|
||||
delete instance; // 删除单例
|
||||
instance = nullptr; // 设置单例为空
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ bool g_modelInfoMonitorStarted = false;
|
||||
SystemControl *systemControl = nullptr;
|
||||
bool g_systemControlStarted = false;
|
||||
|
||||
std::unordered_map<std::string, DataInjectThreadPtr> g_dataInjectThreads;
|
||||
CSVDataInjectThread *g_csvDataInjectThread = nullptr;
|
||||
DataCollect *g_dataCollect = nullptr;
|
||||
|
||||
@ -277,24 +278,6 @@ void XN_StopMonitorModelInfo()
|
||||
}
|
||||
}
|
||||
|
||||
// 清理函数实现
|
||||
void XN_Cleanup()
|
||||
{
|
||||
if (g_initialized) {
|
||||
// 停止并清理系统信息监控
|
||||
if (g_systemInfoMonitorStarted) {
|
||||
XN_StopMonitorSystemInfo();
|
||||
}
|
||||
// 停止并清理模型信息监控
|
||||
if (g_modelInfoMonitorStarted) {
|
||||
XN_StopMonitorModelInfo();
|
||||
}
|
||||
// 清理DDS参与者
|
||||
TopicManager::cleanupParticipant();
|
||||
g_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
int XN_InitializeEngineControl(char *errorMsg, int errorMsgSize)
|
||||
{
|
||||
if (g_systemControlStarted) {
|
||||
@ -360,6 +343,16 @@ void XN_StopEngine(char *errorMsg, int errorMsgSize)
|
||||
systemControl->Stop();
|
||||
}
|
||||
|
||||
void XN_CleanupEngineControl()
|
||||
{
|
||||
if (g_systemControlStarted) {
|
||||
systemControl->cleanup();
|
||||
delete systemControl;
|
||||
systemControl = nullptr;
|
||||
g_systemControlStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
int XN_StartDataMonitor(const char *structName, const int structNameLen, char *errorMsg,
|
||||
int errorMsgSize)
|
||||
{
|
||||
@ -517,8 +510,6 @@ int XN_InjectDataInterface(const char *structName, const int structNameLen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, DataInjectThreadPtr> g_dataInjectThreads;
|
||||
|
||||
int XN_StartInjectContinuous(const char *structName, const int structNameLen,
|
||||
const char *interfaceNameAndData, const int interfaceNameAndDataLen,
|
||||
double frequency, char *infoMsg, int infoMsgSize)
|
||||
@ -585,12 +576,21 @@ int XN_StopInjectContinuous(const char *structName, const int structNameLen, cha
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XN_CleanupInjectContinuous()
|
||||
{
|
||||
for (auto &it : g_dataInjectThreads) {
|
||||
if (it.second) {
|
||||
it.second->stop();
|
||||
it.second.reset();
|
||||
it.second = nullptr;
|
||||
}
|
||||
}
|
||||
g_dataInjectThreads.clear();
|
||||
}
|
||||
// 从csv文件中注入数据接口
|
||||
int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv(const char *injectDataInfo,
|
||||
const int injectDataInfoLen,
|
||||
const char *csvFilePath,
|
||||
const int csvFilePathLen, char *infoMsg,
|
||||
int infoMsgSize)
|
||||
int XN_InjectDataInterfaceFromCsv(const char *injectDataInfo, const int injectDataInfoLen,
|
||||
const char *csvFilePath, const int csvFilePathLen, char *infoMsg,
|
||||
int infoMsgSize)
|
||||
{
|
||||
if (!g_initialized) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
@ -724,10 +724,17 @@ int XN_StopCsvDataInject(char *infoMsg, int infoMsgSize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XNMONITORSERVER_EXPORT XN_StartCollectData(const char *CollectDataInfo,
|
||||
const int CollectDataInfoLen,
|
||||
const char *dcsFilePath, const int dcsFilePathLen,
|
||||
char *infoMsg, int infoMsgSize)
|
||||
void XN_CleanupCsvDataInject()
|
||||
{
|
||||
if (g_csvDataInjectThread != nullptr) {
|
||||
g_csvDataInjectThread->stop();
|
||||
delete g_csvDataInjectThread;
|
||||
g_csvDataInjectThread = nullptr;
|
||||
}
|
||||
}
|
||||
int XN_StartCollectData(const char *CollectDataInfo, const int CollectDataInfoLen,
|
||||
const char *dcsFilePath, const int dcsFilePathLen, char *infoMsg,
|
||||
int infoMsgSize)
|
||||
{
|
||||
if (!g_initialized) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
@ -807,7 +814,7 @@ int XNMONITORSERVER_EXPORT XN_StartCollectData(const char *CollectDataInfo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XNMONITORSERVER_EXPORT XN_GetCollectDataStatus(char *infoMsg, int infoMsgSize)
|
||||
int XN_GetCollectDataStatus(char *infoMsg, int infoMsgSize)
|
||||
{
|
||||
if (!g_initialized) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
@ -828,7 +835,7 @@ int XNMONITORSERVER_EXPORT XN_GetCollectDataStatus(char *infoMsg, int infoMsgSiz
|
||||
return g_dataCollect->isRunning() ? 1 : 0;
|
||||
}
|
||||
|
||||
int XNMONITORSERVER_EXPORT XN_StopCollectData(char *infoMsg, int infoMsgSize)
|
||||
int XN_StopCollectData(char *infoMsg, int infoMsgSize)
|
||||
{
|
||||
if (!g_initialized) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
@ -859,4 +866,41 @@ int XNMONITORSERVER_EXPORT XN_StopCollectData(char *infoMsg, int infoMsgSize)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XN_CleanupDataCollect()
|
||||
{
|
||||
if (g_dataCollect != nullptr) {
|
||||
g_dataCollect->stop();
|
||||
delete g_dataCollect;
|
||||
g_dataCollect = nullptr;
|
||||
}
|
||||
}
|
||||
// 清理函数实现
|
||||
void XN_Cleanup()
|
||||
{
|
||||
if (g_initialized) {
|
||||
// 停止并清理系统信息监控
|
||||
if (g_systemInfoMonitorStarted) {
|
||||
XN_StopMonitorSystemInfo();
|
||||
}
|
||||
// 停止并清理模型信息监控
|
||||
if (g_modelInfoMonitorStarted) {
|
||||
XN_StopMonitorModelInfo();
|
||||
}
|
||||
// 停止并清理引擎控制
|
||||
if (g_systemControlStarted) {
|
||||
XN_CleanupEngineControl();
|
||||
}
|
||||
// 停止并清理数据采集
|
||||
XN_CleanupDataCollect();
|
||||
// 停止并清理CSV数据注入
|
||||
XN_CleanupCsvDataInject();
|
||||
// 停止并清理数据注入
|
||||
XN_CleanupInjectContinuous();
|
||||
|
||||
// 清理DDS参与者
|
||||
TopicManager::cleanupParticipant();
|
||||
g_initialized = false;
|
||||
}
|
||||
}
|
@ -1,11 +1,19 @@
|
||||
/**
|
||||
* @class NetworkMonitor
|
||||
* @description 网络监控组件,用于监控系统网络状态
|
||||
* @description 网络监控组件,用于监控系统网络状态和UDP数据抓包
|
||||
*/
|
||||
class NetworkMonitor extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
this.state = {
|
||||
ip: '127.0.0.1',
|
||||
port: 54321,
|
||||
isMonitoring: false,
|
||||
data: [],
|
||||
timer: null,
|
||||
statusMsg: '',
|
||||
};
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
@ -13,23 +21,268 @@ class NetworkMonitor extends HTMLElement {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
if (this.state.timer) {
|
||||
clearInterval(this.state.timer);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
this.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
font-family: 'Segoe UI', 'PingFang SC', Arial, sans-serif;
|
||||
background: #f4f6fa;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0,0,0,0.07);
|
||||
padding: 24px 20px 20px 20px;
|
||||
max-width: 600px;
|
||||
}
|
||||
.form-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
label {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
}
|
||||
input[type="text"], input[type="number"] {
|
||||
border: 1px solid #d0d7de;
|
||||
border-radius: 6px;
|
||||
padding: 6px 12px;
|
||||
font-size: 15px;
|
||||
outline: none;
|
||||
transition: border 0.2s;
|
||||
background: #fff;
|
||||
margin-left: 4px;
|
||||
}
|
||||
input[type="text"]:focus, input[type="number"]:focus {
|
||||
border: 1.5px solid #409eff;
|
||||
}
|
||||
.status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #eaf6ff;
|
||||
color: #1976d2;
|
||||
border-radius: 8px;
|
||||
padding: 8px 14px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 1px 4px rgba(64,158,255,0.07);
|
||||
}
|
||||
.status::before {
|
||||
content: '\u26A1';
|
||||
margin-right: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
button {
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 7px 20px;
|
||||
font-size: 15px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s, box-shadow 0.2s;
|
||||
box-shadow: 0 1px 4px rgba(64,158,255,0.07);
|
||||
}
|
||||
#startBtn {
|
||||
background: linear-gradient(90deg, #409eff 60%, #66b1ff 100%);
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
#startBtn:hover {
|
||||
background: linear-gradient(90deg, #1976d2 60%, #409eff 100%);
|
||||
}
|
||||
#stopBtn {
|
||||
background: #fff0f0;
|
||||
color: #e53935;
|
||||
font-weight: 600;
|
||||
border: 1px solid #ffcdd2;
|
||||
}
|
||||
#stopBtn:hover {
|
||||
background: #ffcdd2;
|
||||
}
|
||||
.monitor-status {
|
||||
margin-bottom: 14px;
|
||||
font-size: 15px;
|
||||
color: #666;
|
||||
}
|
||||
.monitor-status span {
|
||||
font-weight: bold;
|
||||
color: #43a047;
|
||||
}
|
||||
.monitor-status span.stopped {
|
||||
color: #e53935;
|
||||
}
|
||||
.data-list {
|
||||
max-height: 340px;
|
||||
overflow-y: auto;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #e0e3e7;
|
||||
padding: 10px 0 10px 0;
|
||||
box-shadow: 0 1px 6px rgba(0,0,0,0.04);
|
||||
}
|
||||
.data-item {
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
margin: 10px 16px;
|
||||
padding: 10px 14px 8px 14px;
|
||||
box-shadow: 0 1px 3px rgba(64,158,255,0.04);
|
||||
border-left: 4px solid #409eff;
|
||||
font-size: 14px;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
.data-item:hover {
|
||||
box-shadow: 0 2px 8px rgba(64,158,255,0.13);
|
||||
}
|
||||
.data-item b {
|
||||
color: #1976d2;
|
||||
}
|
||||
.data-item pre {
|
||||
background: #f3f7fa;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
margin: 2px 0 0 0;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
}
|
||||
.nodata {
|
||||
color: #bbb;
|
||||
text-align: center;
|
||||
padding: 30px 0;
|
||||
}
|
||||
</style>
|
||||
<div></div>
|
||||
<div class="status">${this.state.statusMsg}</div>
|
||||
<div class="form-row">
|
||||
<label>IP: <input type="text" id="ip" value="${this.state.ip}" /></label>
|
||||
<label>端口: <input type="number" id="port" value="${this.state.port}" min="1024" max="65535" /></label>
|
||||
<button id="startBtn">开始抓包</button>
|
||||
<button id="stopBtn">停止抓包</button>
|
||||
</div>
|
||||
<div class="monitor-status">抓包状态:<span id="monitorStatus" class="${this.state.isMonitoring ? '' : 'stopped'}">${this.state.isMonitoring ? '运行中' : '已停止'}</span></div>
|
||||
<div class="data-list" id="dataList"></div>
|
||||
`;
|
||||
this.shadowRoot.getElementById('startBtn').onclick = () => this.startMonitor();
|
||||
this.shadowRoot.getElementById('stopBtn').onclick = () => this.stopMonitor();
|
||||
this.shadowRoot.getElementById('ip').onchange = (e) => {
|
||||
this.state.ip = e.target.value;
|
||||
};
|
||||
this.shadowRoot.getElementById('port').onchange = (e) => {
|
||||
this.state.port = parseInt(e.target.value, 10);
|
||||
};
|
||||
this.renderDataList();
|
||||
}
|
||||
|
||||
renderDataList() {
|
||||
const dataList = this.shadowRoot.getElementById('dataList');
|
||||
if (!dataList) return;
|
||||
if (!this.state.data.length) {
|
||||
dataList.innerHTML = '<div class="nodata">暂无数据</div>';
|
||||
return;
|
||||
}
|
||||
dataList.innerHTML = this.state.data.map(item => `
|
||||
<div class="data-item">
|
||||
<div><b>时间:</b> ${new Date(item.timestamp).toLocaleString()}</div>
|
||||
<div><b>来源:</b> ${item.source}</div>
|
||||
<div><b>内容:</b> <pre>${typeof item.data === 'object' ? JSON.stringify(item.data, null, 2) : item.data}</pre></div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
setStatus(msg) {
|
||||
this.state.statusMsg = msg;
|
||||
this.render();
|
||||
}
|
||||
|
||||
async startMonitor() {
|
||||
this.setStatus('正在启动UDP抓包...');
|
||||
try {
|
||||
const res = await fetch('/api/udp-monitor/start', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ip: this.state.ip, port: this.state.port })
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
this.state.isMonitoring = true;
|
||||
this.setStatus(data.message || 'UDP抓包已启动');
|
||||
this.startPolling();
|
||||
} else {
|
||||
this.state.isMonitoring = false;
|
||||
this.setStatus(data.error || '启动失败');
|
||||
}
|
||||
} catch (e) {
|
||||
this.state.isMonitoring = false;
|
||||
this.setStatus('启动UDP抓包失败: ' + e.message);
|
||||
}
|
||||
this.render();
|
||||
}
|
||||
|
||||
async stopMonitor() {
|
||||
this.setStatus('正在停止UDP抓包...');
|
||||
try {
|
||||
const res = await fetch('/api/udp-monitor/stop', { method: 'POST' });
|
||||
const data = await res.json();
|
||||
this.state.isMonitoring = false;
|
||||
this.setStatus(data.message || 'UDP抓包已停止');
|
||||
if (this.state.timer) {
|
||||
clearInterval(this.state.timer);
|
||||
this.state.timer = null;
|
||||
}
|
||||
} catch (e) {
|
||||
this.setStatus('停止UDP抓包失败: ' + e.message);
|
||||
}
|
||||
this.render();
|
||||
}
|
||||
|
||||
startPolling() {
|
||||
if (this.state.timer) clearInterval(this.state.timer);
|
||||
this.state.timer = setInterval(() => this.fetchData(), 1000);
|
||||
}
|
||||
|
||||
async fetchData() {
|
||||
if (!this.state.isMonitoring) return;
|
||||
try {
|
||||
const res = await fetch('/api/udp-monitor/data');
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
if (Array.isArray(data.data) && data.data.length > 0) {
|
||||
this.state.data = this.state.data.concat(data.data);
|
||||
// 最多只保留1000条
|
||||
if (this.state.data.length > 1000) {
|
||||
this.state.data = this.state.data.slice(-1000);
|
||||
}
|
||||
this.renderDataList();
|
||||
}
|
||||
this.state.isMonitoring = data.isMonitoring;
|
||||
this.shadowRoot.getElementById('monitorStatus').textContent = data.isMonitoring ? '运行中' : '已停止';
|
||||
}
|
||||
} catch (e) {
|
||||
this.setStatus('获取UDP数据失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
initialize() {
|
||||
console.log('网络监控组件已初始化');
|
||||
this.setStatus('请设置IP和端口后点击开始抓包');
|
||||
// 检查当前监控状态
|
||||
fetch('/api/udp-monitor/status').then(res => res.json()).then(data => {
|
||||
if (data.success && data.isMonitoring) {
|
||||
this.state.isMonitoring = true;
|
||||
this.state.ip = data.ip || this.state.ip;
|
||||
this.state.port = data.port || this.state.port;
|
||||
this.setStatus('UDP抓包已在运行');
|
||||
this.startPolling();
|
||||
this.render();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reactivate() {
|
||||
console.log('网络监控组件已重新激活');
|
||||
this.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user