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