/** * @file OpcUaMonitoredNode.h * @brief QML component for monitoring a single OPC UA node. * * Inherits QObject + QQmlParserStatus so that initialisation is * deferred until all QML bindings are applied (componentComplete). */ #ifndef OPCUAMONITOREDNODE_H #define OPCUAMONITOREDNODE_H #include #include #include #include #include #include /** * @brief Metadata bundle for a monitored OPC UA node. * * Exposed as a single Q_PROPERTY on OpcUaMonitoredNode so that * the QML API stays simple (only `value` is top-level). * Advanced users can access fields via dot notation: * node.info.displayName, node.info.status, etc. */ struct OpcUaNodeInfo { Q_GADGET Q_PROPERTY (QString displayName MEMBER displayName) Q_PROPERTY (QString description MEMBER description) Q_PROPERTY (QString nodeClass MEMBER nodeClass) Q_PROPERTY (QString dataType MEMBER dataType) Q_PROPERTY (QString accessLevel MEMBER accessLevel) Q_PROPERTY (QString status MEMBER status) Q_PROPERTY (QDateTime sourceTimestamp MEMBER sourceTimestamp) Q_PROPERTY (QDateTime serverTimestamp MEMBER serverTimestamp) public: QString displayName; QString description; QString nodeClass; QString dataType; QString accessLevel; QString status; QDateTime sourceTimestamp; QDateTime serverTimestamp; }; Q_DECLARE_METATYPE (OpcUaNodeInfo) class OpcUaMonitoredNode : public QObject, public QQmlParserStatus { Q_OBJECT Q_INTERFACES (QQmlParserStatus) QML_ELEMENT Q_PROPERTY (QString nodeId READ nodeId WRITE setNodeId NOTIFY nodeIdChanged) Q_PROPERTY ( bool monitored READ monitored WRITE setMonitored NOTIFY monitoredChanged) Q_PROPERTY (double publishingInterval READ publishingInterval WRITE setPublishingInterval NOTIFY publishingIntervalChanged) Q_PROPERTY (QVariant value READ value NOTIFY valueChanged) Q_PROPERTY (bool writable READ writable NOTIFY writableChanged) Q_PROPERTY (OpcUaNodeInfo info READ info NOTIFY infoChanged) public: explicit OpcUaMonitoredNode (QObject *parent = nullptr); QString nodeId () const; void setNodeId (const QString &id); bool monitored () const; void setMonitored (bool monitored); double publishingInterval () const; void setPublishingInterval (double interval); QVariant value () const; bool writable () const; OpcUaNodeInfo info () const; /** * @brief Write a value to the OPC UA node. * * Coerces @a value to the node's data type (auto-detected from the * server's DataType attribute). For array nodes, a comma-separated * string is split and each element coerced individually. * Result is reported asynchronously via writeCompleted(). */ Q_INVOKABLE void writeValue (const QVariant &value); void classBegin () override; void componentComplete () override; signals: void nodeIdChanged (); void monitoredChanged (); void publishingIntervalChanged (); void valueChanged (); void writableChanged (); void infoChanged (); void writeCompleted (bool success, const QString &message); private slots: void handleAttributeUpdated (QOpcUa::NodeAttribute attr, const QVariant &value); void handleValueUpdated (const QVariant &value); void handleClientConnectedChanged (); void handleAttributeWritten (QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode statusCode); void handleEnableMonitoringFinished (QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode statusCode); void handleDisableMonitoringFinished (QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode statusCode); private: void setupNode (); void teardownNode (); void startMonitoring (); void stopMonitoring (); QVariant coerceValue (const QVariant &input) const; QString m_nodeId; bool m_monitored = true; double m_publishingInterval = 250.0; bool m_componentComplete = false; QOpcUaNode *m_node = nullptr; QOpcUa::Types m_valueType = QOpcUa::Types::Undefined; bool m_writable = false; QVariant m_value; OpcUaNodeInfo m_info; }; #endif // OPCUAMONITOREDNODE_H