添加OpenCv

This commit is contained in:
2025-09-15 22:28:43 +08:00
parent c0593df9e1
commit 94282fb1d9
423 changed files with 622349 additions and 97439 deletions

View File

@@ -1,96 +1,201 @@
#include "DataCenter.h"
#include <QDebug>
#include <FileOperation/ConfigFiles.h>
#include <PublicFunctions/Basic.h>
#include <QCoreApplication>
DataCenter* DataCenter::m_instance = nullptr;
QMutex DataCenter::m_mutex; // 仅用于单例模式的线程安全
DataCenter::DataCenter(OpcUaManager *opcManager, QObject *parent)
: QObject(parent)
, m_opcManager(opcManager)
, m_cyclicTimer(new QTimer(this))
, m_batchSize(10)
, m_currentReadIndex(0)
{
Q_ASSERT(opcManager != nullptr); // 确保OPC管理器有效
// 连接定时器
connect(m_cyclicTimer, &QTimer::timeout, this, &DataCenter::onTimerTimeout);
Q_ASSERT(opcManager != nullptr);
// 连接OPC读取信号仅处理数据读取逻辑
connect(m_opcManager, &OpcUaManager::readCompleted,
this, &DataCenter::handleReadCompleted);
// 创建专用线程和工作对象
m_opcThread = new QThread(this);
m_worker = new OpcWorker(opcManager); // 不设置父对象
// 转发错误信号
connect(m_opcManager, &OpcUaManager::errorOccurred,
this, &DataCenter::errorOccurred);
// 将工作对象移动到线程
m_worker->moveToThread(m_opcThread);
connect(m_opcManager, &OpcUaManager::reconnected,
this, &DataCenter::refreshAllNodes);
// 连接定时器信号到工作对象的槽函数
connect(&m_worker->m_cyclicTimer, &QTimer::timeout,
m_worker, &OpcWorker::onTimerTimeout, Qt::DirectConnection);
// 连接工作对象信号到DataCenter
connect(m_worker, &OpcWorker::timeout, this, &DataCenter::onTimerTimeout, Qt::QueuedConnection);
// 连接OPC管理器信号到工作对象
connect(m_opcManager, &OpcUaManager::reconnected, this, &DataCenter::refreshAllNodes, Qt::QueuedConnection);
// 启动线程
m_opcThread->start();
}
//
void DataCenter::InitData(){
QList<QStringList> FileData = ConfigFiles().ReadFile_Csv("./ProgramConfig/OpcUA_Node_Config.csv");
for (int row = 1; row < FileData.size()-1; ++row)
{
addMonitoredNode(FileData.at(row)[3], FileData.at(row)[0],FileData.at(row)[2],FileData.at(row)[1],FileData.at(row)[2]);
}
DataCenter::~DataCenter()
{
if (m_opcThread && m_opcThread->isRunning()) {
m_opcThread->quit();
if (!m_opcThread->wait(500)) { // 等待500ms
m_opcThread->terminate();
m_opcThread->wait();
}
}
delete m_worker; // 释放工作对象
m_worker = nullptr;
}
// 添加监控节点仅数据层操作不涉及UI
void DataCenter::addMonitoredNode(const QString &nodeId, const QString &nodeName,const QString &varName,const QString &TableName,const QString &FieldName)
DataCenter* DataCenter::instance(QObject *parent)
{
if (!m_instance) {
QMutexLocker locker(&m_mutex); // 单例创建时的线程安全锁
if (!m_instance) {
OpcUaManager* opc = OpcUaManager::instance(parent);
m_instance = new DataCenter(opc, parent);
}
}
return m_instance;
}
void DataCenter::initData()
{
// 清空全局变量
gOPC_NodeList.clear();
gOPC_NodeName.clear();
gOPC_NodeValue.clear();
gOPC_VarName.clear();
gOPC_SqlTable.clear();
gOPC_SqlField.clear();
m_initNodeIds.clear();
// 读取初始化节点配置
QList<QStringList> fileDataInit = ConfigFiles().ReadFile_Csv("./ProgramConfig/OpcUA_初始化读取节点_配置.csv");
for (int row = 1; row < fileDataInit.size()-1; row++) {
if (fileDataInit.at(row).size() >= 4) {
addMonitoredNode(fileDataInit.at(row)[3], fileDataInit.at(row)[0],
fileDataInit.at(row)[2], fileDataInit.at(row)[1],
fileDataInit.at(row)[2]);
m_initNodeIds.append(fileDataInit.at(row)[3]);
}
}
// 读取循环节点配置
QList<QStringList> fileData = ConfigFiles().ReadFile_Csv("./ProgramConfig/OpcUA_循环读取节点_配置.csv");
for (int row = 1; row < fileData.size()-1; row++) {
if (fileData.at(row).size() >= 4) {
addMonitoredNode(fileData.at(row)[3], fileData.at(row)[0],
fileData.at(row)[2], fileData.at(row)[1],
fileData.at(row)[2]);
}
}
qDebug() << "数据初始化完成,节点总数:" << gOPC_NodeList.size();
}
void DataCenter::addMonitoredNode(const QString &nodeId, const QString &nodeName,
const QString &varName, const QString &tableName,
const QString &fieldName)
{
if (gOPC_NodeName.contains(nodeId)) {
qWarning() << "节点已存在:" << nodeId;
return;
}
QString NName = nodeName.isEmpty() ? nodeId : nodeName;
QString VName = varName.isEmpty() ? nodeId : varName;
gOPC_NodeName[nodeId] = NName;
gOPC_VarName[nodeId] = VName;
gOPC_SqlTable[nodeId] = TableName;
gOPC_SqlField[nodeId] = FieldName;
// 使用全局变量存储
gOPC_NodeName[nodeId] = nodeName.isEmpty() ? nodeId : nodeName;
gOPC_VarName[nodeId] = varName.isEmpty() ? nodeId : varName;
gOPC_SqlTable[nodeId] = tableName;
gOPC_SqlField[nodeId] = fieldName;
gOPC_NodeList.append(nodeId);
gOPC_NodeValue[nodeId] = QVariant(); // 初始化值
gOPC_NodeValue[nodeId] = QVariant();
}
// 开始循环读取(纯数据操作)
void DataCenter::startCyclicRead(int intervalMs)
void DataCenter::browseRecursive(const QString &nodeId)
{
if (gOPC_NodeList.isEmpty()) {
emit errorOccurred("没有需要监控的节点,请先添加节点");
doBrowse(nodeId, 6, "");
}
void DataCenter::doBrowse(const QString &nodeId, int depth, QString prefix)
{
if (!m_opcManager->getClient() || m_opcManager->getClient()->state() != QOpcUaClient::Connected) {
qDebug() << "客户端未连接";
return;
}
int actualInterval = qMax(intervalMs, 3); // 最小间隔100ms
m_cyclicTimer->stop(); // <-- 关键:先停
m_cyclicTimer->start(actualInterval); // <-- 再启
// 命中目标节点就添加并返回
if (nodeId.startsWith("ns=6;s=::", Qt::CaseInsensitive) && !nodeId.contains("#")) {
addMonitoredNode(nodeId, "", "", "", "");
return;
}
QOpcUaNode *node = m_opcManager->getCachedNode(nodeId);
if (!node) {
return;
}
// 浏览子节点使用QueuedConnection确保跨线程安全
connect(node, &QOpcUaNode::browseFinished,
this, [this, depth, prefix](QVector<QOpcUaReferenceDescription> refs, QOpcUa::UaStatusCode status){
if (status != QOpcUa::UaStatusCode::Good) {
qDebug() << "浏览失败,状态码:" << status;
return;
}
if (refs.isEmpty()) {
return;
}
for (const auto &ref : refs) {
QString childId = ref.targetNodeId().nodeId();
doBrowse(childId, depth + 1, "└─ ");
}
}, Qt::QueuedConnection);
node->browseChildren(QOpcUa::ReferenceTypeId::HierarchicalReferences,
QOpcUa::NodeClass::Undefined);
}
void DataCenter::startCyclicRead(int intervalMs)
{
if (gOPC_NodeList.isEmpty()) {
qWarning()<<"没有需要监控的节点,请先添加节点";
return;
}
int actualInterval = qMax(intervalMs, 20); // 最小间隔10ms
QMetaObject::invokeMethod(m_worker, "startCyclicTimer",
Qt::QueuedConnection,
Q_ARG(int, actualInterval));
m_currentReadIndex = 0;
}
// 停止循环读取
void DataCenter::stopCyclicRead()
{
m_cyclicTimer->stop();
QMetaObject::invokeMethod(m_worker, "stopCyclicTimer", Qt::QueuedConnection);
}
void DataCenter::refreshAllNodes()
{
if (gOPC_NodeList.isEmpty())
return;
// 重置索引
m_currentReadIndex = 0;
// 如果定时器没开,重新启动
if (!m_cyclicTimer->isActive()) {
m_cyclicTimer->start(); // 使用之前设置的间隔
}
// 检查定时器状态并启动
QMetaObject::invokeMethod(m_worker, [this]() {
if (!m_worker->m_cyclicTimer.isActive()) {
m_worker->startCyclicTimer(10); // 使用默认间隔
}
}, Qt::QueuedConnection);
// 立即触发一次读取(可选)
onTimerTimeout();
}
// 通过节点ID获取值
QVariant DataCenter::getNodeValue(const QString &nodeId) const
{
return gOPC_NodeValue.value(nodeId, QVariant());
}
// 通过节点名称获取值
QVariant DataCenter::getNodeValueByName(const QString &nodeName) const
{
for (auto it = gOPC_NodeName.constBegin(); it != gOPC_NodeName.constEnd(); ++it) {
@@ -101,39 +206,26 @@ QVariant DataCenter::getNodeValueByName(const QString &nodeName) const
return QVariant();
}
// 定时器触发,循环读取下一个节点(纯数据逻辑)
void DataCenter::onTimerTimeout()
{
if (gOPC_NodeList.isEmpty()) return;
// 准备批量读取的节点
QList<QString> batchNodes;
int remaining = gOPC_NodeList.size() - m_currentReadIndex;
int takeCount = qMin(m_batchSize, remaining);
for (int i = 0; i < takeCount; ++i) {
batchNodes.append(gOPC_NodeList[m_currentReadIndex + i]);
}
m_currentReadIndex += takeCount;
// 循环索引处理
if (m_currentReadIndex >= gOPC_NodeList.size()) {
m_currentReadIndex = 0;
}
// 读取当前节点(仅数据操作)
QString nodeId = gOPC_NodeList[m_currentReadIndex];
if (!m_opcManager->readNodeValue(nodeId)) {
emit errorOccurred("读取节点失败: " + nodeId);
m_currentReadIndex++; // 无论成功与否都移动到下一个
if (!batchNodes.isEmpty()) {
QMetaObject::invokeMethod(m_opcManager, "readNodesValue",
Qt::QueuedConnection,
Q_ARG(QList<QString>, batchNodes));
}
}
// 处理读取结果并缓存(仅数据处理)
void DataCenter::handleReadCompleted(const QVariant &value, const QString &nodeId)
{
if (!gOPC_NodeName.contains(nodeId)) return;
// 更新缓存值
gOPC_NodeValue[nodeId] = value;
// 发送更新信号仅传递数据不涉及UI
emit nodeValueUpdated(nodeId, gOPC_NodeName[nodeId],gOPC_VarName[nodeId], value);
// 移动到下一个节点
m_currentReadIndex++;
// if(DC_SetST.funts_SetSysInitOjb(gSysInfo,gOPC_VarName[nodeId],value)) return;
// else if (DC_SetST.funts_SetSysInitOjb(gSysInfo,gOPC_VarName[nodeId],value)) return;
}