diff --git a/.gitignore b/.gitignore index 97437bf..8d27025 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,5 @@ compile_commands.json *_qmlcache.qrc + +/Debug/debug/M3KTE_TERM.exe diff --git a/M3KTE_TERM/m3kte.cpp b/M3KTE_TERM/m3kte.cpp index 07d6609..230a60a 100644 --- a/M3KTE_TERM/m3kte.cpp +++ b/M3KTE_TERM/m3kte.cpp @@ -981,7 +981,7 @@ void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum) reply->deleteLater(); } } - +/* void M3KTE::onSpeedUpdate() { stopScanBoard(); @@ -1102,6 +1102,204 @@ void M3KTE::onSpeedUpdate() modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); beginScanBoards(); } +*/ + +void M3KTE::onSpeedUpdate() +{ + stopScanBoard(); + modbusDevice->setTimeout(500); + + switch(m_deviceSettingsDialog->currentSpeed()) { + case 0: + tmp_speed = 9600; + break; + case 1: + tmp_speed = 14400; + break; + case 2: + tmp_speed = 19200; + break; + case 3: + tmp_speed = 31250; + break; + case 4: + tmp_speed = 38400; + break; + case 5: + tmp_speed = 56000; + break; + case 6: + tmp_speed = 57600; + break; + case 7: + tmp_speed = 115200; + break; + } + if(tmp_speed == 0) { + unsigned newRow = loggerTable->rowCount(); + loggerTable->insertRow(newRow); + loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); + loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Программная ошибка"))); + loggerTable->setItem(newRow, 2, new QTableWidgetItem("Неожиданное значение скорости")); + loggerTable->setItem(newRow, 3, new QTableWidgetItem(0)); + loggerTable->setItem(newRow, 4, new QTableWidgetItem("Ошибка при изменении скорости обмена.")); + loggerTable->resizeColumnsToContents(); + if(!loggerTable->verticalScrollBar()->isSliderDown()) + loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum()); + beginScanBoards(); + return; + } + speedChangeRequests.clear(); + pendingSpeedChangeRequestsCount = 0; + for(int i = 0; i < 4; i++) { + speedChangeRequests[i].errorOccurred = false; + speedChangeRequests[i].finished = false; + speedChangeRequests[i].confirmationReceived = false; + } + + for(int i = 0; i < 4; i++) { + if(!Boards[i].isActive) + continue; + QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 173, 1); + unit.setValue(0, m_deviceSettingsDialog->currentSpeed()); + + auto *reply = modbusDevice->sendWriteRequest(unit, Boards[i].adr); + if (reply) { + SpeedChangeRequest req; + req.boardIndex = i; + speedChangeRequests.append(req); + pendingSpeedChangeRequestsCount++; + + connect(reply, &QModbusReply::finished, this, [this, reply, i]() { + this->handleSpeedChangeReply(reply, i); + }); + } + else + { + + } + } +} + +void M3KTE::handleSpeedChangeReply(QModbusReply *reply, int boardIndex) +{ + auto it = std::find_if(speedChangeRequests.begin(), speedChangeRequests.end(), + [boardIndex](const SpeedChangeRequest &r) { return r.boardIndex == boardIndex; }); + + if (it == speedChangeRequests.end()) { + reply->deleteLater(); + return; + } + + // Обновление состояния + it->finished = true; + + if (reply->error() != QModbusDevice::TimeoutError) { + // Произошла ошибка + it->errorOccurred = true; // флаг ошибки + } + + reply->deleteLater(); + + // Отслеживание завершения всех запросов + pendingSpeedChangeRequestsCount--; + + // Проверяем, все ли запросы завершены + if (pendingSpeedChangeRequestsCount == 0) { + // Проверяем, был ли хоть один сбой (кроме тайм-аутов) + bool hasError = false; + for (const auto &req : speedChangeRequests) { + if (req.errorOccurred) { + hasError = true; + break; + } + } + if (hasError) { + // Был сбой — отменяем переход и восстанавливаем старую скорость + // Восстановим старую скорость порта + revertToOldSpeedAndRestart(); + modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); + beginScanBoards(); + } else { + onAllSpeedChangeRepliesReceived(); + } + } +} + +void M3KTE::onAllSpeedChangeRepliesReceived() +{ + // Переключаемся на tmp_speed + modbusDevice->disconnectDevice(); + modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, tmp_speed); + if (!modbusDevice->connectDevice()) { + return; + } + + QModbusDataUnit unitCheck(QModbusDataUnit::InputRegisters, 85, 1); + + int totalActiveBoards = 0; + int confirmedBoards = 0; + + QSet pendingBoards; + + for (int i = 0; i < 4; ++i) { + if (!Boards[i].isActive) + continue; + + totalActiveBoards++; + int slaveAddress = Boards[i].adr; + + QModbusReply *reply = modbusDevice->sendReadRequest(unitCheck, slaveAddress); + if (!reply) { + revertToOldSpeedAndRestart(); + return; + } + + pendingBoards.insert(slaveAddress); + + connect(reply, &QModbusReply::finished, this, [this, reply, slaveAddress, &confirmedBoards, &pendingBoards, totalActiveBoards]() mutable { + if (reply->error() == QModbusDevice::NoError) { + // Проверяем что пришел валидный ответ + QModbusDataUnit unit = reply->result(); + if (unit.valueCount() > 0) { + confirmedBoards++; + } else { + + } + } else { + + } + + pendingBoards.remove(slaveAddress); + reply->deleteLater(); + + if (pendingBoards.isEmpty()) { + if (confirmedBoards != totalActiveBoards) { + revertToOldSpeedAndRestart(); + beginScanBoards(); + } else { + modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); + beginScanBoards(); + } + } + }); + } + // Если нет ни одной активной платы — сразу запускаем сканирование + if (totalActiveBoards == 0) { + modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); + beginScanBoards(); + } +} + +// Вспомогательная функция восстановления старой скорости +void M3KTE::revertToOldSpeedAndRestart() +{ + modbusDevice->disconnectDevice(); + modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, + m_settingsDialog->curBaud()); + modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); + modbusDevice->connectDevice(); +} void M3KTE::onParityUpdate() { @@ -1861,23 +2059,18 @@ bool M3KTE::autoBaudRateScan() } QCoreApplication::processEvents(); } - if(isRun) - { + if(isRun) { onConnectClicked(); bar->close(); bar->deleteLater(); return false; - } - else if(!isRun) - { + } else if(!isRun) { //Нужна проверка типа устройства - if(reply->error()==QModbusDevice::NoError) - { + if(reply->error()==QModbusDevice::NoError) { QModbusResponse resp = reply->rawResult(); QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH)); //result.remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH); - if(result == QString("KTE")) - { + if(result == QString("KTE")) { countOfDeviceOnLine++; KTE[i].append(tmp_adr); } @@ -1889,17 +2082,12 @@ bool M3KTE::autoBaudRateScan() countOfDeviceOnLine = 0; modbusDevice->disconnectDevice(); } - if(m_scanBoard->exec()==QDialog::Accepted) - { - if(m_scanBoard->getCheckState()==Qt::Checked) - { - for(int i = 0; i < 8; i++) - { - for(int j = 0; j < KTE[i].size(); j++) - { + if(m_scanBoard->exec()==QDialog::Accepted) { + if(m_scanBoard->getCheckState()==Qt::Checked) { + for(int i = 0; i < 8; i++) { + for(int j = 0; j < KTE[i].size(); j++) { for(int l = i; l < 8; l++) { - if(KTE[l].indexOf(KTE[i].at(j))==-1) - { + if(KTE[l].indexOf(KTE[i].at(j))==-1) { QMessageBox::warning(this, "Error", QString("Несколько устройств по адресу %1, работающих на скоростях %2 и %3.").arg(KTE[i].at(j)).arg(m_baud[i]).arg(m_baud[l])); return false; } @@ -1912,25 +2100,21 @@ bool M3KTE::autoBaudRateScan() for(int i = 0; i < 8; i++) { bar->setValue(i); bar->setLabelText(tr("Синхронизация плат на скорости %1").arg(m_baud[i])); - for(int j = 0; j < KTE[i].size(); j++) - { + for(int j = 0; j < KTE[i].size(); j++) { modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]); if(!modbusDevice->connectDevice()) { statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000); } auto *reply = modbusDevice->sendWriteRequest(*_unit, KTE[i].at(j)); - if(!reply) - { + if(!reply) { onConnectClicked(); bar->close(); bar->deleteLater(); return false; } - while(!reply->isFinished()) - { - if(isRun) - { + while(!reply->isFinished()) { + if(isRun) { //dfQMessageBox::warning(this, "Ошибка при синхронизации скоростей.", QString("Прерывание по запросу пользователя.")); onConnectClicked(); bar->close(); @@ -1939,19 +2123,15 @@ bool M3KTE::autoBaudRateScan() } QCoreApplication::processEvents(); } - if(reply->error()==QModbusDevice::TimeoutError) - { + if(reply->error()==QModbusDevice::TimeoutError) { modbusDevice->disconnectDevice(); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_settingsDialog->UpdateBaud(m_scanBoard->getBaud())); modbusDevice->connectDevice(); QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1); - if(auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[i].adr)) - { - while(!subreply->isFinished()) - { - if(isRun) - { + if(auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[i].adr)) { + while(!subreply->isFinished()) { + if(isRun) { //dfQMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя.")); onConnectClicked(); bar->close(); @@ -1960,8 +2140,7 @@ bool M3KTE::autoBaudRateScan() } QCoreApplication::processEvents(); } - if(subreply->error()!=QModbusDevice::NoError) - { + if(subreply->error()!=QModbusDevice::NoError) { //QMessageBox::warning(); onConnectClicked(); bar->close(); @@ -1970,8 +2149,7 @@ bool M3KTE::autoBaudRateScan() } } } - else if(reply->error()!=QModbusDevice::NoError) - { + else if(reply->error()!=QModbusDevice::NoError) { return false; } modbusDevice->disconnectDevice(); diff --git a/M3KTE_TERM/m3kte.h b/M3KTE_TERM/m3kte.h index 1d9b702..90aedec 100644 --- a/M3KTE_TERM/m3kte.h +++ b/M3KTE_TERM/m3kte.h @@ -84,6 +84,10 @@ private slots: void boardScan(unsigned boardID); + void handleSpeedChangeReply(QModbusReply *reply, int boardIndex); + void onAllSpeedChangeRepliesReceived(); + void revertToOldSpeedAndRestart(); + public: M3KTE(QWidget *parent = nullptr); ~M3KTE(); @@ -159,5 +163,17 @@ private: }ParsingReg; unsigned AllReg:16; }; + + // Структура для отслеживания состояния запроса смены скорости + struct SpeedChangeRequest { + int boardIndex; + bool errorOccurred = false; + bool finished = false; + bool confirmationReceived = false; + }; + QVector speedChangeRequests; + int pendingSpeedChangeRequestsCount = 0; + int pendingConfirmationsCount = 0; + unsigned tmp_speed = 0; }; #endif // M3KTE_H