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() シグナルを受信すると、リプライ・オブジェクトを使用してデータを取得したり、読み取りエラーをチェックしたりできる:
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 からサンプルを選択します。詳しくは、Building and Running an Exampleを参照してください。
© 2025 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.