Обновление алгоритма смены скорости обмена - промежуточный коммит

This commit is contained in:
Вячеслав Штейбезандт 2025-09-10 16:42:25 +03:00
parent a4cdcb7091
commit d9f58e72e4
3 changed files with 236 additions and 40 deletions

2
.gitignore vendored
View File

@ -54,3 +54,5 @@ compile_commands.json
*_qmlcache.qrc
/Debug/debug/M3KTE_TERM.exe

View File

@ -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<int> 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();

View File

@ -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<SpeedChangeRequest> speedChangeRequests;
int pendingSpeedChangeRequestsCount = 0;
int pendingConfirmationsCount = 0;
unsigned tmp_speed = 0;
};
#endif // M3KTE_H