1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
/**
* @file BobinkNode.h
* @brief QML component representing a single OPC UA node.
*
* Inherits QQuickItem so that monitoring is automatically tied to
* visibility: when the item (or any ancestor) becomes invisible
* (e.g. StackView navigates away, Loader unloads), the monitored
* item is removed from the subscription. When visible again,
* monitoring resumes.
*/
#ifndef BOBINKNODE_H
#define BOBINKNODE_H
#include <QDateTime>
#include <QHash>
#include <QOpcUaNode>
#include <QQuickItem>
class BobinkNode : public QQuickItem
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY (QString nodeId READ nodeId WRITE setNodeId NOTIFY nodeIdChanged)
Q_PROPERTY (QVariant value READ value WRITE setValue NOTIFY valueChanged)
Q_PROPERTY (NodeStatus status READ status NOTIFY statusChanged)
Q_PROPERTY (QDateTime sourceTimestamp READ sourceTimestamp NOTIFY
sourceTimestampChanged)
Q_PROPERTY (QDateTime serverTimestamp READ serverTimestamp NOTIFY
serverTimestampChanged)
public:
explicit BobinkNode (QQuickItem *parent = nullptr);
~BobinkNode () override;
/// Simplified OPC UA status severity.
enum NodeStatus
{
Good,
Uncertain,
Bad
};
Q_ENUM (NodeStatus)
QString nodeId () const;
void setNodeId (const QString &id);
QVariant value () const;
/** Setting value writes to the server; the property updates when
* the server confirms via the monitored data change. */
void setValue (const QVariant &value);
NodeStatus status () const;
QDateTime sourceTimestamp () const;
QDateTime serverTimestamp () const;
/** Read an attribute on demand (DisplayName, Description, DataType, …).
* Result arrives asynchronously via attributeRead(). */
Q_INVOKABLE void readAttribute (const QString &attributeName);
signals:
void nodeIdChanged ();
void valueChanged ();
void statusChanged ();
void sourceTimestampChanged ();
void serverTimestampChanged ();
/** Emitted when a readAttribute() call completes. */
void attributeRead (const QString &attributeName, const QVariant &value);
/** Emitted when a write to the server fails. */
void writeError (const QString &message);
protected:
void componentComplete () override;
void itemChange (ItemChange change, const ItemChangeData &data) override;
private:
void startMonitoring ();
void stopMonitoring ();
void handleDataChange (QOpcUa::NodeAttribute attr, const QVariant &val);
void handleAttributeUpdated (QOpcUa::NodeAttribute attr,
const QVariant &val);
void handleAttributeWritten (QOpcUa::NodeAttribute attr,
QOpcUa::UaStatusCode statusCode);
void handleClientConnectedChanged ();
void handleAttributeReadFinished (QOpcUa::NodeAttributes attrs);
void handleEnableMonitoringFinished (QOpcUa::NodeAttribute attr,
QOpcUa::UaStatusCode statusCode);
void handleDisableMonitoringFinished (QOpcUa::NodeAttribute attr,
QOpcUa::UaStatusCode statusCode);
static NodeStatus statusFromCode (QOpcUa::UaStatusCode code);
static QOpcUa::NodeAttribute attributeFromName (const QString &name);
static QLatin1StringView nameFromAttribute (QOpcUa::NodeAttribute attr);
QString m_nodeId;
QVariant m_value;
NodeStatus m_status = Bad;
QDateTime m_sourceTimestamp;
QDateTime m_serverTimestamp;
QOpcUaNode *m_opcuaNode = nullptr;
bool m_componentComplete = false;
/** Tracks in-flight readAttribute() requests (enum → original name). */
QHash<QOpcUa::NodeAttribute, QString> m_pendingReads;
};
#endif // BOBINKNODE_H
|