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 "qopcuatype.h"
5
6#include <QMetaEnum>
7#include <QRegularExpression>
8#include <QUuid>
9#include <QString>
10#include <QList>
11
12QT_BEGIN_NAMESPACE
13
14/*!
15 \namespace QOpcUa
16 \inmodule QtOpcua
17
18 \brief The QOpcUa namespace contains miscellaneous identifiers used throughout the Qt OPC UA library.
19*/
20
21/*!
22 \enum QOpcUa::NodeClass
23
24 This enum specifies the class a node belongs to. OPC-UA specifies a fixed
25 set of eight different classes.
26
27 \value Undefined The node class is not known. This is the case before
28 the NodeClass attribute has been read on the server.
29
30 \value Object An Object node.
31 \value Variable A Variable node.
32 \value Method A Method node.
33 \value ObjectType An ObjectType node.
34 \value VariableType A VariableType node.
35 \value ReferenceType A ReferenceType node.
36 \value DataType A DataType node.
37 \value View A View node.
38*/
39
40/*!
41 \enum QOpcUa::ReferenceTypeId
42
43 This enum contains the reference types specified in OPC-UA part 3, 7.
44 They are used to filter for a certain reference type in \l QOpcUaNode::browseChildren
45 and for the reference type information in \l QOpcUaReferenceDescription.
46
47 \value Unspecified Not a valid reference type.
48 \value References The abstract base type for all references.
49 \value NonHierarchicalReferences The abstract base type for all non-hierarchical references.
50 \value HierarchicalReferences The abstract base type for all hierarchical references.
51 \value HasChild The abstract base type for all non-looping hierarchical references.
52 \value Organizes The type for hierarchical references that are used to organize nodes.
53 \value HasEventSource The type for non-looping hierarchical references that are used to organize event sources.
54 \value HasModellingRule The type for references from instance declarations to modelling rule nodes.
55 \value HasEncoding The type for references from data type nodes to to data type encoding nodes.
56 \value HasDescription The type for references from data type encoding nodes to data type description nodes.
57 \value HasTypeDefinition The type for references from a instance node to its type definition node.
58 \value GeneratesEvent The type for references from a node to an event type that is raised by node.
59 \value Aggregates The type for non-looping hierarchical references that are used to aggregate nodes into complex types.
60 \value HasSubtype The type for non-looping hierarchical references that are used to define sub types.
61 \value HasProperty The type for non-looping hierarchical reference from a node to its property.
62 \value HasComponent The type for non-looping hierarchical reference from a node to its component.
63 \value HasNotifier The type for non-looping hierarchical references that are used to indicate how events propagate from node to node.
64 \value HasOrderedComponent The type for non-looping hierarchical reference from a node to its component when the order of references matters.
65 \value FromState The type for a reference to the state before a transition.
66 \value ToState The type for a reference to the state after a transition.
67 \value HasCause The type for a reference to a method that can cause a transition to occur.
68 \value HasEffect The type for a reference to an event that may be raised when a transition occurs.
69 \value HasHistoricalConfiguration The type for a reference to the historical configuration for a data variable.
70 \value HasSubStateMachine The type for a reference to a substate for a state.
71 \value HasArgumentDescription The type for a reference to an argument description
72 \value HasOptionalInputArgumentDescription The type for a reference to an optional input argument description
73 \value AlwaysGeneratesEvent The type for references from a node to an event type that is always raised by node.
74 \value HasTrueSubState The type for references from a TRUE super state node to a subordinate state node.
75 \value HasFalseSubState The type for references from a FALSE super state node to a subordinate state node.
76 \value HasCondition The type for references from a ConditionSource node to a Condition.
77 \value HasPubSubConnection The type for a reference to a PubSub connection
78 \value DataSetToWriter The type for a reference to a data set writer
79 \value HasGuard The type for a reference to a guard
80 \value HasDataSetWriter The type for a reference to a data set writer
81 \value HasDataSetReader The type for a reference to data set reader
82 \value HasAlarmSuppressionGroup The type for a reference to an alarm suppression group
83 \value AlarmGroupMember The type for a reference to an alarm group member
84 \value HasEffectDisable The type for a reference to an alarm which is disabled by a transition
85 \value HasDictionaryEntry The type for a reference to a dictionary entry
86 \value HasInterface The type for a reference to an interface
87 \value HasAddIn The type for a reference to an addin
88 \value HasEffectEnable The type for a reference to an alarm which is enabled by a transition
89 \value HasEffectSuppressed The type for a reference to an alarm which is suppressed by a transition
90 \value HasEffectUnsuppressed The type for a reference to an alarm which is unsuppressed by a transition
91 \value HasWriterGroup The type for a reference to a writer group
92 \value HasReaderGroup The type for a reference to a reader group
93 \value AliasFor The type for a reference to the node represented by an alias
94*/
95
96/*!
97\enum QOpcUa::NodeAttribute
98
99 This enum contains the 22 node attributes defined in OPC-UA part 4, 5.
100
101 \value None No node attribute.
102 \value NodeId Mandatory for all nodes. Contains the node's id in the OPC UA address space.
103 \value NodeClass Mandatory for all nodes. Contains the node id describing the node class of the node.
104 \value BrowseName Mandatory for all nodes. Contains a non-localized human readable name of the node.
105 \value DisplayName Mandatory for all nodes. Contains a localized human readable name for display purposes.
106 \value Description Contains a localized human readable description of the node.
107 \value WriteMask Contains a bit mask. Each bit corresponds to a writable attribute (OPC-UA part 3, Table 3).
108 \value UserWriteMask Same as WriteMask but for the current user.
109 \value IsAbstract True if the node is an abstract type which means that no nodes of this type shall exist.
110 \value Symmetric True if a reference's meaning is the same seen from both ends.
111 \value InverseName The localized inverse name of a reference (for example "HasSubtype" has the InverseName "SubtypeOf").
112 \value ContainsNoLoops True if there is no way to get back to a node following forward references in the current view.
113 \value EventNotifier Contains a bit mask used to indicate if subscribing to events and access to historic events is supported (OPC-UA part 3, Table 5).
114 \value Value The value of a Variable node.
115 \value DataType The NodeId of the Value attribute's data type (for example "ns=0;i=13" for DateTime, see https://opcfoundation.org/UA/schemas/1.03/NodeIds.csv).
116 \value ValueRank Contains information about the structure of the Value attribute (scalar/array) (OPC-UA part 3, Table 8).
117 \value ArrayDimensions An array containing the length for each dimension of a multi-dimensional array.
118 \value AccessLevel Contains a bit mask. Each bit corresponds to an access capability (OPC-UA part 3, Table 8).
119 \value UserAccessLevel Same as AccessLevel, but for the current user.
120 \value MinimumSamplingInterval Contains the shortest possible interval in which the server is able to sample the value.
121 \value Historizing True if historical data is collected.
122 \value Executable True if the node is currently executable. Only relevant for Method nodes.
123 \value UserExecutable Same as Executable, but for the current user.
124*/
125
126/*!
127 \enum QOpcUa::WriteMaskBit
128
129 This enum contains all possible bits for the WriteMask and UserWriteMask node attributes
130 defined in OPC-UA part 3, Table 3.
131
132 \value None No attribute is writable.
133 \value AccessLevel The AccessLevel attribute is writable.
134 \value ArrayDimensions The ArrayDimensions attribute is writable.
135 \value BrowseName The BrowseName attribute is writable.
136 \value ContainsNoLoops The ContainsNoLoops attribute is writable.
137 \value DataType The DataType attribute is writable.
138 \value Description The Description attribute is writable.
139 \value DisplayName The DisplayName attribute is writable.
140 \value EventNotifier The EventNotifier attribute is writable.
141 \value Executable The Executable attribute is writable.
142 \value Historizing The Historizing attribute is writable.
143 \value InverseName The InverseName attribute is writable.
144 \value IsAbstract The IsAbstract attribute is writable.
145 \value MinimumSamplingInterval The MinimumSamplingInterval attribute is writable.
146 \value NodeClass The NodeClass attribute is writable.
147 \value NodeId The NodeId attribute is writable.
148 \value Symmetric The Symmetric attribute is writable.
149 \value UserAccessLevel The UserAccessLevel attribute is writable.
150 \value UserExecutable The UserExecutable attribute is writable.
151 \value UserWriteMask The UserWriteMask attribute is writable.
152 \value ValueRank The ValueRank attribute is writable.
153 \value WriteMask The WriteMask attribute is writable.
154 \value ValueForVariableType The Value attribute of a variable type is writable.
155*/
156
157/*!
158 \enum QOpcUa::AccessLevelBit
159
160 This enum contains all possible bits for the AccessLevel and UserAccessLevel node attributes
161 defined in OPC-UA part 3, Table 8.
162
163 \value None No read access to the Value attribute is permitted.
164 \value CurrentRead The current value can be read.
165 \value CurrentWrite The current value can be written.
166 \value HistoryRead The history of the value is readable.
167 \value HistoryWrite The history of the value is writable.
168 \value SemanticChange The property variable generates SemanticChangeEvents.
169 \value StatusWrite The status code of the value is writable.
170 \value TimestampWrite The SourceTimestamp is writable.
171*/
172
173/*!
174 \enum QOpcUa::EventNotifierBit
175
176 This enum contains all possible bits for the EventNotifier node attribute
177 defined in OPC-UA part 3, Table 6.
178
179 \value None The node can't be used to interact with events.
180 \value SubscribeToEvents A client can subscribe to events.
181 \value HistoryRead A client can read the event history.
182 \value HistoryWrite A client can write the event history.
183*/
184
185/*!
186 \fn inline uint QOpcUa::qHash(const QOpcUa::NodeAttribute& attr)
187
188 Returns a \l QHash key for \a attr.
189*/
190
191/*!
192 \enum QOpcUa::Types
193
194 Enumerates the types supported by Qt OPC UA.
195
196 \value Boolean
197 \value Int32
198 \value UInt32
199 \value Double
200 \value Float
201 \value String
202 \value LocalizedText
203 \value DateTime
204 \value UInt16
205 \value Int16
206 \value UInt64
207 \value Int64
208 \value Byte
209 \value SByte
210 \value ByteString
211 \value XmlElement
212 \value NodeId
213 \value Guid
214 \value QualifiedName A name qualified by an OPC UA namespace index.
215 \value StatusCode
216 \value ExtensionObject A data structure which contains a serialized object.
217 \value Range A range composed from the two double values low and high.
218 \value EUInformation The unit of measurement for an analog value.
219 \value ComplexNumber The OPC UA ComplexNumber type.
220 \value DoubleComplexNumber The OPC UA DoubleComplexNumber type.
221 \value AxisInformation Information about an axis.
222 \value XV A float value with a double precision position on an axis.
223 \value ExpandedNodeId A node id with additional namespace URI and server index.
224 \value Argument The OPC UA Argument type.
225 \value Undefined
226*/
227
228/*!
229 \enum QOpcUa::UaStatusCode
230
231 Enumerates all status codes from \l {https://opcfoundation.org/UA/schemas/1.03/Opc.Ua.StatusCodes.csv}
232
233 \value Good
234 \value BadUnexpectedError
235 \value BadInternalError
236 \value BadOutOfMemory
237 \value BadResourceUnavailable
238 \value BadCommunicationError
239 \value BadEncodingError
240 \value BadDecodingError
241 \value BadEncodingLimitsExceeded
242 \value BadRequestTooLarge
243 \value BadResponseTooLarge
244 \value BadUnknownResponse
245 \value BadTimeout
246 \value BadServiceUnsupported
247 \value BadShutdown
248 \value BadServerNotConnected
249 \value BadServerHalted
250 \value BadNothingToDo
251 \value BadTooManyOperations
252 \value BadTooManyMonitoredItems
253 \value BadDataTypeIdUnknown
254 \value BadCertificateInvalid
255 \value BadSecurityChecksFailed
256 \value BadCertificateTimeInvalid
257 \value BadCertificateIssuerTimeInvalid
258 \value BadCertificateHostNameInvalid
259 \value BadCertificateUriInvalid
260 \value BadCertificateUseNotAllowed
261 \value BadCertificateIssuerUseNotAllowed
262 \value BadCertificateUntrusted
263 \value BadCertificateRevocationUnknown
264 \value BadCertificateIssuerRevocationUnknown
265 \value BadCertificateRevoked
266 \value BadCertificateIssuerRevoked
267 \value BadCertificateChainIncomplete
268 \value BadUserAccessDenied
269 \value BadIdentityTokenInvalid
270 \value BadIdentityTokenRejected
271 \value BadSecureChannelIdInvalid
272 \value BadInvalidTimestamp
273 \value BadNonceInvalid
274 \value BadSessionIdInvalid
275 \value BadSessionClosed
276 \value BadSessionNotActivated
277 \value BadSubscriptionIdInvalid
278 \value BadRequestHeaderInvalid
279 \value BadTimestampsToReturnInvalid
280 \value BadRequestCancelledByClient
281 \value BadTooManyArguments
282 \value GoodSubscriptionTransferred
283 \value GoodCompletesAsynchronously
284 \value GoodOverload
285 \value GoodClamped
286 \value BadNoCommunication
287 \value BadWaitingForInitialData
288 \value BadNodeIdInvalid
289 \value BadNodeIdUnknown
290 \value BadAttributeIdInvalid
291 \value BadIndexRangeInvalid
292 \value BadIndexRangeNoData
293 \value BadDataEncodingInvalid
294 \value BadDataEncodingUnsupported
295 \value BadNotReadable
296 \value BadNotWritable
297 \value BadOutOfRange
298 \value BadNotSupported
299 \value BadNotFound
300 \value BadObjectDeleted
301 \value BadNotImplemented
302 \value BadMonitoringModeInvalid
303 \value BadMonitoredItemIdInvalid
304 \value BadMonitoredItemFilterInvalid
305 \value BadMonitoredItemFilterUnsupported
306 \value BadFilterNotAllowed
307 \value BadStructureMissing
308 \value BadEventFilterInvalid
309 \value BadContentFilterInvalid
310 \value BadFilterOperatorInvalid
311 \value BadFilterOperatorUnsupported
312 \value BadFilterOperandCountMismatch
313 \value BadFilterOperandInvalid
314 \value BadFilterElementInvalid
315 \value BadFilterLiteralInvalid
316 \value BadContinuationPointInvalid
317 \value BadNoContinuationPoints
318 \value BadReferenceTypeIdInvalid
319 \value BadBrowseDirectionInvalid
320 \value BadNodeNotInView
321 \value BadServerUriInvalid
322 \value BadServerNameMissing
323 \value BadDiscoveryUrlMissing
324 \value BadSempahoreFileMissing
325 \value BadRequestTypeInvalid
326 \value BadSecurityModeRejected
327 \value BadSecurityPolicyRejected
328 \value BadTooManySessions
329 \value BadUserSignatureInvalid
330 \value BadApplicationSignatureInvalid
331 \value BadNoValidCertificates
332 \value BadIdentityChangeNotSupported
333 \value BadRequestCancelledByRequest
334 \value BadParentNodeIdInvalid
335 \value BadReferenceNotAllowed
336 \value BadNodeIdRejected
337 \value BadNodeIdExists
338 \value BadNodeClassInvalid
339 \value BadBrowseNameInvalid
340 \value BadBrowseNameDuplicated
341 \value BadNodeAttributesInvalid
342 \value BadTypeDefinitionInvalid
343 \value BadSourceNodeIdInvalid
344 \value BadTargetNodeIdInvalid
345 \value BadDuplicateReferenceNotAllowed
346 \value BadInvalidSelfReference
347 \value BadReferenceLocalOnly
348 \value BadNoDeleteRights
349 \value UncertainReferenceNotDeleted
350 \value BadServerIndexInvalid
351 \value BadViewIdUnknown
352 \value BadViewTimestampInvalid
353 \value BadViewParameterMismatch
354 \value BadViewVersionInvalid
355 \value UncertainNotAllNodesAvailable
356 \value GoodResultsMayBeIncomplete
357 \value BadNotTypeDefinition
358 \value UncertainReferenceOutOfServer
359 \value BadTooManyMatches
360 \value BadQueryTooComplex
361 \value BadNoMatch
362 \value BadMaxAgeInvalid
363 \value BadSecurityModeInsufficient
364 \value BadHistoryOperationInvalid
365 \value BadHistoryOperationUnsupported
366 \value BadInvalidTimestampArgument
367 \value BadWriteNotSupported
368 \value BadTypeMismatch
369 \value BadMethodInvalid
370 \value BadArgumentsMissing
371 \value BadTooManySubscriptions
372 \value BadTooManyPublishRequests
373 \value BadNoSubscription
374 \value BadSequenceNumberUnknown
375 \value BadMessageNotAvailable
376 \value BadInsufficientClientProfile
377 \value BadStateNotActive
378 \value BadTcpServerTooBusy
379 \value BadTcpMessageTypeInvalid
380 \value BadTcpSecureChannelUnknown
381 \value BadTcpMessageTooLarge
382 \value BadTcpNotEnoughResources
383 \value BadTcpInternalError
384 \value BadTcpEndpointUrlInvalid
385 \value BadRequestInterrupted
386 \value BadRequestTimeout
387 \value BadSecureChannelClosed
388 \value BadSecureChannelTokenUnknown
389 \value BadSequenceNumberInvalid
390 \value BadProtocolVersionUnsupported
391 \value BadConfigurationError
392 \value BadNotConnected
393 \value BadDeviceFailure
394 \value BadSensorFailure
395 \value BadOutOfService
396 \value BadDeadbandFilterInvalid
397 \value UncertainNoCommunicationLastUsableValue
398 \value UncertainLastUsableValue
399 \value UncertainSubstituteValue
400 \value UncertainInitialValue
401 \value UncertainSensorNotAccurate
402 \value UncertainEngineeringUnitsExceeded
403 \value UncertainSubNormal
404 \value GoodLocalOverride
405 \value BadRefreshInProgress
406 \value BadConditionAlreadyDisabled
407 \value BadConditionAlreadyEnabled
408 \value BadConditionDisabled
409 \value BadEventIdUnknown
410 \value BadEventNotAcknowledgeable
411 \value BadDialogNotActive
412 \value BadDialogResponseInvalid
413 \value BadConditionBranchAlreadyAcked
414 \value BadConditionBranchAlreadyConfirmed
415 \value BadConditionAlreadyShelved
416 \value BadConditionNotShelved
417 \value BadShelvingTimeOutOfRange
418 \value BadNoData
419 \value BadBoundNotFound
420 \value BadBoundNotSupported
421 \value BadDataLost
422 \value BadDataUnavailable
423 \value BadEntryExists
424 \value BadNoEntryExists
425 \value BadTimestampNotSupported
426 \value GoodEntryInserted
427 \value GoodEntryReplaced
428 \value UncertainDataSubNormal
429 \value GoodNoData
430 \value GoodMoreData
431 \value BadAggregateListMismatch
432 \value BadAggregateNotSupported
433 \value BadAggregateInvalidInputs
434 \value BadAggregateConfigurationRejected
435 \value GoodDataIgnored
436 \value BadRequestNotAllowed
437 \value GoodEdited
438 \value GoodPostActionFailed
439 \value UncertainDominantValueChanged
440 \value GoodDependentValueChanged
441 \value BadDominantValueChanged
442 \value UncertainDependentValueChanged
443 \value BadDependentValueChanged
444 \value GoodCommunicationEvent
445 \value GoodShutdownEvent
446 \value GoodCallAgain
447 \value GoodNonCriticalTimeout
448 \value BadInvalidArgument
449 \value BadConnectionRejected
450 \value BadDisconnect
451 \value BadConnectionClosed
452 \value BadInvalidState
453 \value BadEndOfStream
454 \value BadNoDataAvailable
455 \value BadWaitingForResponse
456 \value BadOperationAbandoned
457 \value BadExpectedStreamToBlock
458 \value BadWouldBlock
459 \value BadSyntaxError
460 \value BadMaxConnectionsReached
461*/
462
463/*!
464 \enum QOpcUa::ErrorCategory
465
466 This enum contains simplified categories for OPC UA errors.
467
468 \value NoError The operation has been successful.
469 \value NodeError There is a problem with the node, e. g. it does not exist.
470 \value AttributeError The attributes to operate on where invalid.
471 \value PermissionError The user did not have the permission to perform the operation.
472 \value ArgumentError The arguments supplied by the user were invalid or incomplete.
473 \value TypeError There has been a type mismatch for a write operation.
474 \value ConnectionError Communication with the server did not work as expected.
475 \value UnspecifiedError Any error that is not categorized. The detailed status code must be checked.
476*/
477
478/*!
479 This method can be used to check if a call has successfully finished.
480
481 Returns \c true if \a statusCode's severity field is Good.
482*/
483bool QOpcUa::isSuccessStatus(QOpcUa::UaStatusCode statusCode)
484{
485 return (statusCode & 0xC0000000) == 0;
486}
487
488/*!
489 \typedef QOpcUa::TypedVariant
490
491 This is QPair<QVariant, QOpcUa::Types>.
492*/
493
494static bool isNodeError(QOpcUa::UaStatusCode statusCode)
495{
496 switch (statusCode) {
497 case QOpcUa::UaStatusCode::BadMethodInvalid:
498 case QOpcUa::UaStatusCode::BadNodeIdInvalid:
499 case QOpcUa::UaStatusCode::BadNodeIdExists:
500 case QOpcUa::UaStatusCode::BadNodeIdRejected:
501 case QOpcUa::UaStatusCode::BadNodeIdUnknown:
502 case QOpcUa::UaStatusCode::BadObjectDeleted:
503 return true;
504 default:
505 return false;
506 }
507}
508
509static bool isAttributeError(QOpcUa::UaStatusCode statusCode)
510{
511 switch (statusCode) {
512 case QOpcUa::UaStatusCode::BadAttributeIdInvalid:
513 case QOpcUa::UaStatusCode::BadNodeAttributesInvalid:
514 return true;
515 default:
516 return false;
517 }
518}
519
520static bool isPermissionError(QOpcUa::UaStatusCode statusCode)
521{
522 switch (statusCode) {
523 case QOpcUa::UaStatusCode::BadUserAccessDenied:
524 case QOpcUa::UaStatusCode::BadNotWritable:
525 case QOpcUa::UaStatusCode::BadNoDeleteRights:
526 case QOpcUa::UaStatusCode::BadNotReadable:
527 return true;
528 default:
529 return false;
530 }
531}
532
533static bool isArgumentError(QOpcUa::UaStatusCode statusCode)
534{
535 switch (statusCode) {
536 case QOpcUa::UaStatusCode::BadArgumentsMissing:
537 case QOpcUa::UaStatusCode::BadInvalidArgument:
538 case QOpcUa::UaStatusCode::BadTooManyArguments:
539 case QOpcUa::UaStatusCode::BadInvalidTimestampArgument:
540 return true;
541 default:
542 return false;
543 }
544}
545
546static bool isTypeError(QOpcUa::UaStatusCode statusCode)
547{
548 switch (statusCode) {
549 case QOpcUa::UaStatusCode::BadTypeMismatch:
550 case QOpcUa::UaStatusCode::BadInvalidTimestampArgument:
551 return true;
552 default:
553 return false;
554 }
555}
556
557static bool isConnectionError(QOpcUa::UaStatusCode statusCode)
558{
559 switch (statusCode) {
560 case QOpcUa::UaStatusCode::BadConnectionClosed:
561 case QOpcUa::UaStatusCode::BadNoCommunication:
562 return true;
563 default:
564 return false;
565 }
566}
567
568/*!
569 Converts \a statusCode to an \l ErrorCategory. \l ErrorCategory can be used in cases where the
570 exact error is not important.
571
572 For error handling dependent on status codes, the full status code must be used instead.
573 The meaning of the status codes for the different services is documented in OPC-UA part 4.
574
575 If \a statusCode has not been categorized, UnspecifiedError is returned. In this case, the user
576 must check the full status code.
577*/
578QOpcUa::ErrorCategory QOpcUa::errorCategory(QOpcUa::UaStatusCode statusCode)
579{
580 if (isSuccessStatus(statusCode))
581 return QOpcUa::ErrorCategory::NoError;
582 if (isNodeError(statusCode))
583 return QOpcUa::ErrorCategory::NodeError;
584 if (isAttributeError(statusCode))
585 return QOpcUa::ErrorCategory::AttributeError;
586 if (isPermissionError(statusCode))
587 return QOpcUa::ErrorCategory::PermissionError;
588 if (isArgumentError(statusCode))
589 return QOpcUa::ErrorCategory::ArgumentError;
590 if (isTypeError(statusCode))
591 return QOpcUa::ErrorCategory::TypeError;
592 if (isConnectionError(statusCode))
593 return QOpcUa::ErrorCategory::ConnectionError;
594
595 return QOpcUa::ErrorCategory::UnspecifiedError;
596}
597
598/*!
599 Creates a node id string from the namespace index \a ns and the string \a identifier.
600 \sa QOpcUaNode
601*/
602QString QOpcUa::nodeIdFromString(quint16 ns, const QString &identifier)
603{
604 return QStringLiteral("ns=%1;s=%2").arg(a: ns).arg(a: identifier);
605}
606
607/*!
608 Creates a node id string from the namespace index \a ns and the byte string \a identifier.
609 \sa QOpcUaNode
610*/
611QString QOpcUa::nodeIdFromByteString(quint16 ns, const QByteArray &identifier)
612{
613 return QStringLiteral("ns=%1;b=%2").arg(a: ns).arg(a: QString::fromUtf8(ba: identifier.toBase64()));
614}
615
616/*!
617 Creates a node id string from the namespace index \a ns and the GUID \a identifier.
618 \sa QOpcUaNode
619*/
620QString QOpcUa::nodeIdFromGuid(quint16 ns, const QUuid &identifier)
621{
622 return QStringLiteral("ns=%1;g=").arg(a: ns).append(v: QStringView(identifier.toString()).mid(pos: 1, n: 36)); // Remove enclosing {...};
623}
624
625/*!
626 Creates a node id string from the namespace index \a ns and the integer \a identifier.
627 \sa QOpcUaNode
628*/
629QString QOpcUa::nodeIdFromInteger(quint16 ns, quint32 identifier)
630{
631 return QStringLiteral("ns=%1;i=%2").arg(a: ns).arg(a: identifier);
632}
633
634/*!
635 Creates a node id string for the reference type id \a referenceType.
636*/
637QString QOpcUa::nodeIdFromReferenceType(QOpcUa::ReferenceTypeId referenceType)
638{
639 return QStringLiteral("ns=0;i=%1").arg(a: static_cast<quint32>(referenceType));
640}
641
642/*!
643 Splits the node id string \a nodeIdString in its components.
644 The namespace index of the node id will be copied into \a nsIndex.
645 The identifier string is copied into \a identifier and the identifier type
646 (i, s, g, b) is copied into \a identifierType.
647
648 Returns \c true if the node id could be split successfully.
649
650 For example, "ns=1;s=MyString" is split into 1, 's' and "MyString".
651 If no namespace index is given, ns=0 is assumed.
652*/
653bool QOpcUa::nodeIdStringSplit(const QString &nodeIdString, quint16 *nsIndex, QString *identifier, char *identifierType)
654{
655 quint16 namespaceIndex = 0;
656
657 QStringList components = nodeIdString.split(sep: QLatin1String(";"));
658
659 if (components.size() > 2)
660 return false;
661
662 if (components.size() == 2 && components.at(i: 0).contains(re: QRegularExpression(QLatin1String("^ns=[0-9]+")))) {
663 bool success = false;
664 uint ns = QStringView(components.at(i: 0)).mid(pos: 3).toUInt(ok: &success);
665 if (!success || ns > (std::numeric_limits<quint16>::max)())
666 return false;
667 namespaceIndex = ns;
668 }
669
670 if (components.last().size() < 3)
671 return false;
672
673 if (!components.last().contains(re: QRegularExpression(QLatin1String("^[isgb]="))))
674 return false;
675
676 if (nsIndex)
677 *nsIndex = namespaceIndex;
678 if (identifier)
679 *identifier = QStringView(components.last()).mid(pos: 2).toString();
680 if (identifierType)
681 *identifierType = components.last().at(i: 0).toLatin1();
682
683 return true;
684}
685
686/*!
687 Returns \c true if the two node ids \a first and \a second have the same namespace index and identifier.
688 A node id string without a namespace index is assumed to be in namespace 0.
689*/
690bool QOpcUa::nodeIdEquals(const QString &first, const QString &second)
691{
692 const QStringView fView(first);
693 const QStringView sView(second);
694 if (first.startsWith(s: QLatin1String("ns=0;")) && !second.startsWith(s: QLatin1String("ns=")))
695 return fView.mid(pos: 5) == sView;
696 else if (second.startsWith(s: QLatin1String("ns=0;")) && !first.startsWith(s: QLatin1String("ns=")))
697 return sView.mid(pos: 5) == fView;
698 else
699 return first == second;
700}
701
702/*!
703 Returns a node id string for the namespace 0 identifier \a id.
704*/
705QString QOpcUa::namespace0Id(QOpcUa::NodeIds::Namespace0 id)
706{
707 return QStringLiteral("ns=0;i=%1").arg(a: quint32(id));
708}
709
710/*!
711 Returns the enum value from \l QOpcUa::NodeIds::Namespace0 for \a nodeId.
712
713 If the node id is not in namespace 0 or doesn't have a numeric
714 identifier which is part of the OPC Foundation's NodeIds.csv file,
715 \l {QOpcUa::NodeIds::Namespace0} {Unknown} is returned.
716
717 If Qt OPC UA has been configured with -no-feature-ns0idnames,
718 the check if the numeric identifier is part of the NodeIds.csv
719 file is omitted. If the node id is in namespace 0 and has a
720 numeric identifier, the identifier is returned regardless if it
721 is part of the \l QOpcUa::NodeIds::Namespace0 enum.
722*/
723QOpcUa::NodeIds::Namespace0 QOpcUa::namespace0IdFromNodeId(const QString &nodeId)
724{
725 if (!nodeId.startsWith(s: QLatin1String("ns=0;i=")))
726 return QOpcUa::NodeIds::Namespace0::Unknown;
727
728 const QStringView sv = QStringView{nodeId}.mid(pos: 7);
729
730 bool ok = false;
731 quint32 identifier = sv.toUInt(ok: &ok);
732
733 if (!ok)
734 return QOpcUa::NodeIds::Namespace0::Unknown;
735
736#ifndef QT_OPCUA_NO_NS0IDNAMES
737 if (!QMetaEnum::fromType<QOpcUa::NodeIds::Namespace0>().valueToKey(value: identifier))
738 return QOpcUa::NodeIds::Namespace0::Unknown;
739#endif
740
741 return QOpcUa::NodeIds::Namespace0(identifier);
742}
743
744/*!
745 Returns the name of the namespace 0 node id \a id.
746
747 If \a id is unknown or Qt OPC UA has been configured with -no-feature-ns0idnames,
748 an empty string is returned.
749*/
750QString QOpcUa::namespace0IdName(QOpcUa::NodeIds::Namespace0 id)
751{
752#ifdef QT_OPCUA_NO_NS0IDNAMES
753 Q_UNUSED(id);
754 return QString();
755#else
756 if (id == QOpcUa::NodeIds::Namespace0::Unknown)
757 return QString();
758 return QString::fromUtf8(utf8: QMetaEnum::fromType<QOpcUa::NodeIds::Namespace0>().valueToKey(value: quint32(id)));
759#endif
760}
761
762/*!
763 \enum QOpcUa::AxisScale
764
765 The AxisScale enum as defined by OPC-UA part 8, 5.6.7.
766
767 \value Linear
768 \value Log
769 \value Ln
770*/
771
772/*!
773 Returns a textual representation of \a statusCode.
774
775 Currently, this is the name of the enum value but may be a real message in future releases.
776*/
777QString QOpcUa::statusToString(QOpcUa::UaStatusCode statusCode)
778{
779 const auto enumerator = QMetaEnum::fromType<QOpcUa::UaStatusCode>();
780 const auto key = enumerator.valueToKey(value: statusCode);
781 if (key)
782 return QString::fromLatin1(ba: key);
783 else
784 return QLatin1String("Invalid enum value for UaStatusCode");
785}
786
787/*!
788 \since 5.13
789
790 Returns the Qt OPC UA type from \a type.
791 In case the type does not map, \c QOpcUa::Undefined is returned.
792*/
793QOpcUa::Types QOpcUa::metaTypeToQOpcUaType(QMetaType::Type type) {
794 switch (type) {
795 case QMetaType::Bool:
796 return QOpcUa::Boolean;
797 case QMetaType::UChar:
798 return QOpcUa::Byte;
799 case QMetaType::Char:
800 return QOpcUa::SByte;
801 case QMetaType::UShort:
802 return QOpcUa::UInt16;
803 case QMetaType::Short:
804 return QOpcUa::Int16;
805 case QMetaType::Int:
806 return QOpcUa::Int32;
807 case QMetaType::UInt:
808 return QOpcUa::UInt32;
809 case QMetaType::ULongLong:
810 return QOpcUa::UInt64;
811 case QMetaType::LongLong:
812 return QOpcUa::Int64;
813 case QMetaType::Double:
814 return QOpcUa::Double;
815 case QMetaType::Float:
816 return QOpcUa::Float;
817 case QMetaType::QString:
818 return QOpcUa::String;
819 case QMetaType::QDateTime:
820 return QOpcUa::DateTime;
821 case QMetaType::QByteArray:
822 return QOpcUa::ByteString;
823 case QMetaType::QUuid:
824 return QOpcUa::Guid;
825 default:
826 break;
827 }
828 return QOpcUa::Undefined;
829}
830
831QOpcUa::Types QOpcUa::opcUaDataTypeToQOpcUaType(const QString &type)
832{
833 if (type == QStringLiteral("ns=0;i=1"))
834 return QOpcUa::Boolean;
835 else if (type == QStringLiteral("ns=0;i=3"))
836 return QOpcUa::Byte;
837 else if (type == QStringLiteral("ns=0;i=2"))
838 return QOpcUa::SByte;
839 else if (type == QStringLiteral("ns=0;i=5"))
840 return QOpcUa::UInt16;
841 else if (type == QStringLiteral("ns=0;i=4"))
842 return QOpcUa::Int16;
843 else if (type == QStringLiteral("ns=0;i=6"))
844 return QOpcUa::Int32;
845 else if (type == QStringLiteral("ns=0;i=7"))
846 return QOpcUa::UInt32;
847 else if (type == QStringLiteral("ns=0;i=9"))
848 return QOpcUa::UInt64;
849 else if (type == QStringLiteral("ns=0;i=8"))
850 return QOpcUa::Int64;
851 else if (type == QStringLiteral("ns=0;i=11"))
852 return QOpcUa::Double;
853 else if (type == QStringLiteral("ns=0;i=10"))
854 return QOpcUa::Float;
855 else if (type == QStringLiteral("ns=0;i=12"))
856 return QOpcUa::String;
857 else if (type == QStringLiteral("ns=0;i=13"))
858 return QOpcUa::DateTime;
859 else if (type == QStringLiteral("ns=0;i=15"))
860 return QOpcUa::ByteString;
861 else if (type == QStringLiteral("ns=0;i=14"))
862 return QOpcUa::Guid;
863 else
864 return QOpcUa::Undefined;
865}
866
867/*!
868 \since QtOpcUa 5.14
869
870 Returns \c true if \a securityPolicy is a secure policy, \c false
871 otherwise.
872*/
873bool QOpcUa::isSecurePolicy(const QString &securityPolicy)
874{
875 return securityPolicy == QLatin1String("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15") ||
876 securityPolicy == QLatin1String("http://opcfoundation.org/UA/SecurityPolicy#Basic256") ||
877 securityPolicy == QLatin1String("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256") ||
878 securityPolicy == QLatin1String("http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep") ||
879 securityPolicy == QLatin1String("http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss");
880}
881
882QT_END_NAMESPACE
883
884

source code of qtopcua/src/opcua/client/qopcuatype.cpp