@@ -1,6 +1,6 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
<!DOCTYPE QtCreatorProject> | <!DOCTYPE QtCreatorProject> | ||||
<!-- Written by QtCreator 4.11.1, 2025-08-11T14:46:36. --> | |||||
<!-- Written by QtCreator 4.11.1, 2025-08-12T08:51:43. --> | |||||
<qtcreator> | <qtcreator> | ||||
<data> | <data> | ||||
<variable>EnvironmentId</variable> | <variable>EnvironmentId</variable> | ||||
@@ -17,10 +17,12 @@ | |||||
MainWindow::MainWindow(QWidget *parent) | MainWindow::MainWindow(QWidget *parent) | ||||
: QMainWindow(parent) | : QMainWindow(parent) | ||||
, ui(new Ui::MainWindow) | , ui(new Ui::MainWindow) | ||||
, registerManager(new RegisterManager(this)) | |||||
, modbusManager(new ModbusManager(registerManager, this)) | |||||
{ | { | ||||
ui->setupUi(this); | ui->setupUi(this); | ||||
registerManager = new RegisterManager(this); | |||||
modbusManager = new ModbusManager(registerManager, this); | |||||
// registerManager = new RegisterManager(this); | |||||
// modbusManager = new ModbusManager(registerManager, this); | |||||
// 初始化PLC标签页 | // 初始化PLC标签页 | ||||
ui->plc_tab_widget->setTabsClosable(true); | ui->plc_tab_widget->setTabsClosable(true); | ||||
ui->plc_tab_widget->setMovable(true); | ui->plc_tab_widget->setMovable(true); | ||||
@@ -60,9 +62,6 @@ MainWindow::MainWindow(QWidget *parent) | |||||
// this, &PLC::updateConnectionStatus); | // this, &PLC::updateConnectionStatus); | ||||
// connect(modbusManager, &ModbusManager::errorOccurred, | // connect(modbusManager, &ModbusManager::errorOccurred, | ||||
// this, &PLC::handleModbusError); | // this, &PLC::handleModbusError); | ||||
// connect(this, &PLC::requestWriteRegister, | |||||
// modbusManager, &ModbusManager::writeRegister); | |||||
ui->stackedWidget->setCurrentIndex(0); | ui->stackedWidget->setCurrentIndex(0); | ||||
setWindowTitle("未命名项目 - PLC编辑器"); | setWindowTitle("未命名项目 - PLC编辑器"); | ||||
@@ -207,6 +206,9 @@ void MainWindow::applyProjectToScene(const Project &proj, int pageIndex) | |||||
connect(item, &Item::requestCopy, plcViews[pageIndex], &MyGraphicsView::onItemRequestCopy); | connect(item, &Item::requestCopy, plcViews[pageIndex], &MyGraphicsView::onItemRequestCopy); | ||||
connect(item, &Item::requestDelete, plcViews[pageIndex], &MyGraphicsView::onItemRequestDelete); | connect(item, &Item::requestDelete, plcViews[pageIndex], &MyGraphicsView::onItemRequestDelete); | ||||
connect(item, &Item::requestBindRegister, plcViews[pageIndex], &MyGraphicsView::onItemRequestBindRegister); | connect(item, &Item::requestBindRegister, plcViews[pageIndex], &MyGraphicsView::onItemRequestBindRegister); | ||||
connect(item, &Item::requestCompare, plcViews[pageIndex], &MyGraphicsView::onItemRequestCompare); | |||||
connect(item, &Item::requestReset, plcViews[pageIndex], &MyGraphicsView::onItemRequestReset); | |||||
connect(item, &Item::requestSetON,plcViews[pageIndex], &MyGraphicsView::onItemRequestSetON); | |||||
plcScenes[pageIndex]->addItem(item); | plcScenes[pageIndex]->addItem(item); | ||||
registerManager->bindItem(item,d.registerId); | registerManager->bindItem(item,d.registerId); | ||||
itemObjs.append(item); | itemObjs.append(item); | ||||
@@ -235,6 +237,9 @@ void MainWindow::applyProjectToScene(const Project &proj, int pageIndex) | |||||
connect(item, &Item::requestCopy, hmiViews[pageIndex], &MyGraphicsView::onItemRequestCopy); | connect(item, &Item::requestCopy, hmiViews[pageIndex], &MyGraphicsView::onItemRequestCopy); | ||||
connect(item, &Item::requestDelete, hmiViews[pageIndex], &MyGraphicsView::onItemRequestDelete); | connect(item, &Item::requestDelete, hmiViews[pageIndex], &MyGraphicsView::onItemRequestDelete); | ||||
connect(item, &Item::requestBindRegister, hmiViews[pageIndex], &MyGraphicsView::onItemRequestBindRegister); | connect(item, &Item::requestBindRegister, hmiViews[pageIndex], &MyGraphicsView::onItemRequestBindRegister); | ||||
connect(item, &Item::requestCompare, hmiViews[pageIndex], &MyGraphicsView::onItemRequestCompare); | |||||
connect(item, &Item::requestReset, hmiViews[pageIndex], &MyGraphicsView::onItemRequestReset); | |||||
connect(item, &Item::requestSetON,hmiViews[pageIndex], &MyGraphicsView::onItemRequestSetON); | |||||
hmiScenes[pageIndex]->addItem(item); | hmiScenes[pageIndex]->addItem(item); | ||||
registerManager->bindItem(item,d.registerId); | registerManager->bindItem(item,d.registerId); | ||||
itemObjs.append(item); | itemObjs.append(item); | ||||
@@ -65,35 +65,6 @@ void ModbusManager::stopSimulation() | |||||
pollTimer->stop(); | pollTimer->stop(); | ||||
} | } | ||||
//void ModbusManager::readRegisters() | |||||
//{ | |||||
// if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState) | |||||
// return; | |||||
// // 读取所有D寄存器 (保持寄存器) | |||||
// readRegisterGroup(QModbusDataUnit::HoldingRegisters, 0, 4000); | |||||
// // 读取所有M寄存器 (线圈) | |||||
// readRegisterGroup(QModbusDataUnit::Coils, 0, 4000); | |||||
//} | |||||
//void ModbusManager::readRegisterGroup(QModbusDataUnit::RegisterType type, int startAddr, int count) | |||||
//{ | |||||
// const int MAX_REG_PER_REQUEST = 125; // Modbus RTU限制 | |||||
// for (int addr = startAddr; addr < count; addr += MAX_REG_PER_REQUEST) { | |||||
// int readCount = qMin(MAX_REG_PER_REQUEST, count - addr); | |||||
// QModbusDataUnit unit(type, addr, readCount); | |||||
// if (auto *reply = modbusDevice->sendReadRequest(unit, slaveAddress)) { | |||||
// QString regType = (type == QModbusDataUnit::HoldingRegisters) ? "D" : "M"; | |||||
// pendingRequests[reply] = regType; | |||||
// connect(reply, &QModbusReply::finished, this, &ModbusManager::processModbusReply); | |||||
// } | |||||
// } | |||||
//} | |||||
void ModbusManager::readRegisters() | void ModbusManager::readRegisters() | ||||
{ | { | ||||
if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState) | if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState) | ||||
@@ -174,55 +174,125 @@ void MyGraphicsView::onItemRequestDelete(Item *item) | |||||
delete item; | delete item; | ||||
} | } | ||||
//void MyGraphicsView::onItemRequestBindRegister(Item *item) | |||||
//{ | |||||
// if (!item) return; | |||||
// bool ok = false; | |||||
// QString reg = QInputDialog::getText( | |||||
// this, | |||||
// "绑定寄存器", | |||||
// "格式: <类型><地址>\n" | |||||
// "类型: D(保持寄存器), M(线圈寄存器)\n" | |||||
// "示例: D100, M200\n" | |||||
// "地址范围: 0-4000", | |||||
// QLineEdit::Normal, | |||||
// item->registerId(), | |||||
// &ok | |||||
// ); | |||||
// if (ok && !reg.isEmpty()) { | |||||
// // 验证寄存器格式 | |||||
// QRegularExpression regex("^[DMdm]\\d{1,4}$"); | |||||
// QRegularExpressionMatch match = regex.match(reg); | |||||
// if (!match.hasMatch()) { | |||||
// QMessageBox::warning(this, "格式错误", "请输入有效的寄存器格式\n示例: D100, M200"); | |||||
// return; | |||||
// } | |||||
// int address = reg.mid(1).toInt(); | |||||
// if (address > 4000) { | |||||
// QMessageBox::warning(this, "范围错误", "寄存器地址必须在0-4000范围内"); | |||||
// return; | |||||
// } | |||||
// // 标准化格式 (D100) | |||||
// QString newReg = QString("%1%2").arg(reg[0].toUpper()).arg(address); | |||||
// if (item->setRegisterId(newReg)) | |||||
// { | |||||
// item->update(); | |||||
// // 发出绑定信号 | |||||
// emit itemBoundToRegister(item, newReg); | |||||
// } | |||||
// else | |||||
// { | |||||
// QMessageBox::warning(this, "提示", "请先重置再绑定新的寄存器"); | |||||
// } | |||||
// } | |||||
//} | |||||
void MyGraphicsView::onItemRequestBindRegister(Item *item) | void MyGraphicsView::onItemRequestBindRegister(Item *item) | ||||
{ | { | ||||
if (!item) return; | if (!item) return; | ||||
bool ok = false; | bool ok = false; | ||||
QString reg = QInputDialog::getText( | QString reg = QInputDialog::getText( | ||||
this, | |||||
"绑定寄存器", | |||||
"格式: <类型><地址>\n" | |||||
"类型: D(保持寄存器), M(线圈寄存器)\n" | |||||
"示例: D100, M200\n" | |||||
"地址范围: 0-4000", | |||||
QLineEdit::Normal, | |||||
item->registerId(), | |||||
&ok | |||||
); | |||||
this, | |||||
"绑定寄存器", | |||||
"格式: <类型><地址>\n" | |||||
"类型: D(保持寄存器), M(线圈寄存器), K(常数)\n" | |||||
"示例: D100, M200, K100\n" | |||||
"地址范围: 0-4000\n" | |||||
"常数范围: 0-65535", | |||||
QLineEdit::Normal, | |||||
item->registerId(), | |||||
&ok | |||||
); | |||||
if (ok && !reg.isEmpty()) { | if (ok && !reg.isEmpty()) { | ||||
// 验证寄存器格式 | |||||
QRegularExpression regex("^[DMdm]\\d{1,4}$"); | |||||
// 验证输入格式 | |||||
QRegularExpression regex("^([DMdm]\\d{1,4}|K\\d{1,5})$"); | |||||
QRegularExpressionMatch match = regex.match(reg); | QRegularExpressionMatch match = regex.match(reg); | ||||
if (!match.hasMatch()) { | if (!match.hasMatch()) { | ||||
QMessageBox::warning(this, "格式错误", "请输入有效的寄存器格式\n示例: D100, M200"); | |||||
QMessageBox::warning(this, "格式错误", "请输入有效的格式\n示例: D100, M200, K100"); | |||||
return; | return; | ||||
} | } | ||||
int address = reg.mid(1).toInt(); | |||||
if (address > 4000) { | |||||
QMessageBox::warning(this, "范围错误", "寄存器地址必须在0-4000范围内"); | |||||
return; | |||||
// 提取类型和值 | |||||
QString type = reg.left(1).toUpper(); | |||||
int value = reg.mid(1).toInt(); | |||||
// 检查范围 | |||||
if (type == "K") { | |||||
if (value > 65535) { | |||||
QMessageBox::warning(this, "范围错误", "常数必须在0-65535范围内"); | |||||
return; | |||||
} | |||||
} else { | |||||
if (value > 4000) { | |||||
QMessageBox::warning(this, "范围错误", "寄存器地址必须在0-4000范围内"); | |||||
return; | |||||
} | |||||
} | } | ||||
// 标准化格式 (D100) | |||||
QString newReg = QString("%1%2").arg(reg[0].toUpper()).arg(address); | |||||
// 标准化格式 | |||||
QString newReg = QString("%1%2").arg(type).arg(value); | |||||
if (item->setRegisterId(newReg)) | |||||
{ | |||||
// 对于比较元件,直接设置值 | |||||
if (item->itemType() == "比较" && type == "K") { | |||||
// 常数直接设置值 | |||||
item->setRegisterId(type); | |||||
item->setRegisterValue(type, value); | |||||
item->update(); | item->update(); | ||||
// 发出绑定信号 | |||||
emit itemBoundToRegister(item, newReg); | |||||
} | |||||
else | |||||
{ | |||||
QMessageBox::warning(this, "提示", "请先重置再绑定新的寄存器"); | |||||
}else { | |||||
// 寄存器绑定 | |||||
if (type == "K") | |||||
{ | |||||
QMessageBox::warning(this, "提示", "此元件不能绑定常数"); | |||||
} | |||||
if (item->setRegisterId(newReg)) { | |||||
item->update(); | |||||
emit itemBoundToRegister(item, newReg); | |||||
} else { | |||||
QMessageBox::warning(this, "提示", "请先重置再绑定新的寄存器"); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
void MyGraphicsView::onItemRequestCompare(Item *item) | void MyGraphicsView::onItemRequestCompare(Item *item) | ||||
{ | { | ||||
if (!item) return; | if (!item) return; | ||||