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 を参照してください。
©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。