1 | // Copyright (C) 2016 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 | #ifndef QOPCUANODE_P_H |
5 | #define QOPCUANODE_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtOpcUa/qopcuaclient.h> |
19 | #include <QtOpcUa/qopcuanode.h> |
20 | #include <QtOpcUa/qopcuaeventfilterresult.h> |
21 | #include <private/qopcuanodeimpl_p.h> |
22 | |
23 | #include <private/qobject_p.h> |
24 | #include <QtCore/qpointer.h> |
25 | #include <QtCore/qscopedpointer.h> |
26 | #include <QtCore/qhash.h> |
27 | |
28 | QT_BEGIN_NAMESPACE |
29 | |
30 | class QOpcUaNodePrivate : public QObjectPrivate |
31 | { |
32 | Q_DECLARE_PUBLIC(QOpcUaNode) |
33 | |
34 | public: |
35 | QOpcUaNodePrivate(QOpcUaNodeImpl *impl, QOpcUaClient *client) |
36 | : m_impl(impl) |
37 | , m_client(client) |
38 | { |
39 | m_attributesReadConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::attributesRead, |
40 | slot: [this](QList<QOpcUaReadResult> attr, QOpcUa::UaStatusCode serviceResult) |
41 | { |
42 | QOpcUa::NodeAttributes updatedAttributes; |
43 | Q_Q(QOpcUaNode); |
44 | |
45 | for (auto &entry : std::as_const(t&: attr)) { |
46 | if (serviceResult == QOpcUa::UaStatusCode::Good) |
47 | m_nodeAttributes[entry.attribute()] = entry; |
48 | else { |
49 | QOpcUaReadResult temp = entry; |
50 | temp.setStatusCode(serviceResult); |
51 | temp.setValue(QVariant()); |
52 | m_nodeAttributes[entry.attribute()] = temp; |
53 | } |
54 | |
55 | updatedAttributes |= entry.attribute(); |
56 | emit q->attributeUpdated(attr: entry.attribute(), value: entry.value()); |
57 | } |
58 | |
59 | emit q->attributeRead(attributes: updatedAttributes); |
60 | }); |
61 | |
62 | m_attributeWrittenConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::attributeWritten, |
63 | slot: [this](QOpcUa::NodeAttribute attr, QVariant value, QOpcUa::UaStatusCode statusCode) |
64 | { |
65 | m_nodeAttributes[attr].setStatusCode(statusCode); |
66 | Q_Q(QOpcUaNode); |
67 | |
68 | if (statusCode == QOpcUa::UaStatusCode::Good) { |
69 | m_nodeAttributes[attr].setValue(value); |
70 | emit q->attributeUpdated(attr, value); |
71 | } |
72 | |
73 | emit q->attributeWritten(attribute: attr, statusCode); |
74 | }); |
75 | |
76 | m_dataChangeOccurredConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::dataChangeOccurred, |
77 | slot: [this](QOpcUa::NodeAttribute attr, QOpcUaReadResult value) |
78 | { |
79 | this->m_nodeAttributes[attr] = value; |
80 | Q_Q(QOpcUaNode); |
81 | emit q->dataChangeOccurred(attr, value: value.value()); |
82 | emit q->attributeUpdated(attr, value: value.value()); |
83 | }); |
84 | |
85 | m_monitoringEnableDisableConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::monitoringEnableDisable, |
86 | slot: [this](QOpcUa::NodeAttribute attr, bool subscribe, QOpcUaMonitoringParameters status) |
87 | { |
88 | if (subscribe == true) { |
89 | if (status.statusCode() != QOpcUa::UaStatusCode::BadEntryExists) // Don't overwrite a valid entry |
90 | m_monitoringStatus[attr] = status; |
91 | Q_Q(QOpcUaNode); |
92 | emit q->enableMonitoringFinished(attr, statusCode: status.statusCode()); |
93 | } |
94 | else { |
95 | m_monitoringStatus.remove(key: attr); |
96 | Q_Q(QOpcUaNode); |
97 | emit q->disableMonitoringFinished(attr, statusCode: status.statusCode()); |
98 | } |
99 | }); |
100 | |
101 | m_monitoringStatusChangedConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::monitoringStatusChanged, |
102 | slot: [this](QOpcUa::NodeAttribute attr, QOpcUaMonitoringParameters::Parameters items, QOpcUaMonitoringParameters param) |
103 | { |
104 | auto it = m_monitoringStatus.find(key: attr); |
105 | if (param.statusCode() == QOpcUa::UaStatusCode::Good && it != m_monitoringStatus.end()) { |
106 | if (items & QOpcUaMonitoringParameters::Parameter::PublishingEnabled) |
107 | it->setPublishingEnabled(param.isPublishingEnabled()); |
108 | if (items & QOpcUaMonitoringParameters::Parameter::PublishingInterval) |
109 | it->setPublishingInterval(param.publishingInterval()); |
110 | if (items & QOpcUaMonitoringParameters::Parameter::LifetimeCount) |
111 | it->setLifetimeCount(param.lifetimeCount()); |
112 | if (items & QOpcUaMonitoringParameters::Parameter::MaxKeepAliveCount) |
113 | it->setMaxKeepAliveCount(param.maxKeepAliveCount()); |
114 | if (items & QOpcUaMonitoringParameters::Parameter::MaxNotificationsPerPublish) |
115 | it->setMaxNotificationsPerPublish(param.maxNotificationsPerPublish()); |
116 | if (items & QOpcUaMonitoringParameters::Parameter::Priority) |
117 | it->setPriority(param.priority()); |
118 | if (items & QOpcUaMonitoringParameters::Parameter::SamplingInterval) |
119 | it->setSamplingInterval(param.samplingInterval()); |
120 | if (items & QOpcUaMonitoringParameters::Parameter::Filter) { |
121 | if (param.filter().canConvert<QOpcUaMonitoringParameters::DataChangeFilter>()) |
122 | it->setFilter(param.filter().value<QOpcUaMonitoringParameters::DataChangeFilter>()); |
123 | else if (param.filter().canConvert<QOpcUaMonitoringParameters::EventFilter>()) |
124 | it->setFilter(param.filter().value<QOpcUaMonitoringParameters::EventFilter>()); |
125 | else if (param.filter().isNull()) |
126 | it->clearFilter(); |
127 | if (param.filterResult().canConvert<QOpcUaEventFilterResult>()) |
128 | it->setFilterResult(param.filterResult().value<QOpcUaEventFilterResult>()); |
129 | else if (param.filterResult().isNull()) |
130 | it->clearFilterResult(); |
131 | } |
132 | if (items & QOpcUaMonitoringParameters::Parameter::QueueSize) |
133 | it->setQueueSize(param.queueSize()); |
134 | if (items & QOpcUaMonitoringParameters::Parameter::DiscardOldest) |
135 | it->setDiscardOldest(param.discardOldest()); |
136 | if (items & QOpcUaMonitoringParameters::Parameter::MonitoringMode) |
137 | it->setMonitoringMode(param.monitoringMode()); |
138 | } |
139 | |
140 | Q_Q(QOpcUaNode); |
141 | emit q->monitoringStatusChanged(attr, items, statusCode: param.statusCode()); |
142 | }); |
143 | |
144 | |
145 | m_methodCallFinishedConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::methodCallFinished, |
146 | slot: [this](QString methodNodeId, QVariant result, QOpcUa::UaStatusCode statusCode) |
147 | { |
148 | Q_Q(QOpcUaNode); |
149 | emit q->methodCallFinished(methodNodeId, result, statusCode); |
150 | }); |
151 | |
152 | m_browseFinishedConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::browseFinished, |
153 | slot: [this](QList<QOpcUaReferenceDescription> children, QOpcUa::UaStatusCode statusCode) |
154 | { |
155 | Q_Q(QOpcUaNode); |
156 | emit q->browseFinished(children, statusCode); |
157 | }); |
158 | |
159 | m_resolveBrowsePathFinishedConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::resolveBrowsePathFinished, |
160 | slot: [this](QList<QOpcUaBrowsePathTarget> targets, QList<QOpcUaRelativePathElement> path, |
161 | QOpcUa::UaStatusCode statusCode) |
162 | { |
163 | Q_Q(QOpcUaNode); |
164 | emit q->resolveBrowsePathFinished(targets, path, statusCode); |
165 | }); |
166 | |
167 | m_eventOccurredConnection = QObject::connect(sender: impl, signal: &QOpcUaNodeImpl::eventOccurred, |
168 | slot: [this](QVariantList eventFields) |
169 | { |
170 | Q_Q(QOpcUaNode); |
171 | emit q->eventOccurred(eventFields); |
172 | }); |
173 | } |
174 | |
175 | ~QOpcUaNodePrivate() |
176 | { |
177 | QObject::disconnect(m_attributesReadConnection); |
178 | QObject::disconnect(m_attributeWrittenConnection); |
179 | QObject::disconnect(m_dataChangeOccurredConnection); |
180 | QObject::disconnect(m_monitoringEnableDisableConnection); |
181 | QObject::disconnect(m_monitoringStatusChangedConnection); |
182 | QObject::disconnect(m_methodCallFinishedConnection); |
183 | QObject::disconnect(m_browseFinishedConnection); |
184 | QObject::disconnect(m_resolveBrowsePathFinishedConnection); |
185 | QObject::disconnect(m_eventOccurredConnection); |
186 | |
187 | // Disable remaining monitorings |
188 | QOpcUa::NodeAttributes attr; |
189 | for (auto it = m_monitoringStatus.constBegin(); it != m_monitoringStatus.constEnd(); ++it) { |
190 | if (it->statusCode() == QOpcUa::UaStatusCode::Good) |
191 | attr |= it.key(); |
192 | } |
193 | if (attr != 0 && m_impl) { |
194 | m_impl->disableMonitoring(attr); |
195 | } |
196 | } |
197 | |
198 | QScopedPointer<QOpcUaNodeImpl> m_impl; |
199 | QPointer<QOpcUaClient> m_client; |
200 | |
201 | QHash<QOpcUa::NodeAttribute, QOpcUaReadResult> m_nodeAttributes; |
202 | QHash<QOpcUa::NodeAttribute, QOpcUaMonitoringParameters> m_monitoringStatus; |
203 | |
204 | QMetaObject::Connection m_attributesReadConnection; |
205 | QMetaObject::Connection m_attributeWrittenConnection; |
206 | QMetaObject::Connection m_dataChangeOccurredConnection; |
207 | QMetaObject::Connection m_monitoringEnableDisableConnection; |
208 | QMetaObject::Connection m_monitoringStatusChangedConnection; |
209 | QMetaObject::Connection m_methodCallFinishedConnection; |
210 | QMetaObject::Connection m_browseFinishedConnection; |
211 | QMetaObject::Connection m_resolveBrowsePathFinishedConnection; |
212 | QMetaObject::Connection m_eventOccurredConnection; |
213 | }; |
214 | |
215 | QT_END_NAMESPACE |
216 | |
217 | #endif // QOPCUANODE_P_H |
218 | |