Files
EJM_Display/DataCenter/DataCenter.h

152 lines
4.5 KiB
C
Raw Permalink Normal View History

2025-08-20 23:06:28 +08:00
#ifndef DATACENTER_H
#define DATACENTER_H
#include <QObject>
#include <QVariant>
#include <QTimer>
#include <QMap>
#include <QStringList>
#include "OpcUaManager.h"
2025-09-15 22:28:43 +08:00
#include <QThread>
#include <QMutex>
2025-08-20 23:06:28 +08:00
#include <GlobalDefinitions/Variable.h>
2025-09-15 22:28:43 +08:00
// 工作线程类用于处理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;
};
2025-08-20 23:06:28 +08:00
class DataCenter : public QObject
{
Q_OBJECT
public:
2025-09-15 22:28:43 +08:00
static DataCenter* instance(QObject* parent = nullptr); // 全局唯一获取方式
// 禁止拷贝和赋值
DataCenter(const DataCenter&) = delete;
DataCenter& operator=(const DataCenter&) = delete;
2025-08-20 23:06:28 +08:00
// 添加需要监控的节点
2025-09-15 22:28:43 +08:00
void addMonitoredNode(const QString &nodeId, const QString &nodeName,
const QString &varName, const QString &tableName,
const QString &fieldName);
2025-08-20 23:06:28 +08:00
// 开始/停止循环读取
void startCyclicRead(int intervalMs);
void stopCyclicRead();
// 获取最新的节点值
QVariant getNodeValue(const QString &nodeId) const;
QVariant getNodeValueByName(const QString &nodeName) const;
// 获取所有节点信息
2025-09-15 22:28:43 +08:00
QMap<QString, QString> getAllNodeNames() const { return gOPC_NodeName ; }
// 初始化数据
void initData();
// 浏览节点
void browseRecursive(const QString &nodeId);
// 设置批量读取大小
void setBatchSize(int size) { m_batchSize = qMax(1, size); }
2025-08-20 23:06:28 +08:00
signals:
2025-09-15 22:28:43 +08:00
2025-08-20 23:06:28 +08:00
private slots:
// 定时器触发,执行循环读取
void onTimerTimeout();
2025-09-15 22:28:43 +08:00
// 刷新所有节点
void refreshAllNodes();
2025-08-20 23:06:28 +08:00
2025-09-15 22:28:43 +08:00
private:
explicit DataCenter(OpcUaManager *opcManager, QObject *parent = nullptr); // 私有构造函数
~DataCenter() override; // 析构函数声明
static DataCenter* m_instance; // 静态单例实例
static QMutex m_mutex; // 单例锁仅用于instance()方法)
2025-08-20 23:06:28 +08:00
2025-09-15 22:28:43 +08:00
// 浏览节点实现
void doBrowse(const QString &nodeId, int depth, QString prefix);
2025-08-20 23:06:28 +08:00
2025-09-15 22:28:43 +08:00
OpcUaManager *m_opcManager; // OPC操作实例
QThread* m_opcThread; // OPC工作线程
OpcWorker* m_worker; // OPC工作对象
2025-08-20 23:06:28 +08:00
2025-09-15 22:28:43 +08:00
int m_currentReadIndex = 0; // 当前读取索引
int m_batchSize = 1000; // 批量读取大小
2025-08-20 23:06:28 +08:00
2025-09-15 22:28:43 +08:00
// 节点信息存储
QStringList m_initNodeIds; // 初始化节点ID列表
2025-08-20 23:06:28 +08:00
};
#endif // DATACENTER_H