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#include <array>
29
30QT_BEGIN_NAMESPACE
31
32class QOpcUaNodePrivate : public QObjectPrivate
33{
34 Q_DECLARE_PUBLIC(QOpcUaNode)
35
36public:
37 QOpcUaNodePrivate(QOpcUaNodeImpl *impl, QOpcUaClient *client)
38 : m_impl(impl)
39 , m_client(client)
40 {
41 }
42
43 void createConnections()
44 {
45 Q_Q(QOpcUaNode);
46
47 size_t index = 0;
48 m_connections[index++] = QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::attributesRead,
49 context: q, slot: [this](QList<QOpcUaReadResult> attr, QOpcUa::UaStatusCode serviceResult)
50 {
51 handleAttributesRead(attr, serviceResult);
52 });
53
54 m_connections[index++] = QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::attributeWritten,
55 context: q, slot: [this](QOpcUa::NodeAttribute attr, QVariant value, QOpcUa::UaStatusCode statusCode)
56 {
57 handleAttributesWritten(attr, value, statusCode);
58 });
59
60 m_connections[index++] = QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::dataChangeOccurred,
61 context: q, slot: [this](QOpcUa::NodeAttribute attr, QOpcUaReadResult value)
62 {
63 this->m_nodeAttributes[attr] = value;
64 Q_Q(QOpcUaNode);
65 emit q->dataChangeOccurred(attr, value: value.value());
66 emit q->attributeUpdated(attr, value: value.value());
67
68 if (attr == QOpcUa::NodeAttribute::Value)
69 emit q->valueAttributeUpdated(value: value.value());
70 });
71
72 m_connections[index++] = QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::monitoringEnableDisable,
73 context: q, slot: [this](QOpcUa::NodeAttribute attr, bool subscribe, QOpcUaMonitoringParameters status)
74 {
75 handleMonitoringEnableDisable(attr, subscribe, status);
76 });
77
78 m_connections[index++] = QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::monitoringStatusChanged,
79 context: q, slot: [this](QOpcUa::NodeAttribute attr, QOpcUaMonitoringParameters::Parameters items, QOpcUaMonitoringParameters param)
80 {
81 handleMonitoringStatusChange(attr, items, param);
82 });
83
84 m_connections[index++] =
85 QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::methodCallFinished, context: q,
86 slot: &QOpcUaNode::methodCallFinished);
87
88 m_connections[index++] = QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::browseFinished,
89 context: q, slot: &QOpcUaNode::browseFinished);
90
91 m_connections[index++] =
92 QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::resolveBrowsePathFinished, context: q,
93 slot: &QOpcUaNode::resolveBrowsePathFinished);
94
95 m_connections[index++] = QObject::connect(sender: m_impl.get(), signal: &QOpcUaNodeImpl::eventOccurred,
96 context: q, slot: &QOpcUaNode::eventOccurred);
97
98 Q_ASSERT(index == m_connections.size());
99 }
100
101 ~QOpcUaNodePrivate()
102 {
103 for (auto &c : m_connections)
104 QObject::disconnect(c);
105
106 // Disable remaining monitorings
107 QOpcUa::NodeAttributes attr;
108 for (auto it = m_monitoringStatus.constBegin(); it != m_monitoringStatus.constEnd(); ++it) {
109 if (it->statusCode() == QOpcUa::UaStatusCode::Good)
110 attr |= it.key();
111 }
112 if (attr != 0 && m_impl) {
113 m_impl->disableMonitoring(attr);
114 }
115 }
116
117 void handleAttributesRead(const QList<QOpcUaReadResult> &attr,
118 QOpcUa::UaStatusCode serviceResult)
119 {
120 QOpcUa::NodeAttributes updatedAttributes;
121 Q_Q(QOpcUaNode);
122
123 for (auto &entry : std::as_const(t: attr)) {
124 if (serviceResult == QOpcUa::UaStatusCode::Good)
125 m_nodeAttributes.insert(key: entry.attribute(), value: entry);
126 else {
127 QOpcUaReadResult temp = entry;
128 temp.setStatusCode(serviceResult);
129 temp.setValue(QVariant());
130 m_nodeAttributes.insert(key: entry.attribute(), value: temp);
131 }
132
133 updatedAttributes |= entry.attribute();
134 emit q->attributeUpdated(attr: entry.attribute(), value: entry.value());
135
136 if (entry.attribute() == QOpcUa::NodeAttribute::Value)
137 emit q->valueAttributeUpdated(value: entry.value());
138 }
139
140 emit q->attributeRead(attributes: updatedAttributes);
141 }
142
143 void handleAttributesWritten(QOpcUa::NodeAttribute attr, const QVariant &value,
144 QOpcUa::UaStatusCode statusCode)
145 {
146 m_nodeAttributes[attr].setStatusCode(statusCode);
147 Q_Q(QOpcUaNode);
148
149 if (statusCode == QOpcUa::UaStatusCode::Good) {
150 m_nodeAttributes[attr].setValue(value);
151 emit q->attributeUpdated(attr, value);
152
153 if (attr == QOpcUa::NodeAttribute::Value)
154 emit q->valueAttributeUpdated(value);
155 }
156
157 emit q->attributeWritten(attribute: attr, statusCode);
158 }
159
160 void handleMonitoringEnableDisable(QOpcUa::NodeAttribute attr, bool subscribe,
161 const QOpcUaMonitoringParameters &status)
162 {
163 if (subscribe == true) {
164 if (status.statusCode() != QOpcUa::UaStatusCode::BadEntryExists) // Don't overwrite a valid entry
165 m_monitoringStatus.insert(key: attr, value: status);
166 Q_Q(QOpcUaNode);
167 emit q->enableMonitoringFinished(attr, statusCode: status.statusCode());
168 }
169 else {
170 m_monitoringStatus.remove(key: attr);
171 Q_Q(QOpcUaNode);
172 emit q->disableMonitoringFinished(attr, statusCode: status.statusCode());
173 }
174 }
175
176 void handleMonitoringStatusChange(QOpcUa::NodeAttribute attr,
177 QOpcUaMonitoringParameters::Parameters items,
178 const QOpcUaMonitoringParameters &param)
179 {
180 auto it = m_monitoringStatus.find(key: attr);
181 if (param.statusCode() == QOpcUa::UaStatusCode::Good && it != m_monitoringStatus.end()) {
182 if (items & QOpcUaMonitoringParameters::Parameter::PublishingEnabled)
183 it->setPublishingEnabled(param.isPublishingEnabled());
184 if (items & QOpcUaMonitoringParameters::Parameter::PublishingInterval)
185 it->setPublishingInterval(param.publishingInterval());
186 if (items & QOpcUaMonitoringParameters::Parameter::LifetimeCount)
187 it->setLifetimeCount(param.lifetimeCount());
188 if (items & QOpcUaMonitoringParameters::Parameter::MaxKeepAliveCount)
189 it->setMaxKeepAliveCount(param.maxKeepAliveCount());
190 if (items & QOpcUaMonitoringParameters::Parameter::MaxNotificationsPerPublish)
191 it->setMaxNotificationsPerPublish(param.maxNotificationsPerPublish());
192 if (items & QOpcUaMonitoringParameters::Parameter::Priority)
193 it->setPriority(param.priority());
194 if (items & QOpcUaMonitoringParameters::Parameter::SamplingInterval)
195 it->setSamplingInterval(param.samplingInterval());
196 if (items & QOpcUaMonitoringParameters::Parameter::Filter) {
197 if (param.filter().canConvert<QOpcUaMonitoringParameters::DataChangeFilter>())
198 it->setFilter(param.filter().value<QOpcUaMonitoringParameters::DataChangeFilter>());
199 else if (param.filter().canConvert<QOpcUaMonitoringParameters::EventFilter>())
200 it->setFilter(param.filter().value<QOpcUaMonitoringParameters::EventFilter>());
201 else if (param.filter().isNull())
202 it->clearFilter();
203 if (param.filterResult().canConvert<QOpcUaEventFilterResult>())
204 it->setFilterResult(param.filterResult().value<QOpcUaEventFilterResult>());
205 else if (param.filterResult().isNull())
206 it->clearFilterResult();
207 }
208 if (items & QOpcUaMonitoringParameters::Parameter::QueueSize)
209 it->setQueueSize(param.queueSize());
210 if (items & QOpcUaMonitoringParameters::Parameter::DiscardOldest)
211 it->setDiscardOldest(param.discardOldest());
212 if (items & QOpcUaMonitoringParameters::Parameter::MonitoringMode)
213 it->setMonitoringMode(param.monitoringMode());
214 if (items & QOpcUaMonitoringParameters::Parameter::TriggeredItemIds) {
215 it->setTriggeredItemIds(param.triggeredItemIds());
216 it->setFailedTriggeredItemsStatus(param.failedTriggeredItemsStatus());
217 }
218 }
219
220 Q_Q(QOpcUaNode);
221 emit q->monitoringStatusChanged(attr, items, statusCode: param.statusCode());
222 }
223
224 QScopedPointer<QOpcUaNodeImpl> m_impl;
225 QPointer<QOpcUaClient> m_client;
226
227 QHash<QOpcUa::NodeAttribute, QOpcUaReadResult> m_nodeAttributes;
228 QHash<QOpcUa::NodeAttribute, QOpcUaMonitoringParameters> m_monitoringStatus;
229
230 std::array<QMetaObject::Connection, 9> m_connections;
231};
232
233QT_END_NAMESPACE
234
235#endif // QOPCUANODE_P_H
236

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtopcua/src/opcua/client/qopcuanode_p.h