1// Copyright (C) 2021 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 "qopcuahistoryreadresponseimpl_p.h"
5
6QT_BEGIN_NAMESPACE
7
8quint64 QOpcUaHistoryReadResponseImpl::m_currentHandle = 0;
9
10QOpcUaHistoryReadResponseImpl::QOpcUaHistoryReadResponseImpl(const QOpcUaHistoryReadRawRequest &request)
11 : m_requestType(RequestType::ReadRaw)
12 , m_readRawRequest(request)
13 , m_handle(++m_currentHandle)
14{
15}
16
17QOpcUaHistoryReadResponseImpl::QOpcUaHistoryReadResponseImpl(const QOpcUaHistoryReadEventRequest &request)
18 : m_requestType(RequestType::ReadEvent)
19 , m_readEventRequest(request)
20 , m_handle(++m_currentHandle)
21{
22}
23
24QOpcUaHistoryReadResponseImpl::~QOpcUaHistoryReadResponseImpl()
25{
26 releaseContinuationPoints();
27}
28
29bool QOpcUaHistoryReadResponseImpl::hasMoreData() const
30{
31 return m_state == QOpcUaHistoryReadResponse::State::MoreDataAvailable;
32}
33
34bool QOpcUaHistoryReadResponseImpl::readMoreData()
35{
36 if (!hasMoreData())
37 return false;
38
39 if (m_requestType == RequestType::ReadRaw) {
40 const auto request = createReadRawRequestWithContinuationPoints();
41 emit historyReadRawRequested(request, continuationPoints: m_continuationPoints, releaseContinuationPoints: false, handle: handle());
42 return true;
43 } else if (m_requestType == RequestType::ReadEvent) {
44 const auto request = createEventRequestWithContinuationPoints();
45 emit historyReadEventsRequested(request, continuationPoints: m_continuationPoints, releaseContinuationPoints: false, handle: handle());
46 return true;
47 }
48
49 return false;
50}
51
52QOpcUaHistoryReadResponse::State QOpcUaHistoryReadResponseImpl::state() const
53{
54 return m_state;
55}
56
57bool QOpcUaHistoryReadResponseImpl::releaseContinuationPoints()
58{
59 if (m_requestType == RequestType::ReadRaw) {
60 const auto request = createReadRawRequestWithContinuationPoints();
61
62 if (!request.nodesToRead().isEmpty())
63 emit historyReadRawRequested(request, continuationPoints: m_continuationPoints, releaseContinuationPoints: true, handle: handle());
64
65 m_continuationPoints.clear();
66
67 setState(QOpcUaHistoryReadResponse::State::Finished);
68 } else if (m_requestType == RequestType::ReadEvent) {
69 const auto request = createEventRequestWithContinuationPoints();
70
71 if (!request.nodesToRead().isEmpty())
72 emit historyReadEventsRequested(request, continuationPoints: m_continuationPoints, releaseContinuationPoints: true, handle: handle());
73
74 m_continuationPoints.clear();
75
76 setState(QOpcUaHistoryReadResponse::State::Finished);
77 };
78
79 return true;
80}
81
82QList<QOpcUaHistoryData> QOpcUaHistoryReadResponseImpl::data() const
83{
84 return m_data;
85}
86
87QList<QOpcUaHistoryEvent> QOpcUaHistoryReadResponseImpl::events() const
88{
89 return m_events;
90}
91
92QOpcUa::UaStatusCode QOpcUaHistoryReadResponseImpl::serviceResult() const
93{
94 return m_serviceResult;
95}
96
97void QOpcUaHistoryReadResponseImpl::handleDataAvailable(const QList<QOpcUaHistoryData> &data, const QList<QByteArray> &continuationPoints,
98 QOpcUa::UaStatusCode serviceResult, quint64 responseHandle)
99{
100 if (responseHandle != handle())
101 return;
102
103 m_serviceResult = serviceResult;
104 m_continuationPoints = continuationPoints;
105
106 if (m_data.empty()) {
107 m_data = data;
108 } else {
109 int index = 0;
110 for (const auto &result : data) {
111 auto &target = m_data[m_dataMapping.at(i: index++)];
112 target.setStatusCode(result.statusCode());
113 for (const auto &value : result.result()) {
114 target.addValue(value);
115 }
116 }
117 }
118
119 bool found = false;
120 for (const auto &continuationPoint : m_continuationPoints) {
121 if (!continuationPoint.isEmpty()) {
122 setState(QOpcUaHistoryReadResponse::State::MoreDataAvailable);
123 found = true;
124 break;
125 }
126 }
127
128 if (!found)
129 setState(QOpcUaHistoryReadResponse::State::Finished);
130
131 emit readHistoryDataFinished(results: m_data, serviceResult: m_serviceResult);
132}
133
134void QOpcUaHistoryReadResponseImpl::handleEventsAvailable(const QList<QOpcUaHistoryEvent> &data, const QList<QByteArray> &continuationPoints,
135 QOpcUa::UaStatusCode serviceResult, quint64 responseHandle)
136{
137 if (responseHandle != handle())
138 return;
139
140 m_serviceResult = serviceResult;
141 m_continuationPoints = continuationPoints;
142
143 if (m_events.empty()) {
144 m_events = data;
145 } else {
146 int index = 0;
147 for (const auto &result : data) {
148 auto &target = m_events[m_dataMapping.at(i: index++)];
149 target.setStatusCode(result.statusCode());
150 for (const auto &event : result.events()) {
151 target.addEvent(value: event);
152 }
153 }
154 }
155
156 bool found = false;
157 for (const auto &continuationPoint : m_continuationPoints) {
158 if (!continuationPoint.isEmpty()) {
159 setState(QOpcUaHistoryReadResponse::State::MoreDataAvailable);
160 found = true;
161 break;
162 }
163 }
164
165 if (!found)
166 setState(QOpcUaHistoryReadResponse::State::Finished);
167
168 emit readHistoryEventsFinished(results: m_events, serviceResult: m_serviceResult);
169}
170
171void QOpcUaHistoryReadResponseImpl::handleRequestError(quint64 requestHandle)
172{
173 if (requestHandle == handle())
174 setState(QOpcUaHistoryReadResponse::State::Error);
175}
176
177quint64 QOpcUaHistoryReadResponseImpl::handle() const
178{
179 return m_handle;
180}
181
182void QOpcUaHistoryReadResponseImpl::setState(QOpcUaHistoryReadResponse::State state)
183{
184 if (m_state != state) {
185 m_state = state;
186 emit stateChanged(state);
187 }
188}
189
190QOpcUaHistoryReadRawRequest QOpcUaHistoryReadResponseImpl::createReadRawRequestWithContinuationPoints()
191{
192 QOpcUaHistoryReadRawRequest request;
193 request.setStartTimestamp(m_readRawRequest.startTimestamp());
194 request.setEndTimestamp(m_readRawRequest.endTimestamp());
195 request.setNumValuesPerNode(m_readRawRequest.numValuesPerNode());
196 request.setReturnBounds(m_readRawRequest.returnBounds());
197 request.setTimestampsToReturn(m_readRawRequest.timestampsToReturn());
198
199 int arrayIndex = 0;
200 QList<int> newDataMapping;
201 QList<QByteArray> newContinuationPoints;
202
203 for (const auto &continuationPoint : m_continuationPoints) {
204 int mappingIndex = 0;
205 if (m_dataMapping.empty())
206 mappingIndex = arrayIndex;
207 else
208 mappingIndex = m_dataMapping.at(i: arrayIndex);
209
210 if (!continuationPoint.isEmpty()) {
211 newDataMapping.push_back(t: mappingIndex);
212 newContinuationPoints.push_back(t: continuationPoint);
213 request.addNodeToRead(nodeToRead: m_readRawRequest.nodesToRead().at(i: mappingIndex));
214 }
215
216 ++arrayIndex;
217 }
218
219 m_dataMapping = newDataMapping;
220 m_continuationPoints = newContinuationPoints;
221
222 return request;
223}
224
225QOpcUaHistoryReadEventRequest QOpcUaHistoryReadResponseImpl::createEventRequestWithContinuationPoints()
226{
227 QOpcUaHistoryReadEventRequest request;
228 request.setStartTimestamp(m_readEventRequest.startTimestamp());
229 request.setEndTimestamp(m_readEventRequest.endTimestamp());
230 request.setNumValuesPerNode(m_readEventRequest.numValuesPerNode());
231 request.setFilter(m_readEventRequest.filter());
232
233 int arrayIndex = 0;
234 QList<int> newDataMapping;
235 QList<QByteArray> newContinuationPoints;
236
237 for (const auto &continuationPoint : m_continuationPoints) {
238 int mappingIndex = 0;
239 if (m_dataMapping.empty())
240 mappingIndex = arrayIndex;
241 else
242 mappingIndex = m_dataMapping.at(i: arrayIndex);
243
244 if (!continuationPoint.isEmpty()) {
245 newDataMapping.push_back(t: mappingIndex);
246 newContinuationPoints.push_back(t: continuationPoint);
247 request.addNodeToRead(nodeToRead: m_readEventRequest.nodesToRead().at(i: mappingIndex));
248 }
249
250 ++arrayIndex;
251 }
252
253 m_dataMapping = newDataMapping;
254 m_continuationPoints = newContinuationPoints;
255
256 return request;
257}
258
259QT_END_NAMESPACE
260

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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