Files
EJM_Display/DataCenter/DataCenter.h
2025-09-15 22:28:43 +08:00

152 lines
4.5 KiB
C++
Raw 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.

#ifndef DATACENTER_H
#define DATACENTER_H
#include <QObject>
#include <QVariant>
#include <QTimer>
#include <QMap>
#include <QStringList>
#include "OpcUaManager.h"
#include <QThread>
#include <QMutex>
#include <GlobalDefinitions/Variable.h>
// 工作线程类用于处理OPC通信
class OpcWorker : public QObject
{
Q_OBJECT
public:
explicit OpcWorker(OpcUaManager *opcManager, QObject *parent = nullptr)
: QObject(parent), m_opcManager(opcManager) {
// 定时器在构造函数中创建,确保属于工作线程
m_cyclicTimer.setParent(this);
// 连接定时器信号到自身槽函数
connect(&m_cyclicTimer, &QTimer::timeout,
this, &OpcWorker::onTimerTimeout, Qt::DirectConnection);
}
public slots:
// 启动定时器(确保在工作线程中执行)
void startCyclicTimer(int intervalMs) {
// 检查当前线程是否为工作线程
if (QThread::currentThread() != this->thread()) {
// 如果不是,通过元对象系统切换到工作线程执行
QMetaObject::invokeMethod(this, "startCyclicTimer",
Qt::QueuedConnection,
Q_ARG(int, intervalMs));
return;
}
m_cyclicTimer.setInterval(intervalMs);
if (!m_cyclicTimer.isActive()) {
m_cyclicTimer.start();
}
}
// 停止定时器(确保在工作线程中执行)
void stopCyclicTimer() {
// 检查当前线程是否为工作线程
if (QThread::currentThread() != this->thread()) {
// 如果不是,通过元对象系统切换到工作线程执行
QMetaObject::invokeMethod(this, "stopCyclicTimer",
Qt::QueuedConnection);
return;
}
if (m_cyclicTimer.isActive()) {
m_cyclicTimer.stop();
}
}
signals:
void timeout();
public slots:
void onTimerTimeout() {
emit timeout();
}
// 添加OPC回调处理函数
// void readCompleted(const QVariant &value, const QString &nodeId) {
// emit readCompleted(value, nodeId);
// }
// void batchReadCompleted(const QMap<QString, QVariant> &results) {
// emit batchReadCompleted(results);
// }
// void errorOccurred(const QString &error) {
// emit errorOccurred(error);
// }
public:
OpcUaManager *m_opcManager;
QTimer m_cyclicTimer;
};
class DataCenter : public QObject
{
Q_OBJECT
public:
static DataCenter* instance(QObject* parent = nullptr); // 全局唯一获取方式
// 禁止拷贝和赋值
DataCenter(const DataCenter&) = delete;
DataCenter& operator=(const DataCenter&) = delete;
// 添加需要监控的节点
void addMonitoredNode(const QString &nodeId, const QString &nodeName,
const QString &varName, const QString &tableName,
const QString &fieldName);
// 开始/停止循环读取
void startCyclicRead(int intervalMs);
void stopCyclicRead();
// 获取最新的节点值
QVariant getNodeValue(const QString &nodeId) const;
QVariant getNodeValueByName(const QString &nodeName) const;
// 获取所有节点信息
QMap<QString, QString> getAllNodeNames() const { return gOPC_NodeName ; }
// 初始化数据
void initData();
// 浏览节点
void browseRecursive(const QString &nodeId);
// 设置批量读取大小
void setBatchSize(int size) { m_batchSize = qMax(1, size); }
signals:
private slots:
// 定时器触发,执行循环读取
void onTimerTimeout();
// 刷新所有节点
void refreshAllNodes();
private:
explicit DataCenter(OpcUaManager *opcManager, QObject *parent = nullptr); // 私有构造函数
~DataCenter() override; // 析构函数声明
static DataCenter* m_instance; // 静态单例实例
static QMutex m_mutex; // 单例锁仅用于instance()方法)
// 浏览节点实现
void doBrowse(const QString &nodeId, int depth, QString prefix);
OpcUaManager *m_opcManager; // OPC操作实例
QThread* m_opcThread; // OPC工作线程
OpcWorker* m_worker; // OPC工作对象
int m_currentReadIndex = 0; // 当前读取索引
int m_batchSize = 1000; // 批量读取大小
// 节点信息存储
QStringList m_initNodeIds; // 初始化节点ID列表
};
#endif // DATACENTER_H