// Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QOPEN62541BACKEND_H #define QOPEN62541BACKEND_H #include "qopen62541client.h" #include "qopen62541subscription.h" #include #include #include #include QT_BEGIN_NAMESPACE class Open62541AsyncBackend : public QOpcUaBackend { Q_OBJECT public: Open62541AsyncBackend(QOpen62541Client *parent); ~Open62541AsyncBackend(); public Q_SLOTS: void connectToEndpoint(const QOpcUaEndpointDescription &endpoint); void disconnectFromEndpoint(); void requestEndpoints(const QUrl &url); // Node functions void browse(quint64 handle, UA_NodeId id, const QOpcUaBrowseRequest &request); void readAttributes(quint64 handle, UA_NodeId id, QOpcUa::NodeAttributes attr, QString indexRange); void writeAttribute(quint64 handle, UA_NodeId id, QOpcUa::NodeAttribute attrId, QVariant value, QOpcUa::Types type, QString indexRange); void writeAttributes(quint64 handle, UA_NodeId id, QOpcUaNode::AttributeMap toWrite, QOpcUa::Types valueAttributeType); void enableMonitoring(quint64 handle, UA_NodeId id, QOpcUa::NodeAttributes attr, const QOpcUaMonitoringParameters &settings); void disableMonitoring(quint64 handle, QOpcUa::NodeAttributes attr); void modifyMonitoring(quint64 handle, QOpcUa::NodeAttribute attr, QOpcUaMonitoringParameters::Parameter item, QVariant value); void callMethod(quint64 handle, UA_NodeId objectId, UA_NodeId methodId, QList args); void resolveBrowsePath(quint64 handle, UA_NodeId startNode, const QList &path); void findServers(const QUrl &url, const QStringList &localeIds, const QStringList &serverUris); void readNodeAttributes(const QList &nodesToRead); void writeNodeAttributes(const QList &nodesToWrite); void readHistoryRaw(QOpcUaHistoryReadRawRequest request, QList continuationPoints, bool releaseContinuationPoints, quint64 handle); void readHistoryEvents(const QOpcUaHistoryReadEventRequest &request, const QList &continuationPoints, bool releaseContinuationPoints, quint64 handle); // Node management void addNode(const QOpcUaAddNodeItem &nodeToAdd); void deleteNode(const QString &nodeId, bool deleteTargetReferences); void addReference(const QOpcUaAddReferenceItem &referenceToAdd); void deleteReference(const QOpcUaDeleteReferenceItem &referenceToDelete); // Subscription QOpen62541Subscription *getSubscription(const QOpcUaMonitoringParameters &settings); bool removeSubscription(UA_UInt32 subscriptionId); void iterateClient(); void handleSubscriptionTimeout(QOpen62541Subscription *sub, QList> items); void cleanupSubscriptions(); // Register and unregister nodes void registerNodes(const QStringList &nodesToRegister); void unregisterNodes(const QStringList &nodesToUnregister); // Callbacks static void asyncMethodCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncTranslateBrowsePathCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncAddNodeCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncDeleteNodeCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncAddReferenceCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncDeleteReferenceCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncReadCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncWriteAttributesCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncBrowseCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncBatchReadCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncBatchWriteCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncReadHistoryDataCallBack(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncRegisterNodesCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncUnregisterNodesCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); static void asyncReadHistoryEventsCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); public: UA_Client *m_uaclient; QOpen62541Client *m_clientImpl; bool m_useStateCallback; quint32 m_clientIterateInterval; quint32 m_asyncRequestTimeout; private: static void clientStateCallback(UA_Client *client, UA_SecureChannelState channelState, UA_SessionState sessionState, UA_StatusCode connectStatus); static void inactivityCallback(UA_Client *client); static void open62541LogHandler(void *logContext, UA_LogLevel level, UA_LogCategory category, const char *msg, va_list args); QOpen62541Subscription *getSubscriptionForItem(quint64 handle, QOpcUa::NodeAttribute attr); QOpcUaApplicationDescription convertApplicationDescription(UA_ApplicationDescription &desc); UA_ExtensionObject assembleNodeAttributes(const QOpcUaNodeCreationAttributes &nodeAttributes, QOpcUa::NodeClass nodeClass); UA_UInt32 *copyArrayDimensions(const QList &arrayDimensions, size_t *outputSize); // Helper bool loadFileToByteString(const QString &location, UA_ByteString *target) const; bool loadAllFilesInDirectory(const QString &location, UA_ByteString **target, qsizetype *size) const; void disconnectInternal(QOpcUaClient::ClientError error = QOpcUaClient::ClientError::NoError); QTimer m_clientIterateTimer; QTimer m_disconnectAfterStateChangeTimer; QHash m_subscriptions; QHash> m_attributeMapping; // Handle -> Attribute -> Subscription double m_minPublishingInterval; const UA_Logger m_open62541Logger {open62541LogHandler, nullptr, nullptr}; // Async contexts struct AsyncCallContext { quint64 handle; QString methodNodeId; }; QMap m_asyncCallContext; struct AsyncTranslateContext { quint64 handle; QList path; }; QMap m_asyncTranslateContext; struct AsyncAddNodeContext { QOpcUaExpandedNodeId requestedNodeId; }; QMap m_asyncAddNodeContext; struct AsyncDeleteNodeContext { QString nodeId; }; QMap m_asyncDeleteNodeContext; struct AsyncAddReferenceContext { QString sourceNodeId; QString referenceTypeId; QOpcUaExpandedNodeId targetNodeId; bool isForwardReference; }; QMap m_asyncAddReferenceContext; struct AsyncDeleteReferenceContext { QString sourceNodeId; QString referenceTypeId; QOpcUaExpandedNodeId targetNodeId; bool isForwardReference; }; QMap m_asyncDeleteReferenceContext; struct AsyncReadContext { quint64 handle; QList results; }; QMap m_asyncReadContext; struct AsyncWriteAttributesContext { quint64 handle; QOpcUaNode::AttributeMap toWrite; }; QMap m_asyncWriteAttributesContext; struct AsyncBrowseContext { quint64 handle; bool isBrowseNext; QList results; }; QMap m_asyncBrowseContext; struct AsyncBatchReadContext { QList nodesToRead; }; QMap m_asyncBatchReadContext; struct AsyncBatchWriteContext { QList nodesToWrite; }; QMap m_asyncBatchWriteContext; struct AsyncReadHistoryDataContext { quint64 handle; QOpcUaHistoryReadRawRequest historyReadRawRequest; }; QMap m_asyncReadHistoryDataContext; struct AsyncRegisterUnregisterNodesContext { QStringList nodeIds; }; QMap m_asyncRegisterUnregisterNodesContext; struct AsyncReadHistoryEventsContext { quint64 handle; QOpcUaHistoryReadEventRequest historyReadEventRequest; }; QMap m_asyncReadHistoryEventsContext; }; QT_END_NAMESPACE #endif // QOPEN62541BACKEND_H