1 | // Copyright (C) 2023 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 "qopcuainternaldatatypenode_p.h" |
5 | #include "qopcuagenericstructhandler_p.h" |
6 | |
7 | QT_BEGIN_NAMESPACE |
8 | |
9 | QOpcUaInternalDataTypeNode::QOpcUaInternalDataTypeNode(QOpcUaClient *client) |
10 | : m_client(client) |
11 | { |
12 | } |
13 | |
14 | bool QOpcUaInternalDataTypeNode::initialize(const QString &nodeId) |
15 | { |
16 | if (!m_client) |
17 | return false; |
18 | |
19 | m_nodeId = nodeId; |
20 | |
21 | m_node.reset(other: m_client->node(nodeId)); |
22 | |
23 | if (!m_node) |
24 | return false; |
25 | |
26 | QObject::connect(sender: m_node.get(), signal: &QOpcUaNode::browseFinished, context: this, |
27 | slot: [this](const QList<QOpcUaReferenceDescription> &results, QOpcUa::UaStatusCode result) { |
28 | Q_UNUSED(result); |
29 | |
30 | for (const auto &entry : results) { |
31 | auto child = new QOpcUaInternalDataTypeNode(m_client); |
32 | const auto success = child->initialize(nodeId: entry.targetNodeId().nodeId()); |
33 | |
34 | if (!success) { |
35 | child->deleteLater(); |
36 | handleFinished(success: false); |
37 | qCWarning(lcGenericStructHandler) << "Failed to init child"<< entry.browseName().name(); |
38 | return; |
39 | } |
40 | |
41 | m_children.push_back(x: std::unique_ptr<QOpcUaInternalDataTypeNode>(child)); |
42 | |
43 | QObject::connect(sender: child, signal: &QOpcUaInternalDataTypeNode::initializeFinished, context: this, slot: &QOpcUaInternalDataTypeNode::handleFinished); |
44 | } |
45 | |
46 | const auto success = m_node->readAttributes(attributes: QOpcUa::NodeAttribute::IsAbstract | |
47 | QOpcUa::NodeAttribute::DataTypeDefinition | |
48 | QOpcUa::NodeAttribute::BrowseName); |
49 | |
50 | if (!success) { |
51 | qCWarning(lcGenericStructHandler) << "Failed to read attributes for"<< m_node->nodeId(); |
52 | handleFinished(success: false); |
53 | } |
54 | }); |
55 | |
56 | QObject::connect(sender: m_node.get(), signal: &QOpcUaNode::attributeRead, context: this, slot: [this]() { |
57 | m_isAbstract = m_node->attribute(attribute: QOpcUa::NodeAttribute::IsAbstract).toBool(); |
58 | m_definition = m_node->attribute(attribute: QOpcUa::NodeAttribute::DataTypeDefinition); |
59 | m_name = m_node->attribute(attribute: QOpcUa::NodeAttribute::BrowseName).value<QOpcUaQualifiedName>().name(); |
60 | handleFinished(success: true); |
61 | }); |
62 | |
63 | const auto success = m_node->browseChildren(referenceType: QOpcUa::ReferenceTypeId::HasSubtype, nodeClassMask: QOpcUa::NodeClass::DataType); |
64 | if (!success) { |
65 | qCWarning(lcGenericStructHandler) << "Failed to start browse for"<< m_node->nodeId(); |
66 | handleFinished(success: false); |
67 | } |
68 | |
69 | return success; |
70 | } |
71 | |
72 | QVariant QOpcUaInternalDataTypeNode::definition() const |
73 | { |
74 | return m_definition; |
75 | } |
76 | |
77 | bool QOpcUaInternalDataTypeNode::isAbstract() const |
78 | { |
79 | return m_isAbstract; |
80 | } |
81 | |
82 | QString QOpcUaInternalDataTypeNode::name() const |
83 | { |
84 | return m_name; |
85 | } |
86 | |
87 | QString QOpcUaInternalDataTypeNode::nodeId() const |
88 | { |
89 | return m_nodeId; |
90 | } |
91 | |
92 | const std::vector<std::unique_ptr<QOpcUaInternalDataTypeNode> > &QOpcUaInternalDataTypeNode::children() const |
93 | { |
94 | return m_children; |
95 | } |
96 | |
97 | void QOpcUaInternalDataTypeNode::handleFinished(bool success) |
98 | { |
99 | if (m_hasError) |
100 | return; |
101 | |
102 | m_finishedCount++; |
103 | m_hasError = !success; |
104 | |
105 | if (m_finishedCount == m_children.size() + 1 || m_hasError) |
106 | emit initializeFinished(success: !m_hasError); |
107 | } |
108 | |
109 | QT_END_NAMESPACE |
110 |