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.

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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