XNSim/XNMonitor/DataMonitorWidget/DataMonitorThread.cpp
2025-04-28 12:25:20 +08:00

289 lines
10 KiB
C++
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file DataMonitorThread.cpp
* @author jinchao
* @brief 数据监控线程类实现
* @version 1.0
* @date 2025-03-10
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#include "DataMonitorThread.h"
#include <QMutexLocker>
#include <QDebug>
#include <functional>
#include "../TopicManager/TopicManager.h"
#include "../TopicMonitorFactory/TopicMonitorFactory.h"
DataMonitorThread::DataMonitorThread(QObject *parent) : QThread(parent)
{
}
DataMonitorThread::~DataMonitorThread()
{
// 停止所有主题监控
if (m_TopicMonitorMap.size() > 0) {
for (auto &topicName : m_TopicMonitorMap.keys()) {
m_TopicMonitorMap[topicName]->stopMonitoring(topicName);
m_TopicMonitorMap.remove(topicName);
}
}
}
void DataMonitorThread::run()
{
while (!m_Quit) {
if (m_Active) {
QMutexLocker locker(&m_Mutex);
for (auto &topicName : m_VarNameMap.keys()) {
// 遍历主题名下的所有变量
for (auto &varName : m_VarNameMap[topicName].keys()) {
if (m_VarNameMap[topicName][varName] == 0) {
// 如果变量名对应的监控状态为0则获取数据
QString value = m_TopicMonitorMap[topicName]->getData(topicName, varName);
emit updateMonitoringData(varName, value);
} else if (m_VarNameMap[topicName][varName] == 2) {
// 如果变量名对应的监控状态为2则注入一次数据
m_TopicMonitorMap[topicName]->injectData(
varName, m_InjectValueMap[topicName][varName]);
emit updateMonitoringData(
varName, QString::number(m_InjectValueMap[topicName][varName]));
m_VarNameMap[topicName][varName] = 0;
m_InjectValueMap[topicName].remove(varName);
} else if (m_VarNameMap[topicName][varName] == 3) {
// 如果变量名对应的监控状态为3则注入连续数据
m_TopicMonitorMap[topicName]->injectData(
varName, m_InjectValueMap[topicName][varName]);
emit updateMonitoringData(
varName, QString::number(m_InjectValueMap[topicName][varName]));
}
}
}
}
QThread::msleep(m_SleepTime);
}
}
void DataMonitorThread::onSaveModelDefinition(
const QSharedPointer<ModelDefinition> &modelDefinition)
{
QMutexLocker locker(&m_Mutex);
// 首先检查输入参数是否为空
if (!modelDefinition) {
emit sendDebugMessage(1, "保存模型接口定义失败ModelDefinition指针为空");
return;
}
// 设置最大递归深度
const int MAX_RECURSION_DEPTH = 5;
// 查找所有主题定义的结构体lambda表达式
std::function<void(const QString &, const QVector<QSharedPointer<NamespaceDefinition>> &, int)>
findAllStruct = [this, &findAllStruct, MAX_RECURSION_DEPTH](
const QString &topic,
const QVector<QSharedPointer<NamespaceDefinition>> &nsVector,
int depth) {
// 检查递归深度
if (depth > MAX_RECURSION_DEPTH) {
return;
}
for (auto &ns : nsVector) {
// 检查是否为空指针
if (!ns) {
continue;
}
// 计算新的主题名
QString newTopic =
topic.size() > 0 ? topic + "::" + ns->namespaceName : ns->namespaceName;
// 递归查找所有结构体
findAllStruct(newTopic, ns->childNamespaces, depth + 1);
for (auto &structDef : ns->structDefinitions) {
// 检查是否为空指针
if (!structDef) {
continue;
}
// 保存主题名和结构体定义
m_StructDefinitionList[newTopic + "::" + structDef->structName] = structDef;
// 发送调试信息
emit sendDebugMessage(0,
"保存主题名" + newTopic + "::" + structDef->structName);
}
}
};
// 调用lambda表达式,查找所有主题定义的结构体
findAllStruct("", modelDefinition->namespaceDefinitions, 0);
}
void DataMonitorThread::onStartMonitoring(const QString &modelName, const QString &topicName,
const QString &varName)
{
QMutexLocker locker(&m_Mutex);
// 检查主题名是否在结构体列表中
if (m_StructDefinitionList.contains(topicName)) {
// 如果主题名在结构体列表中,则开始监控
if (StartTopicMonitor(modelName, topicName)) {
// 保存监控状态
m_VarNameMap[topicName][varName] = 0;
// 发送调试信息
emit sendDebugMessage(0, "开始监控主题名" + topicName);
}
} else {
// 如果主题名不在结构体列表中,则发送调试信息
emit sendDebugMessage(2, "未找到需要监控的主题名" + topicName);
}
}
bool DataMonitorThread::StartTopicMonitor(const QString &modelName, const QString &topicName)
{
// 创建主题监控器
m_TopicMonitorMap[topicName] = TopicMonitorFactory::getInstance().createMonitor(modelName);
// 检查主题监控器是否创建成功
if (m_TopicMonitorMap[topicName]) {
// 开始监控
bool bRet = m_TopicMonitorMap[topicName]->startMonitoring(topicName);
// 返回监控结果
return bRet;
}
// 如果主题监控器创建失败则返回false
return false;
}
void DataMonitorThread::onStopMonitoring(const QString &modelName, const QString &topicName,
const QString &varName)
{
QMutexLocker locker(&m_Mutex);
if (m_StructDefinitionList.contains(topicName)) {
// 如果变量名在监控状态中,则删除变量名对应的监控状态
if (m_VarNameMap[topicName].contains(varName))
m_VarNameMap[topicName].remove(varName);
// 如果主题名对应的监控状态表为空,则停止监控主题
if (m_VarNameMap[topicName].size() == 0) {
// 如果主题监控器不存在,则获取主题监控器
if (!m_TopicMonitorMap[topicName]) {
m_TopicMonitorMap[topicName] =
TopicMonitorFactory::getInstance().createMonitor(modelName);
}
// 停止监控主题
m_TopicMonitorMap[topicName]->stopMonitoring(topicName);
// 删除主题监控器
m_TopicMonitorMap.remove(topicName);
// 发送调试信息
emit sendDebugMessage(0, "停止监控主题名" + topicName);
}
} else {
// 如果主题名不在结构体列表中,则发送调试信息
emit sendDebugMessage(2, "未找到需要停止监控的主题名" + topicName);
}
}
void DataMonitorThread::onPauseMonitoring(const QString &modelName, const QString &topicName,
const QString &varName)
{
QMutexLocker locker(&m_Mutex);
if (m_VarNameMap.contains(topicName)) {
// 如果变量名在监控状态中,则暂停监控
if (m_VarNameMap[topicName].contains(varName)) {
m_VarNameMap[topicName][varName] = 1;
// 发送调试信息
emit sendDebugMessage(0, "暂停监控主题名" + topicName + "的变量" + varName);
} else {
// 如果变量名不在监控状态中,则发送调试信息
emit sendDebugMessage(2, "未找到需要暂停监控的主题名" + topicName + "的变量" + varName);
}
} else {
// 如果主题名不在监控状态中,则发送调试信息
emit sendDebugMessage(2, "未找到需要暂停监控的主题名" + topicName);
}
}
void DataMonitorThread::onResumeMonitoring(const QString &modelName, const QString &topicName,
const QString &varName)
{
QMutexLocker locker(&m_Mutex);
if (m_VarNameMap.contains(topicName)) {
// 如果变量名在监控状态中,则恢复监控
if (m_VarNameMap[topicName].contains(varName)) {
m_VarNameMap[topicName][varName] = 0;
// 发送调试信息
emit sendDebugMessage(0, "恢复监控主题名" + topicName + "的变量" + varName);
} else {
// 如果变量名不在监控状态中,则发送调试信息
emit sendDebugMessage(2, "未找到需要恢复监控的主题名" + topicName + "的变量" + varName);
}
} else {
// 如果主题名不在监控状态中,则发送调试信息
emit sendDebugMessage(2, "未找到需要恢复监控的主题名" + topicName);
}
}
void DataMonitorThread::onInjectOnceData(const QString &modelName, const QString &topicName,
const QString &varName, const double &value)
{
QMutexLocker locker(&m_Mutex);
// 检查主题名是否在结构体列表中
if (m_StructDefinitionList.contains(topicName)) {
// 保存监控状态
m_VarNameMap[topicName][varName] = 2;
// 保存注入值
m_InjectValueMap[topicName][varName] = value;
// 发送调试信息
emit sendDebugMessage(0, "注入一次数据主题名" + topicName + "的变量" + varName);
} else {
// 如果主题名不在结构体列表中,则发送调试信息
emit sendDebugMessage(2, "未找到需要注入一次数据的主题名" + topicName);
}
}
void DataMonitorThread::onInjectContinuousData(const QString &modelName, const QString &topicName,
const QString &varName, const double &value)
{
QMutexLocker locker(&m_Mutex);
if (m_StructDefinitionList.contains(topicName)) {
// 保存监控状态
m_VarNameMap[topicName][varName] = 3;
// 保存注入值
m_InjectValueMap[topicName][varName] = value;
// 发送调试信息
emit sendDebugMessage(0, "注入连续数据主题名" + topicName + "的变量" + varName);
} else {
// 如果主题名不在结构体列表中,则发送调试信息
emit sendDebugMessage(2, "未找到需要注入连续数据的主题名" + topicName);
}
}
void DataMonitorThread::onStopInjectContinuousData(const QString &modelName,
const QString &topicName, const QString &varName)
{
QMutexLocker locker(&m_Mutex);
if (m_VarNameMap.contains(topicName)) {
// 如果变量名在监控状态中,则停止注入连续数据
if (m_VarNameMap[topicName].contains(varName)) {
m_VarNameMap[topicName][varName] = 0;
// 删除注入值
m_InjectValueMap[topicName].remove(varName);
// 发送调试信息
emit sendDebugMessage(0, "停止注入连续数据主题名" + topicName + "的变量" + varName);
} else {
// 如果变量名不在监控状态中,则发送调试信息
emit sendDebugMessage(2, "未找到需要停止注入连续数据的主题名" + topicName + "的变量"
+ varName);
}
} else {
// 如果主题名不在监控状态中,则发送调试信息
emit sendDebugMessage(2, "未找到需要停止注入连续数据的主题名" + topicName);
}
}
void DataMonitorThread::onChangeSleepTime(const unsigned int newSleepTime)
{
m_SleepTime = newSleepTime;
}
void DataMonitorThread::onThreadController(const bool &isActive)
{
m_Active = isActive;
}