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 #ifndef QMODBUSCLIENT_P_H
38 #define QMODBUSCLIENT_P_H
39 
40 #include <QtCore/qtimer.h>
41 #include <QtSerialBus/qmodbusclient.h>
42 #include <QtSerialBus/qmodbuspdu.h>
43 
44 #include <private/qmodbusdevice_p.h>
45 
46 //
47 //  W A R N I N G
48 //  -------------
49 //
50 // This file is not part of the Qt API. It exists purely as an
51 // implementation detail. This header file may change from version to
52 // version without notice, or even be removed.
53 //
54 // We mean it.
55 //
56 
57 QT_BEGIN_NAMESPACE
58 
59 class Q_AUTOTEST_EXPORT QModbusClientPrivate : public QModbusDevicePrivate
60 {
61     Q_DECLARE_PUBLIC(QModbusClient)
62 
63 public:
64     QModbusReply *sendRequest(const QModbusRequest &request, int serverAddress,
65                               const QModbusDataUnit *const unit);
66     QModbusRequest createReadRequest(const QModbusDataUnit &data) const;
67     QModbusRequest createWriteRequest(const QModbusDataUnit &data) const;
68     QModbusRequest createRWRequest(const QModbusDataUnit &read, const QModbusDataUnit &write) const;
69 
70     bool processResponse(const QModbusResponse &response, QModbusDataUnit *data);
71 
72     bool processReadCoilsResponse(const QModbusResponse &response, QModbusDataUnit *data);
73     bool processReadDiscreteInputsResponse(const QModbusResponse &response, QModbusDataUnit *data);
74     bool collateBits(const QModbusPdu &pdu, QModbusDataUnit::RegisterType type, QModbusDataUnit *data);
75 
76     bool processReadHoldingRegistersResponse(const QModbusResponse &response, QModbusDataUnit *data);
77     bool processReadInputRegistersResponse(const QModbusResponse &response, QModbusDataUnit *data);
78     bool collateBytes(const QModbusPdu &pdu, QModbusDataUnit::RegisterType type, QModbusDataUnit *data);
79 
80     bool processWriteSingleCoilResponse(const QModbusResponse &response, QModbusDataUnit *data);
81     bool processWriteSingleRegisterResponse(const QModbusResponse &response,
82                                             QModbusDataUnit *data);
83     bool collateSingleValue(const QModbusPdu &pdu, QModbusDataUnit::RegisterType type,
84                          QModbusDataUnit *data);
85 
86     bool processWriteMultipleCoilsResponse(const QModbusResponse &response, QModbusDataUnit *data);
87     bool processWriteMultipleRegistersResponse(const QModbusResponse &response,
88                                                QModbusDataUnit *data);
89     bool collateMultipleValues(const QModbusPdu &pdu, QModbusDataUnit::RegisterType type,
90                           QModbusDataUnit *data);
91 
92     bool processReadWriteMultipleRegistersResponse(const QModbusResponse &response,
93                                                   QModbusDataUnit *data);
94 
enqueueRequest(const QModbusRequest &,int,const QModbusDataUnit &,QModbusReply::ReplyType)95     virtual QModbusReply *enqueueRequest(const QModbusRequest &, int, const QModbusDataUnit &,
96                                          QModbusReply::ReplyType) {
97         return nullptr;
98     }
99     // TODO: Review once we have a transport layer in place.
isOpen()100     virtual bool isOpen() const { return false; }
101 
102     int m_numberOfRetries = 3;
103     int m_responseTimeoutDuration = 1000;
104 
105     struct QueueElement {
106         QueueElement() = default;
107         QueueElement(QModbusReply *r, const QModbusRequest &req, const QModbusDataUnit &u, int num,
108                 int timeout = -1)
replyQueueElement109             : reply(r), requestPdu(req), unit(u), numberOfRetries(num)
110         {
111             if (timeout >= 0) {
112                 // always the case for TCP
113                 timer = QSharedPointer<QTimer>::create();
114                 timer->setSingleShot(true);
115                 timer->setInterval(timeout);
116             }
117         }
118         bool operator==(const QueueElement &other) const {
119             return reply == other.reply;
120         }
121 
122         QPointer<QModbusReply> reply;
123         QModbusRequest requestPdu;
124         QModbusDataUnit unit;
125         int numberOfRetries;
126         QSharedPointer<QTimer> timer;
127         QByteArray adu;
128         qint64 bytesWritten = 0;
129         qint32 m_timerId = INT_MIN;
130     };
131     void processQueueElement(const QModbusResponse &pdu, const QueueElement &element);
132 };
133 
134 QT_END_NAMESPACE
135 
136 #endif // QMODBUSCLIENT_P_H
137 
138