summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2023-02-07 16:15:25 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-02-14 15:14:26 +0000
commit9646d6971b36154f38c6f67ca11aac4f27469b16 (patch)
tree16112bf8faa5c877bb34848ff4163d129cc4a1e8
parent8951ade54136aa8ddef516d411f5f28321213207 (diff)
Modbus Custom Command: update example description
Extend the example description so that it actually highlights the main features shown in the example. Also update the example to match the guidelines: * Do not use Example in the name * Update screenshot * add Connectivity category Task-number: QTBUG-110890 Change-Id: Ia406b974967eaa2f5af9b935c4aac6d09253a9ee Reviewed-by: André Hartmann <aha_1980@gmx.de> Reviewed-by: Alex Blasche <alexander.blasche@qt.io> (cherry picked from commit b3d43080e17b7bdd8b7e2fe7a2d1fcf1ac4b54ab) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--examples/serialbus/modbus/custom/doc/images/custom.pngbin16378 -> 45468 bytes
-rw-r--r--examples/serialbus/modbus/custom/doc/src/custom.qdoc93
-rw-r--r--examples/serialbus/modbus/custom/mainwindow.cpp4
-rw-r--r--examples/serialbus/modbus/custom/mainwindow.ui4
-rw-r--r--examples/serialbus/modbus/custom/modbusclient.cpp6
-rw-r--r--examples/serialbus/modbus/custom/modbusclient.h2
-rw-r--r--examples/serialbus/modbus/custom/modbusserver.cpp4
-rw-r--r--examples/serialbus/modbus/custom/modbusserver.h2
-rw-r--r--src/serialbus/doc/src/qtserialbus-index.qdoc2
9 files changed, 107 insertions, 10 deletions
diff --git a/examples/serialbus/modbus/custom/doc/images/custom.png b/examples/serialbus/modbus/custom/doc/images/custom.png
index c1ad0b7..91347f9 100644
--- a/examples/serialbus/modbus/custom/doc/images/custom.png
+++ b/examples/serialbus/modbus/custom/doc/images/custom.png
Binary files differ
diff --git a/examples/serialbus/modbus/custom/doc/src/custom.qdoc b/examples/serialbus/modbus/custom/doc/src/custom.qdoc
index 35d44c3..97ed182 100644
--- a/examples/serialbus/modbus/custom/doc/src/custom.qdoc
+++ b/examples/serialbus/modbus/custom/doc/src/custom.qdoc
@@ -1,26 +1,105 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*! \example modbus/custom
- \title Modbus Custom command example
+ \title Modbus Custom Command
+ \ingroup qtserialbus-examples
+ \meta category Connectivity
- \brief The example implements a Modbus client-server application.
+ \brief The example shows how to handle custom Modbus function codes.
The example acts as both Modbus client and server in a single application.
The connection between them is established via Modbus TCP. It is used to
send and receive custom Modbus requests and adjusts its internal states
based on the request and response.
+ The main purpose of the example is to provide some demo code on how to
+ implement a Modbus client or Modbus server handling custom Modbus function
+ codes.
+
\image ../images/custom.png
+ \section1 User-Defined Modbus Function Codes
+
+ The Modbus protocol supports function codes in the range \c {1 - 127
+ (0x01 - 0x7F HEX)}. Most of the function codes are well defined and publicly
+ documented. However, there are two ranges that can be used for user-defined
+ functions. Those are \c {65 - 72 (0x41 - 48 HEX)} and
+ \c {100 - 110 (0x64 - 0x6E HEX)}. The user can select function codes from
+ these ranges and handle them in some custom way.
+
+ This application uses function code \c {65 (0x41 HEX)} to implement
+ \c CustomRead command and function code \c {66 (0x42 HEX)} to implement
+ \c CustomWrite command. In this example the custom commands are used to
+ simply read and write the
+ \l {QModbusDataUnit::HoldingRegisters}{Holding Registers}.
+
+ \section1 Sending Custom Modbus Commands
+
+ The custom Modbus commands are sent using the
+ \l QModbusClient::sendRawRequest() method. This method requires to generate
+ a \l QModbusRequest object with the desired function code and a list of
+ arguments which will be encoded into a \l {QByteArray}:
+
+ \snippet modbus/custom/mainwindow.cpp generate_modbus_request
+
+ The \l QModbusClient::sendRawRequest() method returns a \l QModbusReply
+ object which can be used to check for errors as usual:
+
+ \snippet modbus/custom/mainwindow.cpp send_custom_command
+
+ \section1 Custom Modbus Server
+
+ The custom server is derived from the \l QModbusTcpServer class. It
+ overrides the \l QModbusServer::processPrivateRequest() method.
+
+ \snippet modbus/custom/modbusserver.h custom_server
+
+ The base server class calls the
+ \l {QModbusServer::}{processPrivateRequest()} method when a command with a
+ custom function code is received.
+
+ The custom implementation handles the \c CustomRead command by generating
+ a \l QModbusResponse with the values of requested registers:
+
+ \snippet modbus/custom/modbusserver.cpp handle_custom_read
+
+ Handling \c CustomWrite command includes extracting the new values from
+ the received \l QModbusPdu, doing the actual value update, and returning
+ a \l QModbusResponse with the registers that were actually updated:
+
+ \snippet modbus/custom/modbusserver.cpp handle_custom_write
+
+ \section1 Custom Modbus Client
+
+ The custom client is derived from the \l QModbusTcpClient class. It
+ overrides the \l QModbusClient::processPrivateResponse() method.
+
+ \snippet modbus/custom/modbusclient.h custom_client
+
+ The base client class calls the
+ \l {QModbusClient::}{processPrivateResponse()} method to process the server
+ responses with custom function codes.
+
+ The custom implementation handles the responses with \c CustomRead and
+ \c CustomWrite function codes:
+
+ \snippet modbus/custom/modbusclient.cpp private_response
+
+ The \c CustomRead response is handled by decoding the provided \l QModbusPdu
+ and extracting the values for requested registers:
+
+ \snippet modbus/custom/modbusclient.cpp process_custom_read
+
+ The \c CustomWrite response is handled by simply validating the response
+ parameters:
+
+ \snippet modbus/custom/modbusclient.cpp process_custom_write
+
\include examples-run.qdocinc
This example cannot be used in conjunction with other applications. Once the
example is started, it can only exchange custom Modbus commands within the
application itself. All interactions between the client and server use the
Modbus TCP protocol.
-
- The main purpose of the example is to provide some demo code on how to
- implement a Modbus client or Modbus server handling custom Modbus function
- codes.
*/
diff --git a/examples/serialbus/modbus/custom/mainwindow.cpp b/examples/serialbus/modbus/custom/mainwindow.cpp
index 34d3f17..10cbf1e 100644
--- a/examples/serialbus/modbus/custom/mainwindow.cpp
+++ b/examples/serialbus/modbus/custom/mainwindow.cpp
@@ -146,6 +146,7 @@ void MainWindow::onReadButtonClicked()
void MainWindow::onWriteButtonClicked()
{
+//! [generate_modbus_request]
QModbusDataUnit unit {
QModbusDataUnit::HoldingRegisters,
ui->startAddress->value(),
@@ -162,7 +163,9 @@ void MainWindow::onWriteButtonClicked()
quint16(unit.startAddress()),
quint16(unit.valueCount()), byteCount, unit.values()
};
+//! [generate_modbus_request]
+//! [send_custom_command]
if (auto *reply = m_client.sendRawRequest(writeRequest, ui->serverAddress->value())) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, reply]() {
@@ -182,6 +185,7 @@ void MainWindow::onWriteButtonClicked()
} else {
statusBar()->showMessage(tr("Write error: ") + m_client.errorString(), 5000);
}
+//! [send_custom_command]
}
void MainWindow::setupClientContainer()
diff --git a/examples/serialbus/modbus/custom/mainwindow.ui b/examples/serialbus/modbus/custom/mainwindow.ui
index 85e02e7..0837d63 100644
--- a/examples/serialbus/modbus/custom/mainwindow.ui
+++ b/examples/serialbus/modbus/custom/mainwindow.ui
@@ -142,7 +142,7 @@
</font>
</property>
<property name="text">
- <string>0X41</string>
+ <string>0x41</string>
</property>
</widget>
</item>
@@ -199,7 +199,7 @@
</font>
</property>
<property name="text">
- <string>0X42</string>
+ <string>0x42</string>
</property>
</widget>
</item>
diff --git a/examples/serialbus/modbus/custom/modbusclient.cpp b/examples/serialbus/modbus/custom/modbusclient.cpp
index 0bc214a..94f574e 100644
--- a/examples/serialbus/modbus/custom/modbusclient.cpp
+++ b/examples/serialbus/modbus/custom/modbusclient.cpp
@@ -31,6 +31,7 @@ ModbusClient::ModbusClient(QObject *parent)
});
}
+//! [process_custom_read]
static bool collateBytes(const QModbusPdu &response, QModbusDataUnit *data)
{
if (response.dataSize() < MinimumReadResponseSize)
@@ -56,7 +57,9 @@ static bool collateBytes(const QModbusPdu &response, QModbusDataUnit *data)
}
return true;
}
+//! [process_custom_read]
+//! [process_custom_write]
static bool collateMultipleValues(const QModbusPdu &response, QModbusDataUnit *data)
{
if (response.dataSize() != WriteResponseSize)
@@ -72,7 +75,9 @@ static bool collateMultipleValues(const QModbusPdu &response, QModbusDataUnit *d
*data = {QModbusDataUnit::HoldingRegisters, address, count};
return true;
}
+//! [process_custom_write]
+//! [private_response]
bool ModbusClient::processPrivateResponse(const QModbusResponse &response, QModbusDataUnit *data)
{
if (!response.isValid())
@@ -85,3 +90,4 @@ bool ModbusClient::processPrivateResponse(const QModbusResponse &response, QModb
return collateMultipleValues(response, data);
return QModbusClient::processPrivateResponse(response, data);
}
+//! [private_response]
diff --git a/examples/serialbus/modbus/custom/modbusclient.h b/examples/serialbus/modbus/custom/modbusclient.h
index 3cf1457..04fb43d 100644
--- a/examples/serialbus/modbus/custom/modbusclient.h
+++ b/examples/serialbus/modbus/custom/modbusclient.h
@@ -6,6 +6,7 @@
#ifndef MODBUSCLIENT_H
#define MODBUSCLIENT_H
+//! [custom_client]
class ModbusClient : public QModbusTcpClient
{
Q_OBJECT
@@ -20,5 +21,6 @@ public:
private:
bool processPrivateResponse(const QModbusResponse &response, QModbusDataUnit *data) override;
};
+//! [custom_client]
#endif // MODBUSCLIENT_H
diff --git a/examples/serialbus/modbus/custom/modbusserver.cpp b/examples/serialbus/modbus/custom/modbusserver.cpp
index 0adc281..b9b260d 100644
--- a/examples/serialbus/modbus/custom/modbusserver.cpp
+++ b/examples/serialbus/modbus/custom/modbusserver.cpp
@@ -40,6 +40,7 @@ QModbusResponse ModbusServer::processPrivateRequest(const QModbusPdu &request)
if (!request.isValid())
return QModbusServer::processPrivateRequest(request);
+//! [handle_custom_read]
if (ModbusClient::CustomRead == request.functionCode()) {
quint16 startAddress, count;
request.decodeData(&startAddress, &count);
@@ -51,7 +52,9 @@ QModbusResponse ModbusServer::processPrivateRequest(const QModbusPdu &request)
}
return QModbusResponse(request.functionCode(), startAddress, quint8(count * 2), unit.values());
}
+//! [handle_custom_read]
+//! [handle_custom_write]
if (ModbusClient::CustomWrite == request.functionCode()) {
quint8 byteCount;
quint16 startAddress, numberOfRegisters;
@@ -79,6 +82,7 @@ QModbusResponse ModbusServer::processPrivateRequest(const QModbusPdu &request)
return QModbusResponse(request.functionCode(), startAddress, numberOfRegisters);
}
+//! [handle_custom_write]
return QModbusServer::processPrivateRequest(request);
}
diff --git a/examples/serialbus/modbus/custom/modbusserver.h b/examples/serialbus/modbus/custom/modbusserver.h
index 70f2b7d..6143239 100644
--- a/examples/serialbus/modbus/custom/modbusserver.h
+++ b/examples/serialbus/modbus/custom/modbusserver.h
@@ -6,6 +6,7 @@
#ifndef MODBUSSERVER_H
#define MODBUSSERVER_H
+//! [custom_server]
class ModbusServer : public QModbusTcpServer
{
Q_OBJECT
@@ -17,5 +18,6 @@ public:
private:
QModbusResponse processPrivateRequest(const QModbusPdu &request) override;
};
+//! [custom_server]
#endif // MODBUSSERVER_H
diff --git a/src/serialbus/doc/src/qtserialbus-index.qdoc b/src/serialbus/doc/src/qtserialbus-index.qdoc
index f3ae272..acde5c5 100644
--- a/src/serialbus/doc/src/qtserialbus-index.qdoc
+++ b/src/serialbus/doc/src/qtserialbus-index.qdoc
@@ -77,7 +77,7 @@
\li \l {can}{CAN Bus Manager example}
\li \l {modbus/client}{Modbus Client example}
\li \l {modbus/server}{Modbus Server example}
- \li \l {Modbus Custom command example}
+ \li \l {modbus/custom}{Modbus Custom Command example}
\endlist
\section1 Module Evolution