Warning: That file was not part of the compilation database. It may have many parsing errors.

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#ifndef QMODBUSPDU_H
37#define QMODBUSPDU_H
38
39#include <QtCore/qdatastream.h>
40#include <QtCore/qmetatype.h>
41#include <QtCore/qvector.h>
42#include <QtSerialBus/qtserialbusglobal.h>
43
44QT_BEGIN_NAMESPACE
45
46class QModbusPdu
47{
48public:
49 enum ExceptionCode {
50 IllegalFunction = 0x01,
51 IllegalDataAddress = 0x02,
52 IllegalDataValue = 0x03,
53 ServerDeviceFailure = 0x04,
54 Acknowledge = 0x05,
55 ServerDeviceBusy = 0x06,
56 NegativeAcknowledge = 0x07,
57 MemoryParityError = 0x08,
58 GatewayPathUnavailable = 0x0A,
59 GatewayTargetDeviceFailedToRespond = 0x0B,
60 ExtendedException = 0xFF,
61 };
62
63 enum FunctionCode {
64 Invalid = 0x00,
65 ReadCoils = 0x01,
66 ReadDiscreteInputs = 0x02,
67 ReadHoldingRegisters = 0x03,
68 ReadInputRegisters = 0x04,
69 WriteSingleCoil = 0x05,
70 WriteSingleRegister = 0x06,
71 ReadExceptionStatus = 0x07,
72 Diagnostics = 0x08,
73 GetCommEventCounter = 0x0B,
74 GetCommEventLog = 0x0C,
75 WriteMultipleCoils = 0x0F,
76 WriteMultipleRegisters = 0x10,
77 ReportServerId = 0x11,
78 ReadFileRecord = 0x14,
79 WriteFileRecord = 0x15,
80 MaskWriteRegister = 0x16,
81 ReadWriteMultipleRegisters = 0x17,
82 ReadFifoQueue = 0x18,
83 EncapsulatedInterfaceTransport = 0x2B,
84 UndefinedFunctionCode = 0x100
85 };
86
87 QModbusPdu() = default;
88 virtual ~QModbusPdu() = default;
89
90 bool isValid() const {
91 return (m_code >= ReadCoils && m_code < UndefinedFunctionCode)
92 && (m_data.size() < 253);
93 }
94
95 static const quint8 ExceptionByte = 0x80;
96 ExceptionCode exceptionCode() const {
97 if (!m_data.size() || !isException())
98 return ExtendedException;
99 return static_cast<ExceptionCode>(m_data.at(i: 0));
100 }
101 bool isException() const { return m_code & ExceptionByte; }
102
103 qint16 size() const { return dataSize() + 1; }
104 qint16 dataSize() const { return qint16(m_data.size()); }
105
106 FunctionCode functionCode() const {
107 return FunctionCode(quint8(m_code) &~ ExceptionByte);
108 }
109 virtual void setFunctionCode(FunctionCode code) { m_code = code; }
110
111 QByteArray data() const { return m_data; }
112 void setData(const QByteArray &newData) { m_data = newData; }
113
114 template <typename ... Args> void encodeData(Args ... newData) {
115 encode(std::forward<Args>(newData)...);
116 }
117
118 template <typename ... Args> void decodeData(Args && ... newData) const {
119 decode(std::forward<Args>(newData)...);
120 }
121
122protected:
123 QModbusPdu(FunctionCode code, const QByteArray &newData)
124 : m_code(code)
125 , m_data(newData)
126 {}
127
128 QModbusPdu(const QModbusPdu &) = default;
129 QModbusPdu &operator=(const QModbusPdu &) = default;
130
131 template <typename ... Args>
132 QModbusPdu(FunctionCode code, Args ... newData)
133 : m_code(code)
134 {
135 encode(std::forward<Args>(newData)...);
136 }
137
138private:
139 template <typename T, typename ... Ts> struct IsType { enum { value = false }; };
140 template <typename T, typename T1, typename ... Ts> struct IsType<T, T1, Ts...> {
141 enum { value = std::is_same<T, T1>::value || IsType<T, Ts...>::value };
142 };
143
144 template <typename T>
145 using is_pod = std::integral_constant<bool, std::is_trivial<T>::value && std::is_standard_layout<T>::value>;
146
147 template <typename T> void encode(QDataStream *stream, const T &t) {
148 static_assert(is_pod<T>::value, "Only POD types supported.");
149 static_assert(IsType<T, quint8, quint16>::value, "Only quint8 and quint16 supported.");
150 (*stream) << t;
151 }
152 template <typename T> void decode(QDataStream *stream, T &t) const {
153 static_assert(is_pod<T>::value, "Only POD types supported.");
154 static_assert(IsType<T, quint8 *, quint16 *>::value, "Only quint8* and quint16* supported.");
155 (*stream) >> *t;
156 }
157 template <typename T> void encode(QDataStream *stream, const QVector<T> &vector) {
158 static_assert(is_pod<T>::value, "Only POD types supported.");
159 static_assert(IsType<T, quint8, quint16>::value, "Only quint8 and quint16 supported.");
160 for (int i = 0; i < vector.count(); ++i)
161 (*stream) << vector[i];
162 }
163
164 template<typename ... Args> void encode(Args ... newData) {
165 m_data.clear();
166 Q_CONSTEXPR quint32 argCount = sizeof...(Args);
167 if (argCount > 0) {
168 QDataStream stream(&m_data, QIODevice::WriteOnly);
169 char tmp[argCount] = { (encode(&stream, newData), void(), '0')... };
170 Q_UNUSED(tmp)
171 }
172 }
173 template<typename ... Args> void decode(Args ... newData) const {
174 Q_CONSTEXPR quint32 argCount = sizeof...(Args);
175 if (argCount > 0 && !m_data.isEmpty()) {
176 QDataStream stream(m_data);
177 char tmp[argCount] = { (decode(&stream, newData), void(), '0')... };
178 Q_UNUSED(tmp)
179 }
180 }
181
182private:
183 FunctionCode m_code = Invalid;
184 QByteArray m_data;
185 friend class QModbusSerialAdu;
186 friend struct QModbusPduPrivate;
187};
188Q_SERIALBUS_EXPORT QDebug operator<<(QDebug debug, const QModbusPdu &pdu);
189Q_SERIALBUS_EXPORT QDataStream &operator<<(QDataStream &stream, const QModbusPdu &pdu);
190
191class QModbusRequest : public QModbusPdu
192{
193public:
194 QModbusRequest() = default;
195 QModbusRequest(const QModbusPdu &pdu)
196 : QModbusPdu(pdu)
197 {}
198
199 explicit QModbusRequest(FunctionCode code, const QByteArray &newData = QByteArray())
200 : QModbusPdu(code, newData)
201 {}
202
203 Q_SERIALBUS_EXPORT static int minimumDataSize(const QModbusRequest &pdu);
204 Q_SERIALBUS_EXPORT static int calculateDataSize(const QModbusRequest &pdu);
205
206 using CalcFuncPtr = decltype(&calculateDataSize);
207 Q_SERIALBUS_EXPORT static void registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr func);
208
209 template <typename ... Args>
210 QModbusRequest(FunctionCode code, Args ... newData)
211 : QModbusPdu(code, newData...)
212 {}
213};
214Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &stream, QModbusRequest &pdu);
215inline QDataStream &operator<<(QDataStream &stream, const QModbusRequest &pdu)
216{ return stream << static_cast<const QModbusPdu &>(pdu); }
217
218class QModbusResponse : public QModbusPdu
219{
220public:
221 QModbusResponse() = default;
222 QModbusResponse(const QModbusPdu &pdu)
223 : QModbusPdu(pdu)
224 {}
225
226 explicit QModbusResponse(FunctionCode code, const QByteArray &newData = QByteArray())
227 : QModbusPdu(code, newData)
228 {}
229
230 Q_SERIALBUS_EXPORT static int minimumDataSize(const QModbusResponse &pdu);
231 Q_SERIALBUS_EXPORT static int calculateDataSize(const QModbusResponse &pdu);
232
233 using CalcFuncPtr = decltype(&calculateDataSize);
234 Q_SERIALBUS_EXPORT static void registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr func);
235
236 template <typename ... Args>
237 QModbusResponse(FunctionCode code, Args ... newData)
238 : QModbusPdu(code, newData...)
239 {}
240};
241
242class QModbusExceptionResponse : public QModbusResponse
243{
244public:
245 QModbusExceptionResponse() = default;
246 QModbusExceptionResponse(const QModbusPdu &pdu)
247 : QModbusResponse(pdu)
248 {}
249 QModbusExceptionResponse(FunctionCode fc, ExceptionCode ec)
250 : QModbusResponse(FunctionCode(quint8(fc) | ExceptionByte), static_cast<quint8> (ec))
251 {}
252
253 void setFunctionCode(FunctionCode c) {
254 QModbusPdu::setFunctionCode(FunctionCode(quint8(c) | ExceptionByte));
255 }
256 void setExceptionCode(ExceptionCode ec) { QModbusPdu::encodeData(newData: quint8(ec)); }
257};
258Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &stream, QModbusResponse &pdu);
259inline QDataStream &operator<<(QDataStream &stream, const QModbusResponse &pdu)
260{ return stream << static_cast<const QModbusPdu &>(pdu); }
261
262Q_DECLARE_TYPEINFO(QModbusPdu, Q_MOVABLE_TYPE);
263Q_DECLARE_TYPEINFO(QModbusPdu::ExceptionCode, Q_PRIMITIVE_TYPE);
264Q_DECLARE_TYPEINFO(QModbusPdu::FunctionCode, Q_PRIMITIVE_TYPE);
265
266Q_DECLARE_TYPEINFO(QModbusRequest, Q_MOVABLE_TYPE);
267Q_DECLARE_TYPEINFO(QModbusResponse, Q_MOVABLE_TYPE);
268Q_DECLARE_TYPEINFO(QModbusExceptionResponse, Q_MOVABLE_TYPE);
269
270QT_END_NAMESPACE
271
272Q_DECLARE_METATYPE(QModbusPdu::ExceptionCode)
273Q_DECLARE_METATYPE(QModbusPdu::FunctionCode)
274
275#endif // QMODBUSPDU_H
276

Warning: That file was not part of the compilation database. It may have many parsing errors.

source code of qtserialbus/src/serialbus/qmodbuspdu.h