Modbusクライアント
このサンプルは、Modbusクライアントアプリケーションを実装しています。
このサンプルは、シリアルラインまたはTCP経由でModbusリクエストを送信するModbusクライアントとして機能します。表示されるダイアログでは、標準リクエストの定義が可能であり、受信した応答が表示されます。
このサンプルは、「Modbus サーバー」サンプル、または TCP もしくはシリアルポート経由で接続された別の Modbus デバイスと組み合わせて使用する必要があります。
このサンプルで使用される主要なクラス:

QModbusClientの作成
通信を行うには、QModbusClient のインスタンスが必要です。指定された接続タイプに応じて、このサンプルはQModbusRtuSerialClient (シリアル通信用)またはQModbusTcpClient (TCPベースの通信用)をインスタンス化します。
auto type = static_cast<ModbusConnection>(index);
if (type == Serial) {
#if QT_CONFIG(modbus_serialport)
modbusDevice = new QModbusRtuSerialClient(this);
// Try to fill in the first available serial port name if the line edit
// is empty, or contains a url (assume that ':' is only a part of url).
const auto ports = QSerialPortInfo::availablePorts();
const auto currentText = ui->portEdit->text();
if (!ports.isEmpty() && (currentText.isEmpty() || currentText.contains(u':')))
ui->portEdit->setText(ports.front().portName());
#endif
} else if (type == Tcp) {
modbusDevice = new QModbusTcpClient(this);
const QUrl currentUrl = QUrl::fromUserInput(ui->portEdit->text());
// Check if we already have <ip address>:<port>
if (currentUrl.port() <= 0)
ui->portEdit->setText(QLatin1String("127.0.0.1:50200"));
}クライアントの作成後、setConnectionParameter() メソッドを使用して接続パラメータを指定します。パラメータは通信タイプによって異なります:
const auto settings = m_settingsDialog->settings();
if (static_cast<ModbusConnection>(ui->connectType->currentIndex()) == Serial) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
ui->portEdit->text());
#if QT_CONFIG(modbus_serialport)
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
settings.parity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
settings.baud);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
settings.dataBits);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
settings.stopBits);
#endif
} else {
const QUrl url = QUrl::fromUserInput(ui->portEdit->text());
modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, url.port());
modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, url.host());
}
modbusDevice->setTimeout(settings.responseTime);
modbusDevice->setNumberOfRetries(settings.numberOfRetries);クライアントの作成とすべてのパラメータの指定が完了したら、QModbusClient::connectDevice() を使用して Modbus ネットワークに接続します。
データの読み取り
Modbusサーバーからデータを読み取るには、クライアントはサーバーアドレスと、読み取り対象のオブジェクトのパラメータを指定する必要があります:
オブジェクトのパラメータは、QModbusDataUnit クラスによって表されます:
QModbusDataUnit MainWindow::readRequest() const
{
const auto table = ui->writeTable->currentData().value<QModbusDataUnit::RegisterType>();
int startAddress = ui->readAddress->value();
Q_ASSERT(startAddress >= 0 && startAddress < 10);
// do not go beyond 10 entries
quint16 numberOfEntries = qMin(ui->readSize->currentText().toUShort(),
quint16(10 - startAddress));
return QModbusDataUnit(table, startAddress, numberOfEntries);
}パラメータの収集が完了したら、sendReadRequest() メソッドを使用して実際のリクエストを送信します。このメソッドはQModbusReply を返します。これは非同期で処理する必要があるため、QModbusReply::finished() シグナルを使用して、応答の準備が整ったかどうかを確認します。
if (auto *reply = modbusDevice->sendReadRequest(readRequest(), ui->serverEdit->value())) {
if (!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &MainWindow::onReadReady);
else
delete reply; // broadcast replies return immediately
} else {
statusBar()->showMessage(tr("Read error: %1").arg(modbusDevice->errorString()), 5000);
}QModbusReply::finished() シグナルを受信すると、reply オブジェクトを使用してデータを取得したり、読み取りエラーの有無を確認したりできます:
void MainWindow::onReadReady()
{
auto reply = qobject_cast<QModbusReply *>(sender());
if (!reply)
return;
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
for (qsizetype i = 0, total = unit.valueCount(); i < total; ++i) {
const QString entry = tr("Address: %1, Value: %2").arg(unit.startAddress() + i)
.arg(QString::number(unit.value(i),
unit.registerType() <= QModbusDataUnit::Coils ? 10 : 16));
ui->readValue->addItem(entry);
}
} else if (reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Modbus exception: 0x%2)").
arg(reply->errorString()).
arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
} else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()).
arg(reply->error(), -1, 16), 5000);
}
reply->deleteLater();
}データの書き込み
Modbusサーバーにデータを書き込むには、クライアントはサーバーアドレスと、書き込みたいオブジェクトのパラメータを指定する必要があります。データの読み取りと同様に、QModbusDataUnit クラスが、書き込むデータに関する情報を表すために使用されます。この場合、データには目的のvalues も含まれます。sendWriteRequest()メソッドを使用して、目的のデータを書き込みます:
QModbusDataUnit writeUnit = writeRequest();
QModbusDataUnit::RegisterType table = writeUnit.registerType();
for (qsizetype i = 0, total = writeUnit.valueCount(); i < total; ++i) {
const auto addr = i + writeUnit.startAddress();
if (table == QModbusDataUnit::Coils)
writeUnit.setValue(i, writeModel->m_coils[addr]);
else
writeUnit.setValue(i, writeModel->m_holdingRegisters[addr]);
}
if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, ui->serverEdit->value())) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, reply]() {
const auto error = reply->error();
if (error == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Write response error: %1 (Modbus exception: 0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
5000);
} else if (error != QModbusDevice::NoError) {
statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(error, -1, 16), 5000);
}
reply->deleteLater();
});
} else {
// broadcast replies return immediately
reply->deleteLater();
}
} else {
statusBar()->showMessage(tr("Write error: %1").arg(modbusDevice->errorString()), 5000);
}データの読み取りと同様に、返されたQModbusReply オブジェクトを使用して、書き込みエラーの有無を確認します。
例の動作
以下の手順でサンプルを実行できます:
- Qt Creator
Welcome モードを開き、「Examples 」からこのサンプルを選択します。詳細については、「Qt Creator: チュートリアル: ビルドと実行」を参照してください。
- Qt Extension for Visual Studio Code
Command Palette から `Qt: Open Qt examples ` コマンドを実行し、リストからサンプルを選択します。詳細については、Qt Extension for Visual Studio Code の「チュートリアル:ビルドと実行」を参照してください。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.