|
|
@@ -21,7 +21,8 @@ MainWindow::MainWindow(QWidget *parent)
|
|
|
m_dataTable(new QTableView(this)),
|
|
|
m_serial_settingsModel(new QStandardItemModel(this)),
|
|
|
m_deviceModel(new QStandardItemModel(this)),
|
|
|
- m_dataModel(new QStandardItemModel(this)),
|
|
|
+ m_raw_dataModel(new QStandardItemModel(this)),
|
|
|
+ m_bus_dataModel(new QStandardItemModel(this)),
|
|
|
m_dataSeries(new QLineSeries())
|
|
|
{
|
|
|
ui->setupUi(this);
|
|
|
@@ -61,8 +62,9 @@ void MainWindow::initializeSystem()
|
|
|
DeviceInfo device;
|
|
|
device.id = portName;
|
|
|
device.type = "serial";
|
|
|
- device.address = portName;
|
|
|
+ device.address = 1;
|
|
|
device.protocol = "modbus"; // 默认协议
|
|
|
+ device.protocol_detail = "modbus-rtu";
|
|
|
m_busCore->registerDevice(device);
|
|
|
}
|
|
|
}
|
|
|
@@ -72,6 +74,8 @@ void MainWindow::createUI()
|
|
|
// 左侧设备列表
|
|
|
ui->listV_device->setModel(m_deviceModel);
|
|
|
|
|
|
+ ui->lineEdit_serial_send->setText("01 03 01 00 00 5C 44 0F ");
|
|
|
+
|
|
|
// 右侧数据表格(上方为配置表格 ,下方为图表) )
|
|
|
ui->tableV_serial_set->setModel(m_serial_settingsModel);
|
|
|
ui->tableV_serial_set->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
|
|
@@ -100,13 +104,20 @@ void MainWindow::createUI()
|
|
|
m_serial_settingsModel->appendRow(flowControlRow);
|
|
|
|
|
|
// Raw Data Table
|
|
|
- ui->tableV_raw_data->setModel(m_dataModel);
|
|
|
- m_dataModel->setHorizontalHeaderLabels({"时间", "来源", "协议", "数据"});
|
|
|
+ ui->tableV_raw_data->setModel(m_raw_dataModel);
|
|
|
+ m_raw_dataModel->setHorizontalHeaderLabels({"时间", "来源", "协议", "数据"});
|
|
|
ui->tableV_raw_data->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
|
|
ui->tableV_raw_data->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
|
ui->tableV_raw_data->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
ui->tableV_raw_data->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
|
|
+ // Bus Data Table
|
|
|
+ ui->tableV_bus_data->setModel(m_bus_dataModel);
|
|
|
+ m_bus_dataModel->setHorizontalHeaderLabels({"时间", "来源", "协议", "数据"});
|
|
|
+ ui->tableV_bus_data->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
|
|
+ ui->tableV_bus_data->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
|
+ ui->tableV_bus_data->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
+ ui->tableV_bus_data->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
// ui->tableV_bus_data->setModel();
|
|
|
}
|
|
|
|
|
|
@@ -120,7 +131,7 @@ void MainWindow::createConnections()
|
|
|
connect(m_busCore, &SoftBusCore::busMessageStored, this, &MainWindow::updateChart);
|
|
|
|
|
|
// 设备选择信号
|
|
|
- connect(ui->listV_device->selectionModel(), &QItemSelectionModel::currentChanged,this, &MainWindow::onDeviceSelected);
|
|
|
+ connect(ui->listV_device->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::onDeviceSelected);
|
|
|
|
|
|
// 串口管理器信号
|
|
|
connect(m_serialManager, &SerialManager::portDiscovered, this, [this](const QString &portName, const QString &desc)
|
|
|
@@ -163,12 +174,13 @@ void MainWindow::onDeviceSelected(const QModelIndex &index)
|
|
|
|
|
|
showRawData(deviceId);
|
|
|
showBusMessages(deviceId);
|
|
|
+ modbusSetting_ui(deviceId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void MainWindow::showRawData(const QString &deviceId)
|
|
|
{
|
|
|
- m_dataModel->removeRows(0, m_dataModel->rowCount());
|
|
|
+ m_raw_dataModel->removeRows(0, m_raw_dataModel->rowCount());
|
|
|
|
|
|
// 查询最近10分钟的原始数据
|
|
|
qint64 endTime = QDateTime::currentMSecsSinceEpoch();
|
|
|
@@ -185,7 +197,7 @@ void MainWindow::showRawData(const QString &deviceId)
|
|
|
row << new QStandardItem(deviceId);
|
|
|
row << new QStandardItem("RAW");
|
|
|
row << new QStandardItem(data.mid(8).toHex());
|
|
|
- m_dataModel->appendRow(row);
|
|
|
+ m_raw_dataModel->appendRow(row);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -217,7 +229,7 @@ void MainWindow::showBusMessages(const QString &source)
|
|
|
}
|
|
|
|
|
|
row << new QStandardItem(dataStr);
|
|
|
- m_dataModel->appendRow(row);
|
|
|
+ m_bus_dataModel->appendRow(row);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -254,7 +266,6 @@ void MainWindow::on_btn_serial_clear_clicked()
|
|
|
ui->textEdit_serial->clear();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
void MainWindow::on_btn_serial_clear_send_clicked()
|
|
|
{
|
|
|
ui->lineEdit_serial_send->clear();
|
|
|
@@ -263,26 +274,31 @@ void MainWindow::on_btn_serial_clear_send_clicked()
|
|
|
// 发送串口数据
|
|
|
void MainWindow::on_btn_serial_send_clicked()
|
|
|
{
|
|
|
- if (!m_serialManager->isPortOpen(m_currentDeviceId)) {
|
|
|
+ if (!m_serialManager->isPortOpen(m_currentDeviceId))
|
|
|
+ {
|
|
|
QMessageBox::warning(this, "串口未打开", "请先打开串口设备");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
QString dataToSend = ui->lineEdit_serial_send->text();
|
|
|
|
|
|
- if (dataToSend.isEmpty()) {
|
|
|
+ if (dataToSend.isEmpty())
|
|
|
+ {
|
|
|
QMessageBox::information(this, "发送数据", "请输入要发送的数据");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 根据当前显示模式处理数据
|
|
|
- if (ui->checkBox_serial_hex->isChecked()) {
|
|
|
+ if (ui->checkbox_serial_hex->isChecked())
|
|
|
+ {
|
|
|
// 十六进制模式 - 将输入视为十六进制字符串
|
|
|
QByteArray hexData = QByteArray::fromHex(dataToSend.toLatin1());
|
|
|
- m_serialManager->writeData(m_currentDeviceId,hexData);
|
|
|
- } else {
|
|
|
+ m_serialManager->writeData(m_currentDeviceId, hexData);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
// ASCII模式 - 直接发送文本
|
|
|
- m_serialManager->writeData(m_currentDeviceId,dataToSend.toUtf8());
|
|
|
+ m_serialManager->writeData(m_currentDeviceId, dataToSend.toUtf8());
|
|
|
}
|
|
|
|
|
|
// 在接收区显示发送的数据(带发送标记)
|
|
|
@@ -301,10 +317,13 @@ void MainWindow::onSerialDataReceived(const QString &portName, const QByteArray
|
|
|
QString displayData;
|
|
|
QString timestamp = QDateTime::currentDateTime().toString("[hh:mm:ss]");
|
|
|
|
|
|
- if (ui->checkBox_serial_hex->isChecked()) {
|
|
|
+ if (ui->checkbox_serial_hex->isChecked())
|
|
|
+ {
|
|
|
// 十六进制显示
|
|
|
displayData = data.toHex(' ').toUpper();
|
|
|
- } else {
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
// ASCII显示
|
|
|
displayData = QString::fromUtf8(data);
|
|
|
|
|
|
@@ -321,9 +340,9 @@ void MainWindow::onSerialDataReceived(const QString &portName, const QByteArray
|
|
|
}
|
|
|
|
|
|
// 切换显示模式
|
|
|
-void MainWindow::on_checkBox_serial_hex_toggled(bool checked)
|
|
|
+void MainWindow::on_checkbox_serial_hex_toggled(bool checked)
|
|
|
{
|
|
|
- ui->checkBox_serial_ascii->setChecked(!checked);
|
|
|
+ ui->checkbox_serial_ascii->setChecked(!checked);
|
|
|
|
|
|
// 重新显示当前内容
|
|
|
QString currentText = ui->textEdit_serial->toPlainText();
|
|
|
@@ -331,12 +350,460 @@ void MainWindow::on_checkBox_serial_hex_toggled(bool checked)
|
|
|
ui->textEdit_serial->setText(currentText);
|
|
|
}
|
|
|
|
|
|
-void MainWindow::on_checkBox_serial_ascii_toggled(bool checked)
|
|
|
+void MainWindow::on_checkbox_serial_ascii_toggled(bool checked)
|
|
|
{
|
|
|
- ui->checkBox_serial_hex->setChecked(!checked);
|
|
|
+ ui->checkbox_serial_hex->setChecked(!checked);
|
|
|
|
|
|
// 重新显示当前内容
|
|
|
QString currentText = ui->textEdit_serial->toPlainText();
|
|
|
ui->textEdit_serial->clear();
|
|
|
ui->textEdit_serial->setText(currentText);
|
|
|
}
|
|
|
+// 后续使用新的界面,这里是串口的modbus的相关设置
|
|
|
+
|
|
|
+void MainWindow::modbusSetting_ui(const QString &deviceId)
|
|
|
+{
|
|
|
+ // 查询设备相关数据
|
|
|
+ DeviceInfo device;
|
|
|
+ device = m_busCore->getDeviceInfo(deviceId);
|
|
|
+ if (device.id == "")
|
|
|
+ return;
|
|
|
+ // 设置协议类型
|
|
|
+ if (device.protocol == "modbus")
|
|
|
+ {
|
|
|
+ if (device.protocol_detail == "modbus-rtu")
|
|
|
+ {
|
|
|
+ ui->checkbox_modbus_rtu->setChecked(true);
|
|
|
+ ui->checkbox_modbus_ascii->setChecked(false);
|
|
|
+ ui->checkbox_modbus_tcp->setChecked(false);
|
|
|
+ }
|
|
|
+ else if (device.protocol_detail == "modbus-ascii")
|
|
|
+ {
|
|
|
+ ui->checkbox_modbus_rtu->setChecked(false);
|
|
|
+ ui->checkbox_modbus_ascii->setChecked(true);
|
|
|
+ ui->checkbox_modbus_tcp->setChecked(false);
|
|
|
+ }
|
|
|
+ else if (device.protocol_detail == "modbus-tcp")
|
|
|
+ {
|
|
|
+ ui->checkbox_modbus_rtu->setChecked(false);
|
|
|
+ ui->checkbox_modbus_ascii->setChecked(false);
|
|
|
+ ui->checkbox_modbus_tcp->setChecked(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ui->checkbox_modbus_rtu->setChecked(false);
|
|
|
+ ui->checkbox_modbus_ascii->setChecked(false);
|
|
|
+ ui->checkbox_modbus_tcp->setChecked(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 其他设置
|
|
|
+
|
|
|
+ ui->spinBox_modbus_slave_id->setValue(device.address);
|
|
|
+
|
|
|
+ // 添加modbus指令
|
|
|
+ ui->comboBox_modbus_control_list->clear();
|
|
|
+ //
|
|
|
+ QList<QByteArray> modbus_control_list = {
|
|
|
+ "01 读线圈",
|
|
|
+ "02 读离散输入",
|
|
|
+ "03 读输入寄存器",
|
|
|
+ "04 读保持寄存器",
|
|
|
+ "05 写单个线圈",
|
|
|
+ "06 写单个寄存器",
|
|
|
+ "15 写多个线圈",
|
|
|
+ "16 写多个寄存器"};
|
|
|
+
|
|
|
+ for (const QByteArray &control : modbus_control_list)
|
|
|
+ {
|
|
|
+ ui->comboBox_modbus_control_list->addItem(control);
|
|
|
+ }
|
|
|
+ // 添加信号连接
|
|
|
+ connect(ui->comboBox_modbus_control_list, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
|
|
+ this, &MainWindow::onModbusControlChanged);
|
|
|
+
|
|
|
+ // 添加按钮连接
|
|
|
+ connect(ui->btn_confirm_modbus_set, &QPushButton::clicked,
|
|
|
+ this, &MainWindow::onConfirmModbusSet);
|
|
|
+
|
|
|
+ connect(ui->btn_gen_modbus_datagram, &QPushButton::clicked,
|
|
|
+ this, &MainWindow::onGenerateModbusDatagram);
|
|
|
+
|
|
|
+ // 初始更新配置表格
|
|
|
+ QString funcCode = device.properties["function_code"].toString();
|
|
|
+ int index = ui->comboBox_modbus_control_list->findText(funcCode, Qt::MatchStartsWith);
|
|
|
+ if (index != -1)
|
|
|
+ {
|
|
|
+ ui->comboBox_modbus_control_list->setCurrentIndex(index);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ui->comboBox_modbus_control_list->setCurrentIndex(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void MainWindow::onModbusControlChanged(int index)
|
|
|
+{
|
|
|
+ // 清除现有模型
|
|
|
+ QStandardItemModel *model = new QStandardItemModel(this);
|
|
|
+ ui->tableV_serial_modbus_set->setModel(model);
|
|
|
+ ui->tableV_serial_modbus_set->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
|
|
+ model->setHorizontalHeaderLabels({"参数", "值"});
|
|
|
+
|
|
|
+ // 获取当前选择的功能码
|
|
|
+ QString selectedText = ui->comboBox_modbus_control_list->itemText(index);
|
|
|
+ QString funcCode = selectedText.left(2);
|
|
|
+
|
|
|
+ // 根据功能码设置不同的配置项
|
|
|
+ if (funcCode == "01" || funcCode == "02")
|
|
|
+ {
|
|
|
+ // 读线圈/离散输入
|
|
|
+ model->appendRow(createRow("起始地址", "0"));
|
|
|
+ model->appendRow(createRow("线圈数量", "1"));
|
|
|
+ }
|
|
|
+ else if (funcCode == "03" || funcCode == "04")
|
|
|
+ {
|
|
|
+ // 读输入/保持寄存器
|
|
|
+ model->appendRow(createRow("起始地址", "0"));
|
|
|
+ model->appendRow(createRow("寄存器数量", "1"));
|
|
|
+ }
|
|
|
+ else if (funcCode == "05")
|
|
|
+ {
|
|
|
+ // 写单个线圈
|
|
|
+ model->appendRow(createRow("线圈地址", "0"));
|
|
|
+ model->appendRow(createRow("线圈状态", "0 (OFF)"));
|
|
|
+ }
|
|
|
+ else if (funcCode == "06")
|
|
|
+ {
|
|
|
+ // 写单个寄存器
|
|
|
+ model->appendRow(createRow("寄存器地址", "0"));
|
|
|
+ model->appendRow(createRow("寄存器值", "0"));
|
|
|
+ }
|
|
|
+ else if (funcCode == "15")
|
|
|
+ {
|
|
|
+ // 写多个线圈
|
|
|
+ model->appendRow(createRow("起始地址", "0"));
|
|
|
+ model->appendRow(createRow("线圈数量", "1"));
|
|
|
+ model->appendRow(createRow("线圈状态", "0 (OFF)"));
|
|
|
+ }
|
|
|
+ else if (funcCode == "16")
|
|
|
+ {
|
|
|
+ // 写多个寄存器
|
|
|
+ model->appendRow(createRow("起始地址", "0"));
|
|
|
+ model->appendRow(createRow("寄存器数量", "1"));
|
|
|
+ model->appendRow(createRow("寄存器值", "0"));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void MainWindow::onConfirmModbusSet()
|
|
|
+{
|
|
|
+ // 获取当前选中的设备
|
|
|
+ QModelIndex index = ui->listV_device->currentIndex();
|
|
|
+ if (!index.isValid())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ QString deviceId = index.data(Qt::UserRole).toString();
|
|
|
+
|
|
|
+ // 获取设备信息
|
|
|
+ DeviceInfo device = m_busCore->getDeviceInfo(deviceId);
|
|
|
+ if (device.id.isEmpty())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新协议细节
|
|
|
+ if (ui->checkbox_modbus_rtu->isChecked())
|
|
|
+ {
|
|
|
+ device.protocol_detail = "modbus-rtu";
|
|
|
+ }
|
|
|
+ else if (ui->checkbox_modbus_ascii->isChecked())
|
|
|
+ {
|
|
|
+ device.protocol_detail = "modbus-ascii";
|
|
|
+ }
|
|
|
+ else if (ui->checkbox_modbus_tcp->isChecked())
|
|
|
+ {
|
|
|
+ device.protocol_detail = "modbus-tcp";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新从站地址
|
|
|
+ device.address = ui->spinBox_modbus_slave_id->value();
|
|
|
+
|
|
|
+ // 更新Modbus配置
|
|
|
+ QJsonObject properties;
|
|
|
+ properties["slave_id"] = ui->spinBox_modbus_slave_id->value();
|
|
|
+ properties["function_code"] = ui->comboBox_modbus_control_list->currentText().left(2);
|
|
|
+
|
|
|
+ // 保存表格中的配置参数
|
|
|
+ QStandardItemModel *model = qobject_cast<QStandardItemModel *>(ui->tableV_serial_modbus_set->model());
|
|
|
+ if (model)
|
|
|
+ {
|
|
|
+ for (int row = 0; row < model->rowCount(); ++row)
|
|
|
+ {
|
|
|
+ if (model->item(row, 0)->text() == "起始地址")
|
|
|
+ {
|
|
|
+ properties["start_address"] = model->item(row, 1)->text();
|
|
|
+ }
|
|
|
+ else if (model->item(row, 0)->text() == "线圈数量")
|
|
|
+ {
|
|
|
+ properties["coils_count"] = model->item(row, 1)->text();
|
|
|
+ }
|
|
|
+ else if (model->item(row, 0)->text() == "寄存器数量")
|
|
|
+ {
|
|
|
+ properties["registers_count"] = model->item(row, 1)->text();
|
|
|
+ }
|
|
|
+ else if (model->item(row, 0)->text() == "线圈地址")
|
|
|
+ {
|
|
|
+ properties["coil_address"] = model->item(row, 1)->text();
|
|
|
+ }
|
|
|
+ else if (model->item(row, 0)->text() == "线圈状态")
|
|
|
+ {
|
|
|
+ properties["coil_state"] = model->item(row, 1)->text();
|
|
|
+ }
|
|
|
+ else if (model->item(row, 0)->text() == "寄存器地址")
|
|
|
+ {
|
|
|
+ properties["register_address"] = model->item(row, 1)->text();
|
|
|
+ }
|
|
|
+ else if (model->item(row, 0)->text() == "寄存器值")
|
|
|
+ {
|
|
|
+ properties["register_value"] = model->item(row, 1)->text();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 忽略其他参数
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ device.properties = properties;
|
|
|
+
|
|
|
+ // 更新设备信息
|
|
|
+ m_busCore->updateDevice(device);
|
|
|
+
|
|
|
+ QMessageBox::information(this, "配置保存", "Modbus配置已成功保存");
|
|
|
+}
|
|
|
+void MainWindow::onGenerateModbusDatagram()
|
|
|
+{
|
|
|
+ // 获取当前选中的设备
|
|
|
+ QModelIndex index = ui->listV_device->currentIndex();
|
|
|
+ if (!index.isValid())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ QString deviceId = index.data(Qt::UserRole).toString();
|
|
|
+
|
|
|
+ // 获取设备信息
|
|
|
+ DeviceInfo device = m_busCore->getDeviceInfo(deviceId);
|
|
|
+ if (device.id.isEmpty() || !device.properties.contains("function_code"))
|
|
|
+ {
|
|
|
+ QMessageBox::warning(this, "生成报文", "请先配置Modbus参数");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取功能码
|
|
|
+ QString funcCodeStr = device.properties["function_code"].toString();
|
|
|
+ bool ok;
|
|
|
+ int funcCode = funcCodeStr.toInt(&ok);
|
|
|
+ if (!ok)
|
|
|
+ {
|
|
|
+ QMessageBox::warning(this, "生成报文", "无效的功能码");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成Modbus报文
|
|
|
+ QByteArray datagram;
|
|
|
+
|
|
|
+ // 添加从站地址
|
|
|
+ datagram.append(static_cast<char>(device.address));
|
|
|
+
|
|
|
+ // 添加功能码
|
|
|
+ datagram.append(static_cast<char>(funcCode));
|
|
|
+
|
|
|
+ // 根据功能码添加数据
|
|
|
+ switch (funcCode)
|
|
|
+ {
|
|
|
+ case 1: // 读线圈
|
|
|
+ case 2: // 读离散输入
|
|
|
+ case 3: // 读输入寄存器
|
|
|
+ case 4:
|
|
|
+ { // 读保持寄存器
|
|
|
+ int startAddr = device.properties["start_address"].toString().toInt();
|
|
|
+ int count = device.properties["registers_count"].toString().toInt();
|
|
|
+
|
|
|
+ datagram.append(static_cast<char>((startAddr >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(startAddr & 0xFF));
|
|
|
+ datagram.append(static_cast<char>((count >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(count & 0xFF));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 5:
|
|
|
+ { // 写单个线圈
|
|
|
+ int coilAddr = device.properties["coil_address"].toString().toInt();
|
|
|
+ int coilState = device.properties["coil_state"].toString().toInt();
|
|
|
+
|
|
|
+ datagram.append(static_cast<char>((coilAddr >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(coilAddr & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(coilState ? 0xFF : 0x00));
|
|
|
+ datagram.append(static_cast<char>(0x00));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 6:
|
|
|
+ { // 写单个寄存器
|
|
|
+ int regAddr = device.properties["register_address"].toString().toInt();
|
|
|
+ int regValue = device.properties["register_value"].toString().toInt();
|
|
|
+
|
|
|
+ datagram.append(static_cast<char>((regAddr >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(regAddr & 0xFF));
|
|
|
+ datagram.append(static_cast<char>((regValue >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(regValue & 0xFF));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 15:
|
|
|
+ { // 写多个线圈
|
|
|
+ int startAddr = device.properties["start_address"].toString().toInt();
|
|
|
+ int count = device.properties["coils_count"].toString().toInt();
|
|
|
+ QString coilStates = device.properties["coil_state"].toString();
|
|
|
+
|
|
|
+ // 计算字节数
|
|
|
+ int byteCount = (count + 7) / 8;
|
|
|
+ datagram.append(static_cast<char>((startAddr >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(startAddr & 0xFF));
|
|
|
+ datagram.append(static_cast<char>((count >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(count & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(byteCount));
|
|
|
+
|
|
|
+ // 添加线圈状态数据
|
|
|
+ // 这里简化处理,实际需要解析线圈状态字符串
|
|
|
+ for (int i = 0; i < byteCount; ++i)
|
|
|
+ {
|
|
|
+ datagram.append(static_cast<char>(0x00)); // 默认所有线圈为OFF
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 16:
|
|
|
+ { // 写多个寄存器
|
|
|
+ int startAddr = device.properties["start_address"].toString().toInt();
|
|
|
+ int count = device.properties["registers_count"].toString().toInt();
|
|
|
+ QString regValues = device.properties["register_value"].toString();
|
|
|
+
|
|
|
+ // 计算字节数
|
|
|
+ int byteCount = count * 2;
|
|
|
+ datagram.append(static_cast<char>((startAddr >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(startAddr & 0xFF));
|
|
|
+ datagram.append(static_cast<char>((count >> 8) & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(count & 0xFF));
|
|
|
+ datagram.append(static_cast<char>(byteCount));
|
|
|
+
|
|
|
+ // 添加寄存器数据
|
|
|
+ // 这里简化处理,实际需要解析寄存器值字符串
|
|
|
+ for (int i = 0; i < count; ++i)
|
|
|
+ {
|
|
|
+ datagram.append(static_cast<char>(0x00)); // 高字节
|
|
|
+ datagram.append(static_cast<char>(0x00)); // 低字节
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ QMessageBox::warning(this, "生成报文", "不支持的功能码");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果是RTU模式,添加CRC校验
|
|
|
+ if (device.protocol_detail == "modbus-rtu")
|
|
|
+ {
|
|
|
+ quint16 crc = calculateCRC(datagram);
|
|
|
+ datagram.append(static_cast<char>(crc & 0xFF));
|
|
|
+ datagram.append(static_cast<char>((crc >> 8) & 0xFF));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 显示生成的报文
|
|
|
+ ui->lineEdit_serial_send->setText(datagram.toHex(' ').toUpper());
|
|
|
+ QMessageBox::information(this, "生成报文", "Modbus报文已生成并填充到发送框");
|
|
|
+}
|
|
|
+
|
|
|
+// CRC计算函数
|
|
|
+quint16 MainWindow::calculateCRC(const QByteArray &data)
|
|
|
+{
|
|
|
+ quint16 crc = 0xFFFF;
|
|
|
+
|
|
|
+ for (int i = 0; i < data.size(); ++i)
|
|
|
+ {
|
|
|
+ crc ^= static_cast<quint8>(data[i]);
|
|
|
+
|
|
|
+ for (int j = 0; j < 8; j++)
|
|
|
+ {
|
|
|
+ if (crc & 0x0001)
|
|
|
+ {
|
|
|
+ crc = (crc >> 1) ^ 0xA001;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ crc = crc >> 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return crc;
|
|
|
+}
|
|
|
+
|
|
|
+QList<QStandardItem *> MainWindow::createRow(const QString ¶m, const QString &defaultValue)
|
|
|
+{
|
|
|
+ QList<QStandardItem *> row;
|
|
|
+ row << new QStandardItem(param);
|
|
|
+ row << new QStandardItem(defaultValue);
|
|
|
+ return row;
|
|
|
+}
|
|
|
+
|
|
|
+void MainWindow::on_checkbox_modbus_rtu_toggled(bool checked)
|
|
|
+{
|
|
|
+ if (checked)
|
|
|
+ {
|
|
|
+
|
|
|
+ ui->checkbox_modbus_ascii->setChecked(!checked);
|
|
|
+ ui->checkbox_modbus_tcp->setChecked(!checked);
|
|
|
+
|
|
|
+ if (m_currentDeviceId != "")
|
|
|
+ {
|
|
|
+ DeviceInfo device = m_busCore->getDeviceInfo(m_currentDeviceId);
|
|
|
+ device.protocol = "modbus";
|
|
|
+ device.protocol_detail = "modbus-rtu";
|
|
|
+ m_busCore->registerDevice(device);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void MainWindow::on_checkbox_modbus_ascii_toggled(bool checked)
|
|
|
+{
|
|
|
+
|
|
|
+ if (checked)
|
|
|
+ {
|
|
|
+ ui->checkbox_modbus_rtu->setChecked(!checked);
|
|
|
+ ui->checkbox_modbus_tcp->setChecked(!checked);
|
|
|
+
|
|
|
+ if (m_currentDeviceId != "")
|
|
|
+ {
|
|
|
+ DeviceInfo device = m_busCore->getDeviceInfo(m_currentDeviceId);
|
|
|
+ device.protocol = "modbus";
|
|
|
+ device.protocol_detail = "modbus-ascii";
|
|
|
+ m_busCore->registerDevice(device);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void MainWindow::on_checkbox_modbus_tcp_toggled(bool checked)
|
|
|
+{
|
|
|
+ if (checked)
|
|
|
+ {
|
|
|
+
|
|
|
+ ui->checkbox_modbus_rtu->setChecked(!checked);
|
|
|
+ ui->checkbox_modbus_ascii->setChecked(!checked);
|
|
|
+
|
|
|
+ if (m_currentDeviceId != "")
|
|
|
+ {
|
|
|
+ DeviceInfo device = m_busCore->getDeviceInfo(m_currentDeviceId);
|
|
|
+ device.protocol = "modbus";
|
|
|
+ device.protocol_detail = "modbus-tcp";
|
|
|
+ m_busCore->registerDevice(device);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|