summaryrefslogtreecommitdiffstats
path: root/examples/serialbus/modbus/client
diff options
context:
space:
mode:
authorKarsten Heimrich <karsten.heimrich@qt.io>2021-02-24 14:26:24 +0100
committerKarsten Heimrich <karsten.heimrich@qt.io>2021-03-02 11:44:29 +0100
commit10e4ff602f5ab415bf057ac779f35f0e60b849b2 (patch)
tree27af336d03b116c6d5b31e0ddc9a624f0cde348f /examples/serialbus/modbus/client
parent7ba42fb04403bb6b30ffceb0b429ae831a053ead (diff)
Reword example and documentations from master/slave to client/server
Task-number: QTBUG-91213 Task-number: QTBUG-91212 Task-number: QTBUG-91211 Change-Id: I2b585d73b5fa3194459709fa57d44a8f42dceeed Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'examples/serialbus/modbus/client')
-rw-r--r--examples/serialbus/modbus/client/CMakeLists.txt64
-rw-r--r--examples/serialbus/modbus/client/client.pro29
-rw-r--r--examples/serialbus/modbus/client/client.qrc8
-rw-r--r--examples/serialbus/modbus/client/doc/images/modbusclient.pngbin0 -> 15418 bytes
-rw-r--r--examples/serialbus/modbus/client/doc/src/modbusclient.qdoc43
-rw-r--r--examples/serialbus/modbus/client/images/application-exit.pngbin0 -> 11200 bytes
-rw-r--r--examples/serialbus/modbus/client/images/connect.pngbin0 -> 15374 bytes
-rw-r--r--examples/serialbus/modbus/client/images/disconnect.pngbin0 -> 15092 bytes
-rw-r--r--examples/serialbus/modbus/client/images/settings.pngbin0 -> 16039 bytes
-rw-r--r--examples/serialbus/modbus/client/main.cpp65
-rw-r--r--examples/serialbus/modbus/client/mainwindow.cpp394
-rw-r--r--examples/serialbus/modbus/client/mainwindow.h106
-rw-r--r--examples/serialbus/modbus/client/mainwindow.ui520
-rw-r--r--examples/serialbus/modbus/client/settingsdialog.cpp93
-rw-r--r--examples/serialbus/modbus/client/settingsdialog.h94
-rw-r--r--examples/serialbus/modbus/client/settingsdialog.ui237
-rw-r--r--examples/serialbus/modbus/client/writeregistermodel.cpp167
-rw-r--r--examples/serialbus/modbus/client/writeregistermodel.h88
18 files changed, 1908 insertions, 0 deletions
diff --git a/examples/serialbus/modbus/client/CMakeLists.txt b/examples/serialbus/modbus/client/CMakeLists.txt
new file mode 100644
index 0000000..09ae8f5
--- /dev/null
+++ b/examples/serialbus/modbus/client/CMakeLists.txt
@@ -0,0 +1,64 @@
+cmake_minimum_required(VERSION 3.14)
+project(modbusclient LANGUAGES CXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+set(CMAKE_AUTOUIC ON)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/serialbus/modbus/client")
+
+find_package(Qt6 COMPONENTS Core)
+find_package(Qt6 COMPONENTS Gui)
+find_package(Qt6 COMPONENTS SerialBus)
+find_package(Qt6 COMPONENTS Widgets)
+
+qt_add_executable(modbusclient
+ main.cpp
+ mainwindow.cpp mainwindow.h mainwindow.ui
+ settingsdialog.cpp settingsdialog.h settingsdialog.ui
+ writeregistermodel.cpp writeregistermodel.h
+)
+set_target_properties(modbusclient PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+target_link_libraries(modbusclient PUBLIC
+ Qt::Core
+ Qt::Gui
+ Qt::SerialBus
+ Qt::Widgets
+)
+
+
+# Resources:
+set(client_resource_files
+ "images/application-exit.png"
+ "images/connect.png"
+ "images/disconnect.png"
+ "images/settings.png"
+)
+
+qt6_add_resources(modbusclient "client"
+ PREFIX
+ "/"
+ FILES
+ ${client_resource_files}
+)
+
+if(QT_FEATURE_modbus_serialport)
+ target_link_libraries(modbusclient PUBLIC
+ Qt::SerialPort
+ )
+endif()
+
+install(TARGETS modbusclient
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
diff --git a/examples/serialbus/modbus/client/client.pro b/examples/serialbus/modbus/client/client.pro
new file mode 100644
index 0000000..fa31012
--- /dev/null
+++ b/examples/serialbus/modbus/client/client.pro
@@ -0,0 +1,29 @@
+QT += serialbus widgets
+requires(qtConfig(combobox))
+
+qtConfig(modbus-serialport): QT += serialport
+
+TARGET = modbusclient
+TEMPLATE = app
+CONFIG += c++11
+
+SOURCES += \
+ main.cpp\
+ mainwindow.cpp \
+ settingsdialog.cpp \
+ writeregistermodel.cpp
+
+HEADERS += \
+ mainwindow.h \
+ settingsdialog.h \
+ writeregistermodel.h
+
+FORMS += \
+ mainwindow.ui \
+ settingsdialog.ui
+
+RESOURCES += \
+ client.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/serialbus/modbus/client
+INSTALLS += target
diff --git a/examples/serialbus/modbus/client/client.qrc b/examples/serialbus/modbus/client/client.qrc
new file mode 100644
index 0000000..5e8e998
--- /dev/null
+++ b/examples/serialbus/modbus/client/client.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/application-exit.png</file>
+ <file>images/connect.png</file>
+ <file>images/disconnect.png</file>
+ <file>images/settings.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/serialbus/modbus/client/doc/images/modbusclient.png b/examples/serialbus/modbus/client/doc/images/modbusclient.png
new file mode 100644
index 0000000..b2d771c
--- /dev/null
+++ b/examples/serialbus/modbus/client/doc/images/modbusclient.png
Binary files differ
diff --git a/examples/serialbus/modbus/client/doc/src/modbusclient.qdoc b/examples/serialbus/modbus/client/doc/src/modbusclient.qdoc
new file mode 100644
index 0000000..7467b6c
--- /dev/null
+++ b/examples/serialbus/modbus/client/doc/src/modbusclient.qdoc
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \example modbus/client
+ \title Modbus Client example
+
+ \brief The example implements a Modbus client application.
+
+ The example acts as Modbus client sending Modbus request via serial line
+ and TCP respectively. The shown dialog allows the definition of standard
+ requests and displays incoming responses.
+
+ \image ../images/modbusclient.png
+
+ \include examples-run.qdocinc
+
+ The example must be used in conjunction with the \l {Modbus server example}
+ or another Modbus device which is either connected via TCP or Serial Port.
+*/
diff --git a/examples/serialbus/modbus/client/images/application-exit.png b/examples/serialbus/modbus/client/images/application-exit.png
new file mode 100644
index 0000000..32be6b3
--- /dev/null
+++ b/examples/serialbus/modbus/client/images/application-exit.png
Binary files differ
diff --git a/examples/serialbus/modbus/client/images/connect.png b/examples/serialbus/modbus/client/images/connect.png
new file mode 100644
index 0000000..dd5a51e
--- /dev/null
+++ b/examples/serialbus/modbus/client/images/connect.png
Binary files differ
diff --git a/examples/serialbus/modbus/client/images/disconnect.png b/examples/serialbus/modbus/client/images/disconnect.png
new file mode 100644
index 0000000..fd58f7a
--- /dev/null
+++ b/examples/serialbus/modbus/client/images/disconnect.png
Binary files differ
diff --git a/examples/serialbus/modbus/client/images/settings.png b/examples/serialbus/modbus/client/images/settings.png
new file mode 100644
index 0000000..3d1042e
--- /dev/null
+++ b/examples/serialbus/modbus/client/images/settings.png
Binary files differ
diff --git a/examples/serialbus/modbus/client/main.cpp b/examples/serialbus/modbus/client/main.cpp
new file mode 100644
index 0000000..19a1d5b
--- /dev/null
+++ b/examples/serialbus/modbus/client/main.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QLoggingCategory>
+
+int main(int argc, char *argv[])
+{
+ // Uncomment the following line to enable logging
+ // QLoggingCategory::setFilterRules(QStringLiteral("qt.modbus* = true"));
+ QApplication a(argc, argv);
+ MainWindow w;
+ w.show();
+
+ return a.exec();
+}
diff --git a/examples/serialbus/modbus/client/mainwindow.cpp b/examples/serialbus/modbus/client/mainwindow.cpp
new file mode 100644
index 0000000..a7d1d5e
--- /dev/null
+++ b/examples/serialbus/modbus/client/mainwindow.cpp
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "settingsdialog.h"
+#include "writeregistermodel.h"
+
+#include <QModbusTcpClient>
+#include <QModbusRtuSerialClient>
+#include <QStandardItemModel>
+#include <QStatusBar>
+#include <QUrl>
+
+enum ModbusConnection {
+ Serial,
+ Tcp
+};
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
+ , ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+
+ m_settingsDialog = new SettingsDialog(this);
+
+ initActions();
+
+ writeModel = new WriteRegisterModel(this);
+ writeModel->setStartAddress(ui->writeAddress->value());
+ writeModel->setNumberOfValues(ui->writeSize->currentText());
+
+ ui->writeValueTable->setModel(writeModel);
+ ui->writeValueTable->hideColumn(2);
+ connect(writeModel, &WriteRegisterModel::updateViewport,
+ ui->writeValueTable->viewport(), QOverload<>::of(&QWidget::update));
+
+ ui->writeTable->addItem(tr("Coils"), QModbusDataUnit::Coils);
+ ui->writeTable->addItem(tr("Discrete Inputs"), QModbusDataUnit::DiscreteInputs);
+ ui->writeTable->addItem(tr("Input Registers"), QModbusDataUnit::InputRegisters);
+ ui->writeTable->addItem(tr("Holding Registers"), QModbusDataUnit::HoldingRegisters);
+
+#if QT_CONFIG(modbus_serialport)
+ ui->connectType->setCurrentIndex(0);
+ onConnectTypeChanged(0);
+#else
+ // lock out the serial port option
+ ui->connectType->setCurrentIndex(1);
+ onConnectTypeChanged(1);
+ ui->connectType->setEnabled(false);
+#endif
+
+ auto model = new QStandardItemModel(10, 1, this);
+ for (int i = 0; i < 10; ++i)
+ model->setItem(i, new QStandardItem(QStringLiteral("%1").arg(i + 1)));
+ ui->writeSize->setModel(model);
+ ui->writeSize->setCurrentText("10");
+ connect(ui->writeSize, &QComboBox::currentTextChanged,
+ writeModel, &WriteRegisterModel::setNumberOfValues);
+
+ auto valueChanged = QOverload<int>::of(&QSpinBox::valueChanged);
+ connect(ui->writeAddress, valueChanged, writeModel, &WriteRegisterModel::setStartAddress);
+ connect(ui->writeAddress, valueChanged, this, [this, model](int i) {
+ int lastPossibleIndex = 0;
+ const int currentIndex = ui->writeSize->currentIndex();
+ for (int ii = 0; ii < 10; ++ii) {
+ if (ii < (10 - i)) {
+ lastPossibleIndex = ii;
+ model->item(ii)->setEnabled(true);
+ } else {
+ model->item(ii)->setEnabled(false);
+ }
+ }
+ if (currentIndex > lastPossibleIndex)
+ ui->writeSize->setCurrentIndex(lastPossibleIndex);
+ });
+}
+
+MainWindow::~MainWindow()
+{
+ if (modbusDevice)
+ modbusDevice->disconnectDevice();
+ delete modbusDevice;
+
+ delete ui;
+}
+
+void MainWindow::initActions()
+{
+ ui->actionConnect->setEnabled(true);
+ ui->actionDisconnect->setEnabled(false);
+ ui->actionExit->setEnabled(true);
+ ui->actionOptions->setEnabled(true);
+
+ connect(ui->connectButton, &QPushButton::clicked,
+ this, &MainWindow::onConnectButtonClicked);
+ connect(ui->actionConnect, &QAction::triggered,
+ this, &MainWindow::onConnectButtonClicked);
+ connect(ui->actionDisconnect, &QAction::triggered,
+ this, &MainWindow::onConnectButtonClicked);
+ connect(ui->readButton, &QPushButton::clicked,
+ this, &MainWindow::onReadButtonClicked);
+ connect(ui->writeButton, &QPushButton::clicked,
+ this, &MainWindow::onWriteButtonClicked);
+ connect(ui->readWriteButton, &QPushButton::clicked,
+ this, &MainWindow::onReadWriteButtonClicked);
+ connect(ui->connectType, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &MainWindow::onConnectTypeChanged);
+ connect(ui->writeTable, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &MainWindow::onWriteTableChanged);
+
+ connect(ui->actionExit, &QAction::triggered, this, &QMainWindow::close);
+ connect(ui->actionOptions, &QAction::triggered, m_settingsDialog, &QDialog::show);
+}
+
+void MainWindow::onConnectTypeChanged(int index)
+{
+ if (modbusDevice) {
+ modbusDevice->disconnectDevice();
+ delete modbusDevice;
+ modbusDevice = nullptr;
+ }
+
+ auto type = static_cast<ModbusConnection>(index);
+ if (type == Serial) {
+#if QT_CONFIG(modbus_serialport)
+ modbusDevice = new QModbusRtuSerialClient(this);
+#endif
+ } else if (type == Tcp) {
+ modbusDevice = new QModbusTcpClient(this);
+ if (ui->portEdit->text().isEmpty())
+ ui->portEdit->setText(QLatin1String("127.0.0.1:502"));
+ }
+
+ connect(modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) {
+ statusBar()->showMessage(modbusDevice->errorString(), 5000);
+ });
+
+ if (!modbusDevice) {
+ ui->connectButton->setDisabled(true);
+ statusBar()->showMessage(tr("Could not create Modbus client."), 5000);
+ } else {
+ connect(modbusDevice, &QModbusClient::stateChanged,
+ this, &MainWindow::onModbusStateChanged);
+ }
+}
+
+void MainWindow::onConnectButtonClicked()
+{
+ if (!modbusDevice)
+ return;
+
+ statusBar()->clearMessage();
+ if (modbusDevice->state() != QModbusDevice::ConnectedState) {
+ if (static_cast<ModbusConnection>(ui->connectType->currentIndex()) == Serial) {
+ modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
+ ui->portEdit->text());
+#if QT_CONFIG(modbus_serialport)
+ modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
+ m_settingsDialog->settings().parity);
+ modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
+ m_settingsDialog->settings().baud);
+ modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
+ m_settingsDialog->settings().dataBits);
+ modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
+ m_settingsDialog->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(m_settingsDialog->settings().responseTime);
+ modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries);
+ if (!modbusDevice->connectDevice()) {
+ statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
+ } else {
+ ui->actionConnect->setEnabled(false);
+ ui->actionDisconnect->setEnabled(true);
+ }
+ } else {
+ modbusDevice->disconnectDevice();
+ ui->actionConnect->setEnabled(true);
+ ui->actionDisconnect->setEnabled(false);
+ }
+}
+
+void MainWindow::onModbusStateChanged(int state)
+{
+ bool connected = (state != QModbusDevice::UnconnectedState);
+ ui->actionConnect->setEnabled(!connected);
+ ui->actionDisconnect->setEnabled(connected);
+
+ if (state == QModbusDevice::UnconnectedState)
+ ui->connectButton->setText(tr("Connect"));
+ else if (state == QModbusDevice::ConnectedState)
+ ui->connectButton->setText(tr("Disconnect"));
+}
+
+void MainWindow::onReadButtonClicked()
+{
+ if (!modbusDevice)
+ return;
+ ui->readValue->clear();
+ statusBar()->clearMessage();
+
+ 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: ") + modbusDevice->errorString(), 5000);
+ }
+}
+
+void MainWindow::onReadReady()
+{
+ auto reply = qobject_cast<QModbusReply *>(sender());
+ if (!reply)
+ return;
+
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ for (int i = 0, total = int(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();
+}
+
+void MainWindow::onWriteButtonClicked()
+{
+ if (!modbusDevice)
+ return;
+ statusBar()->clearMessage();
+
+ QModbusDataUnit writeUnit = writeRequest();
+ QModbusDataUnit::RegisterType table = writeUnit.registerType();
+ for (int i = 0, total = int(writeUnit.valueCount()); i < total; ++i) {
+ if (table == QModbusDataUnit::Coils)
+ writeUnit.setValue(i, writeModel->m_coils[i + writeUnit.startAddress()]);
+ else
+ writeUnit.setValue(i, writeModel->m_holdingRegisters[i + writeUnit.startAddress()]);
+ }
+
+ if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, ui->serverEdit->value())) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, this, [this, reply]() {
+ if (reply->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 (reply->error() != QModbusDevice::NoError) {
+ statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
+ arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
+ }
+ reply->deleteLater();
+ });
+ } else {
+ // broadcast replies return immediately
+ reply->deleteLater();
+ }
+ } else {
+ statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
+ }
+}
+
+void MainWindow::onReadWriteButtonClicked()
+{
+ if (!modbusDevice)
+ return;
+ ui->readValue->clear();
+ statusBar()->clearMessage();
+
+ QModbusDataUnit writeUnit = writeRequest();
+ QModbusDataUnit::RegisterType table = writeUnit.registerType();
+ for (int i = 0, total = int(writeUnit.valueCount()); i < total; ++i) {
+ if (table == QModbusDataUnit::Coils)
+ writeUnit.setValue(i, writeModel->m_coils[i + writeUnit.startAddress()]);
+ else
+ writeUnit.setValue(i, writeModel->m_holdingRegisters[i + writeUnit.startAddress()]);
+ }
+
+ if (auto *reply = modbusDevice->sendReadWriteRequest(readRequest(), writeUnit,
+ 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: ") + modbusDevice->errorString(), 5000);
+ }
+}
+
+void MainWindow::onWriteTableChanged(int index)
+{
+ const bool coilsOrHolding = index == 0 || index == 3;
+ if (coilsOrHolding) {
+ ui->writeValueTable->setColumnHidden(1, index != 0);
+ ui->writeValueTable->setColumnHidden(2, index != 3);
+ ui->writeValueTable->resizeColumnToContents(0);
+ }
+
+ ui->readWriteButton->setEnabled(index == 3);
+ ui->writeButton->setEnabled(coilsOrHolding);
+ ui->writeGroupBox->setEnabled(coilsOrHolding);
+}
+
+QModbusDataUnit MainWindow::readRequest() const
+{
+ const auto table =
+ static_cast<QModbusDataUnit::RegisterType>(ui->writeTable->currentData().toInt());
+
+ 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);
+}
+
+QModbusDataUnit MainWindow::writeRequest() const
+{
+ const auto table =
+ static_cast<QModbusDataUnit::RegisterType>(ui->writeTable->currentData().toInt());
+
+ int startAddress = ui->writeAddress->value();
+ Q_ASSERT(startAddress >= 0 && startAddress < 10);
+
+ // do not go beyond 10 entries
+ quint16 numberOfEntries = qMin(ui->writeSize->currentText().toUShort(), quint16(10 - startAddress));
+ return QModbusDataUnit(table, startAddress, numberOfEntries);
+}
diff --git a/examples/serialbus/modbus/client/mainwindow.h b/examples/serialbus/modbus/client/mainwindow.h
new file mode 100644
index 0000000..186d004
--- /dev/null
+++ b/examples/serialbus/modbus/client/mainwindow.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QModbusDataUnit>
+
+QT_BEGIN_NAMESPACE
+
+class QModbusClient;
+class QModbusReply;
+
+namespace Ui {
+class MainWindow;
+class SettingsDialog;
+}
+
+QT_END_NAMESPACE
+
+class SettingsDialog;
+class WriteRegisterModel;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = nullptr);
+ ~MainWindow();
+
+private:
+ void initActions();
+ QModbusDataUnit readRequest() const;
+ QModbusDataUnit writeRequest() const;
+
+private slots:
+ void onConnectButtonClicked();
+ void onModbusStateChanged(int state);
+
+ void onReadButtonClicked();
+ void onReadReady();
+
+ void onWriteButtonClicked();
+ void onReadWriteButtonClicked();
+
+ void onConnectTypeChanged(int);
+ void onWriteTableChanged(int);
+
+private:
+ Ui::MainWindow *ui = nullptr;
+ QModbusReply *lastRequest = nullptr;
+ QModbusClient *modbusDevice = nullptr;
+ SettingsDialog *m_settingsDialog = nullptr;
+ WriteRegisterModel *writeModel = nullptr;
+};
+
+#endif // MAINWINDOW_H
diff --git a/examples/serialbus/modbus/client/mainwindow.ui b/examples/serialbus/modbus/client/mainwindow.ui
new file mode 100644
index 0000000..4c4eb4e
--- /dev/null
+++ b/examples/serialbus/modbus/client/mainwindow.ui
@@ -0,0 +1,520 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>516</width>
+ <height>378</height>
+ </rect>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>1000</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Modbus Client Example</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="5">
+ <widget class="QLabel" name="label_27">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Server Address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="7">
+ <widget class="QPushButton" name="connectButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Connect</string>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="6">
+ <widget class="QSpinBox" name="serverEdit">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>247</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="connectType">
+ <item>
+ <property name="text">
+ <string>Serial</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>TCP</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Port:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Connection type:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QLineEdit" name="portEdit">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="minimumSize">
+ <size>
+ <width>250</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Read</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Start address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="readAddress">
+ <property name="maximum">
+ <number>9</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Number of values:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="readSize">
+ <property name="currentIndex">
+ <number>9</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>9</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>10</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Result:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QListWidget" name="readValue">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="writeGroupBox">
+ <property name="minimumSize">
+ <size>
+ <width>225</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Write</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Start address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QTreeView" name="writeValueTable">
+ <property name="showDropIndicator" stdset="0">
+ <bool>true</bool>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
+ </property>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
+ <property name="expandsOnDoubleClick">
+ <bool>false</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>true</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="writeAddress">
+ <property name="maximum">
+ <number>9</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Number of values:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="writeSize">
+ <property name="currentIndex">
+ <number>9</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>9</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>10</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Table:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="writeTable"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>17</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="readButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Read</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="writeButton">
+ <property name="text">
+ <string>Write</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="readWriteButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Read-Write</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>516</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuDevice">
+ <property name="title">
+ <string>&amp;Device</string>
+ </property>
+ <addaction name="actionConnect"/>
+ <addaction name="actionDisconnect"/>
+ <addaction name="separator"/>
+ <addaction name="actionExit"/>
+ </widget>
+ <widget class="QMenu" name="menuToo_ls">
+ <property name="title">
+ <string>Too&amp;ls</string>
+ </property>
+ <addaction name="actionOptions"/>
+ </widget>
+ <addaction name="menuDevice"/>
+ <addaction name="menuToo_ls"/>
+ </widget>
+ <action name="actionConnect">
+ <property name="icon">
+ <iconset resource="client.qrc">
+ <normaloff>:/images/connect.png</normaloff>:/images/connect.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Connect</string>
+ </property>
+ </action>
+ <action name="actionDisconnect">
+ <property name="icon">
+ <iconset resource="client.qrc">
+ <normaloff>:/images/disconnect.png</normaloff>:/images/disconnect.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Disconnect</string>
+ </property>
+ </action>
+ <action name="actionExit">
+ <property name="icon">
+ <iconset resource="client.qrc">
+ <normaloff>:/images/application-exit.png</normaloff>:/images/application-exit.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ </action>
+ <action name="actionOptions">
+ <property name="icon">
+ <iconset resource="client.qrc">
+ <normaloff>:/images/settings.png</normaloff>:/images/settings.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Options</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <tabstops>
+ <tabstop>connectType</tabstop>
+ <tabstop>portEdit</tabstop>
+ <tabstop>serverEdit</tabstop>
+ <tabstop>connectButton</tabstop>
+ <tabstop>readAddress</tabstop>
+ <tabstop>readSize</tabstop>
+ <tabstop>readValue</tabstop>
+ <tabstop>writeAddress</tabstop>
+ <tabstop>writeSize</tabstop>
+ <tabstop>writeValueTable</tabstop>
+ <tabstop>writeTable</tabstop>
+ <tabstop>readButton</tabstop>
+ <tabstop>writeButton</tabstop>
+ <tabstop>readWriteButton</tabstop>
+ </tabstops>
+ <resources>
+ <include location="client.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/examples/serialbus/modbus/client/settingsdialog.cpp b/examples/serialbus/modbus/client/settingsdialog.cpp
new file mode 100644
index 0000000..0a5eb43
--- /dev/null
+++ b/examples/serialbus/modbus/client/settingsdialog.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "settingsdialog.h"
+#include "ui_settingsdialog.h"
+
+SettingsDialog::SettingsDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::SettingsDialog)
+{
+ ui->setupUi(this);
+
+ ui->parityCombo->setCurrentIndex(1);
+#if QT_CONFIG(modbus_serialport)
+ ui->baudCombo->setCurrentText(QString::number(m_settings.baud));
+ ui->dataBitsCombo->setCurrentText(QString::number(m_settings.dataBits));
+ ui->stopBitsCombo->setCurrentText(QString::number(m_settings.stopBits));
+#endif
+ ui->timeoutSpinner->setValue(m_settings.responseTime);
+ ui->retriesSpinner->setValue(m_settings.numberOfRetries);
+
+ connect(ui->applyButton, &QPushButton::clicked, [this]() {
+#if QT_CONFIG(modbus_serialport)
+ m_settings.parity = ui->parityCombo->currentIndex();
+ if (m_settings.parity > 0)
+ m_settings.parity++;
+ m_settings.baud = ui->baudCombo->currentText().toInt();
+ m_settings.dataBits = ui->dataBitsCombo->currentText().toInt();
+ m_settings.stopBits = ui->stopBitsCombo->currentText().toInt();
+#endif
+ m_settings.responseTime = ui->timeoutSpinner->value();
+ m_settings.numberOfRetries = ui->retriesSpinner->value();
+
+ hide();
+ });
+}
+
+SettingsDialog::~SettingsDialog()
+{
+ delete ui;
+}
+
+SettingsDialog::Settings SettingsDialog::settings() const
+{
+ return m_settings;
+}
diff --git a/examples/serialbus/modbus/client/settingsdialog.h b/examples/serialbus/modbus/client/settingsdialog.h
new file mode 100644
index 0000000..fbeb97a
--- /dev/null
+++ b/examples/serialbus/modbus/client/settingsdialog.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SETTINGSDIALOG_H
+#define SETTINGSDIALOG_H
+
+#include <QtSerialBus/qtserialbusglobal.h>
+#include <QDialog>
+#if QT_CONFIG(modbus_serialport)
+#include <QSerialPort>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+class SettingsDialog;
+}
+
+QT_END_NAMESPACE
+
+class SettingsDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ struct Settings {
+#if QT_CONFIG(modbus_serialport)
+ int parity = QSerialPort::EvenParity;
+ int baud = QSerialPort::Baud19200;
+ int dataBits = QSerialPort::Data8;
+ int stopBits = QSerialPort::OneStop;
+#endif
+ int responseTime = 1000;
+ int numberOfRetries = 3;
+ };
+
+ explicit SettingsDialog(QWidget *parent = nullptr);
+ ~SettingsDialog();
+
+ Settings settings() const;
+
+private:
+ Settings m_settings;
+ Ui::SettingsDialog *ui = nullptr;
+};
+
+#endif // SETTINGSDIALOG_H
diff --git a/examples/serialbus/modbus/client/settingsdialog.ui b/examples/serialbus/modbus/client/settingsdialog.ui
new file mode 100644
index 0000000..fb594f4
--- /dev/null
+++ b/examples/serialbus/modbus/client/settingsdialog.ui
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SettingsDialog</class>
+ <widget class="QDialog" name="SettingsDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>239</width>
+ <height>256</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Modbus Settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="3" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>43</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="timeoutSpinner">
+ <property name="accelerated">
+ <bool>true</bool>
+ </property>
+ <property name="suffix">
+ <string> ms</string>
+ </property>
+ <property name="minimum">
+ <number>-1</number>
+ </property>
+ <property name="maximum">
+ <number>5000</number>
+ </property>
+ <property name="singleStep">
+ <number>20</number>
+ </property>
+ <property name="value">
+ <number>200</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Response Timeout:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QPushButton" name="applyButton">
+ <property name="text">
+ <string>Apply</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Serial Parameters</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Parity:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="parityCombo">
+ <item>
+ <property name="text">
+ <string>No</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Even</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Odd</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Space</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Mark</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Baud Rate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="baudCombo">
+ <item>
+ <property name="text">
+ <string>1200</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2400</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4800</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>9600</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>19200</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>38400</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>57600</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>115200</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Data Bits:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="dataBitsCombo">
+ <item>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Stop Bits:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="stopBitsCombo">
+ <item>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Number of retries:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="retriesSpinner">
+ <property name="value">
+ <number>3</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/serialbus/modbus/client/writeregistermodel.cpp b/examples/serialbus/modbus/client/writeregistermodel.cpp
new file mode 100644
index 0000000..441f643
--- /dev/null
+++ b/examples/serialbus/modbus/client/writeregistermodel.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "writeregistermodel.h"
+
+enum { NumColumn = 0, CoilsColumn = 1, HoldingColumn = 2, ColumnCount = 3, RowCount = 10 };
+
+WriteRegisterModel::WriteRegisterModel(QObject *parent)
+ : QAbstractTableModel(parent),
+ m_coils(RowCount, false), m_holdingRegisters(RowCount, 0u)
+{
+}
+
+int WriteRegisterModel::rowCount(const QModelIndex &/*parent*/) const
+{
+ return RowCount;
+}
+
+int WriteRegisterModel::columnCount(const QModelIndex &/*parent*/) const
+{
+ return ColumnCount;
+}
+
+QVariant WriteRegisterModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
+ return QVariant();
+
+ Q_ASSERT(m_coils.count() == RowCount);
+ Q_ASSERT(m_holdingRegisters.count() == RowCount);
+
+ if (index.column() == NumColumn && role == Qt::DisplayRole)
+ return QString::number(index.row());
+
+ if (index.column() == CoilsColumn && role == Qt::CheckStateRole) // coils
+ return m_coils.at(index.row()) ? Qt::Checked : Qt::Unchecked;
+
+ if (index.column() == HoldingColumn && role == Qt::DisplayRole) // holding registers
+ return QString("0x%1").arg(QString::number(m_holdingRegisters.at(index.row()), 16));
+
+ return QVariant();
+
+}
+
+QVariant WriteRegisterModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Horizontal) {
+ switch (section) {
+ case NumColumn:
+ return QStringLiteral("#");
+ case CoilsColumn:
+ return QStringLiteral("Coils ");
+ case HoldingColumn:
+ return QStringLiteral("Holding Registers");
+ default:
+ break;
+ }
+ }
+ return QVariant();
+}
+
+bool WriteRegisterModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
+ return false;
+
+ Q_ASSERT(m_coils.count() == RowCount);
+ Q_ASSERT(m_holdingRegisters.count() == RowCount);
+
+ if (index.column() == CoilsColumn && role == Qt::CheckStateRole) { // coils
+ auto s = static_cast<Qt::CheckState>(value.toUInt());
+ s == Qt::Checked ? m_coils.setBit(index.row()) : m_coils.clearBit(index.row());
+ emit dataChanged(index, index);
+ return true;
+ }
+
+ if (index.column() == HoldingColumn && role == Qt::EditRole) { // holding registers
+ bool result = false;
+ quint16 newValue = value.toString().toUShort(&result, 16);
+ if (result)
+ m_holdingRegisters[index.row()] = newValue;
+
+ emit dataChanged(index, index);
+ return result;
+ }
+
+ return false;
+}
+
+Qt::ItemFlags WriteRegisterModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
+ return QAbstractTableModel::flags(index);
+
+ Qt::ItemFlags flags = QAbstractTableModel::flags(index);
+ if ((index.row() < m_address) || (index.row() >= (m_address + m_number)))
+ flags &= ~Qt::ItemIsEnabled;
+
+ if (index.column() == CoilsColumn) // coils
+ return flags | Qt::ItemIsUserCheckable;
+ if (index.column() == HoldingColumn) // holding registers
+ return flags | Qt::ItemIsEditable;
+
+ return flags;
+}
+
+void WriteRegisterModel::setStartAddress(int address)
+{
+ m_address = address;
+ emit updateViewport();
+}
+
+void WriteRegisterModel::setNumberOfValues(const QString &number)
+{
+ m_number = number.toInt();
+ emit updateViewport();
+}
diff --git a/examples/serialbus/modbus/client/writeregistermodel.h b/examples/serialbus/modbus/client/writeregistermodel.h
new file mode 100644
index 0000000..4f29812
--- /dev/null
+++ b/examples/serialbus/modbus/client/writeregistermodel.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WRITEREGISTERMODEL_H
+#define WRITEREGISTERMODEL_H
+
+#include <QAbstractItemModel>
+#include <QBitArray>
+#include <QObject>
+
+class WriteRegisterModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ WriteRegisterModel(QObject *parent = nullptr);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+
+public slots:
+ void setStartAddress(int address);
+ void setNumberOfValues(const QString &number);
+
+signals:
+ void updateViewport();
+
+public:
+ int m_number = 0;
+ int m_address = 0;
+ QBitArray m_coils;
+ QList<quint16> m_holdingRegisters;
+};
+
+#endif // WRITEREGISTERMODEL_H