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 "qmodbusdevice.h"
38#include "qmodbusdevice_p.h"
39#include "qmodbusdataunit.h"
40
41#include <QtCore/qloggingcategory.h>
42
43QT_BEGIN_NAMESPACE
44
45/*!
46 \class QModbusDevice
47 \inmodule QtSerialBus
48 \since 5.8
49
50 \brief The QModbusDevice class is the base class for Modbus classes, \l QModbusServer
51 and \l QModbusClient.
52*/
53
54/*!
55 Constructs a Modbus device with the specified \a parent.
56*/
57QModbusDevice::QModbusDevice(QObject *parent)
58 : QObject(*new QModbusDevicePrivate, parent)
59{
60}
61
62/*!
63 \internal
64*/
65QModbusDevice::QModbusDevice(QModbusDevicePrivate &dd, QObject *parent)
66 : QObject(dd, parent)
67{
68}
69
70/*!
71 Destroys the QModbusDevice instance
72*/
73QModbusDevice::~QModbusDevice()
74{
75}
76
77/*!
78 \enum QModbusDevice::ConnectionParameter
79
80 This enum describes the possible values that can be set for a Modbus device
81 connection.
82
83 The general purpose value (and the associated types) are:
84
85 \value SerialPortNameParameter This parameter holds the serial port used for
86 device communication, e.g. COM1. \c QString
87 \value SerialParityParameter This parameter holds the parity checking mode.
88 \c QSerialPort::Parity
89 \value SerialBaudRateParameter This parameter holds the data baud rate for
90 the communication. \c QSerialPort::BaudRate
91 \value SerialDataBitsParameter This parameter holds the data bits in a frame.
92 \c QSerialPort::DataBits
93 \value SerialStopBitsParameter This parameter holds the number of stop bits in a
94 frame. \c QSerialPort::StopBits
95 \value NetworkPortParameter This parameter holds the network port. \c int
96 \value NetworkAddressParameter This parameter holds the host address for network
97 communication. \c QString
98
99 User options:
100
101 \value UserParameter This enum value has been deprecated. There
102 will be no replacement.
103*/
104
105/*!
106 Returns the value associated with the given connection \a parameter. The
107 returned value can be empty.
108
109 By default the \c QModbusDevice is initialized with some common values. The
110 serial port settings are even parity, a baud rate of 19200 bits per second,
111 eight data bits and one stop bit. The network settings for the host address
112 is set to local host and port to 502.
113
114 \note For a serial connection to succeed, the \l SerialPortNameParameter
115 needs to be set to a valid communication port. The information about valid
116 serial ports can be obtained from \l QSerialPortInfo.
117
118 \note If the device is already connected, the settings are taken into account
119 after reconnecting the device.
120
121 \sa ConnectionParameter
122*/
123QVariant QModbusDevice::connectionParameter(int parameter) const
124{
125 Q_D(const QModbusDevice);
126 switch (parameter) {
127#if QT_CONFIG(modbus_serialport)
128 case SerialPortNameParameter:
129 return d->m_comPort;
130 case SerialDataBitsParameter:
131 return d->m_dataBits;
132 case SerialParityParameter:
133 return d->m_parity;
134 case SerialStopBitsParameter:
135 return d->m_stopBits;
136 case SerialBaudRateParameter:
137 return d->m_baudRate;
138#endif
139 case NetworkPortParameter:
140 return d->m_networkPort;
141 case NetworkAddressParameter:
142 return d->m_networkAddress;
143 default:
144 break;
145 }
146 return d->m_userConnectionParams.value(akey: parameter); // ### Qt6: remove
147}
148
149/*!
150 Sets the value of \a parameter to \a value. If the \a parameter already
151 exists, the previous value is overwritten. A active or running connection
152 is not affected by such parameter changes.
153
154 \sa ConnectionParameter
155 \sa connectionParameter()
156*/
157void QModbusDevice::setConnectionParameter(int parameter, const QVariant &value)
158{
159 Q_D(QModbusDevice);
160 switch (parameter) {
161#if QT_CONFIG(modbus_serialport)
162 case SerialPortNameParameter:
163 d->m_comPort = value.toString();
164 break;
165 case SerialDataBitsParameter:
166 d->m_dataBits = QSerialPort::DataBits(value.toInt());
167 break;
168 case SerialParityParameter:
169 d->m_parity = QSerialPort::Parity(value.toInt());
170 break;
171 case SerialStopBitsParameter:
172 d->m_stopBits = QSerialPort::StopBits(value.toInt());
173 break;
174 case SerialBaudRateParameter:
175 d->m_baudRate = QSerialPort::BaudRate(value.toInt());
176 break;
177#endif
178 case NetworkPortParameter:
179 d->m_networkPort = value.toInt();
180 break;
181 case NetworkAddressParameter:
182 d->m_networkAddress = value.toString();
183 break;
184 default:
185 d->m_userConnectionParams.insert(akey: parameter, avalue: value); // ### Qt6: remove
186 break;
187 }
188}
189
190/*!
191 \enum QModbusDevice::Error
192 This enum describes all the possible error conditions.
193
194 \value NoError No errors have occurred.
195 \value ReadError An error occurred during a read operation.
196 \value WriteError An error occurred during a write operation.
197 \value ConnectionError An error occurred when attempting to open the
198 backend.
199 \value ConfigurationError An error occurred when attempting to set a
200 configuration parameter.
201 \value TimeoutError A timeout occurred during I/O. An I/O operation
202 did not finish within a given time frame.
203 \value ProtocolError A Modbus specific protocol error occurred.
204 \value ReplyAbortedError The reply was aborted due to a disconnection of
205 the device.
206 \value UnknownError An unknown error occurred.
207*/
208
209/*!
210 \enum QModbusDevice::State
211 This enum describes all possible device states.
212
213 \value UnconnectedState The device is disconnected.
214 \value ConnectingState The device is being connected.
215 \value ConnectedState The device is connected to the Modbus network.
216 \value ClosingState The device is being closed.
217*/
218
219/*!
220 \fn QModbusDevice::errorOccurred(QModbusDevice::Error error)
221
222 This signal is emitted when an error of the type, \a error, occurs.
223*/
224
225/*!
226 \fn void QModbusDevice::stateChanged(QModbusDevice::State state)
227
228 This signal is emitted every time the state of the device changes.
229 The new state is represented by \a state.
230
231 \sa setState(), state()
232*/
233
234/*!
235 Connects the device to the Modbus network. Returns \c true if the connection
236 process was successfully initiated; otherwise \c false. Final connection
237 success confirmation requires the \l state() changing to \l QModbusDevice::ConnectedState.
238
239
240 This function calls \l open() as part of its implementation.
241
242 \sa open()
243*/
244bool QModbusDevice::connectDevice()
245{
246 Q_D(QModbusDevice);
247
248 if (d->state != QModbusDevice::UnconnectedState)
249 return false;
250
251 setState(ConnectingState);
252
253 if (!open()) {
254 setState(UnconnectedState);
255 return false;
256 }
257
258 //Connected is set by backend -> might be delayed by event loop
259 return true;
260}
261
262/*!
263 Disconnects the device.
264
265 This function calls \l close() as part of its implementation.
266*/
267void QModbusDevice::disconnectDevice()
268{
269 if (state() == QModbusDevice::UnconnectedState)
270 return;
271
272 setState(QModbusDevice::ClosingState);
273
274 //Unconnected is set by backend -> might be delayed by event loop
275 close();
276}
277
278/*!
279 Sets the state of the device to \a newState. Modbus device implementations
280 must use this function to update the device state.
281*/
282void QModbusDevice::setState(QModbusDevice::State newState)
283{
284 Q_D(QModbusDevice);
285
286 if (newState == d->state)
287 return;
288
289 d->state = newState;
290 emit stateChanged(state: newState);
291}
292
293/*!
294 Returns the current state of the device.
295
296 \sa setState(), stateChanged()
297*/
298QModbusDevice::State QModbusDevice::state() const
299{
300 return d_func()->state;
301}
302
303/*!
304 Sets the error state of the device. ModBus device implementations
305 must use this function in case of an error to set the \a error type and
306 a descriptive \a errorText.
307
308 \sa QModbusDevice::Error
309*/
310void QModbusDevice::setError(const QString &errorText, QModbusDevice::Error error)
311{
312 Q_D(QModbusDevice);
313
314 d->error = error;
315 d->errorString = errorText;
316 emit errorOccurred(error);
317}
318
319/*!
320 Returns the error state of the device.
321
322 \sa QModbusDevice::Error
323*/
324QModbusDevice::Error QModbusDevice::error() const
325{
326 return d_func()->error;
327}
328
329/*!
330 Returns descriptive error text for the device error.
331
332 \sa QModbusDevice::Error
333*/
334QString QModbusDevice::errorString() const
335{
336 return d_func()->errorString;
337}
338
339/*!
340 \since 5.14
341
342 Returns the underlying \l QIODevice used for ModBus communication or
343 \c nullptr if the device was not yet fully initialized.
344
345 \note Do not store a pointer to the underlying device, because it can be
346 invalidated at any point in time.
347*/
348QIODevice *QModbusDevice::device() const
349{
350 return d_func()->device();
351}
352
353/*!
354 \fn bool QModbusDevice::open()
355
356 This function is called by connectDevice(). Subclasses must provide
357 an implementation that returns \c true on successful Modbus connection
358 or connection initiation; otherwise returns \c false.
359
360 The implementation must ensure that the instance's \l state()
361 is set to \l QModbusDevice::ConnectingState or \l QModbusDevice::ConnectedState upon success; otherwise
362 \l QModbusDevice::UnconnectedState. Typically, \l QModbusDevice::ConnectingState is used
363 when the connection process reports back asynchronously and \l QModbusDevice::ConnectedState
364 in case of synchronous connect behavior.
365
366 \sa connectDevice()
367*/
368
369/*!
370 \fn void QModbusDevice::close()
371
372 This function is responsible for closing the Modbus connection.
373 The implementation must ensure that the instance's
374 \l state() is set to \l QModbusDevice::UnconnectedState.
375
376 \sa disconnectDevice()
377*/
378
379Q_LOGGING_CATEGORY(QT_MODBUS, "qt.modbus")
380Q_LOGGING_CATEGORY(QT_MODBUS_LOW, "qt.modbus.lowlevel")
381
382QT_END_NAMESPACE
383

source code of qtserialbus/src/serialbus/qmodbusdevice.cpp