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

source code of qtopcua/src/plugins/opcua/open62541/qopen62541backend.h