| 1 | // Copyright (C) 2017 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
| 3 |  | 
| 4 | #ifndef QOPEN62541BACKEND_H | 
| 5 | #define QOPEN62541BACKEND_H | 
| 6 |  | 
| 7 | #include "qopen62541client.h" | 
| 8 | #include "qopen62541subscription.h" | 
| 9 | #include <private/qopcuabackend_p.h> | 
| 10 |  | 
| 11 | #include <QtCore/qset.h> | 
| 12 | #include <QtCore/qstring.h> | 
| 13 | #include <QtCore/qtimer.h> | 
| 14 |  | 
| 15 | QT_BEGIN_NAMESPACE | 
| 16 |  | 
| 17 | class Open62541AsyncBackend : public QOpcUaBackend | 
| 18 | { | 
| 19 |     Q_OBJECT | 
| 20 | public: | 
| 21 |     Open62541AsyncBackend(QOpen62541Client *parent); | 
| 22 |     ~Open62541AsyncBackend(); | 
| 23 |  | 
| 24 | public Q_SLOTS: | 
| 25 |     void connectToEndpoint(const QOpcUaEndpointDescription &endpoint); | 
| 26 |     void disconnectFromEndpoint(); | 
| 27 |     void requestEndpoints(const QUrl &url); | 
| 28 |  | 
| 29 |     // Node functions | 
| 30 |     void browse(quint64 handle, UA_NodeId id, const QOpcUaBrowseRequest &request); | 
| 31 |     void readAttributes(quint64 handle, UA_NodeId id, QOpcUa::NodeAttributes attr, QString indexRange); | 
| 32 |  | 
| 33 |     void writeAttribute(quint64 handle, UA_NodeId id, QOpcUa::NodeAttribute attrId, QVariant value, QOpcUa::Types type, QString indexRange); | 
| 34 |     void writeAttributes(quint64 handle, UA_NodeId id, QOpcUaNode::AttributeMap toWrite, QOpcUa::Types valueAttributeType); | 
| 35 |     void enableMonitoring(quint64 handle, UA_NodeId id, QOpcUa::NodeAttributes attr, const QOpcUaMonitoringParameters &settings); | 
| 36 |     void disableMonitoring(quint64 handle, QOpcUa::NodeAttributes attr); | 
| 37 |     void modifyMonitoring(quint64 handle, QOpcUa::NodeAttribute attr, QOpcUaMonitoringParameters::Parameter item, QVariant value); | 
| 38 |     void callMethod(quint64 handle, UA_NodeId objectId, UA_NodeId methodId, QList<QOpcUa::TypedVariant> args); | 
| 39 |     void resolveBrowsePath(quint64 handle, UA_NodeId startNode, const QList<QOpcUaRelativePathElement> &path); | 
| 40 |     void findServers(const QUrl &url, const QStringList &localeIds, const QStringList &serverUris); | 
| 41 |  | 
| 42 |     void readNodeAttributes(const QList<QOpcUaReadItem> &nodesToRead); | 
| 43 |     void writeNodeAttributes(const QList<QOpcUaWriteItem> &nodesToWrite); | 
| 44 |  | 
| 45 |     void readHistoryRaw(QOpcUaHistoryReadRawRequest request, QList<QByteArray> continuationPoints, bool releaseContinuationPoints, quint64 handle); | 
| 46 |     void readHistoryEvents(const QOpcUaHistoryReadEventRequest &request, const QList<QByteArray> &continuationPoints, | 
| 47 |                            bool releaseContinuationPoints, quint64 handle); | 
| 48 |  | 
| 49 |     // Node management | 
| 50 |     void addNode(const QOpcUaAddNodeItem &nodeToAdd); | 
| 51 |     void deleteNode(const QString &nodeId, bool deleteTargetReferences); | 
| 52 |     void addReference(const QOpcUaAddReferenceItem &referenceToAdd); | 
| 53 |     void deleteReference(const QOpcUaDeleteReferenceItem &referenceToDelete); | 
| 54 |  | 
| 55 |     // Subscription | 
| 56 |     QOpen62541Subscription *getSubscription(const QOpcUaMonitoringParameters &settings); | 
| 57 |     bool removeSubscription(UA_UInt32 subscriptionId); | 
| 58 |     void iterateClient(); | 
| 59 |     void handleSubscriptionTimeout(QOpen62541Subscription *sub, QList<QPair<quint64, QOpcUa::NodeAttribute>> items); | 
| 60 |     void cleanupSubscriptions(); | 
| 61 |  | 
| 62 |     // Register and unregister nodes | 
| 63 |     void registerNodes(const QStringList &nodesToRegister); | 
| 64 |     void unregisterNodes(const QStringList &nodesToUnregister); | 
| 65 |  | 
| 66 |     // Callbacks | 
| 67 |     static void asyncMethodCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 68 |     static void asyncTranslateBrowsePathCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 69 |     static void asyncAddNodeCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 70 |     static void asyncDeleteNodeCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 71 |     static void asyncAddReferenceCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 72 |     static void asyncDeleteReferenceCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 73 |     static void asyncReadCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 74 |     static void asyncWriteAttributesCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 75 |     static void asyncBrowseCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 76 |     static void asyncBatchReadCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 77 |     static void asyncBatchWriteCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 78 |     static void asyncReadHistoryDataCallBack(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 79 |     static void asyncRegisterNodesCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 80 |     static void asyncUnregisterNodesCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 81 |     static void asyncReadHistoryEventsCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response); | 
| 82 |  | 
| 83 | public: | 
| 84 |     UA_Client *m_uaclient; | 
| 85 |     QOpen62541Client *m_clientImpl; | 
| 86 |     bool m_useStateCallback; | 
| 87 |     quint32 m_clientIterateInterval; | 
| 88 |     quint32 m_asyncRequestTimeout; | 
| 89 |  | 
| 90 | private: | 
| 91 |     static void clientStateCallback(UA_Client *client, | 
| 92 |                                     UA_SecureChannelState channelState, | 
| 93 |                                     UA_SessionState sessionState, | 
| 94 |                                     UA_StatusCode connectStatus); | 
| 95 |  | 
| 96 |     static void inactivityCallback(UA_Client *client); | 
| 97 |  | 
| 98 |     static void open62541LogHandler(void *logContext, UA_LogLevel level, UA_LogCategory category, | 
| 99 |                                     const char *msg, va_list args); | 
| 100 |  | 
| 101 |     QOpen62541Subscription *getSubscriptionForItem(quint64 handle, QOpcUa::NodeAttribute attr); | 
| 102 |     QOpcUaApplicationDescription convertApplicationDescription(UA_ApplicationDescription &desc); | 
| 103 |  | 
| 104 |     UA_ExtensionObject assembleNodeAttributes(const QOpcUaNodeCreationAttributes &nodeAttributes, QOpcUa::NodeClass nodeClass); | 
| 105 |     UA_UInt32 *copyArrayDimensions(const QList<quint32> &arrayDimensions, size_t *outputSize); | 
| 106 |  | 
| 107 |     // Helper | 
| 108 |     bool loadFileToByteString(const QString &location, UA_ByteString *target) const; | 
| 109 |     bool loadAllFilesInDirectory(const QString &location, UA_ByteString **target, qsizetype *size) const; | 
| 110 |  | 
| 111 |     void disconnectInternal(QOpcUaClient::ClientError error = QOpcUaClient::ClientError::NoError); | 
| 112 |  | 
| 113 |     QTimer m_clientIterateTimer; | 
| 114 |     QTimer m_disconnectAfterStateChangeTimer; | 
| 115 |  | 
| 116 |     QHash<quint32, QOpen62541Subscription *> m_subscriptions; | 
| 117 |  | 
| 118 |     QHash<quint64, QHash<QOpcUa::NodeAttribute, QOpen62541Subscription *>> m_attributeMapping; // Handle -> Attribute -> Subscription | 
| 119 |  | 
| 120 |     double m_minPublishingInterval; | 
| 121 |  | 
| 122 |     const UA_Logger m_open62541Logger {.log: open62541LogHandler, .context: nullptr, .clear: nullptr}; | 
| 123 |  | 
| 124 |     // Async contexts | 
| 125 |  | 
| 126 |     struct AsyncCallContext { | 
| 127 |         quint64 handle; | 
| 128 |         QString methodNodeId; | 
| 129 |     }; | 
| 130 |     QMap<quint32, AsyncCallContext> m_asyncCallContext; | 
| 131 |  | 
| 132 |     struct AsyncTranslateContext { | 
| 133 |         quint64 handle; | 
| 134 |         QList<QOpcUaRelativePathElement> path; | 
| 135 |     }; | 
| 136 |     QMap<quint32, AsyncTranslateContext> m_asyncTranslateContext; | 
| 137 |  | 
| 138 |     struct AsyncAddNodeContext { | 
| 139 |         QOpcUaExpandedNodeId requestedNodeId; | 
| 140 |     }; | 
| 141 |     QMap<quint32, AsyncAddNodeContext> m_asyncAddNodeContext; | 
| 142 |  | 
| 143 |     struct AsyncDeleteNodeContext { | 
| 144 |         QString nodeId; | 
| 145 |     }; | 
| 146 |     QMap<quint32, AsyncDeleteNodeContext> m_asyncDeleteNodeContext; | 
| 147 |  | 
| 148 |     struct AsyncAddReferenceContext { | 
| 149 |         QString sourceNodeId; | 
| 150 |         QString referenceTypeId; | 
| 151 |         QOpcUaExpandedNodeId targetNodeId; | 
| 152 |         bool isForwardReference; | 
| 153 |     }; | 
| 154 |     QMap<quint32, AsyncAddReferenceContext> m_asyncAddReferenceContext; | 
| 155 |  | 
| 156 |     struct AsyncDeleteReferenceContext { | 
| 157 |         QString sourceNodeId; | 
| 158 |         QString referenceTypeId; | 
| 159 |         QOpcUaExpandedNodeId targetNodeId; | 
| 160 |         bool isForwardReference; | 
| 161 |     }; | 
| 162 |     QMap<quint32, AsyncDeleteReferenceContext> m_asyncDeleteReferenceContext; | 
| 163 |  | 
| 164 |     struct AsyncReadContext { | 
| 165 |         quint64 handle; | 
| 166 |         QList<QOpcUaReadResult> results; | 
| 167 |     }; | 
| 168 |     QMap<quint32, AsyncReadContext> m_asyncReadContext; | 
| 169 |  | 
| 170 |     struct AsyncWriteAttributesContext { | 
| 171 |         quint64 handle; | 
| 172 |         QOpcUaNode::AttributeMap toWrite; | 
| 173 |     }; | 
| 174 |     QMap<quint32, AsyncWriteAttributesContext> m_asyncWriteAttributesContext; | 
| 175 |  | 
| 176 |     struct AsyncBrowseContext { | 
| 177 |         quint64 handle; | 
| 178 |         bool isBrowseNext; | 
| 179 |         QList<QOpcUaReferenceDescription> results; | 
| 180 |     }; | 
| 181 |     QMap<quint32, AsyncBrowseContext> m_asyncBrowseContext; | 
| 182 |  | 
| 183 |     struct AsyncBatchReadContext { | 
| 184 |         QList<QOpcUaReadItem> nodesToRead; | 
| 185 |     }; | 
| 186 |     QMap<quint32, AsyncBatchReadContext> m_asyncBatchReadContext; | 
| 187 |  | 
| 188 |     struct AsyncBatchWriteContext { | 
| 189 |         QList<QOpcUaWriteItem> nodesToWrite; | 
| 190 |     }; | 
| 191 |     QMap<quint32, AsyncBatchWriteContext> m_asyncBatchWriteContext; | 
| 192 |  | 
| 193 |     struct AsyncReadHistoryDataContext { | 
| 194 |         quint64 handle; | 
| 195 |         QOpcUaHistoryReadRawRequest historyReadRawRequest; | 
| 196 |     }; | 
| 197 |     QMap<quint32, AsyncReadHistoryDataContext> m_asyncReadHistoryDataContext; | 
| 198 |  | 
| 199 |     struct AsyncRegisterUnregisterNodesContext { | 
| 200 |         QStringList nodeIds; | 
| 201 |     }; | 
| 202 |     QMap<quint32, AsyncRegisterUnregisterNodesContext> m_asyncRegisterUnregisterNodesContext; | 
| 203 |  | 
| 204 |     struct AsyncReadHistoryEventsContext { | 
| 205 |         quint64 handle; | 
| 206 |         QOpcUaHistoryReadEventRequest historyReadEventRequest; | 
| 207 |     }; | 
| 208 |     QMap<quint32, AsyncReadHistoryEventsContext> m_asyncReadHistoryEventsContext; | 
| 209 | }; | 
| 210 |  | 
| 211 | QT_END_NAMESPACE | 
| 212 |  | 
| 213 | #endif // QOPEN62541BACKEND_H | 
| 214 |  |