#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include "settingdialog.h"
#include <QModbusRtuSerialMaster>
#include <QModbusReply>
#include <QStandardItemModel>
#include <QModbusDataUnit>
#include <QModbusTcpClient>
//连接类型枚举变量
enum ModbusConnection {
Serial,
Tcp
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建对象
m_settingDialog = new SettingDialog(this);
//初始化信号与槽
initActions();
//创建写模型
writeModel = new WriteRegisterModel(this);
writeModel->setStartAddress(ui->sbWriteStartAddr->value());
writeModel->setNumberOfValues(ui->cbWriteCount->currentText());
//MVC
ui->treeViewWrite->setModel(writeModel);
//隐藏第二列
ui->treeViewWrite->hideColumn(2);
connect(writeModel, &WriteRegisterModel::updateViewport,
ui->treeViewWrite->viewport(), QOverload<>::of(&QWidget::update));
//默认为串口连接方式
ui->cbConnType->setCurrentIndex(0);
onConnectTypeChanged(0);
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->cbWriteCount->setModel(model);
ui->cbWriteCount->setCurrentText("10");
connect(ui->cbWriteCount, &QComboBox::currentTextChanged,
writeModel, &WriteRegisterModel::setNumberOfValues);
auto valueChanged = QOverload<int>::of(&QSpinBox::valueChanged);
connect(ui->sbWriteStartAddr, valueChanged, writeModel, &WriteRegisterModel::setStartAddress);
connect(ui->sbWriteStartAddr, valueChanged, this, [this, model](int i){
int lastIndex = 0;
const int curIndex = ui->cbWriteCount->currentIndex();
for (int j = 0; j < 10; j++)
{
//设置使能
if (j < (10 - i))
{
lastIndex = j;
model->item(j)->setEnabled(true);
}
else
{
//设置禁用
model->item(j)->setEnabled(false);
}
}
if (curIndex > lastIndex)
{
ui->cbWriteCount->setCurrentIndex(lastIndex);
}
});
}
//析构函数
MainWindow::~MainWindow()
{
if (modbusDevice)
{
modbusDevice->disconnectDevice();
delete modbusDevice;
}
delete ui;
}
//信号与槽进行关联s
void MainWindow::initActions()
{
//使能部分功能
ui->actionConnect->setEnabled(true);
ui->actionDisconnect->setEnabled(false);
ui->actionQuit->setEnabled(true);
ui->actionOption->setEnabled(true);
//禁用读写操作
ui->btnRead->setEnabled(false);
ui->btnWrite->setEnabled(false);
ui->btnReadWrite->setEnabled(false);
//信号与槽关联
connect(ui->btnConnect, &QPushButton::clicked,
this, &MainWindow::onConnectButtonClicked);
connect(ui->actionConnect, &QAction::triggered,
this, &MainWindow::onConnectButtonClicked);
connect(ui->actionDisconnect, &QAction::triggered,
this, &MainWindow::onConnectButtonClicked);
//读操作按钮槽函数关联
connect(ui->btnRead, &QPushButton::clicked,
this, &MainWindow::onReadButtonClicked);
connect(ui->btnWrite, &QPushButton::clicked,
this, &MainWindow::onWriteButtonClicked);
connect(ui->btnReadWrite, &QPushButton::clicked,
this, &MainWindow::onReadWriteButtonClicked);
connect(ui->cbRegisterType, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MainWindow::onWriteTableChanged);
connect(ui->cbConnType, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MainWindow::onConnectTypeChanged);
//退出菜单
connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::close);
//显示参数设置对话框
connect(ui->actionOption, &QAction::triggered, m_settingDialog, &QDialog::show);
connect(ui->actionAbout, &QAction::triggered, [=]() {
QMessageBox::aboutQt(this, "About Qt");
});
}
//构建请求报文
QModbusDataUnit MainWindow::readRequest() const
{
//const auto type = static_cast<QModbusDataUnit::RegisterType>(ui->cbRegisterType->currentData().toInt());
QModbusDataUnit::RegisterType type = QModbusDataUnit::Invalid;
qDebug() << ui->cbRegisterType->currentText();
if (ui->cbRegisterType->currentText() == QString("线圈"))
{
type = QModbusDataUnit::Coils;
}
else if (ui->cbRegisterType->currentText() == QString("离散输入"))
{
type = QModbusDataUnit::DiscreteInputs;
}
else if (ui->cbRegisterType->currentText() == QString("输入寄存器"))
{
type = QModbusDataUnit::InputRegisters;
}
else if (ui->cbRegisterType->currentText() == QString("保持寄存器"))
{
type = QModbusDataUnit::HoldingRegisters;
}
qDebug() << "请求报文类型: " << type;
//获取
int startAddress = ui->spReadStartAddr->value();
Q_ASSERT(startAddress >= 0 && startAddress < 10);
quint16 numberOfEntries = ui->cbReadCount->currentText().toUShort();
return QModbusDataUnit(type, startAddress, numberOfEntries);
}
//写请求数据包封装
QModbusDataUnit MainWindow::writeRequest() const
{
QModbusDataUnit::RegisterType type = QModbusDataUnit::Invalid;
qDebug() << ui->cbRegisterType->currentText();
if (ui->cbRegisterType->currentText() == QString("线圈"))
{
type = QModbusDataUnit::Coils;
}
else if (ui->cbRegisterType->currentText() == QString("离散输入"))
{
type = QModbusDataUnit::DiscreteInputs;
}
else if (ui->cbRegisterType->currentText() == QString("输入寄存器"))
{
type = QModbusDataUnit::InputRegisters;
}
else if (ui->cbRegisterType->currentText() == QString("保持寄存器"))
{
type = QModbusDataUnit::HoldingRegisters;
}
qDebug() << "请求报文类型: " << type;
//获取
int startAddress = ui->sbWriteStartAddr->value();
Q_ASSERT(startAddress >= 0 && startAddress < 10);
quint16 numberOfEntries = ui->cbWriteCount->currentText().toUShort();
//qDebug() << "Test: " << startAddress << " " << numberOfEntries;
return QModbusDataUnit(type, startAddress, numberOfEntries);
}
//连接和断开连接的槽函数
void MainWindow::onConnectButtonClicked()
{
if (!modbusDevice)
{
return;
}
//清空状态栏消息
statusBar()->clearMessage();
if (modbusDevice->state() != QModbusDevice::ConnectedState)
{
auto type = static_cast<ModbusConnection>(ui->cbConnType->currentIndex());
if (type == Serial)
{
//设置串口连接信息
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
m_settingDialog->settings().serialName);
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
m_settingDialog->settings().parity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
m_settingDialog->settings().baud);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
m_settingDialog->settings().dataBits);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
m_settingDialog->settings().stopBits);