1// Copyright (C) 2015 basysKom GmbH, opensource@basyskom.com
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qopcuaplugin.h"
5#include "qopcuaprovider.h"
6#include <QtOpcUa/qopcuaclient.h>
7#include <QtOpcUa/qopcuanode.h>
8#include <QtOpcUa/qopcuatype.h>
9#include <QtOpcUa/qopcuaapplicationidentity.h>
10#include <QtOpcUa/qopcuapkiconfiguration.h>
11#include <private/qopcuanodeimpl_p.h>
12#include <QtOpcUa/qopcuaqualifiedname.h>
13#include <QtOpcUa/qopcuarange.h>
14#include <QtOpcUa/qopcuaeuinformation.h>
15#include <QtOpcUa/qopcuacomplexnumber.h>
16#include <QtOpcUa/qopcuadoublecomplexnumber.h>
17#include <QtOpcUa/qopcuaaxisinformation.h>
18#include <QtOpcUa/qopcuaxvalue.h>
19#include <QtOpcUa/qopcuaargument.h>
20#include <QtOpcUa/qopcuaextensionobject.h>
21#include <QtOpcUa/qopcuaendpointdescription.h>
22#include <QtOpcUa/qopcuaexpandednodeid.h>
23#include <QtOpcUa/qopcuarelativepathelement.h>
24#include <QtOpcUa/qopcuabrowsepathtarget.h>
25#include <QtOpcUa/qopcuaenumdefinition.h>
26#include <QtOpcUa/qopcuaenumfield.h>
27#include <QtOpcUa/qopcuastructuredefinition.h>
28#include <QtOpcUa/qopcuastructurefield.h>
29
30#include <QtCore/qcborarray.h>
31#include <private/qfactoryloader_p.h>
32#include <QtCore/qloggingcategory.h>
33#include <QtCore/qpluginloader.h>
34
35QT_BEGIN_NAMESPACE
36
37Q_LOGGING_CATEGORY(QT_OPCUA, "qt.opcua")
38Q_LOGGING_CATEGORY(QT_OPCUA_SECURITY, "qt.opcua.security")
39
40/*!
41 \class QOpcUaProvider
42 \inmodule QtOpcUa
43
44 \brief QOpcUaProvider creates an instance of QOpcUaClient.
45
46 QOpcUaProvider allows the user to create an instance of QOpcUaClient by
47 loading a QOpcUaPlugin using the Qt plugin system.
48
49 \section1 Example
50 This code creates a client using the first available backend:
51 \code
52 QOpcUaProvider provider;
53 QStringList available = provider.availableBackends();
54 if (!available.isEmpty()) {
55 QOpcUaClient *client = provider.createClient(available[0]);
56 if (client)
57 qDebug() << "Client successfully created";
58 }
59 \endcode
60*/
61
62Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, qOpcualoader,
63 (QOpcUaProviderFactory_iid, QLatin1String("/opcua")))
64
65/*!
66 \fn static QHash<QString, QCborMap> loadPluginMetadata()
67
68 Reads the meta data from the plugins known by the loader.
69*/
70static QHash<QString, QCborMap> loadPluginMetadata()
71{
72 QHash<QString, QCborMap> plugins;
73 const QFactoryLoader *l = qOpcualoader();
74 QList<QPluginParsedMetaData> const meta = l->metaData();
75 for (int i = 0; i < meta.size(); ++i) {
76 QCborMap map = meta.at(i).value(k: QtPluginMetaDataKeys::MetaData).toMap();
77 map.insert(key: QLatin1String("index"), value_: i);
78 plugins.insert(key: map.value(key: QLatin1String("Provider")).toString(), value: map);
79 }
80 return plugins;
81}
82
83/*!
84 \fn static QHash<QString, QCborMap> plugins()
85
86 Returns a \l QHash mapping names to JSON objects containing the meta data of
87 available plugins.
88*/
89static QHash<QString, QCborMap> plugins()
90{
91 static QHash<QString, QCborMap> plugins;
92 static bool alreadyDiscovered = false;
93
94 if (!alreadyDiscovered) {
95 plugins = loadPluginMetadata();
96 alreadyDiscovered = true;
97 }
98 return plugins;
99}
100
101/*!
102 Creates a new OPC UA provider with a given \a parent.
103 */
104QOpcUaProvider::QOpcUaProvider(QObject *parent)
105 : QObject(parent)
106{
107 qRegisterMetaType<QOpcUa::Types>();
108 qRegisterMetaType<QOpcUa::TypedVariant>();
109 qRegisterMetaType<QList<QOpcUa::TypedVariant>>();
110 qRegisterMetaType<QOpcUa::UaStatusCode>();
111 qRegisterMetaType<QOpcUa::NodeClass>();
112 qRegisterMetaType<QOpcUa::NodeClasses>();
113 qRegisterMetaType<QOpcUaQualifiedName>();
114 qRegisterMetaType<QOpcUa::NodeAttribute>();
115 qRegisterMetaType<QOpcUa::NodeAttributes>();
116 qRegisterMetaType<QOpcUaNode::AttributeMap>();
117 qRegisterMetaType<QList<QOpcUaReadResult>>();
118 qRegisterMetaType<QOpcUaClient::ClientState>();
119 qRegisterMetaType<QOpcUaClient::ClientError>();
120 qRegisterMetaType<QOpcUa::ReferenceTypeId>();
121 qRegisterMetaType<QOpcUaMonitoringParameters::SubscriptionType>();
122 qRegisterMetaType<QOpcUaMonitoringParameters::Parameter>();
123 qRegisterMetaType<QOpcUaMonitoringParameters::Parameters>();
124 qRegisterMetaType<QOpcUaMonitoringParameters>();
125 qRegisterMetaType<QOpcUaReferenceDescription>();
126 qRegisterMetaType<QList<QOpcUaReferenceDescription>>();
127 qRegisterMetaType<QOpcUa::ReferenceTypeId>();
128 qRegisterMetaType<QOpcUaRange>();
129 qRegisterMetaType<QOpcUaEUInformation>();
130 qRegisterMetaType<QOpcUaComplexNumber>();
131 qRegisterMetaType<QOpcUaDoubleComplexNumber>();
132 qRegisterMetaType<QOpcUaAxisInformation>();
133 qRegisterMetaType<QOpcUaXValue>();
134 qRegisterMetaType<QOpcUaExpandedNodeId>();
135 qRegisterMetaType<QOpcUaRelativePathElement>();
136 qRegisterMetaType<QList<QOpcUaRelativePathElement>>();
137 qRegisterMetaType<QOpcUaBrowsePathTarget>();
138 qRegisterMetaType<QList<QOpcUaBrowsePathTarget>>();
139 qRegisterMetaType<QOpcUaEndpointDescription>();
140 qRegisterMetaType<QList<QOpcUaEndpointDescription>>();
141 qRegisterMetaType<QOpcUaArgument>();
142 qRegisterMetaType<QOpcUaExtensionObject>();
143 qRegisterMetaType<QOpcUaBrowseRequest>();
144 qRegisterMetaType<QOpcUaReadItem>();
145 qRegisterMetaType<QOpcUaReadResult>();
146 qRegisterMetaType<QList<QOpcUaReadItem>>();
147 qRegisterMetaType<QList<QOpcUaReadResult>>();
148 qRegisterMetaType<QOpcUaWriteItem>();
149 qRegisterMetaType<QOpcUaWriteResult>();
150 qRegisterMetaType<QList<QOpcUaWriteItem>>();
151 qRegisterMetaType<QList<QOpcUaWriteResult>>();
152 qRegisterMetaType<QOpcUaNodeCreationAttributes>();
153 qRegisterMetaType<QOpcUaAddNodeItem>();
154 qRegisterMetaType<QOpcUaAddReferenceItem>();
155 qRegisterMetaType<QOpcUaDeleteReferenceItem>();
156 qRegisterMetaType<QList<QOpcUaApplicationDescription>>();
157 qRegisterMetaType<QOpcUaApplicationIdentity>();
158 qRegisterMetaType<QOpcUaPkiConfiguration>();
159 qRegisterMetaType<QOpcUaStructureDefinition>();
160 qRegisterMetaType<QOpcUaStructureField>();
161 qRegisterMetaType<QOpcUaEnumDefinition>();
162 qRegisterMetaType<QOpcUaEnumField>();
163}
164
165QOpcUaProvider::~QOpcUaProvider()
166{
167 qDeleteAll(c: m_plugins);
168}
169
170static QOpcUaPlugin *loadPlugin(const QString &key)
171{
172 const int index = qOpcualoader()->indexOf(needle: key);
173 if (index != -1) {
174 QObject *factoryObject = qOpcualoader()->instance(index);
175 if (QOpcUaPlugin *plugin = qobject_cast<QOpcUaPlugin *>(object: factoryObject)) {
176 return plugin;
177 }
178 }
179 return nullptr;
180}
181
182/*!
183 Returns a pointer to a QOpcUaClient object by loading the selected \a backend
184 as a plugin and creating a client object.
185 If the plugin loading fails, \c nullptr is returned instead.
186
187 The user is responsible for deleting the returned \l QOpcUaClient object
188 when it is no longer needed.
189
190 The optional argument \a backendProperties can be used to pass custom backend specific settings as key value pairs.
191 Those settings are specific to the backend being instantiated.
192
193 Available settings are
194 \table
195 \header
196 \li Setting string
197 \li Backend
198 \li Description
199 \row
200 \li minimumClientIterateIntervalMs
201 \li open62541
202 \li This parameter is no longer evaluated by the backend and has been replaced by \c clientIterateIntervalMs.
203 \row
204 \li clientIterateIntervalMs
205 \li open62541
206 \li Defines the client iterate interval for the backend. If the client is causing too much CPU load,
207 setting this value higher than the default will reduce the CPU load at the price of an increased
208 response time to service requests and value updates from subscriptions.
209 The default value is 50ms.
210 \row
211 \li asyncRequestTimeoutMs
212 \li open62541
213 \li Defines the timeout for asynchronous requests to an OPC UA server. If the server doesn't reply to
214 a service request before the timeout occurs, the service call fails and the finished signal will
215 contain a \c bad status code. The default value is 15000ms.
216 \endtable
217*/
218QOpcUaClient *QOpcUaProvider::createClient(const QString &backend, const QVariantMap &backendProperties)
219{
220 QOpcUaPlugin *plugin;
221 auto it = m_plugins.find(key: backend);
222 if (it == m_plugins.end()) {
223 plugin = loadPlugin(key: backend);
224 if (!plugin) {
225 qCWarning(QT_OPCUA) << "Failed to load OPC UA plugin:" << backend;
226 qCWarning(QT_OPCUA) << "Available plugins:" << availableBackends();
227 return nullptr;
228 }
229 m_plugins.insert(key: backend, value: plugin);
230 }
231 else {
232 plugin = it.value();
233 }
234 return plugin->createClient(backendProperties);
235}
236
237/*!
238 Returns a QStringList of available plugins.
239*/
240QStringList QOpcUaProvider::availableBackends()
241{
242 return plugins().keys();
243}
244
245QT_END_NAMESPACE
246

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtopcua/src/opcua/core/qopcuaprovider.cpp