#include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); modbusMaster = new QModbusRtuSerialClient(this); modbusMaster->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity); modbusMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600); modbusMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8); modbusMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop); modbusMaster->setTimeout(1000); modbusMaster->setNumberOfRetries(3); connect(modbusMaster, &QModbusRtuSerialClient::stateChanged, this, [&](QModbusDevice::State state) { switch (state) { case QModbusDevice::ConnectingState: setConnectionState(ConnectionState::Connecting); break; case QModbusDevice::ConnectedState: setConnectionState(ConnectionState::Connected); break; case QModbusDevice::UnconnectedState: setConnectionState(ConnectionState::Disconnected); break; default: break; } }); readTimer = new QTimer(this); connect(readTimer, &QTimer::timeout, this, [&]() { QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::InputRegisters, 0, 1); if (modbusMaster->state() != QModbusDevice::ConnectedState) return; if (auto reply = modbusMaster->sendReadRequest(request, 1)) { if (!reply->isFinished()) { connect(reply, &QModbusReply::finished, this, [&]() { parseReply(qobject_cast(sender())); }); } else { parseReply(reply); } } }); connectionTimer = new QTimer(this); connect(connectionTimer, &QTimer::timeout, this, [&]() { if (modbusMaster->state() == QModbusDevice::State::UnconnectedState) { if (!modbusMaster->connectDevice()) setConnectionState(ConnectionState::TimeOut); } }); connect(ui->serialPortListRefreshButton, &QPushButton::clicked, this, [&]() { const auto infos = QSerialPortInfo::availablePorts(); ui->serialPortListBox->clear(); for (const QSerialPortInfo &info : infos) ui->serialPortListBox->addItem(info.portName()); }); emit ui->serialPortListRefreshButton->clicked(); setConnectionState(ConnectionState::Disconnected); } MainWindow::~MainWindow() { readTimer->stop(); connectionTimer->stop(); if (modbusMaster) { modbusMaster->disconnectDevice(); delete modbusMaster; } delete ui; } void MainWindow::on_connectButton_clicked() { readTimer->stop(); connectionTimer->stop(); if (modbusMaster->state() == QModbusDevice::State::UnconnectedState) { modbusMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter, ui->serialPortListBox->currentText()); if (!modbusMaster->connectDevice()) setConnectionState(ConnectionState::Error); readTimer->start(500); connectionTimer->start(100); } else { modbusMaster->disconnectDevice(); } } void MainWindow::setConnectionState(ConnectionState state) { ui->statusLabel->setStyleSheet("color: black"); switch (state) { case ConnectionState::Connected: ui->statusLabel->setText(tr("Connected.")); break; case ConnectionState::Disconnected: ui->statusLabel->setText(tr("Disconnected.")); break; case ConnectionState::Connecting: ui->statusLabel->setText(tr("Connecting...")); break; case ConnectionState::TimeOut: ui->statusLabel->setStyleSheet("color: red"); ui->statusLabel->setText(tr("Connection timed out.")); break; case ConnectionState::Error: ui->statusLabel->setStyleSheet("color: red"); ui->statusLabel->setText(tr("Connection failed.")); break; default: break; } ui->serialPortListBox->setEnabled(state != ConnectionState::Connected); ui->serialPortListRefreshButton->setEnabled(state != ConnectionState::Connected); ui->connectButton->setText(state == ConnectionState::Connected ? tr("Disconnect") : tr("Connect")); } void MainWindow::parseReply(QModbusReply *reply) { if (!reply) return; if (reply->error() != QModbusDevice::NoError) return; ui->inputRegister0->setText(QString("%1").arg(reply->result().value(0), 2, 16, QChar('0')).toUpper()); }