1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2017 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtSerialBus module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL3$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or later as published by the Free |
28 | ** Software Foundation and appearing in the file LICENSE.GPL included in |
29 | ** the packaging of this file. Please review the following information to |
30 | ** ensure the GNU General Public License version 2.0 requirements will be |
31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
32 | ** |
33 | ** $QT_END_LICENSE$ |
34 | ** |
35 | ****************************************************************************/ |
36 | |
37 | #include <QtCore/qdebug.h> |
38 | #include <QtSerialBus/qmodbuspdu.h> |
39 | |
40 | #include <QtTest/QtTest> |
41 | |
42 | static QString s_msg; |
43 | static void myMessageHandler(QtMsgType, const QMessageLogContext &, const QString &msg) |
44 | { |
45 | s_msg = msg; |
46 | } |
47 | |
48 | class DebugHandler |
49 | { |
50 | public: |
51 | DebugHandler(QtMessageHandler newMessageHandler) |
52 | : oldMessageHandler(qInstallMessageHandler(newMessageHandler)) {} |
53 | ~DebugHandler() { |
54 | qInstallMessageHandler(oldMessageHandler); |
55 | } |
56 | private: |
57 | QtMessageHandler oldMessageHandler; |
58 | }; |
59 | |
60 | static int minimumDataSize(const QModbusPdu &pdu, bool request) |
61 | { |
62 | if (pdu.isException()) |
63 | return 1; |
64 | |
65 | switch (pdu.functionCode()) { |
66 | case QModbusPdu::ReadCoils: |
67 | case QModbusPdu::ReadDiscreteInputs: |
68 | return request ? 4 : 2; |
69 | case QModbusPdu::WriteSingleCoil: |
70 | case QModbusPdu::WriteSingleRegister: |
71 | return 4; |
72 | case QModbusPdu::ReadHoldingRegisters: |
73 | case QModbusPdu::ReadInputRegisters: |
74 | return request ? 4 : 3; |
75 | case QModbusPdu::ReadExceptionStatus: |
76 | return request ? 0 : 1; |
77 | case QModbusPdu::Diagnostics: |
78 | return 4; |
79 | case QModbusPdu::GetCommEventCounter: |
80 | return request ? 0 : 4; |
81 | case QModbusPdu::GetCommEventLog: |
82 | return request ? 0 : 8; |
83 | case QModbusPdu::WriteMultipleCoils: |
84 | return request ? 6 : 4; |
85 | case QModbusPdu::WriteMultipleRegisters: |
86 | return request ? 7 : 4; |
87 | case QModbusPdu::ReportServerId: |
88 | return request ? 0 : 3; |
89 | case QModbusPdu::ReadFileRecord: |
90 | return request ? 8 : 5; |
91 | case QModbusPdu::WriteFileRecord: |
92 | return 10; |
93 | case QModbusPdu::MaskWriteRegister: |
94 | return 6; |
95 | case QModbusPdu::ReadWriteMultipleRegisters: |
96 | return request ? 11 : 3; |
97 | case QModbusPdu::ReadFifoQueue: |
98 | return request ? 2 : 6; |
99 | case QModbusPdu::EncapsulatedInterfaceTransport: |
100 | return 2; |
101 | case QModbusPdu::Invalid: |
102 | case QModbusPdu::UndefinedFunctionCode: |
103 | return -1; |
104 | } |
105 | return -1; |
106 | } |
107 | |
108 | class tst_QModbusPdu : public QObject |
109 | { |
110 | Q_OBJECT |
111 | |
112 | private slots: |
113 | void testDefaultConstructor() |
114 | { |
115 | QModbusRequest request; |
116 | QCOMPARE(request.isValid(), false); |
117 | QCOMPARE(request.isException(), false); |
118 | QCOMPARE(request.functionCode(), QModbusRequest::FunctionCode(0x00)); |
119 | QCOMPARE(request.exceptionCode(), QModbusPdu::ExtendedException); |
120 | QCOMPARE(request.data().toHex(), QByteArray()); |
121 | |
122 | QModbusResponse response; |
123 | QCOMPARE(response.isValid(), false); |
124 | QCOMPARE(response.isException(), false); |
125 | QCOMPARE(response.functionCode(), QModbusResponse::FunctionCode(0x00)); |
126 | QCOMPARE(response.exceptionCode(), QModbusPdu::ExtendedException); |
127 | QCOMPARE(response.data().toHex(), QByteArray()); |
128 | |
129 | QModbusExceptionResponse exception; |
130 | QCOMPARE(exception.isValid(), false); |
131 | QCOMPARE(exception.isException(), false); |
132 | QCOMPARE(exception.exceptionCode(), QModbusPdu::ExtendedException); |
133 | QCOMPARE(exception.functionCode(), QModbusExceptionResponse::FunctionCode(0x00)); |
134 | QCOMPARE(exception.data().toHex(), QByteArray()); |
135 | } |
136 | |
137 | void testVaridicConstructor() |
138 | { |
139 | QModbusRequest request(QModbusRequest::ReportServerId); |
140 | QCOMPARE(request.isValid(), true); |
141 | QCOMPARE(request.isException(), false); |
142 | QCOMPARE(request.functionCode(), QModbusRequest::ReportServerId); |
143 | QCOMPARE(request.exceptionCode(), QModbusPdu::ExtendedException); |
144 | QCOMPARE(request.data().toHex(), QByteArray()); |
145 | |
146 | // Byte Count, Server ID, Run Indicator Status |
147 | QModbusResponse response(QModbusResponse::ReportServerId, quint8(0x02), quint8(0x01), |
148 | quint8(0xff)); |
149 | QCOMPARE(response.isValid(), true); |
150 | QCOMPARE(response.isException(), false); |
151 | QCOMPARE(response.functionCode(), QModbusResponse::ReportServerId); |
152 | QCOMPARE(response.exceptionCode(), QModbusPdu::ExtendedException); |
153 | QCOMPARE(response.data().toHex(), QByteArray("0201ff" )); |
154 | } |
155 | |
156 | void testQByteArrayConstructor() |
157 | { |
158 | QModbusRequest request(QModbusRequest::ReportServerId, QByteArray()); |
159 | QCOMPARE(request.isValid(), true); |
160 | QCOMPARE(request.isException(), false); |
161 | QCOMPARE(request.functionCode(), QModbusRequest::ReportServerId); |
162 | QCOMPARE(request.data().toHex(), QByteArray()); |
163 | |
164 | // Byte Count, Server ID, Run Indicator Status |
165 | QModbusResponse response(QModbusResponse::ReportServerId, QByteArray::fromHex(hexEncoded: "ff0102" )); |
166 | QCOMPARE(response.isValid(), true); |
167 | QCOMPARE(response.isException(), false); |
168 | QCOMPARE(response.functionCode(), QModbusResponse::ReportServerId); |
169 | QCOMPARE(response.data().toHex(), QByteArray("ff0102" )); |
170 | } |
171 | |
172 | void testCopyConstructorAndAssignment() |
173 | { |
174 | QModbusPdu pdu; |
175 | pdu.setFunctionCode(QModbusPdu::ReadCoils); |
176 | |
177 | QModbusRequest request(pdu); |
178 | QCOMPARE(request.functionCode(), QModbusResponse::ReadCoils); |
179 | |
180 | QModbusResponse response(pdu); |
181 | QCOMPARE(response.functionCode(), QModbusResponse::ReadCoils); |
182 | |
183 | pdu.setFunctionCode(QModbusPdu::WriteMultipleCoils); |
184 | |
185 | request = pdu; |
186 | QCOMPARE(request.functionCode(), QModbusResponse::WriteMultipleCoils); |
187 | |
188 | response = pdu; |
189 | QCOMPARE(response.functionCode(), QModbusResponse::WriteMultipleCoils); |
190 | } |
191 | |
192 | void testEncodeDecode() |
193 | { |
194 | QModbusRequest invalid; |
195 | quint8 data = 0xff; |
196 | invalid.decodeData(newData: &data); |
197 | QCOMPARE(data, quint8(0xff)); |
198 | invalid.encodeData(newData: data); |
199 | QCOMPARE(invalid.data().toHex(), QByteArray("ff" )); |
200 | |
201 | data = 0x00; |
202 | QModbusRequest request(QModbusRequest::ReportServerId); |
203 | request.decodeData(newData: &data); |
204 | QCOMPARE(data, quint8(0x00)); |
205 | QCOMPARE(request.data().toHex(), QByteArray()); |
206 | |
207 | QModbusResponse response(QModbusResponse::ReportServerId); |
208 | response.encodeData(newData: quint8(0x02), newData: quint8(0x01), newData: quint8(0xff)); |
209 | quint8 count = 0, id = 0, run = 0; |
210 | response.decodeData(newData: &count, newData: &id, newData: &run); |
211 | QCOMPARE(count, quint8(0x02)); |
212 | QCOMPARE(id, quint8(0x01)); |
213 | QCOMPARE(run, quint8(0xff)); |
214 | QCOMPARE(response.data().toHex(), QByteArray("0201ff" )); |
215 | |
216 | count = 0, id = 0, run = 0; |
217 | response = QModbusResponse(QModbusResponse::ReportServerId, QByteArray::fromHex(hexEncoded: "0201ff" )); |
218 | QCOMPARE(response.isValid(), true); |
219 | QCOMPARE(response.isException(), false); |
220 | QCOMPARE(response.functionCode(), QModbusResponse::ReportServerId); |
221 | QCOMPARE(response.data().toHex(), QByteArray("0201ff" )); |
222 | response.decodeData(newData: &count, newData: &id, newData: &run); |
223 | QCOMPARE(count, quint8(0x02)); |
224 | QCOMPARE(id, quint8(0x01)); |
225 | QCOMPARE(run, quint8(0xff)); |
226 | |
227 | QModbusRequest readCoils(QModbusRequest::ReadCoils); |
228 | // starting address and quantity of coils |
229 | readCoils.encodeData(newData: quint16(12), newData: quint16(10)); |
230 | quint16 address, quantity; |
231 | readCoils.decodeData(newData: &address, newData: &quantity); |
232 | QCOMPARE(address, quint16(0x0c)); |
233 | QCOMPARE(quantity, quint16(0x0a)); |
234 | |
235 | request = QModbusRequest(QModbusRequest::WriteMultipleCoils, |
236 | QByteArray::fromHex(hexEncoded: "0013000a02cd01" )); |
237 | QCOMPARE(request.data().toHex(), QByteArray("0013000a02cd01" )); |
238 | address = 0xffff, quantity = 0xffff; |
239 | quint8 bytes = 0xff, firstByte = 0xff, secondByte = 0xff; |
240 | request.decodeData(newData: &address, newData: &quantity, newData: &bytes, newData: &firstByte, newData: &secondByte); |
241 | QCOMPARE(address, quint16(19)); |
242 | QCOMPARE(quantity, quint16(10)); |
243 | QCOMPARE(bytes, quint8(2)); |
244 | QCOMPARE(firstByte, quint8(0xcd)); |
245 | QCOMPARE(secondByte, quint8(0x01)); |
246 | } |
247 | |
248 | void testQModbusExceptionResponsePdu() |
249 | { |
250 | QModbusExceptionResponse exception(QModbusExceptionResponse::ReportServerId, |
251 | QModbusExceptionResponse::ServerDeviceFailure); |
252 | QCOMPARE(exception.isValid(), true); |
253 | QCOMPARE(exception.isException(), true); |
254 | QCOMPARE(exception.functionCode(), QModbusExceptionResponse::ReportServerId); |
255 | QCOMPARE(exception.data().toHex(), QByteArray("04" )); |
256 | QCOMPARE(exception.exceptionCode(), QModbusExceptionResponse::ServerDeviceFailure); |
257 | |
258 | QModbusExceptionResponse response; |
259 | QCOMPARE(response.isValid(), false); |
260 | QCOMPARE(response.isException(), false); |
261 | QCOMPARE(response.functionCode(), QModbusExceptionResponse::Invalid); |
262 | |
263 | response.setFunctionCode(QModbusExceptionResponse::ReportServerId); |
264 | response.setExceptionCode(QModbusExceptionResponse::ServerDeviceFailure); |
265 | QCOMPARE(response.isValid(), true); |
266 | QCOMPARE(response.isException(), true); |
267 | QCOMPARE(response.functionCode(), QModbusExceptionResponse::ReportServerId); |
268 | QCOMPARE(response.data().toHex(), QByteArray("04" )); |
269 | QCOMPARE(exception.exceptionCode(), QModbusExceptionResponse::ServerDeviceFailure); |
270 | |
271 | QModbusPdu pdu; |
272 | pdu.setFunctionCode(QModbusExceptionResponse::FunctionCode(QModbusPdu::ReadCoils |
273 | | QModbusPdu::ExceptionByte)); |
274 | QCOMPARE(pdu.isException(), true); |
275 | QCOMPARE(pdu.functionCode(), QModbusPdu::ReadCoils); |
276 | |
277 | QModbusExceptionResponse exception2(pdu); |
278 | QCOMPARE(exception2.isException(), true); |
279 | QCOMPARE(exception2.functionCode(), QModbusPdu::ReadCoils); |
280 | QCOMPARE(exception2.exceptionCode(), QModbusExceptionResponse::ExtendedException); |
281 | exception2.setExceptionCode(QModbusExceptionResponse::IllegalFunction); |
282 | QCOMPARE(exception2.exceptionCode(), QModbusExceptionResponse::IllegalFunction); |
283 | |
284 | QModbusExceptionResponse exception3 = pdu; |
285 | QCOMPARE(exception3.isException(), true); |
286 | QCOMPARE(exception3.functionCode(), QModbusPdu::ReadCoils); |
287 | QCOMPARE(exception3.exceptionCode(), QModbusExceptionResponse::ExtendedException); |
288 | } |
289 | |
290 | void testQDebugStreamOperator() |
291 | { |
292 | DebugHandler mhs(myMessageHandler); |
293 | { |
294 | QDebug d = qDebug(); |
295 | d << QModbusPdu(); |
296 | d << QModbusRequest(); |
297 | d << QModbusResponse(); |
298 | d << QModbusExceptionResponse(); |
299 | } |
300 | QCOMPARE(s_msg, QString::fromLatin1("0x00 0x00 0x00 0x00" )); |
301 | |
302 | { |
303 | QDebug d = qDebug(); |
304 | d << QModbusRequest(QModbusRequest::ReadCoils, quint16(19), quint16(19)); |
305 | } |
306 | QCOMPARE(s_msg, QString::fromLatin1("0x0100130013" )); |
307 | |
308 | { |
309 | QDebug d = qDebug(); |
310 | d << QModbusResponse(QModbusResponse::ReadCoils, QByteArray::fromHex(hexEncoded: "03cd6b05" )); |
311 | } |
312 | QCOMPARE(s_msg, QString::fromLatin1("0x0103cd6b05" )); |
313 | |
314 | { |
315 | QDebug d = qDebug(); |
316 | d << QModbusExceptionResponse(QModbusExceptionResponse::ReadCoils, |
317 | QModbusExceptionResponse::IllegalDataAddress); |
318 | } |
319 | QCOMPARE(s_msg, QString::fromLatin1("0x8102" )); |
320 | } |
321 | |
322 | void testMinimumDataSize() |
323 | { |
324 | bool request = true; |
325 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadCoils), request), |
326 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadCoils))); |
327 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadDiscreteInputs), request), |
328 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadDiscreteInputs))); |
329 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteSingleCoil), request), |
330 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteSingleCoil))); |
331 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadHoldingRegisters), request), |
332 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadHoldingRegisters))); |
333 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadInputRegisters), request), |
334 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadInputRegisters))); |
335 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteSingleRegister), request), |
336 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteSingleRegister))); |
337 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadExceptionStatus), request), |
338 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadExceptionStatus))); |
339 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::Diagnostics), request), |
340 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::Diagnostics))); |
341 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::GetCommEventCounter), request), |
342 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::GetCommEventCounter))); |
343 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::GetCommEventLog), request), |
344 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::GetCommEventLog))); |
345 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteMultipleCoils), request), |
346 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteMultipleCoils))); |
347 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteMultipleRegisters), request), |
348 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteMultipleRegisters))); |
349 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReportServerId), request), |
350 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReportServerId))); |
351 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadFileRecord), request), |
352 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadFileRecord))); |
353 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteFileRecord), request), |
354 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteFileRecord))); |
355 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::MaskWriteRegister), request), |
356 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::MaskWriteRegister))); |
357 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadWriteMultipleRegisters), request), |
358 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadWriteMultipleRegisters))); |
359 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadFifoQueue), request), |
360 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadFifoQueue))); |
361 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::EncapsulatedInterfaceTransport), request), |
362 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::EncapsulatedInterfaceTransport))); |
363 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::Invalid), request), |
364 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::Invalid))); |
365 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::UndefinedFunctionCode), request), |
366 | QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::Invalid))); |
367 | |
368 | request = false; |
369 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadCoils), request), |
370 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadCoils))); |
371 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadDiscreteInputs), request), |
372 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadDiscreteInputs))); |
373 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteSingleCoil), request), |
374 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteSingleCoil))); |
375 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadHoldingRegisters), request), |
376 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadHoldingRegisters))); |
377 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadInputRegisters), request), |
378 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadInputRegisters))); |
379 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteSingleRegister), request), |
380 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteSingleRegister))); |
381 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadExceptionStatus), request), |
382 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadExceptionStatus))); |
383 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::Diagnostics), request), |
384 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::Diagnostics))); |
385 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::GetCommEventCounter), request), |
386 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::GetCommEventCounter))); |
387 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::GetCommEventLog), request), |
388 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::GetCommEventLog))); |
389 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteMultipleCoils), request), |
390 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteMultipleCoils))); |
391 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteMultipleRegisters), request), |
392 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteMultipleRegisters))); |
393 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReportServerId), request), |
394 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReportServerId))); |
395 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadFileRecord), request), |
396 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadFileRecord))); |
397 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteFileRecord), request), |
398 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteFileRecord))); |
399 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::MaskWriteRegister), request), |
400 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::MaskWriteRegister))); |
401 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadWriteMultipleRegisters), request), |
402 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadWriteMultipleRegisters))); |
403 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadFifoQueue), request), |
404 | QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadFifoQueue))); |
405 | QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::EncapsulatedInterfaceTransport), request), |
406 | QModbusResponse::minimumDataSize(QModbusRequest(QModbusPdu::EncapsulatedInterfaceTransport))); |
407 | QCOMPARE(minimumDataSize(QModbusResponse(QModbusPdu::Invalid), request), |
408 | QModbusRequest::minimumDataSize(QModbusResponse(QModbusPdu::Invalid))); |
409 | QCOMPARE(minimumDataSize(QModbusResponse(QModbusPdu::UndefinedFunctionCode), request), |
410 | QModbusRequest::minimumDataSize(QModbusResponse(QModbusPdu::Invalid))); |
411 | |
412 | QModbusExceptionResponse exception(QModbusResponse::ReadCoils, QModbusPdu::IllegalFunction); |
413 | QCOMPARE(minimumDataSize(exception, request), 1); |
414 | QCOMPARE(QModbusResponse::minimumDataSize(exception), 1); |
415 | } |
416 | |
417 | void testQModbusRequestStreamOperator_data() |
418 | { |
419 | QTest::addColumn<QModbusPdu::FunctionCode>(name: "fc" ); |
420 | QTest::addColumn<QByteArray>(name: "data" ); |
421 | QTest::addColumn<QByteArray>(name: "pdu" ); |
422 | |
423 | QTest::newRow(dataTag: "ReadCoils" ) << QModbusRequest::ReadCoils << QByteArray::fromHex(hexEncoded: "00130013" ) |
424 | << QByteArray::fromHex(hexEncoded: "0100130013" ); |
425 | QTest::newRow(dataTag: "ReadDiscreteInputs" ) << QModbusRequest::ReadDiscreteInputs |
426 | << QByteArray::fromHex(hexEncoded: "00c40016" ) << QByteArray::fromHex(hexEncoded: "0200c40016" ); |
427 | QTest::newRow(dataTag: "ReadHoldingRegisters" ) << QModbusRequest::ReadHoldingRegisters |
428 | << QByteArray::fromHex(hexEncoded: "006b0003" ) << QByteArray::fromHex(hexEncoded: "03006b0003" ); |
429 | QTest::newRow(dataTag: "ReadInputRegisters" ) << QModbusRequest::ReadInputRegisters |
430 | << QByteArray::fromHex(hexEncoded: "00080001" ) << QByteArray::fromHex(hexEncoded: "0400080001" ); |
431 | QTest::newRow(dataTag: "WriteSingleCoil" ) << QModbusRequest::WriteSingleCoil |
432 | << QByteArray::fromHex(hexEncoded: "00acff00" ) << QByteArray::fromHex(hexEncoded: "0500acff00" ); |
433 | QTest::newRow(dataTag: "WriteSingleRegister" ) << QModbusRequest::WriteSingleRegister |
434 | << QByteArray::fromHex(hexEncoded: "00010003" ) << QByteArray::fromHex(hexEncoded: "0600010003" ); |
435 | QTest::newRow(dataTag: "ReadExceptionStatus" ) << QModbusRequest::ReadExceptionStatus |
436 | << QByteArray() << QByteArray::fromHex(hexEncoded: "07" ); |
437 | QTest::newRow(dataTag: "Diagnostics" ) << QModbusRequest::Diagnostics |
438 | << QByteArray::fromHex(hexEncoded: "0000a537" ) << QByteArray::fromHex(hexEncoded: "080000a537" ); |
439 | QTest::newRow(dataTag: "GetCommEventCounter" ) << QModbusRequest::GetCommEventCounter |
440 | << QByteArray() << QByteArray::fromHex(hexEncoded: "0b" ); |
441 | QTest::newRow(dataTag: "GetCommEventLog" ) << QModbusRequest::GetCommEventLog |
442 | << QByteArray() << QByteArray::fromHex(hexEncoded: "0c" ); |
443 | QTest::newRow(dataTag: "WriteMultipleCoils" ) << QModbusRequest::WriteMultipleCoils |
444 | << QByteArray::fromHex(hexEncoded: "0013000a02cd01" ) << QByteArray::fromHex(hexEncoded: "0f0013000a02cd01" ); |
445 | QTest::newRow(dataTag: "WriteMultipleRegisters" ) << QModbusRequest::WriteMultipleRegisters |
446 | << QByteArray::fromHex(hexEncoded: "0001000204000a0102" ) << QByteArray::fromHex(hexEncoded: "100001000204000a0102" ); |
447 | QTest::newRow(dataTag: "ReportServerId" ) << QModbusRequest::ReportServerId |
448 | << QByteArray() << QByteArray::fromHex(hexEncoded: "11" ); |
449 | QTest::newRow(dataTag: "ReadFileRecord" ) << QModbusRequest::ReadFileRecord |
450 | << QByteArray::fromHex(hexEncoded: "0e0600040001000206000300090002" ) |
451 | << QByteArray::fromHex(hexEncoded: "140e0600040001000206000300090002" ); |
452 | QTest::newRow(dataTag: "WriteFileRecord" ) << QModbusRequest::WriteFileRecord |
453 | << QByteArray::fromHex(hexEncoded: "0d0600040007000306af04be100d" ) |
454 | << QByteArray::fromHex(hexEncoded: "150d0600040007000306af04be100d" ); |
455 | QTest::newRow(dataTag: "MaskWriteRegister" ) << QModbusRequest::MaskWriteRegister |
456 | << QByteArray::fromHex(hexEncoded: "000400f20025" ) << QByteArray::fromHex(hexEncoded: "16000400f20025" ); |
457 | QTest::newRow(dataTag: "ReadWriteMultipleRegisters" ) << QModbusRequest::ReadWriteMultipleRegisters |
458 | << QByteArray::fromHex(hexEncoded: "00030006000e00030600ff00ff00ff" ) |
459 | << QByteArray::fromHex(hexEncoded: "1700030006000e00030600ff00ff00ff" ); |
460 | QTest::newRow(dataTag: "ReadFifoQueue" ) << QModbusRequest::ReadFifoQueue |
461 | << QByteArray::fromHex(hexEncoded: "04de" ) << QByteArray::fromHex(hexEncoded: "1804de" ); |
462 | QTest::newRow(dataTag: "EncapsulatedInterfaceTransport" ) |
463 | << QModbusRequest::EncapsulatedInterfaceTransport |
464 | << QByteArray::fromHex(hexEncoded: "0e0100" ) << QByteArray::fromHex(hexEncoded: "2b0e0100" ); |
465 | } |
466 | |
467 | void testQModbusRequestStreamOperator() |
468 | { |
469 | QFETCH(QModbusPdu::FunctionCode, fc); |
470 | QFETCH(QByteArray, data); |
471 | QFETCH(QByteArray, pdu); |
472 | |
473 | QByteArray ba; |
474 | QDataStream output(&ba, QIODevice::WriteOnly); |
475 | output << QModbusRequest(fc, data); |
476 | QCOMPARE(ba, pdu); |
477 | |
478 | QModbusRequest request; |
479 | QDataStream input(pdu); |
480 | input >> request; |
481 | QCOMPARE(request.functionCode(), fc); |
482 | QCOMPARE(request.data(), data); |
483 | } |
484 | |
485 | void testQModbusResponseStreamOperator_data() |
486 | { |
487 | QTest::addColumn<QModbusPdu::FunctionCode>(name: "fc" ); |
488 | QTest::addColumn<QByteArray>(name: "data" ); |
489 | QTest::addColumn<QByteArray>(name: "pdu" ); |
490 | |
491 | QTest::newRow(dataTag: "ReadCoils" ) << QModbusResponse::ReadCoils << QByteArray::fromHex(hexEncoded: "03cd6b05" ) |
492 | << QByteArray::fromHex(hexEncoded: "0103cd6b05" ); |
493 | QTest::newRow(dataTag: "ReadDiscreteInputs" ) << QModbusResponse::ReadDiscreteInputs |
494 | << QByteArray::fromHex(hexEncoded: "03acdb35" ) << QByteArray::fromHex(hexEncoded: "0203acdb35" ); |
495 | QTest::newRow(dataTag: "ReadHoldingRegisters" ) << QModbusResponse::ReadHoldingRegisters |
496 | << QByteArray::fromHex(hexEncoded: "06022b00000064" ) << QByteArray::fromHex(hexEncoded: "0306022b00000064" ); |
497 | QTest::newRow(dataTag: "ReadInputRegisters" ) << QModbusResponse::ReadInputRegisters |
498 | << QByteArray::fromHex(hexEncoded: "02000a" ) << QByteArray::fromHex(hexEncoded: "0402000a" ); |
499 | QTest::newRow(dataTag: "WriteSingleCoil" ) << QModbusResponse::WriteSingleCoil |
500 | << QByteArray::fromHex(hexEncoded: "00acff00" ) << QByteArray::fromHex(hexEncoded: "0500acff00" ); |
501 | QTest::newRow(dataTag: "WriteSingleRegister" ) << QModbusResponse::WriteSingleRegister |
502 | << QByteArray::fromHex(hexEncoded: "00010003" ) << QByteArray::fromHex(hexEncoded: "0600010003" ); |
503 | QTest::newRow(dataTag: "ReadExceptionStatus" ) << QModbusResponse::ReadExceptionStatus |
504 | << QByteArray::fromHex(hexEncoded: "6d" ) << QByteArray::fromHex(hexEncoded: "076d" ); |
505 | QTest::newRow(dataTag: "Diagnostics" ) << QModbusResponse::Diagnostics |
506 | << QByteArray::fromHex(hexEncoded: "ffff0108" ) << QByteArray::fromHex(hexEncoded: "08ffff0108" ); |
507 | QTest::newRow(dataTag: "GetCommEventCounter" ) << QModbusResponse::GetCommEventCounter |
508 | << QByteArray::fromHex(hexEncoded: "ffff0108" ) << QByteArray::fromHex(hexEncoded: "0bffff0108" ); |
509 | QTest::newRow(dataTag: "GetCommEventLog" ) << QModbusResponse::GetCommEventLog |
510 | << QByteArray::fromHex(hexEncoded: "080000010801212000" ) << QByteArray::fromHex(hexEncoded: "0c080000010801212000" ); |
511 | QTest::newRow(dataTag: "WriteMultipleCoils" ) << QModbusResponse::WriteMultipleCoils |
512 | << QByteArray::fromHex(hexEncoded: "0013000a" ) << QByteArray::fromHex(hexEncoded: "0f0013000a" ); |
513 | QTest::newRow(dataTag: "WriteMultipleRegisters" ) << QModbusResponse::WriteMultipleRegisters |
514 | << QByteArray::fromHex(hexEncoded: "00010002" ) << QByteArray::fromHex(hexEncoded: "1000010002" ); |
515 | QTest::newRow(dataTag: "ReportServerId" ) << QModbusResponse::ReportServerId |
516 | << QByteArray::fromHex(hexEncoded: "030aff12" ) << QByteArray::fromHex(hexEncoded: "11030aff12" ); |
517 | QTest::newRow(dataTag: "ReadFileRecord" ) << QModbusResponse::ReadFileRecord |
518 | << QByteArray::fromHex(hexEncoded: "0c05060dfe0020050633cd0040" ) |
519 | << QByteArray::fromHex(hexEncoded: "140c05060dfe0020050633cd0040" ); |
520 | QTest::newRow(dataTag: "WriteFileRecord" ) << QModbusResponse::WriteFileRecord |
521 | << QByteArray::fromHex(hexEncoded: "0d0600040007000306af04be100d" ) |
522 | << QByteArray::fromHex(hexEncoded: "150d0600040007000306af04be100d" ); |
523 | QTest::newRow(dataTag: "MaskWriteRegister" ) << QModbusResponse::MaskWriteRegister |
524 | << QByteArray::fromHex(hexEncoded: "000400f20025" ) << QByteArray::fromHex(hexEncoded: "16000400f20025" ); |
525 | QTest::newRow(dataTag: "ReadWriteMultipleRegisters" ) << QModbusResponse::ReadWriteMultipleRegisters |
526 | << QByteArray::fromHex(hexEncoded: "0c00fe0acd00010003000d00ff" ) |
527 | << QByteArray::fromHex(hexEncoded: "170c00fe0acd00010003000d00ff" ); |
528 | QTest::newRow(dataTag: "ReadFifoQueue" ) << QModbusResponse::ReadFifoQueue |
529 | << QByteArray::fromHex(hexEncoded: "0006000201b81284" ) << QByteArray::fromHex(hexEncoded: "180006000201b81284" ); |
530 | QTest::newRow(dataTag: "EncapsulatedInterfaceTransport" ) |
531 | << QModbusResponse::EncapsulatedInterfaceTransport |
532 | << QByteArray::fromHex(hexEncoded: "0e01010000030016" ) + "Company identification" + |
533 | QByteArray::fromHex(hexEncoded: "010c" ) + "Product code" + QByteArray::fromHex(hexEncoded: "0205" ) + |
534 | "V2.11" |
535 | << QByteArray::fromHex(hexEncoded: "2b0e01010000030016" ) + "Company identification" + |
536 | QByteArray::fromHex(hexEncoded: "010c" ) + "Product code" + QByteArray::fromHex(hexEncoded: "0205" ) + |
537 | "V2.11" ; |
538 | |
539 | QModbusExceptionResponse ex(QModbusPdu::ReadCoils, QModbusPdu::IllegalDataAddress); |
540 | QTest::newRow(dataTag: "StreamExceptionResponse" ) |
541 | << QModbusPdu::FunctionCode(ex.functionCode() | QModbusPdu::ExceptionByte) |
542 | << QByteArray::fromHex(hexEncoded: "02" ) << QByteArray::fromHex(hexEncoded: "8102" ); |
543 | } |
544 | |
545 | void testQModbusResponseStreamOperator() |
546 | { |
547 | QFETCH(QModbusPdu::FunctionCode, fc); |
548 | QFETCH(QByteArray, data); |
549 | QFETCH(QByteArray, pdu); |
550 | |
551 | QByteArray ba; |
552 | QDataStream output(&ba, QIODevice::WriteOnly); |
553 | output << QModbusResponse(fc, data); |
554 | QCOMPARE(ba, pdu); |
555 | |
556 | QModbusResponse response; |
557 | QDataStream input(pdu); |
558 | input >> response; |
559 | if (response.isException()) |
560 | QCOMPARE(quint8(response.functionCode()), quint8(fc &~ QModbusPdu::ExceptionByte)); |
561 | else |
562 | QCOMPARE(response.functionCode(), fc); |
563 | QCOMPARE(response.data(), data); |
564 | } |
565 | |
566 | void testEncapsulatedInterfaceTransportStreamOperator() |
567 | { |
568 | const QByteArray valid = QByteArray::fromHex(hexEncoded: "0e01010000030016" ) + "Company identification" |
569 | + QByteArray::fromHex(hexEncoded: "010c" ) + "Product code" + QByteArray::fromHex(hexEncoded: "0205" ) |
570 | + "V2.11" ; |
571 | { |
572 | QByteArray ba; |
573 | QDataStream output(&ba, QIODevice::ReadWrite); |
574 | output << QModbusResponse(QModbusResponse::EncapsulatedInterfaceTransport, valid); |
575 | |
576 | QModbusResponse response; |
577 | QDataStream input(ba); |
578 | input >> response; |
579 | QCOMPARE(response.functionCode(), QModbusResponse::EncapsulatedInterfaceTransport); |
580 | QCOMPARE(response.data(), valid); |
581 | } |
582 | |
583 | // valid embedded |
584 | const QByteArray suffix = QByteArray::fromHex(hexEncoded: "ffffffffff" ); |
585 | { |
586 | QByteArray ba; |
587 | QDataStream output(&ba, QIODevice::ReadWrite); |
588 | output << QModbusResponse(QModbusResponse::EncapsulatedInterfaceTransport, valid |
589 | + suffix); |
590 | |
591 | QModbusResponse response; |
592 | QDataStream input(ba); |
593 | input >> response; |
594 | QCOMPARE(response.functionCode(), QModbusResponse::EncapsulatedInterfaceTransport); |
595 | QCOMPARE(response.data(), valid); |
596 | } |
597 | |
598 | const QByteArray invalid = QByteArray::fromHex(hexEncoded: "0e01010000030016" ) + "Company identification" |
599 | + QByteArray::fromHex(hexEncoded: "01ff" ) + "Product code" + QByteArray::fromHex(hexEncoded: "0205" ) |
600 | + "V2.11" ; |
601 | { |
602 | QByteArray ba; |
603 | QDataStream output(&ba, QIODevice::ReadWrite); |
604 | output << QModbusResponse(QModbusResponse::EncapsulatedInterfaceTransport, invalid); |
605 | |
606 | QModbusResponse response; |
607 | QDataStream input(ba); |
608 | input >> response; |
609 | QCOMPARE(response.functionCode(), QModbusResponse::Invalid); |
610 | QCOMPARE(response.data(), QByteArray()); |
611 | } |
612 | |
613 | const QByteArray invalidShort = QByteArray::fromHex(hexEncoded: "0e01010000030016" ) |
614 | + "Company identification" + QByteArray::fromHex(hexEncoded: "01" ); |
615 | { |
616 | QByteArray ba; |
617 | QDataStream output(&ba, QIODevice::ReadWrite); |
618 | output << QModbusResponse(QModbusResponse::EncapsulatedInterfaceTransport, invalidShort); |
619 | |
620 | QModbusResponse response; |
621 | QDataStream input(ba); |
622 | input >> response; |
623 | QCOMPARE(response.functionCode(), QModbusResponse::Invalid); |
624 | QCOMPARE(response.data(), QByteArray()); |
625 | } |
626 | } |
627 | |
628 | void testCalculateDataSize() |
629 | { |
630 | // CanOpenGeneralReference |
631 | QModbusResponse cogr(QModbusPdu::EncapsulatedInterfaceTransport, quint8(0x0d)); |
632 | QCOMPARE(QModbusResponse::calculateDataSize(cogr), -1); |
633 | cogr.encodeData(newData: quint8(0x0d), newData: quint8(0x00)); |
634 | QCOMPARE(QModbusResponse::calculateDataSize(cogr), 2); |
635 | // TODO: fix the following once we can calculate the size for CanOpenGeneralReference |
636 | cogr.encodeData(newData: quint8(0x0d), newData: quint8(0x00), newData: quint8(0x00)); |
637 | QCOMPARE(QModbusResponse::calculateDataSize(cogr), 2); |
638 | |
639 | // ReadDeviceIdentification |
640 | QModbusResponse rdi(QModbusPdu::EncapsulatedInterfaceTransport, quint8(0x0e)); |
641 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), -1); |
642 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01)); |
643 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
644 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01)); |
645 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
646 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00)); |
647 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
648 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00)); |
649 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
650 | |
651 | // single object |
652 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
653 | newData: quint8(0x01)); // object count |
654 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
655 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
656 | newData: quint8(0x01), |
657 | newData: quint8(0x00)); // object id |
658 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
659 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
660 | newData: quint8(0x01), |
661 | newData: quint8(0x00), newData: quint8(0x01)); // object size |
662 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 9); |
663 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
664 | newData: quint8(0x01), |
665 | newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff)); // object data |
666 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 9); |
667 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
668 | newData: quint8(0x01), |
669 | newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff), |
670 | newData: quint8(0xff)); // dummy additional data |
671 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 9); |
672 | |
673 | // multiple objects equal size |
674 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), newData: quint8(0x02), |
675 | newData: quint8(0x02)); // object count |
676 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
677 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), newData: quint8(0x02), |
678 | newData: quint8(0x02), |
679 | newData: quint8(0x00)); // object id |
680 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
681 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
682 | newData: quint8(0x02), |
683 | newData: quint8(0x00), newData: quint8(0x01)); // object size |
684 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 11); |
685 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
686 | newData: quint8(0x02), |
687 | newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff)); // object data |
688 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 11); |
689 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
690 | newData: quint8(0x02), |
691 | newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff), |
692 | newData: quint8(0x01)); // second object id |
693 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 11); |
694 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
695 | newData: quint8(0x02), |
696 | newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff), |
697 | newData: quint8(0x01), newData: quint8(0x01)); // second object size |
698 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 12); |
699 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
700 | newData: quint8(0x02), |
701 | newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff), |
702 | newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff)); // second object data |
703 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 12); |
704 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
705 | newData: quint8(0x02), |
706 | newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff), |
707 | newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), |
708 | newData: quint8(0xff)); // dummy additional data |
709 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 12); |
710 | |
711 | // multiple objects different size |
712 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), newData: quint8(0x02), |
713 | newData: quint8(0x03)); |
714 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
715 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), newData: quint8(0x02), |
716 | newData: quint8(0x03), |
717 | newData: quint8(0x00)); |
718 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8); |
719 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
720 | newData: quint8(0x03), |
721 | newData: quint8(0x00), newData: quint8(0x01)); |
722 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 13); |
723 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
724 | newData: quint8(0x03), |
725 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff)); |
726 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14); |
727 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
728 | newData: quint8(0x03), |
729 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff)); |
730 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14); |
731 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
732 | newData: quint8(0x03), |
733 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
734 | newData: quint8(0x01)); |
735 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14); |
736 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
737 | newData: quint8(0x03), |
738 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
739 | newData: quint8(0x01), newData: quint8(0x03)); |
740 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14); |
741 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
742 | newData: quint8(0x03), |
743 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
744 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff)); |
745 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14); |
746 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
747 | newData: quint8(0x03), |
748 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
749 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff)); |
750 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 17); |
751 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
752 | newData: quint8(0x03), |
753 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
754 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff)); |
755 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 17); |
756 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
757 | newData: quint8(0x03), |
758 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
759 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
760 | newData: quint8(0x02)); |
761 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 17); |
762 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
763 | newData: quint8(0x03), |
764 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
765 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
766 | newData: quint8(0x02), newData: quint8(0x05)); |
767 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22); |
768 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
769 | newData: quint8(0x03), |
770 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
771 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
772 | newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff)); |
773 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22); |
774 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
775 | newData: quint8(0x03), |
776 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
777 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
778 | newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff)); |
779 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22); |
780 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
781 | newData: quint8(0x03), |
782 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
783 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
784 | newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff)); |
785 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22); |
786 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
787 | newData: quint8(0x03), |
788 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
789 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
790 | newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff)); |
791 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22); |
792 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
793 | newData: quint8(0x03), |
794 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
795 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
796 | newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff)); |
797 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22); |
798 | rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00), |
799 | newData: quint8(0x03), |
800 | newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff), |
801 | newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
802 | newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), |
803 | newData: quint8(0xff)); // dummy additional data |
804 | QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22); |
805 | } |
806 | |
807 | void testCustomCalculator() |
808 | { |
809 | // request |
810 | QModbusRequest request(QModbusRequest::WriteSingleCoil); |
811 | request.encodeData(newData: quint8(0x00), newData: quint8(0xac), newData: quint8(0xff), newData: quint8(0x00)); |
812 | QCOMPARE(QModbusRequest::calculateDataSize(request), 4); |
813 | |
814 | QModbusRequest::registerDataSizeCalculator(fc: QModbusRequest::WriteSingleCoil, |
815 | func: [](const QModbusRequest &)->int { |
816 | return 15; |
817 | }); |
818 | QCOMPARE(QModbusRequest::calculateDataSize(request), 15); |
819 | |
820 | QModbusRequest::registerDataSizeCalculator(fc: QModbusRequest::WriteSingleCoil, func: nullptr); |
821 | QCOMPARE(QModbusRequest::calculateDataSize(request), 4); |
822 | |
823 | // response |
824 | QModbusResponse response(QModbusRequest::WriteSingleCoil); |
825 | response.encodeData(newData: quint8(0x00), newData: quint8(0xac), newData: quint8(0xff), newData: quint8(0x00)); |
826 | QCOMPARE(QModbusResponse::calculateDataSize(request), 4); |
827 | |
828 | QModbusResponse::registerDataSizeCalculator(fc: QModbusResponse::WriteSingleCoil, |
829 | func: [](const QModbusResponse &)->int { |
830 | return 15; |
831 | }); |
832 | QCOMPARE(QModbusResponse::calculateDataSize(response), 15); |
833 | |
834 | QModbusResponse::registerDataSizeCalculator(fc: QModbusResponse::WriteSingleCoil, func: nullptr); |
835 | QCOMPARE(QModbusResponse::calculateDataSize(response), 4); |
836 | |
837 | // custom |
838 | QModbusPdu::FunctionCode custom = QModbusPdu::FunctionCode(0x30); |
839 | request.setFunctionCode(custom); |
840 | QCOMPARE(QModbusRequest::calculateDataSize(request), -1); |
841 | |
842 | QModbusRequest::registerDataSizeCalculator(fc: custom, func: [](const QModbusRequest &)->int { |
843 | return 27; |
844 | }); |
845 | QCOMPARE(QModbusRequest::calculateDataSize(request), 27); |
846 | } |
847 | |
848 | void testCalculateLongDataSize() |
849 | { |
850 | QByteArray longData = QByteArray(128, ' '); |
851 | longData[0] = longData.size(); |
852 | const QModbusResponse response(QModbusResponse::ReadCoils, longData); |
853 | QCOMPARE(QModbusResponse::calculateDataSize(response), 1 + longData.size()); |
854 | |
855 | const QModbusRequest wfrRequest(QModbusPdu::WriteFileRecord, longData); |
856 | QCOMPARE(QModbusRequest::calculateDataSize(wfrRequest), 1 + longData.size()); |
857 | |
858 | longData = QByteArray(4 + 128, ' '); |
859 | longData[4] = char(128); |
860 | const QModbusRequest wmcRequest(QModbusPdu::WriteMultipleCoils, longData); |
861 | QCOMPARE(QModbusRequest::calculateDataSize(wmcRequest), 1 + longData.size()); |
862 | |
863 | const QModbusRequest wmrRequest(QModbusPdu::WriteMultipleRegisters, longData); |
864 | QCOMPARE(QModbusRequest::calculateDataSize(wmrRequest), 1 + longData.size()); |
865 | } |
866 | }; |
867 | |
868 | QTEST_MAIN(tst_QModbusPdu) |
869 | |
870 | #include "tst_qmodbuspdu.moc" |
871 | |