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 "qmodbusrtuserialslave.h"
38 #include "qmodbusrtuserialslave_p.h"
39
40 #include <QtCore/qloggingcategory.h>
41
42 QT_BEGIN_NAMESPACE
43
44 /*!
45 \class QModbusRtuSerialSlave
46 \inmodule QtSerialBus
47 \since 5.8
48
49 \brief The QModbusRtuSerialSlave class represents a Modbus server
50 that uses a serial port for its communication with the Modbus client.
51
52 Communication via Modbus requires the interaction between a single Modbus
53 client instance and multiple Modbus server. This class provides the Modbus
54 server implementation via a serial port.
55
56 Since multiple Modbus server instances can interact with a Modbus client
57 at the same time (using a serial bus), servers are identified by their
58 \l serverAddress().
59 */
60
61 /*!
62 Constructs a QModbusRtuSerialSlave with the specified \a parent. The
63 \l serverAddress preset is \c 1.
64 */
QModbusRtuSerialSlave(QObject * parent)65 QModbusRtuSerialSlave::QModbusRtuSerialSlave(QObject *parent)
66 : QModbusServer(*new QModbusRtuSerialSlavePrivate, parent)
67 {
68 Q_D(QModbusRtuSerialSlave);
69 d->setupSerialPort();
70 }
71
72 /*!
73 Destroys the QModbusRtuSerialSlave instance.
74 */
~QModbusRtuSerialSlave()75 QModbusRtuSerialSlave::~QModbusRtuSerialSlave()
76 {
77 close();
78 }
79
80 /*!
81 \internal
82 */
QModbusRtuSerialSlave(QModbusRtuSerialSlavePrivate & dd,QObject * parent)83 QModbusRtuSerialSlave::QModbusRtuSerialSlave(QModbusRtuSerialSlavePrivate &dd, QObject *parent)
84 : QModbusServer(dd, parent)
85 {
86 Q_D(QModbusRtuSerialSlave);
87 d->setupSerialPort();
88 }
89
90 /*!
91 \reimp
92 */
processesBroadcast() const93 bool QModbusRtuSerialSlave::processesBroadcast() const
94 {
95 return d_func()->m_processesBroadcast;
96 }
97
98 /*!
99 \reimp
100
101 \note When calling this function, existing buffered data is removed from
102 the serial port.
103 */
open()104 bool QModbusRtuSerialSlave::open()
105 {
106 if (state() == QModbusDevice::ConnectedState)
107 return true;
108
109 Q_D(QModbusRtuSerialSlave);
110 d->setupEnvironment(); // to be done before open
111 if (d->m_serialPort->open(QIODevice::ReadWrite)) {
112 setState(QModbusDevice::ConnectedState);
113 d->m_serialPort->clear(); // only possible after open
114 } else {
115 setError(d->m_serialPort->errorString(), QModbusDevice::ConnectionError);
116 }
117 return (state() == QModbusDevice::ConnectedState);
118 }
119
120 /*!
121 \reimp
122 */
close()123 void QModbusRtuSerialSlave::close()
124 {
125 if (state() == QModbusDevice::UnconnectedState)
126 return;
127
128 Q_D(QModbusRtuSerialSlave);
129 if (d->m_serialPort->isOpen())
130 d->m_serialPort->close();
131
132 setState(QModbusDevice::UnconnectedState);
133 }
134
135 /*!
136 \reimp
137
138 Processes the Modbus client request specified by \a request and returns a
139 Modbus response.
140
141 The Modbus function \l QModbusRequest::EncapsulatedInterfaceTransport with
142 MEI Type 13 (0x0D) CANopen General Reference is filtered out because it is
143 usually Modbus TCP or Modbus serial ASCII only.
144
145 A request to the RTU serial slave will be answered with a Modbus exception
146 response with the exception code QModbusExceptionResponse::IllegalFunction.
147 */
processRequest(const QModbusPdu & request)148 QModbusResponse QModbusRtuSerialSlave::processRequest(const QModbusPdu &request)
149 {
150 if (request.functionCode() == QModbusRequest::EncapsulatedInterfaceTransport) {
151 quint8 meiType;
152 request.decodeData(&meiType);
153 if (meiType == EncapsulatedInterfaceTransport::CanOpenGeneralReference) {
154 return QModbusExceptionResponse(request.functionCode(),
155 QModbusExceptionResponse::IllegalFunction);
156 }
157 }
158 return QModbusServer::processRequest(request);
159 }
160
161 QT_END_NAMESPACE
162
163 #include "moc_qmodbusrtuserialslave.cpp"
164