diff --git a/M3KTE_TERM/adcgraphdialog.cpp b/M3KTE_TERM/adcgraphdialog.cpp index e147ad3..d8dc37f 100644 --- a/M3KTE_TERM/adcgraphdialog.cpp +++ b/M3KTE_TERM/adcgraphdialog.cpp @@ -26,36 +26,31 @@ AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) : m_teNumber(-1), m_adcZero(0), m_adcOneVolt(4096), - m_series(new QLineSeries()), - m_chart(new QChart()), m_stableStartLine(new QLineSeries()), m_stableEndLine(new QLineSeries()), m_stableStartIndex(-1), m_stableEndIndex(-1), + m_series(new QLineSeries()), + m_chart(new QChart()), m_startAddress(0), m_registerCount(100) { ui->setupUi(this); - // Настройка основного графика m_series->setName("АЦП данные"); m_chart->addSeries(m_series); - // Настройка линий стабильного участка m_stableStartLine->setName("Начало стаб. участка"); m_stableStartLine->setColor(Qt::red); m_stableStartLine->setPen(QPen(Qt::red, 2, Qt::DashLine)); m_chart->addSeries(m_stableStartLine); - m_stableEndLine->setName("Конец стаб. участка"); m_stableEndLine->setColor(Qt::green); m_stableEndLine->setPen(QPen(Qt::green, 2, Qt::DashLine)); m_chart->addSeries(m_stableEndLine); - m_chart->setTitle("График АЦП"); m_chart->legend()->setVisible(true); m_chart->legend()->setAlignment(Qt::AlignTop); - m_axisX = new QValueAxis(); m_axisX->setTitleText("Отсчеты АЦП"); m_axisX->setRange(0, m_registerCount); @@ -63,7 +58,6 @@ AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) : m_series->attachAxis(m_axisX); m_stableStartLine->attachAxis(m_axisX); m_stableEndLine->attachAxis(m_axisX); - m_axisY = new QValueAxis(); m_axisY->setTitleText("Напряжение, В"); m_axisY->setRange(-1.3, 1.3); @@ -71,13 +65,10 @@ AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) : m_series->attachAxis(m_axisY); m_stableStartLine->attachAxis(m_axisY); m_stableEndLine->attachAxis(m_axisY); - QChartView *chartView = new QChartView(m_chart); chartView->setRenderHint(QPainter::Antialiasing); - QVBoxLayout *layout = new QVBoxLayout(ui->plotWidget); layout->addWidget(chartView); - // Подключаем сигналы элементов управления диапазоном connect(ui->registerCountSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &AdcGraphDialog::on_registerCountChanged); @@ -85,21 +76,16 @@ AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) : this, &AdcGraphDialog::on_rangeApplyClicked); connect(ui->teNumberSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &AdcGraphDialog::on_teNumberChanged); - connect(m_updateTimer, &QTimer::timeout, this, &AdcGraphDialog::onUpdateTimer); connect(ui->closeBtn, &QPushButton::clicked, this, &AdcGraphDialog::on_closeBtn_clicked); } - - AdcGraphDialog::~AdcGraphDialog() { stopGraph(); delete ui; } - - void AdcGraphDialog::setModbusDevice(QModbusClient *device) { m_modbusDevice = device; @@ -113,28 +99,25 @@ void AdcGraphDialog::on_teNumberChanged(int value) void AdcGraphDialog::setTENumber(int boardID, int teNumber) { - if (m_boardAddress == -1) return; - + if(m_boardAddress == -1) + return; m_teNumber = teNumber; m_boardId = boardID; m_boardAddress = m_boardId + 1; - // Обновляем заголовок окна setWindowTitle(QString("График АЦП - Плата %1, ТЭ %2 (адр %3-%4)") - .arg(m_boardId + 1) - .arg(m_teNumber) - .arg(m_startAddress) - .arg(m_startAddress + m_registerCount - 1)); - + .arg(m_boardId + 1) + .arg(m_teNumber) + .arg(m_startAddress) + .arg(m_startAddress + m_registerCount - 1)); // Записываем новый номер ТЭ в устройство - if (m_modbusDevice) { + if(m_modbusDevice) { QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, REG_TE_NUMBER, 1); unit.setValue(0, teNumber); - - if (auto *reply = m_modbusDevice->sendWriteRequest(unit, m_boardAddress)) { - if (!reply->isFinished()) { + if(auto *reply = m_modbusDevice->sendWriteRequest(unit, m_boardAddress)) { + if(!reply->isFinished()) connect(reply, &QModbusReply::finished, this, [this, reply, teNumber]() { - if (reply->error() == QModbusDevice::NoError) { + if(reply->error() == QModbusDevice::NoError) { qDebug() << "TE number changed to:" << teNumber; // Можно обновить данные сразу после смены ТЭ readAdcDataAndIndices(); @@ -143,9 +126,8 @@ void AdcGraphDialog::setTENumber(int boardID, int teNumber) } reply->deleteLater(); }); - } else { + else reply->deleteLater(); - } } } ui->teNumberSpinBox->setValue(teNumber); @@ -153,130 +135,111 @@ void AdcGraphDialog::setTENumber(int boardID, int teNumber) void AdcGraphDialog::readCalibrationValues() { - if (!m_modbusDevice || m_boardAddress == -1) return; - + if(!m_modbusDevice || m_boardAddress == -1) + return; // Читаем калибровочные значения (регистры 555 и 556) QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_ADC_ZERO, 2); - - if (auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { - if (!reply->isFinished()) { + if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { + if(!reply->isFinished()) connect(reply, &QModbusReply::finished, this, [this, reply]() { - if (reply->error() == QModbusDevice::NoError) { + if(reply->error() == QModbusDevice::NoError) { const QModbusDataUnit result = reply->result(); - if (result.valueCount() >= 2) { + if(result.valueCount() >= 2) { m_adcZero = result.value(0); m_adcOneVolt = result.value(1); - //qDebug() << "Calibration values - Zero:" << m_adcZero << "1V:" << m_adcOneVolt; } - } else { - //qDebug() << "Error reading calibration:" << reply->errorString(); } reply->deleteLater(); }); - } else { + else reply->deleteLater(); - } } } void AdcGraphDialog::readStableIndices() { - if (!m_modbusDevice || m_boardAddress == -1) return; - + if(!m_modbusDevice || m_boardAddress == -1) + return; // Читаем индексы стабильного участка (регистры 557 и 558) QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_STABLE_START, 2); - - if (auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { - if (!reply->isFinished()) { + if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { + if(!reply->isFinished()) connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onStableIndicesReady); - } else { + else reply->deleteLater(); - } } } void AdcGraphDialog::onStableIndicesReady() { auto *reply = qobject_cast(sender()); - if (!reply) return; - - if (reply->error() == QModbusDevice::NoError) { + if(!reply) + return; + if(reply->error() == QModbusDevice::NoError) { const QModbusDataUnit result = reply->result(); - if (result.valueCount() >= 2) { + if(result.valueCount() >= 2) { m_stableStartIndex = result.value(0); m_stableEndIndex = result.value(1); - //qDebug() << "Stable indices updated - Start:" << m_stableStartIndex << "End:" << m_stableEndIndex; updateStableLines(); - // Обновляем статистику с новыми индексами updateStatisticsWithStableInfo(); } - } else { - //qDebug() << "Error reading stable indices:" << reply->errorString(); } - reply->deleteLater(); } void AdcGraphDialog::updateStatistics() { - if (m_series->count() > 0) { + if(m_series->count() > 0) { double min = 1000, max = -1000, sum = 0; - for (const QPointF &point : m_series->points()) { + for(const QPointF &point : m_series->points()) { double y = point.y(); - if (y < min) min = y; - if (y > max) max = y; + if(y < min) + min = y; + if(y > max) + max = y; sum += y; } double avg = sum / m_series->count(); - ui->minLabel->setText(QString::number(min, 'f', 3) + " В"); ui->maxLabel->setText(QString::number(max, 'f', 3) + " В"); ui->avgLabel->setText(QString::number(avg, 'f', 3) + " В"); - // Обновляем информацию о стабильном участке updateStatisticsWithStableInfo(); } } - - void AdcGraphDialog::updateStatisticsWithStableInfo() { - if (m_series->count() > 0) { + if(m_series->count() > 0) // Используем абсолютные индексы в формате "начальный-конечный" ui->samplesLabel->setText( - QString("%1 отсч. (адр %2-%3) [стаб: %4-%5]") - .arg(m_series->count()) - .arg(m_startAddress) - .arg(m_startAddress + m_registerCount - 1) - .arg(m_stableStartIndex) // Абсолютный начальный индекс - .arg(m_stableEndIndex) // Абсолютный конечный индекс - ); - } + QString("%1 отсч. (адр %2-%3) [стаб: %4-%5]") + .arg(m_series->count()) + .arg(m_startAddress) + .arg(m_startAddress + m_registerCount - 1) + .arg(m_stableStartIndex) // Абсолютный начальный индекс + .arg(m_stableEndIndex) // Абсолютный конечный индекс + ); } - void AdcGraphDialog::updateStableLines() { // Очищаем предыдущие линии m_stableStartLine->clear(); m_stableEndLine->clear(); - // Получаем текущий диапазон оси Y double yMin = m_axisY->min(); double yMax = m_axisY->max(); - // Добавляем вертикальную линию для начала стабильного участка // Учитываем текущий диапазон отображения - if (m_stableStartIndex >= m_startAddress && m_stableStartIndex < m_startAddress + m_registerCount) { + if(m_stableStartIndex >= m_startAddress && m_stableStartIndex < m_startAddress + m_registerCount) { int relativeStartIndex = m_stableStartIndex - m_startAddress; m_stableStartLine->append(relativeStartIndex, yMin); m_stableStartLine->append(relativeStartIndex, yMax); } - // Добавляем вертикальную линию для конца стабильного участка - if (m_stableEndIndex >= m_startAddress && m_stableEndIndex < m_startAddress + m_registerCount) { + if(m_stableEndIndex >= m_startAddress && m_stableEndIndex < m_startAddress + m_registerCount) { int relativeEndIndex = m_stableEndIndex - m_startAddress; m_stableEndLine->append(relativeEndIndex, yMin); m_stableEndLine->append(relativeEndIndex, yMax); @@ -288,111 +251,83 @@ void AdcGraphDialog::updateGraphRange() // Обновляем диапазон оси X m_axisX->setRange(0, m_registerCount); m_axisX->setTitleText(QString("Отсчеты АЦП (%1-%2)").arg(m_startAddress).arg(m_startAddress + m_registerCount - 1)); - // Сбрасываем ось Y к разумному диапазону по умолчанию m_axisY->setRange(-1.2, 1.2); - // Обновляем линии стабильного участка с учетом нового диапазона updateStableLines(); } void AdcGraphDialog::readAdcDataAndIndices() { - if (!m_modbusDevice || m_boardAddress == -1) return; - + if(!m_modbusDevice || m_boardAddress == -1) + return; // Создаем один запрос для данных АЦП + индексов стабильности // Адреса: данные АЦП (571+), индексы (557-558) int start = m_startAddress + REG_ADC_BUFFER_START; int count = m_registerCount; - // Читаем индексы стабильности (557-558) и данные АЦП одним запросом QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_STABLE_START, count + (start - REG_STABLE_START)); - - //qDebug() << "Reading combined data from address" << REG_STABLE_START << "count:" << unit.valueCount(); - - if (auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { - if (!reply->isFinished()) { + if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { + if(!reply->isFinished()) connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onCombinedDataReady); - } else { + else reply->deleteLater(); - } - } else { - //qDebug() << "Failed to send combined data read request"; } } - void AdcGraphDialog::onCombinedDataReady() { auto *reply = qobject_cast(sender()); - if (!reply) return; - - if((m_adcZero == 0) || (m_adcOneVolt == 0)) - { + if(!reply) + return; + if((m_adcZero == 0) || (m_adcOneVolt == 0)) { readCalibrationValues(); return; } - - if (reply->error() == QModbusDevice::NoError) { + if(reply->error() == QModbusDevice::NoError) { const QModbusDataUnit result = reply->result(); - // Обрабатываем индексы стабильности (первые 2 регистра) - if (result.valueCount() >= 2) { + if(result.valueCount() >= 2) { m_stableStartIndex = result.value(0); m_stableEndIndex = result.value(1); - //qDebug() << "Stable indices - Start:" << m_stableStartIndex << "End:" << m_stableEndIndex; } - // Обрабатываем данные АЦП (остальные регистры) - int adcDataStartIndex = (m_startAddress + REG_ADC_BUFFER_START) - REG_STABLE_START; - + uint adcDataStartIndex = (m_startAddress + REG_ADC_BUFFER_START) - REG_STABLE_START; // Очищаем предыдущие данные m_series->clear(); - // Добавляем новые точки и определяем диапазон double minVoltage = 1000, maxVoltage = -1000; - for (int i = 0; i < m_registerCount; ++i) { - if (adcDataStartIndex + i < result.valueCount()) { + for(int i = 0; i < m_registerCount; ++i) { + if(adcDataStartIndex + i < result.valueCount()) { double voltage = convertAdcToVoltage(result.value(adcDataStartIndex + i)); m_series->append(i, voltage); - // Обновляем мин/макс для автоматического масштабирования - if (voltage < minVoltage) minVoltage = voltage; - if (voltage > maxVoltage) maxVoltage = voltage; + if(voltage < minVoltage) + minVoltage = voltage; + if(voltage > maxVoltage) + maxVoltage = voltage; } } - // Обновляем график и статистику updateYAxisRange(minVoltage, maxVoltage); updateStableLines(); updateStatistics(); - - } else { - // qDebug() << "Error reading combined data:" << reply->errorString(); } - reply->deleteLater(); } - void AdcGraphDialog::readAdcBuffer() { - if (!m_modbusDevice || m_boardAddress == -1) return; - + if(!m_modbusDevice || m_boardAddress == -1) + return; // Читаем выбранный диапазон буфера АЦП QModbusDataUnit unit(QModbusDataUnit::InputRegisters, m_startAddress+REG_ADC_BUFFER_START, m_registerCount); - - // qDebug() << "Reading ADC buffer from address" << m_startAddress << "count:" << m_registerCount; - - if (auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { - if (!reply->isFinished()) { + if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { + if(!reply->isFinished()) connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onReadReady); - } else { + else reply->deleteLater(); - } - } else { - // qDebug() << "Failed to send ADC buffer read request"; } } @@ -401,34 +336,25 @@ void AdcGraphDialog::startGraph(int boardId, int teNumber) m_boardId = boardId; m_teNumber = teNumber; m_boardAddress = boardId + 1; - // Устанавливаем начальное значение в спинбокс ui->teNumberSpinBox->setValue(teNumber); - setWindowTitle(QString("График АЦП - Плата %1, ТЭ %2 (адр %3-%4)") - .arg(boardId + 1) - .arg(teNumber) - .arg(m_startAddress) - .arg(m_startAddress + m_registerCount - 1)); - + .arg(boardId + 1) + .arg(teNumber) + .arg(m_startAddress) + .arg(m_startAddress + m_registerCount - 1)); // Очищаем предыдущие данные m_series->clear(); m_stableStartLine->clear(); m_stableEndLine->clear(); - // Обновляем диапазон графика updateGraphRange(); - readCalibrationValues(); - // Записываем начальный номер ТЭ setTENumber(m_boardAddress, teNumber); - m_updateTimer->start(m_timeout); } - - void AdcGraphDialog::setTimeout(int timeout) { m_timeout = timeout; @@ -439,17 +365,15 @@ void AdcGraphDialog::stopGraph() m_updateTimer->stop(); m_boardId = -1; m_boardAddress = -1; - // Отменяем все pending запросы Modbus - if (m_modbusDevice) { + if(m_modbusDevice) m_modbusDevice->disconnect(this); // Отключаем все сигналы - } - } void AdcGraphDialog::onUpdateTimer() { - if (m_boardAddress == -1) return; + if(m_boardAddress == -1) + return; // Читаем и буфер АЦП, и индексы стабильности каждый период readAdcDataAndIndices(); } @@ -457,54 +381,46 @@ void AdcGraphDialog::onUpdateTimer() void AdcGraphDialog::onReadReady() { auto *reply = qobject_cast(sender()); - if (!reply) return; - - if (reply->error() == QModbusDevice::NoError) { + if(!reply) + return; + if(reply->error() == QModbusDevice::NoError) { const QModbusDataUnit result = reply->result(); - // Очищаем предыдущие данные m_series->clear(); - // Добавляем новые точки и определяем диапазон double minVoltage = 1000, maxVoltage = -1000; - for (int i = 0; i < result.valueCount(); ++i) { + for(uint i = 0; i < result.valueCount(); ++i) { double voltage = convertAdcToVoltage(result.value(i)); m_series->append(i, voltage); - // Обновляем мин/макс для автоматического масштабирования - if (voltage < minVoltage) minVoltage = voltage; - if (voltage > maxVoltage) maxVoltage = voltage; + if(voltage < minVoltage) + minVoltage = voltage; + if(voltage > maxVoltage) + maxVoltage = voltage; } - // Автоматически настраиваем диапазон оси Y updateYAxisRange(minVoltage, maxVoltage); - // Обновляем линии стабильного участка updateStableLines(); - // Обновляем статистику - if (m_series->count() > 0) { + if(m_series->count() > 0) { double min = 1000, max = -1000, sum = 0; - for (const QPointF &point : m_series->points()) { + for(const QPointF &point : m_series->points()) { double y = point.y(); - if (y < min) min = y; - if (y > max) max = y; + if(y < min) + min = y; + if(y > max) + max = y; sum += y; } double avg = sum / m_series->count(); - ui->minLabel->setText(QString::number(min, 'f', 3) + " В"); ui->maxLabel->setText(QString::number(max, 'f', 3) + " В"); ui->avgLabel->setText(QString::number(avg, 'f', 3) + " В"); - // Обновляем информацию о стабильном участке updateStatisticsWithStableInfo(); } - - } else { - // qDebug() << "Error reading ADC buffer:" << reply->errorString(); } - reply->deleteLater(); } @@ -513,65 +429,38 @@ void AdcGraphDialog::updateYAxisRange(double minVoltage, double maxVoltage) // Добавляем запас 10% к диапазону double range = maxVoltage - minVoltage; double margin = range * 0.1; - double yMin = minVoltage - margin; double yMax = maxVoltage + margin; - // Если диапазон слишком маленький или слишком большой, устанавливаем разумные пределы -// if ((range < 0.1) || ((maxVoltage > 0.5) && (minVoltage < -0.5))) -// { -// yMin = -1.5; -// yMax = 1.5; -// } -// else if(maxVoltage > 0.5) { -// yMin = -0.1; -// yMax = 1.5; -// } -// else if(minVoltage < -0.5) -// { -// yMin = -1.5; -// yMax =0.1; -// } -// else - { - yMin = -1.5; - yMax = 1.5; - } - + yMin = -1.5; + yMax = 1.5; // Ограничиваем разумными пределами yMin = qMax(yMin, -5.0); // Не ниже -5В yMax = qMin(yMax, 5.0); // Не выше 5В - // Устанавливаем новый диапазон m_axisY->setRange(yMin, yMax); - // Обновляем линии стабильного участка с новым диапазоном updateStableLines(); } - double AdcGraphDialog::convertAdcToVoltage(quint16 adcValue) { - if (m_adcOneVolt == m_adcZero) return 0; + if(m_adcOneVolt == m_adcZero) + return 0; return (adcValue - m_adcZero) * 1.1 / (m_adcOneVolt - m_adcZero); } - void AdcGraphDialog::on_registerCountChanged(int value) { m_registerCount = value; - // qDebug() << "Register count changed to:" << value; } void AdcGraphDialog::on_rangeApplyClicked() { - // qDebug() << "Applying new range - Start:" << m_startAddress << "Count:" << m_registerCount; updateGraphRange(); - // Немедленно обновляем данные - if (m_boardAddress != -1) { + if(m_boardAddress != -1) readAdcBuffer(); - } } void AdcGraphDialog::on_closeBtn_clicked() diff --git a/M3KTE_TERM/adcgraphdialog.h b/M3KTE_TERM/adcgraphdialog.h index ca36877..90e413b 100644 --- a/M3KTE_TERM/adcgraphdialog.h +++ b/M3KTE_TERM/adcgraphdialog.h @@ -19,21 +19,17 @@ class AdcGraphDialog; class AdcGraphDialog : public QDialog { Q_OBJECT - public: explicit AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent = nullptr); ~AdcGraphDialog(); - void setTENumber(int boardID, int teNumber); void setModbusDevice(QModbusClient *device); void startGraph(int boardId, int teNumber); void stopGraph(); void setTimeout(int timeout); void readyClose(); - signals: void dialogClosed(); - protected: void closeEvent(QCloseEvent *event) override { stopGraph(); @@ -41,7 +37,6 @@ protected: emit dialogClosed(); QDialog::closeEvent(event); } - private slots: void on_teNumberChanged(int value); void onUpdateTimer(); @@ -50,7 +45,6 @@ private slots: void on_closeBtn_clicked(); void on_registerCountChanged(int value); void on_rangeApplyClicked(); - private: Ui::AdcGraphDialog *ui; QModbusClient *m_modbusDevice; @@ -59,27 +53,22 @@ private: int m_boardAddress; int m_teNumber; int m_timeout; - // Калибровочные значения double m_adcZero; double m_adcOneVolt; - // Для отображения стабильного участка QLineSeries *m_stableStartLine; QLineSeries *m_stableEndLine; int m_stableStartIndex; int m_stableEndIndex; - // Данные графика QLineSeries *m_series; QValueAxis *m_axisX; QValueAxis *m_axisY; QChart *m_chart; // Добавить указатель на chart - // Управление диапазоном регистров int m_startAddress; int m_registerCount; - void updateStatistics(); void readAdcDataAndIndices(); void onCombinedDataReady(); diff --git a/M3KTE_TERM/debugterminaldialog.cpp b/M3KTE_TERM/debugterminaldialog.cpp index 15fc3da..bf5aab9 100644 --- a/M3KTE_TERM/debugterminaldialog.cpp +++ b/M3KTE_TERM/debugterminaldialog.cpp @@ -17,23 +17,19 @@ DebugTerminalDialog::DebugTerminalDialog(QWidget *parent) : boards[0].error5V = ui->discErr5TestChkBox_1; boards[0].error5VSCI = ui->discErr5VsciTestChkBox_1; boards[0].error5VA = ui->discErr5VATestChkBox_1; - boards[1].error24V = ui->discErr24TestChkBox_2; boards[1].error5V = ui->discErr5TestChkBox_2; boards[1].error5VSCI = ui->discErr5VsciTestChkBox_2; boards[1].error5VA = ui->discErr5VATestChkBox_2; - boards[2].error24V = ui->discErr24TestChkBox_3; boards[2].error5V = ui->discErr5TestChkBox_3; boards[2].error5VSCI = ui->discErr5VsciTestChkBox_3; boards[2].error5VA = ui->discErr5VATestChkBox_3; - boards[3].error24V = ui->discErr24TestChkBox_4; boards[3].error5V = ui->discErr5TestChkBox_4; boards[3].error5VSCI = ui->discErr5VsciTestChkBox_4; boards[3].error5VA = ui->discErr5VATestChkBox_4; initializeConnections(); - // Создаем AdcGraphDialog с nullptr m_adcGraphDialog = new AdcGraphDialog(nullptr, this); } @@ -50,9 +46,8 @@ void DebugTerminalDialog::setMainTerm(M3KTE* term) void DebugTerminalDialog::setModbusDevice(QModbusClient *device) { m_modbusDevice = device; - if (m_adcGraphDialog && device) { + if(m_adcGraphDialog && device) m_adcGraphDialog->setModbusDevice(device); - } } void DebugTerminalDialog::setDebugTerminalCoil(int enable) @@ -67,9 +62,7 @@ void DebugTerminalDialog::showEvent(QShowEvent *event) { QDialog::showEvent(event); // При открытии окна записываем в коил 555 значение "1" - resetAll(); - setDebugTerminalCoil(1); } @@ -80,76 +73,7 @@ void DebugTerminalDialog::closeEvent(QCloseEvent *event) QDialog::closeEvent(event); } -void DebugTerminalDialog::initializeConnections() -{ -// // Подключаем кнопки OK и RestoreDefaults -// connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &DebugTerminalDialog::on_buttonBox_clicked); - -// // Подключаем все чекбоксы для платы 1 -// connect(ui->continiusCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_continiusCallChkBox_1_stateChanged); -// connect(ui->calibrateCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_calibrateCallChkBox_1_stateChanged); -// connect(ui->pollTECallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_pollTECallChkBox_1_stateChanged); -// connect(ui->resetKeyCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_resetKeyCallChkBox_1_stateChanged); -// connect(ui->resetDefaultCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_resetDefaultCallChkBox_1_stateChanged); -// connect(ui->getHardfaultCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_getHardfaultCallChkBox_1_stateChanged); - - -// connect(ui->enableLedTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::enableLedTestChkBox_1_stateChanged); - -// connect(ui->discWorkTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discWorkTestChkBox_1_stateChanged); -// connect(ui->discWarnTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discWarnTestChkBox_1_stateChanged); -// connect(ui->discErrTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErrTestChkBox_1_stateChanged); - - -// connect(ui->discErr24TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr24TestChkBox_1_stateChanged); -// ui->discErr24TestChkBox_1->setAttribute(Qt::WA_TransparentForMouseEvents, true); -// connect(ui->discErr5TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5TestChkBox_1_stateChanged); -// ui->discErr5TestChkBox_1->setAttribute(Qt::WA_TransparentForMouseEvents, true); -// connect(ui->discErr5VsciTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5VsciTestChkBox_1_stateChanged); -// ui->discErr5VsciTestChkBox_1->setAttribute(Qt::WA_TransparentForMouseEvents, true); -// connect(ui->discErr5VATestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5VATestChkBox_1_stateChanged); -// ui->discErr5VATestChkBox_1->setAttribute(Qt::WA_TransparentForMouseEvents, true); - -// connect(ui->ledWorkTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledWorkTestChkBox_1_stateChanged); -// connect(ui->ledWarnTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledWarnTestChkBox_1_stateChanged); -// connect(ui->ledErrTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledErrTestChkBox_1_stateChanged); -// connect(ui->ledConnectTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledConnectTestChkBox_1_stateChanged); -// connect(ui->ledVH1TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH1TestChkBox_1_stateChanged); -// connect(ui->ledVH2TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH2TestChkBox_1_stateChanged); -// connect(ui->ledVH3TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH3TestChkBox_1_stateChanged); - -// // Подключаем все чекбоксы для платы 2 -// connect(ui->continiusCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_continiusCallChkBox_2_stateChanged); -// connect(ui->calibrateCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_calibrateCallChkBox_2_stateChanged); -// connect(ui->pollTECallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_pollTECallChkBox_2_stateChanged); -// connect(ui->resetKeyCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_resetKeyCallChkBox_2_stateChanged); -// connect(ui->resetDefaultCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_resetDefaultCallChkBox_2_stateChanged); -// connect(ui->getHardfaultCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_getHardfaultCallChkBox_2_stateChanged); - -// connect(ui->enableLedTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::enableLedTestChkBox_2_stateChanged); - -// connect(ui->discWorkTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discWorkTestChkBox_2_stateChanged); -// connect(ui->discWarnTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discWarnTestChkBox_2_stateChanged); -// connect(ui->discErrTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErrTestChkBox_2_stateChanged); - -// connect(ui->discErr24TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr24TestChkBox_2_stateChanged); -// ui->discErr24TestChkBox_2->setAttribute(Qt::WA_TransparentForMouseEvents, true); -// connect(ui->discErr5TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5TestChkBox_2_stateChanged); -// ui->discErr5TestChkBox_2->setAttribute(Qt::WA_TransparentForMouseEvents, true); -// connect(ui->discErr5VsciTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5VsciTestChkBox_2_stateChanged); -// ui->discErr5VsciTestChkBox_2->setAttribute(Qt::WA_TransparentForMouseEvents, true); -// connect(ui->discErr5VATestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5VATestChkBox_2_stateChanged); -// ui->discErr5VATestChkBox_2->setAttribute(Qt::WA_TransparentForMouseEvents, true); - -// connect(ui->ledWorkTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledWorkTestChkBox_2_stateChanged); -// connect(ui->ledWarnTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledWarnTestChkBox_2_stateChanged); -// connect(ui->ledErrTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledErrTestChkBox_2_stateChanged); -// connect(ui->ledConnectTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledConnectTestChkBox_2_stateChanged); -// connect(ui->ledVH1TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH1TestChkBox_2_stateChanged); -// connect(ui->ledVH2TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH2TestChkBox_2_stateChanged); -// connect(ui->ledVH3TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH3TestChkBox_2_stateChanged); - -} +void DebugTerminalDialog::initializeConnections(){} void DebugTerminalDialog::updateConnectionStatus(int boardID, bool connected) { @@ -568,16 +492,14 @@ void DebugTerminalDialog::on_ledVH3TestChkBox_4_stateChanged(int state) void DebugTerminalDialog::openAdc(int boardID, int teNumber) { // Удаляем старый диалог и создаем новый - if (m_adcGraphDialog) { + if(m_adcGraphDialog) { m_adcGraphDialog->deleteLater(); m_adcGraphDialog = nullptr; } - m_adcGraphDialog = new AdcGraphDialog(m_modbusDevice, this); connect(m_adcGraphDialog, &AdcGraphDialog::dialogClosed, this, [this]() { setDebugTerminalCoil(0); }); - setGraphUpdateInterval(1000); m_adcGraphDialog->startGraph(boardID, teNumber); m_adcGraphDialog->show(); @@ -587,9 +509,8 @@ void DebugTerminalDialog::openAdc(int boardID, int teNumber) void DebugTerminalDialog::setGraphUpdateInterval(int milliseconds) { - if (m_adcGraphDialog) { - m_adcGraphDialog->setTimeout(milliseconds); - } + if(m_adcGraphDialog) + m_adcGraphDialog->setTimeout(milliseconds); } void DebugTerminalDialog::writeCoil(int boardID, int coil, int value) @@ -624,22 +545,20 @@ void DebugTerminalDialog::setBoardActive(int boardID, bool active) case 3: boardGroup = ui->DbgPlate_4; break; // Плата 4 default: return; } - if (boardGroup) { + if(boardGroup) { boardGroup->setEnabled(active); // Можно добавить визуальное отличие неактивных плат - if (!active) { + if(!active) boardGroup->setStyleSheet("QGroupBox { color: gray; }"); - } else { + else boardGroup->setStyleSheet(""); // Сброс стиля - } } } void DebugTerminalDialog::updateBoardStates(bool activeBoards[4]) { - for (int i = 0; i < 4; i++) { + for(int i = 0; i < 4; i++) setBoardActive(i, activeBoards[i]); - } } void DebugTerminalDialog::resetAll() @@ -651,17 +570,14 @@ void DebugTerminalDialog::resetAll() ui->resetKeyCallChkBox_1->setChecked(false); ui->resetDefaultCallChkBox_1->setChecked(false); ui->getHardfaultCallChkBox_1->setChecked(false); - ui->enableLedTestChkBox_1->setChecked(false); ui->leds_1->setEnabled(false); ui->discs_1->setEnabled(false); - ui->discWorkTestChkBox_1->setChecked(false); // Сброс всех чекбоксов теста дискретных сигналов ui->discWorkTestChkBox_1->setChecked(false); ui->discWarnTestChkBox_1->setChecked(false); ui->discErrTestChkBox_1->setChecked(false); - // Сброс всех чекбоксов теста светодиодов ui->ledWorkTestChkBox_1->setChecked(false); ui->ledWarnTestChkBox_1->setChecked(false); @@ -670,7 +586,6 @@ void DebugTerminalDialog::resetAll() ui->ledVH1TestChkBox_1->setChecked(false); ui->ledVH2TestChkBox_1->setChecked(false); ui->ledVH3TestChkBox_1->setChecked(false); - // Сброс всех чекбоксов вызова функций ui->continiusCallChkBox_2->setChecked(false); ui->calibrateCallChkBox_2->setChecked(false); @@ -678,17 +593,14 @@ void DebugTerminalDialog::resetAll() ui->resetKeyCallChkBox_2->setChecked(false); ui->resetDefaultCallChkBox_2->setChecked(false); ui->getHardfaultCallChkBox_2->setChecked(false); - ui->enableLedTestChkBox_2->setChecked(false); ui->leds_2->setEnabled(false); ui->discs_2->setEnabled(false); - ui->discWorkTestChkBox_2->setChecked(false); // Сброс всех чекбоксов теста дискретных сигналов ui->discWorkTestChkBox_2->setChecked(false); ui->discWarnTestChkBox_2->setChecked(false); ui->discErrTestChkBox_2->setChecked(false); - // Сброс всех чекбоксов теста светодиодов ui->ledWorkTestChkBox_2->setChecked(false); ui->ledWarnTestChkBox_2->setChecked(false); @@ -697,7 +609,6 @@ void DebugTerminalDialog::resetAll() ui->ledVH1TestChkBox_2->setChecked(false); ui->ledVH2TestChkBox_2->setChecked(false); ui->ledVH3TestChkBox_2->setChecked(false); - // Сброс всех чекбоксов вызова функций ui->continiusCallChkBox_3->setChecked(false); ui->calibrateCallChkBox_3->setChecked(false); @@ -705,17 +616,14 @@ void DebugTerminalDialog::resetAll() ui->resetKeyCallChkBox_3->setChecked(false); ui->resetDefaultCallChkBox_3->setChecked(false); ui->getHardfaultCallChkBox_3->setChecked(false); - ui->enableLedTestChkBox_3->setChecked(false); ui->leds_3->setEnabled(false); ui->discs_3->setEnabled(false); - ui->discWorkTestChkBox_3->setChecked(false); // Сброс всех чекбоксов теста дискретных сигналов ui->discWorkTestChkBox_3->setChecked(false); ui->discWarnTestChkBox_3->setChecked(false); ui->discErrTestChkBox_3->setChecked(false); - // Сброс всех чекбоксов теста светодиодов ui->ledWorkTestChkBox_3->setChecked(false); ui->ledWarnTestChkBox_3->setChecked(false); @@ -724,7 +632,6 @@ void DebugTerminalDialog::resetAll() ui->ledVH1TestChkBox_3->setChecked(false); ui->ledVH2TestChkBox_3->setChecked(false); ui->ledVH3TestChkBox_3->setChecked(false); - // Сброс всех чекбоксов вызова функций ui->continiusCallChkBox_4->setChecked(false); ui->calibrateCallChkBox_4->setChecked(false); @@ -732,17 +639,14 @@ void DebugTerminalDialog::resetAll() ui->resetKeyCallChkBox_4->setChecked(false); ui->resetDefaultCallChkBox_4->setChecked(false); ui->getHardfaultCallChkBox_4->setChecked(false); - ui->enableLedTestChkBox_4->setChecked(false); ui->leds_4->setEnabled(false); ui->discs_4->setEnabled(false); - ui->discWorkTestChkBox_4->setChecked(false); // Сброс всех чекбоксов теста дискретных сигналов ui->discWorkTestChkBox_4->setChecked(false); ui->discWarnTestChkBox_4->setChecked(false); ui->discErrTestChkBox_4->setChecked(false); - // Сброс всех чекбоксов теста светодиодов ui->ledWorkTestChkBox_4->setChecked(false); ui->ledWarnTestChkBox_4->setChecked(false); @@ -757,13 +661,10 @@ void DebugTerminalDialog::boardDebugReading(int boardID) { if(mainTerm == nullptr) return; - if(!boards[boardID].isActive) return; - if(!this->isVisible()) return; - QModbusReply *_24V = mainTerm->readSingleCoil(boardID, 603); if(_24V != nullptr) connect(_24V, &QModbusReply::finished, this, [this, boardID, _24V]() { @@ -771,7 +672,6 @@ void DebugTerminalDialog::boardDebugReading(int boardID) boards[boardID].error24V->setChecked(_24V->result().value(0)); _24V->deleteLater(); }); - QModbusReply *_5V = mainTerm->readSingleCoil(boardID, 604); if(_5V != nullptr) connect(_5V, &QModbusReply::finished, this, [this, boardID, _5V]() { @@ -779,7 +679,6 @@ void DebugTerminalDialog::boardDebugReading(int boardID) boards[boardID].error5V->setChecked(_5V->result().value(0)); _5V->deleteLater(); }); - QModbusReply *_5VSCI = mainTerm->readSingleCoil(boardID, 605); if(_5VSCI != nullptr) connect(_5VSCI, &QModbusReply::finished, this, [this, boardID, _5VSCI]() { @@ -787,7 +686,6 @@ void DebugTerminalDialog::boardDebugReading(int boardID) boards[boardID].error5VSCI->setChecked(_5VSCI->result().value(0)); _5VSCI->deleteLater(); }); - QModbusReply *_5VA = mainTerm->readSingleCoil(boardID, 606); if(_5VA != nullptr) connect(_5VA, &QModbusReply::finished, this, [this, boardID, _5VA]() { @@ -805,7 +703,5 @@ void DebugTerminalDialog::setScanBoardActive(bool flag, int boardID) void DebugTerminalDialog::offAllBoard() { for(int i = 0; i < 4; i++) - { boards[i].isActive = false; - } } diff --git a/M3KTE_TERM/debugterminaldialog.h b/M3KTE_TERM/debugterminaldialog.h index 0c37b41..f910a6b 100644 --- a/M3KTE_TERM/debugterminaldialog.h +++ b/M3KTE_TERM/debugterminaldialog.h @@ -45,8 +45,6 @@ class AdcGraphDialog; #define REGISTER_TE_NUMB 564 - - namespace Ui { class DebugTerminalDialog; } @@ -54,7 +52,6 @@ class DebugTerminalDialog; class DebugTerminalDialog : public QDialog { Q_OBJECT - public: explicit DebugTerminalDialog(QWidget *parent = nullptr); ~DebugTerminalDialog(); @@ -68,21 +65,15 @@ public: void writeTENumber(int boardId, int teNumber); void openAdc(int boardID, int teNumber); void setMainTerm(M3KTE* term); - public slots: void boardDebugReading(int boardID); void setScanBoardActive(bool flag, int boardID); void offAllBoard(); - protected: void showEvent(QShowEvent *event) override; void closeEvent(QCloseEvent *event) override; - private slots: - - void on_buttonBox_clicked(QAbstractButton *button); - // Плата 1 void on_continiusCallChkBox_1_stateChanged(int state); void on_calibrateCallChkBox_1_stateChanged(int state); @@ -90,9 +81,7 @@ private slots: void on_resetKeyCallChkBox_1_stateChanged(int state); void on_resetDefaultCallChkBox_1_stateChanged(int state); void on_getHardfaultCallChkBox_1_stateChanged(int state); - void on_enableLedTestChkBox_1_stateChanged(int state); - void on_discWorkTestChkBox_1_stateChanged(int state); void on_discWarnTestChkBox_1_stateChanged(int state); void on_discErrTestChkBox_1_stateChanged(int state); @@ -100,7 +89,6 @@ private slots: void on_discErr5TestChkBox_1_stateChanged(int state); void on_discErr5VsciTestChkBox_1_stateChanged(int state); void on_discErr5VATestChkBox_1_stateChanged(int state); - void on_ledWorkTestChkBox_1_stateChanged(int state); void on_ledWarnTestChkBox_1_stateChanged(int state); void on_ledErrTestChkBox_1_stateChanged(int state); @@ -108,7 +96,6 @@ private slots: void on_ledVH1TestChkBox_1_stateChanged(int state); void on_ledVH2TestChkBox_1_stateChanged(int state); void on_ledVH3TestChkBox_1_stateChanged(int state); - // Плата 2 void on_continiusCallChkBox_2_stateChanged(int state); void on_calibrateCallChkBox_2_stateChanged(int state); @@ -116,9 +103,7 @@ private slots: void on_resetKeyCallChkBox_2_stateChanged(int state); void on_resetDefaultCallChkBox_2_stateChanged(int state); void on_getHardfaultCallChkBox_2_stateChanged(int state); - void on_enableLedTestChkBox_2_stateChanged(int state); - void on_discWorkTestChkBox_2_stateChanged(int state); void on_discWarnTestChkBox_2_stateChanged(int state); void on_discErrTestChkBox_2_stateChanged(int state); @@ -126,7 +111,6 @@ private slots: void on_discErr5TestChkBox_2_stateChanged(int state); void on_discErr5VsciTestChkBox_2_stateChanged(int state); void on_discErr5VATestChkBox_2_stateChanged(int state); - void on_ledWorkTestChkBox_2_stateChanged(int state); void on_ledWarnTestChkBox_2_stateChanged(int state); void on_ledErrTestChkBox_2_stateChanged(int state); @@ -134,8 +118,6 @@ private slots: void on_ledVH1TestChkBox_2_stateChanged(int state); void on_ledVH2TestChkBox_2_stateChanged(int state); void on_ledVH3TestChkBox_2_stateChanged(int state); - - // Плата 3 void on_continiusCallChkBox_3_stateChanged(int state); void on_calibrateCallChkBox_3_stateChanged(int state); @@ -143,9 +125,7 @@ private slots: void on_resetKeyCallChkBox_3_stateChanged(int state); void on_resetDefaultCallChkBox_3_stateChanged(int state); void on_getHardfaultCallChkBox_3_stateChanged(int state); - void on_enableLedTestChkBox_3_stateChanged(int state); - void on_discWorkTestChkBox_3_stateChanged(int state); void on_discWarnTestChkBox_3_stateChanged(int state); void on_discErrTestChkBox_3_stateChanged(int state); @@ -153,7 +133,6 @@ private slots: void on_discErr5TestChkBox_3_stateChanged(int state); void on_discErr5VsciTestChkBox_3_stateChanged(int state); void on_discErr5VATestChkBox_3_stateChanged(int state); - void on_ledWorkTestChkBox_3_stateChanged(int state); void on_ledWarnTestChkBox_3_stateChanged(int state); void on_ledErrTestChkBox_3_stateChanged(int state); @@ -161,7 +140,6 @@ private slots: void on_ledVH1TestChkBox_3_stateChanged(int state); void on_ledVH2TestChkBox_3_stateChanged(int state); void on_ledVH3TestChkBox_3_stateChanged(int state); - // Плата 4 void on_continiusCallChkBox_4_stateChanged(int state); void on_calibrateCallChkBox_4_stateChanged(int state); @@ -169,9 +147,7 @@ private slots: void on_resetKeyCallChkBox_4_stateChanged(int state); void on_resetDefaultCallChkBox_4_stateChanged(int state); void on_getHardfaultCallChkBox_4_stateChanged(int state); - void on_enableLedTestChkBox_4_stateChanged(int state); - void on_discWorkTestChkBox_4_stateChanged(int state); void on_discWarnTestChkBox_4_stateChanged(int state); void on_discErrTestChkBox_4_stateChanged(int state); @@ -179,7 +155,6 @@ private slots: void on_discErr5TestChkBox_4_stateChanged(int state); void on_discErr5VsciTestChkBox_4_stateChanged(int state); void on_discErr5VATestChkBox_4_stateChanged(int state); - void on_ledWorkTestChkBox_4_stateChanged(int state); void on_ledWarnTestChkBox_4_stateChanged(int state); void on_ledErrTestChkBox_4_stateChanged(int state); @@ -187,25 +162,20 @@ private slots: void on_ledVH1TestChkBox_4_stateChanged(int state); void on_ledVH2TestChkBox_4_stateChanged(int state); void on_ledVH3TestChkBox_4_stateChanged(int state); - signals: void coilValueChanged(int boardID, int coil, int value); void writeRegister(int boardID, int reg, int value); void readCoil(int boardID, int coil, QModbusReply *reply); - private: Ui::DebugTerminalDialog *ui; QModbusClient *m_modbusDevice; // Храним указатель здесь M3KTE* mainTerm = nullptr; - // Карты для хранения состояний QMap m_functionCalls; // boardId -> coil -> state QMap m_discreteTests; // boardId -> coil -> state QMap m_ledTests; // boardId -> coil -> state - // Номера ТЭ для каждой платы int m_teNumbers[4] = {0, 0, 0, 0}; - struct boardErrorLinks{ bool isActive = false; QCheckBox* error24V = nullptr; @@ -214,9 +184,7 @@ private: QCheckBox* error5VA = nullptr; }; boardErrorLinks boards[4]; - void initializeConnections(); - void writeCoil(int boardID, int coil, int value); //void readCoil(int coil); void resetAll(); diff --git a/M3KTE_TERM/devicesettingsdialog.cpp b/M3KTE_TERM/devicesettingsdialog.cpp index 0557943..2ad231e 100644 --- a/M3KTE_TERM/devicesettingsdialog.cpp +++ b/M3KTE_TERM/devicesettingsdialog.cpp @@ -10,17 +10,14 @@ DeviceSettingsDialog::DeviceSettingsDialog(QWidget *parent) : { ui->setupUi(this); on_buttonApplyChangeTimer_clicked(); - { - _m_timer[0] = ui->spinTimerBoard_1; - _m_timer[1] = ui->spinTimerBoard_2; - _m_timer[2] = ui->spinTimerBoard_3; - _m_timer[3] = ui->spinTimerBoard_4; - } + _m_timer[0] = ui->spinTimerBoard_1; + _m_timer[1] = ui->spinTimerBoard_2; + _m_timer[2] = ui->spinTimerBoard_3; + _m_timer[3] = ui->spinTimerBoard_4; _currentSpeed = ui->speedBox->currentText().toUInt(); _currentParity = ui->parityBox->currentIndex(); - for(int i = 0; i < 4; i++) { + for(int i = 0; i < 4; i++) _currentAdrs[i] = i+1; - } } DeviceSettingsDialog::~DeviceSettingsDialog() @@ -74,7 +71,7 @@ unsigned short DeviceSettingsDialog::currentParity() void DeviceSettingsDialog::updateSettingsAfterConnection(unsigned tmp_speed, unsigned tmp_parity, unsigned *tmp_adr, bool *ActiveDevices) { ui->speedBox->setCurrentText(QString::number(_currentSpeed=tmp_speed, 10)); - if(tmp_parity>0) + if(tmp_parity > 0) tmp_parity--; ui->parityBox->setCurrentIndex(_currentParity = tmp_parity); for(int i = 0; i < 4; i++) { @@ -82,9 +79,8 @@ void DeviceSettingsDialog::updateSettingsAfterConnection(unsigned tmp_speed, uns _m_timer[i]->setEnabled(true); ui->idComboBox->addItem(QString::number(i)); _currentAdrs[i] = tmp_adr[i]; - } else { + } else _m_timer[i]->setEnabled(false); - } } on_idComboBox_currentIndexChanged(ui->idComboBox->currentIndex()); } @@ -107,9 +103,8 @@ void DeviceSettingsDialog::on_buttonBox_clicked(QAbstractButton *button) _currentSpeed = ui->speedBox->currentText().toUInt(); ui->parityBox->setCurrentIndex(0); _currentParity = ui->parityBox->currentIndex(); - for(int i = 0; i < 4; i++) { - _currentAdrs[i] = i+1; - } + for(int i = 0; i < 4; i++) + _currentAdrs[i] = i + 1; ui->adrSpinBox->setValue(_currentAdrs[ui->idComboBox->currentIndex()]); break; case QDialogButtonBox::AcceptRole: @@ -122,7 +117,7 @@ void DeviceSettingsDialog::on_buttonBox_clicked(QAbstractButton *button) void DeviceSettingsDialog::initPollForBoard(unsigned boardID, unsigned boardAdr) { - ui->idPollComboBox->addItem(QString("Плата №%1 (ID %2)").arg(boardID+1).arg(boardAdr), QVariant(boardID)); + ui->idPollComboBox->addItem(QString("Плата №%1 (ID %2)").arg(boardID + 1).arg(boardAdr), QVariant(boardID)); } void DeviceSettingsDialog::updatePollStatus(unsigned boardID, bool status) diff --git a/M3KTE_TERM/devicesettingsdialog.h b/M3KTE_TERM/devicesettingsdialog.h index 6fcbd0f..57482b3 100644 --- a/M3KTE_TERM/devicesettingsdialog.h +++ b/M3KTE_TERM/devicesettingsdialog.h @@ -12,10 +12,8 @@ class BoardIdHasBeenChanged : public QEvent public: BoardIdHasBeenChanged(const short num, const short newId) : QEvent(QEvent::User) {_BoardNum = num; _BoardNewID = newId;} ~BoardIdHasBeenChanged() {} - short BoardNum() const {return _BoardNum;} short BoardNewID() const {return _BoardNewID;} - private: short _BoardNum; short _BoardNewID; @@ -26,10 +24,8 @@ class pollStatusChange : public QEvent public: pollStatusChange(unsigned BoardID, bool Stat) : QEvent((QEvent::Type)1001) {_BoardID = BoardID; _Status = Stat;} ~pollStatusChange() {} - unsigned BoardID() const {return _BoardID;} bool Status() const {return _Status;} - private: unsigned _BoardID; bool _Status; @@ -42,11 +38,9 @@ class DeviceSettingsDialog; class DeviceSettingsDialog : public QDialog { Q_OBJECT - public: explicit DeviceSettingsDialog(QWidget *parent = nullptr); ~DeviceSettingsDialog(); - unsigned currentBoardTimer(unsigned short _ID); unsigned currentSpeed(); unsigned short currentParity(); @@ -58,30 +52,19 @@ public: signals: void parityChanged(); void speedChanged(); - void firstBoardAdrHasBeenChanged(); void secondBoardAdrHasBeenChanged(); void thirdBoardAdrHasBeenChanged(); void fourthBoardAdrHasBeenChanged(); - private slots: - void on_buttonApplyChangeTimer_clicked(); - void on_buttonApplyChangeSpeed_clicked(); - void on_buttonApplyChangeParity_clicked(); - void on_buttonApplyChangeAdr_clicked(); - void on_idComboBox_currentIndexChanged(int index); - void on_buttonBox_clicked(QAbstractButton *button); - void on_buttonApplyChangePoll_clicked(); - void on_idPollComboBox_currentIndexChanged(int index); - private: QSpinBox *_m_timer[4]; unsigned _currentBoardTimers[4]; @@ -89,7 +72,6 @@ private: unsigned short _currentParity; unsigned _currentAdrs[4]; bool _currentPollStatus[4]; - Ui::DeviceSettingsDialog *ui; }; diff --git a/M3KTE_TERM/lineringer.cpp b/M3KTE_TERM/lineringer.cpp index 1f4e9ea..35d2b73 100644 --- a/M3KTE_TERM/lineringer.cpp +++ b/M3KTE_TERM/lineringer.cpp @@ -6,11 +6,10 @@ LineRinger::LineRinger(QWidget *parent) : ui(new Ui::LineRinger) { ui->setupUi(this); - const auto listPorts = QSerialPortInfo::availablePorts(); - for (const auto& port: listPorts) { + for(const auto& port: listPorts) ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName())); - } + //чётность { ui->parityControlBox->addItem("No", QVariant(QSerialPort::NoParity)); ui->parityControlBox->addItem("Even", QVariant(QSerialPort::EvenParity)); @@ -18,6 +17,7 @@ LineRinger::LineRinger(QWidget *parent) : ui->parityControlBox->addItem("Space", QVariant(QSerialPort::SpaceParity)); ui->parityControlBox->addItem("Mark", QVariant(QSerialPort::MarkParity)); } + //данные { ui->dataBox->addItem("Data5", QVariant(QSerialPort::Data5)); ui->dataBox->addItem("Data6", QVariant(QSerialPort::Data6)); @@ -25,6 +25,7 @@ LineRinger::LineRinger(QWidget *parent) : ui->dataBox->addItem("Data8", QVariant(QSerialPort::Data8)); ui->dataBox->setCurrentIndex(3); } + //стопбиты { ui->stopBox->addItem("One", QVariant(QSerialPort::OneStop)); ui->stopBox->addItem("OneAndHalf", QVariant(QSerialPort::OneAndHalfStop)); @@ -33,15 +34,13 @@ LineRinger::LineRinger(QWidget *parent) : ui->deviceOnlineView->horizontalHeader()->setVisible(true); syncColumnHeaders(); ui->deviceOnlineView->setColumnHidden(1, true); - ui->ringButton->setEnabled(false); - modbusDevice = new QModbusRtuSerialMaster(this); } LineRinger::~LineRinger() { - if (modbusDevice->state() == QModbusDevice::ConnectedState) + if(modbusDevice->state() == QModbusDevice::ConnectedState) on_connectButton_clicked(); delete ui; } @@ -73,9 +72,9 @@ void LineRinger::on_connectButton_clicked() #endif modbusDevice->setTimeout(50); modbusDevice->setNumberOfRetries(0); - if(!modbusDevice->connectDevice()) { + if(!modbusDevice->connectDevice()) QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения."); - } else { + else { ui->connectButton->setText(tr("Отключить")); ui->ringButton->setEnabled(true); currentBaudRate = ui->baudRateBox->currentText().toUInt(nullptr, 10); @@ -99,13 +98,13 @@ LineRinger::callStatus LineRinger::lineCall() *tmp_isRun = true; }); connect(this, &LineRinger::stopLineCall, this, [tmp_isRun]() { - *tmp_isRun = true; + *tmp_isRun = true; }); bar->setLabelText(tr("Поиск устройств... Текущий адрес: %1").arg(tmp_adr)); bar->setCancelButton(nullptr); bar->setRange(1, 247); bar->setMinimumDuration(100); - for(tmp_adr = 1; tmp_adr<248; tmp_adr++) { + for(tmp_adr = 1; tmp_adr < 248; tmp_adr++) { bar->setValue(tmp_adr); bar->setLabelText(tr("Поиск устройств... Текущий адрес: %1/247").arg(tmp_adr)); auto *reply = modbusDevice->sendRawRequest(readDeviceBasicIdentification, tmp_adr); @@ -130,7 +129,7 @@ LineRinger::callStatus LineRinger::lineCall() return callStatus::INTERRUPT; } else if(!isRun) { //Нужна проверка типа устройства - if(reply->error()!=QModbusDevice::TimeoutError) { + if(reply->error() != QModbusDevice::TimeoutError) { deviceOnLine currentDevice; currentDevice.adr = tmp_adr; currentDevice.baudRate = currentBaudRate; @@ -143,17 +142,16 @@ LineRinger::callStatus LineRinger::lineCall() for(int tmp_obj = 0; tmp_obj < numOfObject; tmp_obj++) { uint8_t objectID = result.at(0); uint8_t lengthOfObject = result.at(1); - if(lengthOfObject>0) { + if(lengthOfObject > 0) currentDevice.fields[objectID].clear(); - } - for(int i = 0; i < lengthOfObject; i++) { - currentDevice.fields[objectID] += QString(result.at(2+i)); - } - result.remove(0, lengthOfObject+2); + for(int i = 0; i < lengthOfObject; i++) + currentDevice.fields[objectID] += QString(result.at(2 + i)); + result.remove(0, lengthOfObject + 2); } auto *regularReply = modbusDevice->sendRawRequest(readDeviceRegularIdentification, tmp_adr); if(regularReply == nullptr) { - QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(modbusDevice->error()).arg(modbusDevice->errorString())); + QMessageBox::warning(this, "Ошибка при сканировании.", + QString("%1: %2").arg(modbusDevice->error()).arg(modbusDevice->errorString())); bar->close(); bar->deleteLater(); return callStatus::ERROR; @@ -183,13 +181,11 @@ LineRinger::callStatus LineRinger::lineCall() if(objectID > 0x06) continue; uint8_t lengthOfObject = regularResult.at(1); - if(lengthOfObject>0) { + if(lengthOfObject > 0) currentDevice.fields[objectID].clear(); - } - for (int i = 0; i < lengthOfObject; i++) { - currentDevice.fields[objectID] += QString(regularResult.at(2+i)); - } - regularResult.remove(0, lengthOfObject+2); + for(int i = 0; i < lengthOfObject; i++) + currentDevice.fields[objectID] += QString(regularResult.at(2 + i)); + regularResult.remove(0, lengthOfObject + 2); } } } @@ -199,14 +195,12 @@ LineRinger::callStatus LineRinger::lineCall() ui->deviceOnlineView->insertRow(newRow); ui->deviceOnlineView->setItem(newRow, 0, new QTableWidgetItem(QString::number(currentDevice.adr))); ui->deviceOnlineView->setItem(newRow, 1, new QTableWidgetItem(QString::number(currentDevice.baudRate))); - for (int i = 0; i < 7; i++) { - ui->deviceOnlineView->setItem(newRow, i+2, new QTableWidgetItem(currentDevice.fields[i])); - } - if(reply->error()!=QModbusDevice::NoError) { + for(int i = 0; i < 7; i++) + ui->deviceOnlineView->setItem(newRow, i + 2, new QTableWidgetItem(currentDevice.fields[i])); + if(reply->error()!=QModbusDevice::NoError) ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(QString("%1: %2").arg(reply->error()).arg(reply->errorString()))); - } else if(regularReplyError) { - ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString)); - } + else if(regularReplyError) + ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString)); ui->deviceOnlineView->resizeColumnsToContents(); syncColumnHeaders(); } @@ -221,8 +215,8 @@ void LineRinger::on_ringButton_clicked() ui->deviceOnlineView->clear(); devicesList.clear(); syncColumnHeaders(); - while(ui->deviceOnlineView->rowCount()!=0) - ui->deviceOnlineView->removeRow(ui->deviceOnlineView->rowCount()-1); + while(ui->deviceOnlineView->rowCount() != 0) + ui->deviceOnlineView->removeRow(ui->deviceOnlineView->rowCount() - 1); if(isAutoBaud) { auto bar = new QProgressDialog(this); bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate)); @@ -231,16 +225,16 @@ void LineRinger::on_ringButton_clicked() bar->setMinimumDuration(0); bar->setCancelButton(nullptr); connect(bar, &QProgressDialog::canceled, this, [this]() { - emit stopLineCall(); + emit stopLineCall(); }); bar->setValue(0); ui->deviceOnlineView->setColumnHidden(1, false); modbusDevice->disconnectDevice(); - for (int i = 0; i < ui->baudRateBox->count(); i++) { - bar->setValue(i+1); + for(int i = 0; i < ui->baudRateBox->count(); i++) { + bar->setValue(i + 1); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, ui->baudRateBox->itemText(i).toInt(nullptr, 10)); - if (!modbusDevice->connectDevice()) { + if(!modbusDevice->connectDevice()) { QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения."); on_connectButton_clicked(); break; @@ -248,7 +242,8 @@ void LineRinger::on_ringButton_clicked() currentBaudRate = ui->baudRateBox->itemText(i).toUInt(nullptr, 10); bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate)); if(lineCall() == callStatus::INTERRUPT) { - QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); + QMessageBox::warning(this, "Уведомление", + QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); modbusDevice->disconnectDevice(); on_connectButton_clicked(); bar->close(); @@ -262,9 +257,9 @@ void LineRinger::on_ringButton_clicked() on_connectButton_clicked(); } else { ui->deviceOnlineView->setColumnHidden(1, true); - if(lineCall() == callStatus::INTERRUPT) { - QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); - } + if(lineCall() == callStatus::INTERRUPT) + QMessageBox::warning(this, "Уведомление", + QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); } ui->timer->setTime(QTime::currentTime()); ui->timer->setDate(QDate::currentDate()); diff --git a/M3KTE_TERM/lineringer.h b/M3KTE_TERM/lineringer.h index 48c1458..e156616 100644 --- a/M3KTE_TERM/lineringer.h +++ b/M3KTE_TERM/lineringer.h @@ -16,35 +16,25 @@ class LineRinger; class LineRinger : public QWidget { Q_OBJECT - public: enum callStatus{ NOERROR = 0, ERROR = 1, INTERRUPT = 2 }; - explicit LineRinger(QWidget *parent = nullptr); ~LineRinger(); callStatus lineCall(); - signals: void stopLineCall(); - private slots: void on_connectButton_clicked(); - void on_ringButton_clicked(); - void on_checkAutoBaud_stateChanged(int arg1); - private: Ui::LineRinger *ui; - void syncColumnHeaders(); - - struct deviceOnLine - { + struct deviceOnLine{ uint8_t adr; unsigned baudRate; QString fields[7] = {"Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined"}; @@ -52,7 +42,6 @@ private: QVectordevicesList; bool isAutoBaud = false; unsigned currentBaudRate; - QModbusClient *modbusDevice = nullptr; }; diff --git a/M3KTE_TERM/m3kte.cpp b/M3KTE_TERM/m3kte.cpp index a278d38..776dd81 100644 --- a/M3KTE_TERM/m3kte.cpp +++ b/M3KTE_TERM/m3kte.cpp @@ -359,12 +359,12 @@ M3KTE::M3KTE(QWidget *parent) ui->writeTable->addItem(tr("Warnings"), QModbusDataUnit::HoldingRegisters); ui->writeTable->addItem(tr("Accidents"), QModbusDataUnit::HoldingRegisters); for(int i = 0; i < 4; i++) { - Boards[i].ModbusModelCoil = new WriteRegisterModel(this, 85 - (i/3*20), false); + Boards[i].ModbusModelCoil = new WriteRegisterModel(this, 85 - (i / 3 * 20), false); Boards[i].ModbusModelCoil->setStartAddress(0); - Boards[i].ModbusModelCoil->setNumberOfValues(QString::number(85-(i/3*20))); - Boards[i].ModbusModelHoldingReg = new WriteRegisterModel(this, (85 - (i/3*20))*2, true); + Boards[i].ModbusModelCoil->setNumberOfValues(QString::number(85 - (i / 3 * 20))); + Boards[i].ModbusModelHoldingReg = new WriteRegisterModel(this, (85 - (i / 3 * 20)) * 2, true); Boards[i].ModbusModelHoldingReg->setStartAddress(0); - Boards[i].ModbusModelHoldingReg->setNumberOfValues(QString::number(85-(i/3*20))); + Boards[i].ModbusModelHoldingReg->setNumberOfValues(QString::number(85 - (i / 3 * 20))); } m_deviceSettingsDialog = new DeviceSettingsDialog(this); m_debugTerminalDialog = new DebugTerminalDialog(this); @@ -396,7 +396,6 @@ M3KTE::M3KTE(QWidget *parent) } bool activeBoards[4] = {false, false, false, false}; m_debugTerminalDialog->updateBoardStates(activeBoards); - ui->M3kteRegSettings->setEnabled(false); ui->BSM_Warning->setEnabled(false); ui->BSM_Accident->setEnabled(false); @@ -437,7 +436,6 @@ M3KTE::M3KTE(QWidget *parent) Boards[2].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_3; Boards[3].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_4; - Boards[0].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_1; Boards[1].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_2; Boards[2].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_3; @@ -447,11 +445,9 @@ M3KTE::M3KTE(QWidget *parent) Boards[1].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_2; Boards[2].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_3; Boards[3].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_4; - } { // не кликабельные чекбоксы и радиобоксы - for(int i = 0; i < 4; i++) - { + for(int i = 0; i < 4; i++) { connect(Boards[i].localState[LOCAL_STATE_POLL], &QCheckBox::clicked, this, [i, this](bool checked) {m_deviceSettingsDialog->sendPollCommand(i, checked);}); Boards[i].localState[LOCAL_STATE_WARN]->setAttribute(Qt::WA_TransparentForMouseEvents, true); @@ -471,9 +467,8 @@ M3KTE::M3KTE(QWidget *parent) Boards[i].timerStatus->setText(" ");; Boards[i].localError->setText(" ");; } - for(int i = 0; i < 5; i++) { + for(int i = 0; i < 5; i++) ui->writeValueTable->resizeColumnToContents(i); - } QBrush tb(Qt::transparent); // Transparent brush, solid pattern for(int i = 0; i < 320; i++) { m_ProgressBar[i]->setTextVisible(true); @@ -481,7 +476,7 @@ M3KTE::M3KTE(QWidget *parent) m_ProgressBar[i]->setMaximumSize(25, 25); m_ProgressBar[i]->resize(25, 25); m_ProgressBar[i]->setAlignment(Qt::AlignCenter); - m_ProgressBar[i]->setFormat(QString("%1").arg((i%85+1))); + m_ProgressBar[i]->setFormat(QString("%1").arg((i % 85 + 1))); m_ProgressBar[i]->setValue(3); QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} "; m_ProgressBar[i]->setStyleSheet(style_fc_off); @@ -490,7 +485,7 @@ M3KTE::M3KTE(QWidget *parent) ThePhantomMenace[i]->setPalette(QPalette(tb, tb, tb, tb, tb, tb, tb, tb, tb)); connect(ThePhantomMenace[i], &QPushButton::clicked, this, [this, i]() { selectPositionOnTree(i); - m_debugTerminalDialog->writeTENumber(i/85, i - (i/85)*85 + 1); + m_debugTerminalDialog->writeTENumber(i / 85, i - (i / 85) * 85 + 1); }); } connect(m_deviceSettingsDialog, &DeviceSettingsDialog::parityChanged, this, &M3KTE::onParityUpdate); @@ -507,12 +502,17 @@ M3KTE::M3KTE(QWidget *parent) M3KTE::~M3KTE() { - if(modbusDevice->state() == QModbusDevice::ConnectedState) { + if(modbusDevice->state() == QModbusDevice::ConnectedState) onConnectClicked(); - } delete ui; } +/** + * @brief Инициализация действий и сигналов интерфейса пользователя. + * + * Этот метод настраивает начальные состояния элементов интерфейса и соединяет + * сигналы пользовательских действий с соответствующими слотами для обработки. + */ void M3KTE::initActions() { ui->ConnectionMenuConnect->setEnabled(true); @@ -537,12 +537,10 @@ void M3KTE::initActions() m_debugTerminalDialog->setDebugTerminalCoil(1); m_debugTerminalDialog->openAdc(0, 1); }); - connect(m_debugTerminalDialog, &DebugTerminalDialog::coilValueChanged, this, &M3KTE::writeSingleCoil); connect(m_debugTerminalDialog, &DebugTerminalDialog::writeRegister, this, &M3KTE::writeSingleRegister); - connect(ui->LineCall, &QAction::triggered, m_lineRinger, &QWidget::show); connect(ui->M3kteRegSettings, &QAction::triggered, m_regMultipleSettings, &QDialog::show); connect(m_regMultipleSettings, &MultipleSettings::write, this, &M3KTE::slotmultipleRegWrite); @@ -552,6 +550,17 @@ void M3KTE::initActions() connect(ui->ParameterScan, &QAction::triggered, m_parameterWorkspace, &QWidget::show); } +/** + * @brief Записывает сообщение об ошибке в таблицу логирования. + * + * Этот метод добавляет новую строку в таблицу loggerTable с информацией об ошибке, + * включая время, место возникновения, описание ошибки, счётчик ошибок и дополнительную информацию. + * + * @param errorPlace Строка, указывающая место возникновения ошибки. + * @param errorString Строка с описанием самой ошибки. + * @param errorCount Общее число ошибок этого типа (или другое релевантное значение). + * @param description Дополнительное описание ошибки. + */ void M3KTE::logError(const QString &errorPlace, const QString &errorString, unsigned errorCount, const QString &description) { unsigned newRow = loggerTable->rowCount(); @@ -565,12 +574,19 @@ void M3KTE::logError(const QString &errorPlace, const QString &errorString, unsi if(!loggerTable->verticalScrollBar()->isSliderDown()) loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum()); } + +/** + * @brief Очищает содержимое таблицы логирования. + * + * Этот метод удаляет все строки из таблицы loggerTable. Перед удалением + * обновление пользовательского интерфейса временно отключается для повышения производительности. + * Если таблица не инициализирована, метод просто завершает работу. + */ void M3KTE::clearLogger() { // Проверяем, что таблица инициализирована - if (!loggerTable) { + if(!loggerTable) return; - } // Отключаем обновление UI для повышения производительности loggerTable->setUpdatesEnabled(false); // Очищаем все строки таблицы @@ -579,6 +595,24 @@ void M3KTE::clearLogger() loggerTable->setUpdatesEnabled(true); } +/** + * @brief Обработчик нажатия кнопки "Подключиться". + * + * Эта функция устанавливает соединение с устройством Modbus, если оно не подключено, + * или разрывает соединение, если уже подключено. + * В процессе подключения происходит настройка параметров соединения (порт, параллельность, + * скорость передачи и др.), а также опрос устройств для определения их состояния. + * В случае успешного подключения включаются соответствующие элементы интерфейса и + * происходит подготовка данных для дальнейшей работы. + * В случае разрыва соединения происходит сброс настроек интерфейса и отключение устройств. + * + * Основные действия: + * - Проверка актуальности объекта modbusDevice. + * - Настройка параметров соединения и попытка подключения. + * - В случае успеха — обновление интерфейса и активация элементов. + * - В случае неудачи — отображение сообщения об ошибке. + * - При уже активном соединении — отключение устройства, сброс данных и интерфейса. + */ void M3KTE::onConnectClicked() { if(!modbusDevice) @@ -599,14 +633,13 @@ void M3KTE::onConnectClicked() #endif modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries); - if(!modbusDevice->connectDevice()) { + if(!modbusDevice->connectDevice()) statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000); - } else { + else { ui->ConnectionMenuConnect->setEnabled(false); ui->ConnectionMenuDisconnect->setEnabled(true); - if(pingNetworkDevices()) //Опрос устройст - { - //m_parameterWorkspace->setDeviceCount(1); + //Опрос устройст + if(pingNetworkDevices()) { unsigned tmp_adr[4]; bool ActiveDevices[4]; for(int i = 0; i < 4; i++) { @@ -614,7 +647,10 @@ void M3KTE::onConnectClicked() ActiveDevices[i] = Boards[i].isActive; } ui->M3kteRegSettings->setEnabled(true); - m_deviceSettingsDialog->updateSettingsAfterConnection(m_settingsDialog->settings().baud, m_settingsDialog->settings().parity, tmp_adr, ActiveDevices); + m_deviceSettingsDialog->updateSettingsAfterConnection(m_settingsDialog->settings().baud, + m_settingsDialog->settings().parity, + tmp_adr, + ActiveDevices); m_debugTerminalDialog->updateBoardStates(ActiveDevices); ui->boardSelectBox->setCurrentIndex(0); ui->writeTable->setCurrentIndex(0); @@ -638,21 +674,21 @@ void M3KTE::onConnectClicked() Boards[i].boardScanners->stop(); Boards_Fields[i]->setEnabled(false); Boards[i].isActive=false; - for(int j = 0; j < (85 - (i/3*20)); j++) { + for(int j = 0; j < (85 - (i / 3 * 20)); j++) { Boards[i].coil[j] = false; - Boards[i].ModbusModelCoil->m_coils[j]=0; - Boards[i].ModbusModelHoldingReg->m_currentU[j]=0; + Boards[i].ModbusModelCoil->m_coils[j] = 0; + Boards[i].ModbusModelHoldingReg->m_currentU[j] = 0; Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j] = 0; - Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j + (85 - (i/3*20))] = 0; + Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j + (85 - (i / 3 * 20))] = 0; } - Boards_Fields[i]->setTitle(QString("Плата №%1").arg(i+1)); + Boards_Fields[i]->setTitle(QString("Плата №%1").arg(i + 1)); Boards[i].timerData->setText(" ");; Boards[i].timerStatus->setText(" ");; Boards[i].localError->setText(" ");; } for(int i = 0; i < 320; i++) { - m_ProgressBar[i]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85))); - m_ProgressBar[i]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85))); + m_ProgressBar[i]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i / 85 + 1), QString::number(i % 85))); + m_ProgressBar[i]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i / 85 + 1), QString::number(i % 85))); m_ProgressBar[i]->setValue(3); m_ProgressBar[i]->setStyleSheet(style_fc_off); } @@ -678,6 +714,13 @@ void M3KTE::onConnectClicked() } } +/** + * @brief Обработчик нажатия кнопки чтения. + * + * Этот слот вызывается при нажатии кнопки для чтения данных по протоколу Modbus. + * В случае успешного создания запроса, подключает обработчик завершения запроса. + * Если произошла ошибка при отправке запроса, выводит сообщение об ошибке в статус-бар. + */ void M3KTE::onReadButtonClicked() { if(!modbusDevice) @@ -688,29 +731,34 @@ void M3KTE::onReadButtonClicked() connect(reply, &QModbusReply::finished, this, &M3KTE::onReadReady); else delete reply; // broadcast replies return immediately - } else { + } else statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000); - } } +/** + * @brief Обрабатывает завершение ответа на запрос чтения Modbus. + * + * Этот слот вызывается, когда ответ на запрос Modbus готов. Он получает указатель + * на объект QModbusReply, обрабатывает успешный ответ, обновляет состояние устройств + * и модели данных, а также выводит сообщения об ошибках при необходимости. + */ void M3KTE::onReadReady() { auto reply = qobject_cast(sender()); if(!reply) return; int Adr = 255; - for(int i = 0; i < 4; i++) { - if(Boards[i].isActive && Boards[i].adr==reply->serverAddress()) { + for(int i = 0; i < 4; i++) + if(Boards[i].isActive && Boards[i].adr == reply->serverAddress()) { Adr = i; break; } - } if(reply->error() == QModbusDevice::NoError) { const QModbusDataUnit unit = reply->result(); - for(int i = 0, total = int(unit.valueCount()); i < total; ++i) { + for(int i = 0, total = int(unit.valueCount()); i < total; ++i) if(unit.registerType() == QModbusDataUnit::Coils) { Boards[Adr].coil[i + unit.startAddress()] = unit.value(i); - if(unit.value(i)==1) + if(unit.value(i) == 1) Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Checked, Qt::CheckStateRole); else Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Unchecked, Qt::CheckStateRole); @@ -718,7 +766,6 @@ void M3KTE::onReadReady() Boards[Adr].HR[i + unit.startAddress()] = unit.value(i); Boards[Adr].ModbusModelHoldingReg->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 10), Qt::EditRole); } - } switch(unit.registerType()) { case QModbusDataUnit::Coils: Boards[Adr].ModbusModelCoil->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 2), @@ -735,20 +782,27 @@ void M3KTE::onReadReady() statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)"). arg(reply->errorString()). arg(reply->rawResult().exceptionCode(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr), + logError(tr("Плата %1 (ID %2)").arg(Adr + 1).arg(Boards[Adr].adr), reply->errorString(), ++Boards[Adr].error_RX, QString::number(reply->rawResult().exceptionCode())); } else { statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)"). arg(reply->errorString()). arg(reply->error(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr), + logError(tr("Плата %1 (ID %2)").arg(Adr + 1).arg(Boards[Adr].adr), reply->errorString(), ++Boards[Adr].error_RX, QString::number(reply->error(), 16)); } reply->deleteLater(); } +/** + * @brief Обрабатывает событие нажатия кнопки записи. + * + * Этот слот собирает данные из моделей, формирует запрос на запись по протоколу Modbus + * и отправляет его на устройство. Обрабатывает завершение запроса и отображает + * сообщения об ошибках при необходимости. + */ void M3KTE::onWriteButtonClicked() { if(!modbusDevice) @@ -758,12 +812,12 @@ void M3KTE::onWriteButtonClicked() QModbusDataUnit::RegisterType table = writeUnit.registerType(); for(int i = 0, total = int(writeUnit.valueCount()); i < total; ++i) { if(table == QModbusDataUnit::Coils) { - Boards[ui->boardSelectBox->currentIndex()].coil[i+writeUnit.startAddress()] = + Boards[ui->boardSelectBox->currentIndex()].coil[i + writeUnit.startAddress()] = Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]; writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]); } else { - Boards[ui->boardSelectBox->currentIndex()].HR[i+writeUnit.startAddress()] = - Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i+writeUnit.startAddress()]; + Boards[ui->boardSelectBox->currentIndex()].HR[i + writeUnit.startAddress()] = + Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i + writeUnit.startAddress()]; writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i + writeUnit.startAddress()]); } } @@ -774,175 +828,257 @@ void M3KTE::onWriteButtonClicked() if(reply->error() == QModbusDevice::ProtocolError) { statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)") .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr), + logError(tr("Плата %1 (ID %2)").arg(tmp_id + 1).arg(Boards[tmp_id].adr), reply->errorString(), ++Boards[tmp_id].error_TX, QString::number(reply->rawResult().exceptionCode(), 16)); } else if(reply->error() != QModbusDevice::NoError) { statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)"). arg(reply->errorString()).arg(reply->error(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr), + logError(tr("Плата %1 (ID %2)").arg(tmp_id + 1).arg(Boards[tmp_id].adr), reply->errorString(), ++Boards[tmp_id].error_TX, QString::number(reply->error())); } reply->deleteLater(); }); - } else { + } else // broadcast replies return immediately reply->deleteLater(); - } } else { statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000); logError(tr("Терминал"), modbusDevice->errorString(), 0, ""); } } +/** + * @brief Обрабатывает изменение выбранной платы. + * + * Этот метод вызывается при изменении выбора платы пользователем. + * Он вызывает changeTable с текущими индексами платы и таблицы. + * + * @param index Индекс выбранной платы. + */ void M3KTE::onSelectedBoardChanged(int index) { changeTable(index, ui->writeTable->currentIndex()); } +/** + * @brief Обрабатывает изменение выбранной таблицы. + * + * Этот метод вызывается при переключении таблицы пользователем. + * Он вызывает changeTable с текущими индексами выбранной платы и таблицы. + * + * @param index Индекс выбранной таблицы. + */ void M3KTE::onWriteTableChanged(int index) { changeTable(ui->boardSelectBox->currentIndex(), index); } +/** + * @brief Частично меняет отображаемую таблицу в зависимости от типа. + * + * В зависимости от типа таблицы (например, "Реле" или "Регистры") устанавливает + * соответствующую модель данных, скрывает или показывает строки и колонки, + * а также подгоняет ширину колонок. + * + * @param board Индекс выбранной платы. + * @param tabletype Тип таблицы (0 — Coil, 1 или другой — Holding Registers). + */ void M3KTE::changeTable(int board, int tabletype) { - if(tabletype==0) { + if(tabletype == 0) { ui->writeValueTable->setModel(Boards[board].ModbusModelCoil); int i = 0; - for(;irowCount();i++) { + for(; i < Boards[board].ModbusModelHoldingReg->rowCount(); i++) ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false); - } ui->writeValueTable->hideColumn(3); ui->writeValueTable->showColumn(2); } else { ui->writeValueTable->setModel(Boards[board].ModbusModelHoldingReg); - if(tabletype==1) { + if(tabletype == 1) { Boards[board].ModbusModelHoldingReg->setStartAddress(0); int i = 0; - for(;irowCount()/2;i++) { + for(; i < Boards[board].ModbusModelHoldingReg->rowCount() / 2; i++) ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false); - } - for(;irowCount();i++) { + for(; i < Boards[board].ModbusModelHoldingReg->rowCount(); i++) ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true); - } } else { - Boards[board].ModbusModelHoldingReg->setStartAddress(Boards[board].ModbusModelHoldingReg->rowCount()/2); + Boards[board].ModbusModelHoldingReg->setStartAddress(Boards[board].ModbusModelHoldingReg->rowCount() / 2); int i = 0; - for(;irowCount()/2;i++) { + for(; i < Boards[board].ModbusModelHoldingReg->rowCount() / 2; i++) ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true); - } - for(;irowCount();i++) { + for(; i < Boards[board].ModbusModelHoldingReg->rowCount(); i++) ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false); - } } ui->writeValueTable->hideColumn(2); ui->writeValueTable->showColumn(3); } - for(int i = 0; i < 5; i++) { + for(int i = 0; i < 5; i++) ui->writeValueTable->resizeColumnToContents(i); - } } +/** + * @brief Создает и возвращает объект запроса чтения для Modbus. + * + * Этот метод формирует объект QModbusDataUnit в соответствии с текущими настройками интерфейса: + * - определяет тип данных (коэли или регистры) в зависимости от выбранной таблицы; + * - вычисляет стартовый адрес на основе текущего индекса таблицы; + * - определяет число записей для чтения, ограниченное диапазоном доступных данных. + * + * @return Объект QModbusDataUnit, готовый для отправки запроса чтения. + */ QModbusDataUnit M3KTE::readRequest() const { const auto table = static_cast(ui->writeTable->currentData().toInt()); - int startAddress = 85 * (ui->writeTable->currentIndex()/2); + int startAddress = 85 * (ui->writeTable->currentIndex() / 2); Q_ASSERT(startAddress >= 0 && startAddress < 340); - quint16 numberOfEntries = qMin((ushort)(85 - (ui->boardSelectBox->currentIndex()/3*20)), quint16(340 - startAddress)); + quint16 numberOfEntries = qMin((ushort)(85 - (ui->boardSelectBox->currentIndex() / 3 * 20)), quint16(340 - startAddress)); return QModbusDataUnit(table, startAddress, numberOfEntries); } +/** + * @brief Создает и возвращает объект запроса записи для Modbus. + * + * Этот метод формирует объект QModbusDataUnit для отправки данных на устройство, + * основываясь на текущих настройках интерфейса: + * - определяет тип данных (например, кони или регистры) в зависимости от выбранной таблицы; + * - вычисляет стартовый адрес для записи, исходя из текущего индекса таблицы; + * - задает количество записей для записи, учитывая ограничение диапазона данных. + * + * @return Объект QModbusDataUnit, подготовленный для отправки запроса записи. + */ QModbusDataUnit M3KTE::writeRequest() const { const auto table = static_cast(ui->writeTable->currentData().toInt()); - int startAddress = 85 * (ui->writeTable->currentIndex()/2); + int startAddress = 85 * (ui->writeTable->currentIndex() / 2); Q_ASSERT(startAddress >= 0 && startAddress < 340); - quint16 numberOfEntries = qMin((ushort)(85 - (ui->boardSelectBox->currentIndex()/3*20)), quint16(340 - startAddress)); + quint16 numberOfEntries = qMin((ushort)(85 - (ui->boardSelectBox->currentIndex() / 3 * 20)), quint16(340 - startAddress)); return QModbusDataUnit(table, startAddress, numberOfEntries); } +/** + * @brief Обрабатывает пользовательские события, связанные с изменением ID платы и её статуса. + * + * Метод переопределяет обработку событий QWidget. В зависимости от типа события: + * - При `QEvent::User` выполняется изменение ID платы через Modbus и последующая проверка. + * - При типе 1001 (кастомный тип) происходит обновление состояния платы. + * + * Логируются ошибки при неудачных операциях, осуществляется управление асинхронными запросами Modbus. + * + * @param event Указатель на событие + * @return true, если событие обработано; иначе вызывает базовый обработчик + */ bool M3KTE::event(QEvent *event) { if(event->type() == QEvent::User) { - BoardIdHasBeenChanged* _event = static_cast(event); - QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 172, 1); + // Обработка пользовательского события изменения ID платы + auto _event = static_cast(event); + // Создаем запрос на запись нового ID в регистр + auto *_unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 172, 1); _unit->setValue(0, _event->BoardNewID()); + + // Обновляем локально временный адрес платы Boards[_event->BoardNum()]._tmp_adr = _event->BoardNewID(); + + // Отправка запроса на изменение адреса через Modbus if(auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[_event->BoardNum()].adr)) { - if(!reply->isFinished()) + if(!reply->isFinished()) { + // Обработка завершения ответа через сигнал finished connect(reply, &QModbusReply::finished, this, [reply, this, _event, _unit]() { - if(reply->error()==QModbusDevice::TimeoutError) { + if(reply->error() == QModbusDevice::TimeoutError) { + // В случае тайм-аута, отправляем запрос на чтение адреса if(auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[_event->BoardNum()]._tmp_adr)) { if(!subreply->isFinished()) { connect(subreply, &QModbusReply::finished, this, [subreply, this, _event]() { checkAdrChange(subreply, _event->BoardNum()); }); } else { - logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr), - subreply->errorString(), ++Boards[_event->BoardNum()].error_adr_change, - "Не удалось изменить адрес устройства. [1]"); + // Обработка ошибки чтения адреса + logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum() + 1).arg(Boards[_event->BoardNum()].adr), + subreply->errorString(), ++Boards[_event->BoardNum()].error_adr_change, + "Не удалось изменить адрес устройства. [1]"); reply->deleteLater(); - delete subreply; // broadcast replies return immediately + delete subreply; } } else { - logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr), + // Ошибка при создании запроса на чтение + logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum() + 1).arg(Boards[_event->BoardNum()].adr), modbusDevice->errorString(), ++Boards[_event->BoardNum()].error_adr_change, "Не удалось изменить адрес устройства. [2]"); reply->deleteLater(); } } else { - logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr), + // Ошибка при ответе на запись + logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum() + 1).arg(Boards[_event->BoardNum()].adr), reply->errorString(), ++Boards[_event->BoardNum()].error_adr_change, "Не удалось изменить адрес устройства. [3]"); reply->deleteLater(); } }); - else { - logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr), + } else { + // Запрос завершился сразу — ошибка + logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum() + 1).arg(Boards[_event->BoardNum()].adr), reply->errorString(), ++Boards[_event->BoardNum()].error_adr_change, "Не удалось изменить адрес устройства. [4]"); reply->deleteLater(); delete reply; } } else { - logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr), + // Не удалось отправить запрос + logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum() + 1).arg(Boards[_event->BoardNum()].adr), modbusDevice->errorString(), ++Boards[_event->BoardNum()].error_adr_change, "Не удалось изменить адрес устройства. [5]"); reply->deleteLater(); } + m_deviceSettingsDialog->show(); return true; } else if(event->type() == (QEvent::Type)1001) { - pollStatusChange* _event = static_cast(event); - QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 170, 1); + // Обработка смены статуса плат + auto _event = static_cast(event); + auto *_unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 170, 1); _unit->setValue(0, _event->Status()); + + // Отправка команды на изменение статуса if(auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[_event->BoardID()].adr)) { - if(!reply->isFinished()) + if(!reply->isFinished()) { connect(reply, &QModbusReply::finished, this, [reply, this, _event]() { - if(reply->error()!=QModbusDevice::NoError) { - logError(tr("Плата %1 (ID %2)").arg(_event->BoardID()+1).arg(Boards[_event->BoardID()].adr), + if(reply->error() != QModbusDevice::NoError) { + // Логирование ошибок + logError(tr("Плата %1 (ID %2)").arg(_event->BoardID() + 1).arg(Boards[_event->BoardID()].adr), reply->errorString(), ++Boards[_event->BoardID()].error_cmd_change, ""); reply->deleteLater(); } }); + } } else { - logError(tr("Плата %1 (ID %2)").arg(_event->BoardID()+1).arg(Boards[_event->BoardID()].adr), + // Не удалось отправить команду + logError(tr("Плата %1 (ID %2)").arg(_event->BoardID() + 1).arg(Boards[_event->BoardID()].adr), modbusDevice->errorString(), ++Boards[_event->BoardID()].error_cmd_change, ""); reply->deleteLater(); } return true; } + // В случаене распознанного события вызываем дефолтный обработчик return QWidget::event(event); } +/** + * @brief Проверяет результат изменения адреса устройства после Modbus-запроса. + * + * Анализирует ответ `reply`, обновляет текущий адрес в структуре `Boards` + * при успешной проверке. В случае ошибки логирует сообщение и увеличивает счетчик ошибок. + * + * @param reply Указатель на объект QModbusReply, содержащий ответ на запрос изменения адреса. + * @param boardNum Индекс устройства в массиве `Boards`. + */ void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum) { if(!reply) { - logError(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr), + logError(tr("Плата %1 (ID %2)").arg(boardNum + 1).arg(Boards[boardNum].adr), modbusDevice->errorString(), ++Boards[boardNum].error_adr_change, "Не удалось проверить изменение адреса устройства."); reply->deleteLater(); @@ -953,13 +1089,27 @@ void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum) Boards[boardNum].adr = Boards[boardNum]._tmp_adr; reply->deleteLater(); } else { - logError(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr), + logError(tr("Плата %1 (ID %2)").arg(boardNum + 1).arg(Boards[boardNum].adr), reply->errorString(), ++Boards[boardNum].error_adr_change, "Ошибка при подтверждении изменения адреса устройства."); reply->deleteLater(); } } +/** + * @brief Проверяет состояние всех активных плат через Modbus. + * + * Этот метод инициирует последовательные асинхронные чтения входных регистров (адрес 85) + * для всех активных плат, используя `QSharedPointer` для безопасного управления счётчиками и наборами. + * После завершения всех запросов генерируются сигналы: + * - `successAtCheckBoards()`, если все платы успешно подтвердили состояние, + * - `errorAtCheckBoards()`, если произошла ошибка или не все платы подтвердили. + * + * В случае неуспешной отправки запроса по плате, вызывается сигнал `errorAtCheckBoards()`, + * и выполнение метода завершается. + * + * Если активных плат не обнаружено, также генерируется сигнал `errorAtCheckBoards()`. + */ void M3KTE::checkBoards() { QModbusDataUnit unitCheck(QModbusDataUnit::InputRegisters, 85, 1); @@ -974,36 +1124,53 @@ void M3KTE::checkBoards() int slaveAddress = Boards[i].adr; QModbusReply *reply = modbusDevice->sendReadRequest(unitCheck, slaveAddress); if(!reply) { - revertToOldSpeedAndRestart(); + emit errorAtCheckBoards(); return; } pendingBoards->insert(slaveAddress); connect(reply, &QModbusReply::finished, this, [this, i, reply, slaveAddress, totalActiveBoards, confirmedBoards, pendingBoards]() { - if(reply->error() == QModbusDevice::NoError) { + if(reply->error() == QModbusDevice::NoError) (*confirmedBoards)++; - } else { - logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAddress), + else + logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAddress), reply->errorString(), ++Boards[i].error_baud_change, "Ошибка при подтверждении изменения скорости обмена."); - } pendingBoards->remove(slaveAddress); reply->deleteLater(); if(pendingBoards->isEmpty()) { - if(*confirmedBoards != *totalActiveBoards) { + if(*confirmedBoards != *totalActiveBoards) emit errorAtCheckBoards(); - } else { + else emit successAtCheckBoards(); - } } }); } // Если нет ни одной активной платы - if(*totalActiveBoards == 0) { + if(*totalActiveBoards == 0) emit errorAtCheckBoards(); - } } +/** + * @brief Обновляет скорость обмена данными и проверяет ее подтверждение для устройств. + * + * Этот метод выполняет изменение скорости обмена, отправляя команды через Modbus, + * и после подтверждения повторно подключается с новой скоростью или восстанавливает предыдущие настройки при ошибках. + * + * Основные шаги: + * 1. Останавливает сканирование плат. + * 2. Устанавливает таймаут для модбас-устройства. + * 3. Определяет новую скорость исходя из текущих настроек. + * 4. Проверяет допустимость выбранной скорости. + * 5. Отправляет команды записи скорости на все активные платы. + * 6. После подтверждения всех плат — обновляет настройки соединения и перезапускает сканирование. + * 7. В случае ошибок — восстанавливает предыдущую скорость и перезапускает скан. + * + * Для синхронизации используем `QSharedPointer` для счетчиков активных и подтвержденных плат, + * а для списков активных плат — `QSharedPointer>`. + * + * Лямбда `processResult` вызывается после обработки всех плат, чтобы завершить или повторить операцию в случае ошибок. + */ void M3KTE::onSpeedUpdate() { stopScanBoard(); @@ -1019,23 +1186,19 @@ void M3KTE::onSpeedUpdate() case 6: tmp_speed = 57600; break; case 7: tmp_speed = 115200; break; } - if(tmp_speed == 0) { logError(tr("Программная ошибка"), "Неожиданное значение скорости", 0, "Ошибка при изменении скорости обмена."); beginScanBoards(); return; } - // Используем shared pointers вместо ссылок на стековые переменные auto totalActiveBoards = QSharedPointer::create(0); auto confirmedBoards = QSharedPointer::create(0); auto pendingBoards = QSharedPointer>::create(); auto newSpeed = tmp_speed; // копируем для захвата - QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 173, 1); unit.setValue(0, m_deviceSettingsDialog->currentSpeed()); - // Лямбда для обработки результата auto processResult = [this, totalActiveBoards, confirmedBoards, newSpeed]() { if(*confirmedBoards != *totalActiveBoards) { @@ -1046,32 +1209,27 @@ void M3KTE::onSpeedUpdate() modbusDevice->disconnectDevice(); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, newSpeed); modbusDevice->connectDevice(); - // Используем QPointer для безопасного доступа к this QPointer safeThis(this); - connect(this, &M3KTE::errorAtCheckBoards, this, [safeThis]() { - if (!safeThis) + if(!safeThis) return; safeThis->disconnect(safeThis, &M3KTE::errorAtCheckBoards, safeThis, nullptr); safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime); safeThis->revertToOldSpeedAndRestart(); safeThis->beginScanBoards(); }); - connect(this, &M3KTE::successAtCheckBoards, this, [safeThis]() { - if (!safeThis) + if(!safeThis) return; safeThis->disconnect(safeThis, &M3KTE::successAtCheckBoards, safeThis, nullptr); safeThis->m_settingsDialog->UpdateBaud(safeThis->m_deviceSettingsDialog->currentSpeed()); safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime); safeThis->beginScanBoards(); }); - checkBoards(); } }; - for(int i = 0; i < 4; i++) { if(!Boards[i].isActive) continue; @@ -1080,33 +1238,35 @@ void M3KTE::onSpeedUpdate() if(reply) { (*totalActiveBoards)++; pendingBoards->insert(slaveAdress); - // Захватываем shared pointers по значению - это безопасно connect(reply, &QModbusReply::finished, this, [this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() { - if(reply->error() == QModbusDevice::TimeoutError) { + if(reply->error() == QModbusDevice::TimeoutError) (*confirmedBoards)++; - } else if (reply->error() == QModbusDevice::NoError) { - logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress), + else if(reply->error() == QModbusDevice::NoError) + logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAdress), tr("Неожиданный ответ."), ++Boards[i].error_baud_change, "Ошибка при изменении скорости обмена."); - } else { - logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress), + else + logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAdress), reply->errorString(), ++Boards[i].error_baud_change, "Ошибка при изменении скорости обмена."); - } pendingBoards->remove(slaveAdress); reply->deleteLater(); - - if(pendingBoards->isEmpty()) { + if(pendingBoards->isEmpty()) processResult(); - } }); } } } -// Вспомогательная функция восстановления старой скорости +/** + * @brief Восстанавливает предыдущую скорость обмена и перезапускает соединение. + * + * Этот метод отключает текущий модбас-устройник, устанавливает скорость соединения + * в значение, сохраненное в настройках (`curBaud()`), и затем переподключается. + * Используется для возврата к исходной скорости обмена при ошибках или отмене операции. + */ void M3KTE::revertToOldSpeedAndRestart() { modbusDevice->disconnectDevice(); @@ -1116,31 +1276,50 @@ void M3KTE::revertToOldSpeedAndRestart() modbusDevice->connectDevice(); } +/** + * @brief Обрабатывает изменение параметра четности (parity) для устройств. + * + * Отправляет запросы на изменение параметра четности на активных платах, + * затем обрабатывает результаты, при необходимости откатывая изменения. + */ void M3KTE::onParityUpdate() { + // Останавливаем сканирование плат stopScanBoard(); - modbusDevice->setTimeout(500); + + // Настройка регистра для установки режима четности QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 174, 1); switch(m_deviceSettingsDialog->currentParity()) { - case 0: unit.setValue(0, 0x000); break; //Нет контроля - case 1: unit.setValue(0, 0x0400); break;//Четный - case 2: unit.setValue(0, 0x0600); break;//Нечетный + case 0: unit.setValue(0, 0x0000); break; // Нет контроля + case 1: unit.setValue(0, 0x0400); break; // Четный + case 2: unit.setValue(0, 0x0600); break; // Нечетный } - // Используем shared pointers вместо ссылок на стековые переменные + + // Переменные для подсчёта прогресса auto totalActiveBoards = QSharedPointer::create(0); auto confirmedBoards = QSharedPointer::create(0); auto pendingBoards = QSharedPointer>::create(); - auto oldParity = m_settingsDialog->curParity(); // сохраняем старую четность для отката + + // Сохраняем текущий и новый параметры четности для отката при ошибках + auto oldParity = m_settingsDialog->curParity(); auto newParity = m_deviceSettingsDialog->currentParity(); - // Лямбда для обработки результата + + /** + * Лямбда-функция, вызываемая по завершении всех запросов. + * Обрабатывает успешное изменение или ошибку. + */ auto processResult = [this, totalActiveBoards, confirmedBoards, oldParity, newParity]() { if(*confirmedBoards != *totalActiveBoards) { + // Не все подтвердили — повторно запускаем скан modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); beginScanBoards(); } else { + // Все подтвердили — меняем параметры соединения modbusDevice->disconnectDevice(); modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, newParity); modbusDevice->connectDevice(); + + // Обработка ошибок и успеха при смене паритета auto errorHandler = [this, oldParity]() { disconnect(this, &M3KTE::errorAtCheckBoards, this, nullptr); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); @@ -1149,49 +1328,96 @@ void M3KTE::onParityUpdate() modbusDevice->connectDevice(); beginScanBoards(); }; + auto successHandler = [this, newParity]() { disconnect(this, &M3KTE::successAtCheckBoards, this, nullptr); m_settingsDialog->UpdateParity(newParity); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); beginScanBoards(); }; + + // Подписка на события успеха и ошибки connect(this, &M3KTE::errorAtCheckBoards, this, errorHandler); connect(this, &M3KTE::successAtCheckBoards, this, successHandler); + + // Запускаем повторную проверку плат checkBoards(); } }; + + // Отправляем запросы на каждую активную плату for(int i = 0; i < 4; i++) { if(!Boards[i].isActive) continue; - int slaveAdress = Boards[i].adr; - auto *reply = modbusDevice->sendWriteRequest(unit, slaveAdress); + + int slaveAddress = Boards[i].adr; + auto *reply = modbusDevice->sendWriteRequest(unit, slaveAddress); if(reply) { (*totalActiveBoards)++; - pendingBoards->insert(slaveAdress); - connect(reply, &QModbusReply::finished, this, - [this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() { - if(reply->error() == QModbusDevice::TimeoutError) { - (*confirmedBoards)++; - } else if (reply->error() == QModbusDevice::NoError) { - logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress), - tr("Неожиданный ответ."), ++Boards[i].error_baud_change, - "Ошибка при изменении чётности."); - } else { - logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress), - reply->errorString(), ++Boards[i].error_baud_change, - "Ошибка при изменении чётности."); - } - pendingBoards->remove(slaveAdress); - reply->deleteLater(); + pendingBoards->insert(slaveAddress); - if(pendingBoards->isEmpty()) { - processResult(); - } - }); + // Обработка завершения ответа + connect(reply, &QModbusReply::finished, this, + [this, i, reply, slaveAddress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() { + if(reply->error() == QModbusDevice::TimeoutError) + (*confirmedBoards)++; + else if(reply->error() == QModbusDevice::NoError) + logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAddress), + tr("Неожиданный ответ."), ++Boards[i].error_baud_change, + "Ошибка при изменении чётности."); + else + logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAddress), + reply->errorString(), ++Boards[i].error_baud_change, + "Ошибка при изменении чётности."); + + // Удаляем складной ответ + pendingBoards->remove(slaveAddress); + reply->deleteLater(); + + // Когда все ответы получены, обрабатываем результат + if(pendingBoards->isEmpty()) + processResult(); + }); } } } +/** + * @brief Функция реакция на ошибку при инициализации устройств. + * + * Инициирует отключение, закрывает прогресс-бар, и настраивает параметры + * таймаута и количества повторных попыток. + * + * @param bar Указатель на прогресс-бар для отображения процесса. + * @return false, так как функция, в текущем виде, всегда возвращает false. + */ +bool M3KTE::deadPing(QProgressDialog *bar) +{ + onConnectClicked(); + bar->close(); + bar->deleteLater(); + modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); + modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries); + return false; +} + +/** + * @brief Выполняет сканирование сети устройств (плат) по Modbus-адресам. + * + * Эта функция последовательно посылает запросы на определения типа устройства и идентификатора платы + * по адресу от 1 до 246. Если устройство отвечает ожидаемым ответом, оно считается найденным и + * добавляется в список активных плат. После сканирования отображается окно с результатами, и при необходимости + * выполняется считывание текущих настроек каждой активной платы. + * + * Основные шаги: + * - Открытие прогресс-диалога и настройка обработки отмены. + * - Посылка запросов для определения типа и ID платы. + * - Обработка ответов, обновление информации о платах. + * - Взаимодействие с пользователем: сообщение о завершении сканирования и опрос настроек. + * - Обновление интерфейса и состояния устройств. + * + * @return true, если сканирование прошло успешно и завершено; false — при ошибках или отмене. + */ bool M3KTE::pingNetworkDevices() { CurrentConnectedDevice = 0; @@ -1211,83 +1437,56 @@ bool M3KTE::pingNetworkDevices() QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404")); QModbusRequest requestOfBoardID(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0401")); modbusDevice->setTimeout(50); - for(CurrentConnectedDevice=0; CurrentConnectedDevice<4;) { + for(CurrentConnectedDevice = 0; CurrentConnectedDevice < 4;) { auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr); //Запрос типа устройства. - if(reply == nullptr) { - onConnectClicked(); - bar->close(); - bar->deleteLater(); - return false; - } + if(reply == nullptr) + return deadPing(bar); while(!reply->isFinished()) { - if(isRun && CurrentConnectedDevice < 1) { - onConnectClicked(); - bar->close(); - bar->deleteLater(); - return false; - } else if(isRun) { + if(isRun && CurrentConnectedDevice < 1) + return deadPing(bar); + else if(isRun) break; - } QCoreApplication::processEvents(); } - if(isRun && CurrentConnectedDevice < 1) { - onConnectClicked(); - bar->close(); - bar->deleteLater(); - return false; - } else if(isRun) { + if(isRun && CurrentConnectedDevice < 1) + return deadPing(bar); + else if(isRun) break; - } 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)); if(result == QString("KTE")) { - //modbusDevice->setTimeout(1000); auto *subreply = modbusDevice->sendRawRequest(requestOfBoardID, tmp_adr); - while(!subreply->isFinished()) { - if(isRun && CurrentConnectedDevice < 1) { - onConnectClicked(); - bar->close(); - bar->deleteLater(); - return false; - } else if(isRun) { + if(isRun && CurrentConnectedDevice < 1) + return deadPing(bar); + else if(isRun) break; - } QCoreApplication::processEvents(); } int plata_ind = 0; if(subreply->rawResult().data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) // ответ принят plata_ind = subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) - 0x30; // парс ответа - if(plata_ind < 1 || plata_ind > 4) { QMessageBox::warning(this, "Ошибка при сканировании сети.", QString("Не удалось получить порядковый номер платы по адресу %1").arg(tmp_adr)); - onConnectClicked(); - bar->close(); - bar->deleteLater(); - return false; + return deadPing(bar); } - int board_ind = plata_ind-1; - if(isRun && CurrentConnectedDevice < 1) { - onConnectClicked(); - bar->close(); - bar->deleteLater(); - return false; - } else if(isRun) { + int board_ind = plata_ind - 1; + if(isRun && CurrentConnectedDevice < 1) + return deadPing(bar); + else if(isRun) break; - } else { + else { statusBar()->showMessage(tr("Плата %1 найдена по адресу %2.").arg(board_ind).arg(tmp_adr), m_settingsDialog->settings().responseTime); if(Boards[board_ind].isActive) { QMessageBox::warning(this, "Ошибка при сканировании сети.", QString("Платы по адресам %1 и %2 имеют одинаковый порядковый номер %3").arg(Boards[board_ind].adr).arg(tmp_adr).arg(plata_ind)); - onConnectClicked(); - bar->close(); - bar->deleteLater(); - return false; + return deadPing(bar); } CurrentConnectedDevice++; Boards[board_ind].adr = Boards[board_ind]._tmp_adr = tmp_adr; @@ -1299,150 +1498,147 @@ bool M3KTE::pingNetworkDevices() } tmp_adr++; bar->setLabelText(tr("Поиск плат... Текущий адрес: %1").arg(tmp_adr)); - if(tmp_adr>=247 && (CurrentConnectedDevice<1)) { + if(tmp_adr >= 247 && (CurrentConnectedDevice < 1)) { //ERROR //OUT OF RANGE QMessageBox::warning(this, "Ошибка при сканировании сети.", QString("Выход за пределы допустимых адресов. Найдено %1 плат.").arg(CurrentConnectedDevice)); bar->setValue(4); - bar->close(); - bar->deleteLater(); - onConnectClicked(); - return false; - } else if(tmp_adr>=247) { + return deadPing(bar); + } else if(tmp_adr >= 247) break; - } - } - isRun=false; - QMessageBox::warning(this, "Сканирование сети завершено.", tr("Найдено плат: %1 из 4.").arg(CurrentConnectedDevice)); - if(isRun) { - QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя.")); - onConnectClicked(); - bar->close(); - bar->deleteLater(); - return false; } + isRun = false; + // Создаем QMessageBox + QMessageBox msgBox; + msgBox.setWindowTitle("Сканирование сети завершено."); + msgBox.setText(QString("Найдено плат: %1 из 4.").arg(CurrentConnectedDevice)); + // Добавляем две кнопки + QPushButton *requestSettingsBtn = msgBox.addButton("Запросить настройки", QMessageBox::AcceptRole); + QPushButton *cancelBtn = msgBox.addButton("Прервать подключение", QMessageBox::RejectRole); + // Выполняем модальное окно и ожидаем ответ + msgBox.exec(); + // Обработка нажатия + if(msgBox.clickedButton() == cancelBtn) + return deadPing(bar); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); bar->setLabelText(tr("Считывание текущих настроек...")); - bar->setRange(0, CurrentConnectedDevice*3); + bar->setRange(0, CurrentConnectedDevice * 3); for(int i = 0; i < 4; i++) { if(Boards[i].isActive) { QModbusDataUnit* _unit_settings[3]; - _unit_settings[0] = new QModbusDataUnit(QModbusDataUnit::Coils, 0, 85-(i/3*20)); - _unit_settings[1] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 0, 85-(i/3*20)); - _unit_settings[2] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 85, 85-(i/3*20)); + QModbusDataUnit cCoils(QModbusDataUnit::Coils, 0, 85 - (i / 3 * 20)); + QModbusDataUnit wHR(QModbusDataUnit::HoldingRegisters, 0, 85 - (i / 3 * 20)); + QModbusDataUnit aHR(QModbusDataUnit::HoldingRegisters, 85, 85 - (i / 3 * 20)); + _unit_settings[0] = &cCoils; + _unit_settings[1] = &wHR; + _unit_settings[2] = &aHR; Boards_Fields[i]->setEnabled(true); for(int j = 0; j < 3; j++) { - bar->setValue(i*3+j); - if(isRun) { - onConnectClicked(); - bar->close(); - bar->deleteLater(); - delete _unit_settings[0]; - delete _unit_settings[1]; - delete _unit_settings[2]; - return false; - } + bar->setValue(i * 3 + j); + if(isRun) + return deadPing(bar); auto *reply = modbusDevice->sendReadRequest(*_unit_settings[j], Boards[i].adr); - if(!reply) { - onConnectClicked(); - bar->close(); - bar->deleteLater(); - delete _unit_settings[0]; - delete _unit_settings[1]; - delete _unit_settings[2]; - return false; - } + if(!reply) + return deadPing(bar); while(!reply->isFinished()) { if(isRun) { QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя.")); - onConnectClicked(); - bar->close(); - bar->deleteLater(); - delete _unit_settings[0]; - delete _unit_settings[1]; - delete _unit_settings[2]; - return false; + return deadPing(bar); } QCoreApplication::processEvents(); } - if(reply->error()==QModbusDevice::NoError) { + if(reply->error()==QModbusDevice::NoError) applySettingsFromScan(reply); - } else { + else { QMessageBox::warning(this, "Ошибка при получении текущих настроек.", - QString("Таймаут при опросе устройства %1 по адресу %2").arg(i+1).arg(Boards[i].adr)); - bar->setValue(CurrentConnectedDevice*3); - bar->close(); - bar->deleteLater(); - onConnectClicked(); - delete _unit_settings[0]; - delete _unit_settings[1]; - delete _unit_settings[2]; - return false; + QString("Таймаут при опросе устройства %1 по адресу %2").arg(i + 1).arg(Boards[i].adr)); + bar->setValue(CurrentConnectedDevice * 3); + return deadPing(bar); } } - Boards_Fields[i]->setTitle(QString("Плата №%1 (ID %2)").arg(i+1).arg(Boards[i].adr)); - delete _unit_settings[0]; - delete _unit_settings[1]; - delete _unit_settings[2]; + Boards_Fields[i]->setTitle(QString("Плата №%1 (ID %2)").arg(i + 1).arg(Boards[i].adr)); } } int totalBoardsActive = 0; for(int i = 0; i < 4; i++) - { if(Boards[i].isActive) totalBoardsActive++; - } m_parameterWorkspace->setDeviceCount(totalBoardsActive); - modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries); beginScanBoards(); bar->deleteLater(); return true; } +/** + * @brief Запускает процесс сканирования активных плат в системе. + * + * Эта функция перебирает все возможные платы (от 0 до 3), проверяет их активность, + * и для каждой активной платы инициализирует её сканирование: + * - Обновляет состояние интерфейса для отображения активных плат. + * - Инициализирует опрос настроек устройства по адресу. + * - Запускает процедуру сканирования платы. + * - Обновляет рабочее пространство параметров с информацией об активной плате. + * + * После завершения процедуры все активные платы будут обработаны, и пользователь увидит актуальное состояние. + */ void M3KTE::beginScanBoards() { int totalBoardsActive = 0; - for(int i = 0; i < 4; i++) { + for(int i = 0; i < 4; i++) if(Boards[i].isActive) { m_debugTerminalDialog->setScanBoardActive(true, i); m_deviceSettingsDialog->initPollForBoard(i, Boards[i].adr); boardScan(i); m_parameterWorkspace->updateDevice(totalBoardsActive++, Boards[i].isActive, Boards[i].adr); } - } return; } +/** + * @brief Выполняет сканирование данных платы по Modbus. + * + * Эта функция инициирует последовательные запросы к плате с идентификатором `boardID` для получения + * статуса и полного набора данных через Modbus. Обрабатывает завершения запросов асинхронно, используя сигналы и слоты, + * измеряет время отклика, логирует ошибки и запусквает следующий цикл сканирования. + * + * Основные шаги: + * - Проверяет наличие активного Modbus-устройства. + * - Генерирует запрос чтения регистра статуса (регистры 85). + * - Обрабатывает ответ по таймеру; при успешном ответе: + * - извлекает статус регистра; + * - инициирует запрос полного набора данных (с учётом идентификатора платы); + * - обрабатывает ответ данных, вызывает функцию отображения результата, + * и перезапускает таймер следующего сканирования. + * - В случае ошибок или завершения запросов мгновенно, логирует ошибку и перезапускает цикл. + * + * @param boardID Идентификатор платы (индекс в массиве). + */ void M3KTE::boardScan(unsigned boardID) { - if (!modbusDevice) { + if(!modbusDevice) return; - } emit boardReading(boardID); - statusBar()->clearMessage(); - QModbusDataUnit statusUnit(QModbusDataUnit::InputRegisters, 85, 1); - - if (auto *reply = modbusDevice->sendReadRequest(statusUnit, Boards[boardID].adr)) { + if(auto *reply = modbusDevice->sendReadRequest(statusUnit, Boards[boardID].adr)) { Boards[boardID].timerToStatusResponse.start(); - if (!reply->isFinished()) { + if(!reply->isFinished()) { connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() { if(!Boards[boardID].isActive) return; // Обработка ответа статуса Boards[boardID].timerStatus->setText(QString("Status: %1 ms").arg(Boards[boardID].timerToStatusResponse.elapsed())); - if (reply->error() == QModbusDevice::NoError) { + if(reply->error() == QModbusDevice::NoError) { statusreg StatusReg; StatusReg.AllReg = reply->result().value(0); // Запрос полных данных - QModbusDataUnit dataUnit(QModbusDataUnit::InputRegisters, 0, 85-(boardID/3*20)); - if (auto *dataReply = modbusDevice->sendReadRequest(dataUnit, Boards[boardID].adr)) { + QModbusDataUnit dataUnit(QModbusDataUnit::InputRegisters, 0, 85 - (boardID / 3 * 20)); + if(auto *dataReply = modbusDevice->sendReadRequest(dataUnit, Boards[boardID].adr)) { Boards[boardID].timerToDataResponse.start(); - if (!dataReply->isFinished()) { + if(!dataReply->isFinished()) { connect(dataReply, &QModbusReply::finished, this, [this, boardID, dataReply, StatusReg]() { if(!Boards[boardID].isActive) return; @@ -1456,29 +1652,26 @@ void M3KTE::boardScan(unsigned boardID) // Мгновенно завершенный запрос данных Boards[boardID].timerToDataResponse.elapsed(); // shouldLog для dataReply должен определяться здесь, но используем тот же принцип - if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) { + if(Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), modbusDevice->errorString(), ++Boards[boardID].error_TX, ""); - } dataReply->deleteLater(); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID); Boards[boardID].boardScanners->start(timerInterval); } } else { // Ошибка отправки запроса данных - if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) { + if(Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), modbusDevice->errorString(), ++Boards[boardID].error_TX, ""); - } unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID); Boards[boardID].boardScanners->start(timerInterval); } } else { // Ошибка в ответе статуса - if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) { + if(Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), reply->errorString(), ++Boards[boardID].error_TX, ""); - } unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID); Boards[boardID].boardScanners->start(timerInterval); } @@ -1488,25 +1681,30 @@ void M3KTE::boardScan(unsigned boardID) // Мгновенно завершенный запрос статуса Boards[boardID].timerToStatusResponse.elapsed(); // Для мгновенно завершенных запросов определяем shouldLog здесь - if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) { + if(Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), modbusDevice->errorString(), ++Boards[boardID].error_TX, ""); - } reply->deleteLater(); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID); Boards[boardID].boardScanners->start(timerInterval); } - } else { + } else // Ошибка отправки запроса статуса - if (Boards[boardID].isActive) { + if(Boards[boardID].isActive) logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), modbusDevice->errorString(), ++Boards[boardID].error_TX, ""); - } - } } - - +/** + * @brief Обрабатывает и отображает результат сканирования Modbus-ответа. + * + * Эта функция анализирует ответ, обновляет состояние элементов пользовательского интерфейса + * и регистров, а также регистрирует ошибки и предупреждения. + * + * @param reply Указатель на объект QModbusReply, содержащий ответ. + * @param boardID Индекс платы, которую обрабатываем. + * @param status Статус регистра, полученный из устройства. + */ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status) { if(!reply) @@ -1515,8 +1713,8 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status) const QModbusDataUnit unit = reply->result(); bool W_Flag = false; bool A_Flag = false; - if(unit.startAddress() != 0 || unit.valueCount() != (unsigned)(85-(boardID/3*20))) { - logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr), + if(unit.startAddress() != 0 || unit.valueCount() != (unsigned)(85 - (boardID / 3 * 20))) { + logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), "Ошибка при приёме.", ++Boards[boardID].error_RX, tr("Принятый ответ: Стартовый адрес %1, Количество элементов %2").arg(unit.startAddress()).arg(unit.valueCount())); reply->deleteLater(); @@ -1528,14 +1726,13 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status) QString statusText; int state = StatusReg.ParsingReg.mzkte_status; int numb_err = StatusReg.ParsingReg.mzkte_error; - if (state == 0) { + if(state == 0) statusText = "Ok"; - } else if (state == 1) { + else if(state == 1) statusText = "Non-Critical"; - } else if (state == 2) { + else if(state == 2) statusText = "Critical"; - } - if (state) { + if(state) { switch (numb_err) { case 1: statusText += QString(" (Err 5 VD)"); break; case 2: statusText += QString(" (Err 5 VA)"); break; @@ -1559,46 +1756,45 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status) QString W_Adr; QString A_Adr; int total_qnt; - if(boardID == 3) { + if(boardID == 3) total_qnt = 65; - } else { + else total_qnt = 85; - } for(int i = unit.startAddress(), total = total_qnt; i < total; ++i) { if(Boards[boardID].coil[i]==true) { int j = 0; - if(Boards[boardID].HR[i+85] > unit.value(i)) { + if(Boards[boardID].HR[i + 85] > unit.value(i)) { j = 1; - if(j != m_ProgressBar[i+boardID*85]->value()) { + if(j != m_ProgressBar[i + boardID * 85]->value()) { A_Adr += tr("ТЭ%1 ").arg(i); Boards[boardID].error_A++; } - m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85))); - m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85))); + m_ProgressBar[i + boardID * 85]->setStatusTip(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID + 1), QString::number(i % 85))); + m_ProgressBar[i + boardID * 85]->setWhatsThis(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID + 1), QString::number(i % 85))); A_Flag = true; } else if(Boards[boardID].HR[i] > unit.value(i)) { j = 2; - if(j != m_ProgressBar[i+boardID*85]->value()) { + if(j != m_ProgressBar[i + boardID * 85]->value()) { W_Adr += tr("ТЭ%1 ").arg(i); Boards[boardID].error_W++; } - m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85))); - m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85))); + m_ProgressBar[i + boardID * 85]->setStatusTip(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID + 1), QString::number(i % 85))); + m_ProgressBar[i + boardID * 85]->setWhatsThis(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID + 1), QString::number(i % 85))); W_Flag = true; } else { j = 3; - m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID+1), QString::number(i%85))); - m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID+1), QString::number(i%85))); + m_ProgressBar[i + boardID * 85]->setStatusTip(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID + 1), QString::number(i % 85))); + m_ProgressBar[i + boardID * 85]->setWhatsThis(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID + 1), QString::number(i % 85))); } - m_ProgressBar[i+boardID*85]->setValue(j); - QString style_fc = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(j*50-50) + ", 255, 255, 100%);} "; - m_ProgressBar[i+boardID*85]->setStyleSheet(style_fc); + m_ProgressBar[i + boardID * 85]->setValue(j); + QString style_fc = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(j * 50 - 50) + ", 255, 255, 100%);} "; + m_ProgressBar[i + boardID * 85]->setStyleSheet(style_fc); } else { - m_ProgressBar[i+boardID*85]->setValue(3); - m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID+1), QString::number(i%85))); - m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID+1), QString::number(i%85))); + m_ProgressBar[i + boardID * 85]->setValue(3); + m_ProgressBar[i + boardID * 85]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID + 1), QString::number(i % 85))); + m_ProgressBar[i + boardID * 85]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID + 1), QString::number(i % 85))); QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} "; - m_ProgressBar[i+boardID*85]->setStyleSheet(style_fc_off); + m_ProgressBar[i + boardID * 85]->setStyleSheet(style_fc_off); } Boards[boardID].ModbusModelCoil->set_currentU(unit.value(i), i); Boards[boardID].ModbusModelHoldingReg->set_currentU(unit.value(i), i); @@ -1609,13 +1805,13 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status) ui->writeValueTable->model()->index(unit.startAddress() + total_qnt -1, 3)); if(A_Flag && !A_Adr.isEmpty()) { statusM3KTE.Accidents[boardID] = true; - logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr), + logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), "Авария", Boards[boardID].error_A, A_Adr); } else statusM3KTE.Accidents[boardID] = false; if(W_Flag && !W_Adr.isEmpty()) { statusM3KTE.Warnings[boardID] = true; - logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr), + logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), "Предупреждение", Boards[boardID].error_W, W_Adr); } else statusM3KTE.Warnings[boardID] = false; @@ -1638,38 +1834,45 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status) } else if(reply->error() == QModbusDevice::ProtocolError) { statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)"). arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr), + logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), reply->errorString(), ++Boards[boardID].error_RX, QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16)); } else { statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)"). arg(reply->errorString()).arg(reply->error(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr), + logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), reply->errorString(), ++Boards[boardID].error_RX, QString::number(reply->error(), 16)); } reply->deleteLater(); } +/** + * @brief Обрабатывает ответ Modbus и применяет настройки к платам. + * + * Эта функция проверяет ошибку ответа и, при успешном ответе, + * обновляет данные в моделях и элементах интерфейса для соответствующей платы. + * В случае ошибок отображает сообщения и регистрирует ошибки. + * + * @param reply Указатель на объект QModbusReply с ответом от устройства. + */ void M3KTE::applySettingsFromScan(QModbusReply *reply) { int Adr = 255; - for(int i = 0; i < 4; i++) { + for(int i = 0; i < 4; i++) if(Boards[i].adr==reply->serverAddress() &&Boards[i].isActive) { Adr = i; break; } - } if(reply->error() == QModbusDevice::NoError) { const QModbusDataUnit unit = reply->result(); for(int i = 0, total = int(unit.valueCount()); i < (total); ++i) { if(unit.registerType() == QModbusDataUnit::Coils) { Boards[Adr].coil[i + unit.startAddress()] = unit.value(i); - if(unit.value(i)==1) { + if(unit.value(i) == 1) Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Checked, Qt::CheckStateRole); - } else { + else Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Unchecked, Qt::CheckStateRole); - } } else if(unit.registerType() == QModbusDataUnit::HoldingRegisters) { Boards[Adr].HR[i + unit.startAddress()] = unit.value(i); Boards[Adr].ModbusModelHoldingReg->setData(Boards[Adr].ModbusModelHoldingReg->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 10), Qt::EditRole); @@ -1678,19 +1881,25 @@ void M3KTE::applySettingsFromScan(QModbusReply *reply) } else if(reply->error() == QModbusDevice::ProtocolError) { statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)"). arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr), + logError(tr("Плата %1 (ID %2)").arg(Adr + 1).arg(Boards[Adr].adr), reply->errorString(), ++Boards[Adr].error_RX, QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16)); } else { statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)"). arg(reply->errorString()).arg(reply->error(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr), + logError(tr("Плата %1 (ID %2)").arg(Adr + 1).arg(Boards[Adr].adr), reply->errorString(), ++Boards[Adr].error_RX, QString::number(reply->error(), 16)); } reply->deleteLater(); } +/** + * @brief Слот для обработки команды записи нескольких регистров. + * + * Проверяет наличие активного соединения с Modbus-устройством и + * вызывает функцию `multipleRegWrite()` для выполнения записи. + */ void M3KTE::slotmultipleRegWrite() { if(!modbusDevice) @@ -1698,6 +1907,13 @@ void M3KTE::slotmultipleRegWrite() multipleRegWrite(); } +/** + * @brief Слот для записи нескольких регистров и отправки данных. + * + * Проверяет наличие активного соединения с Modbus-устройством и, + * если соединение установлено, вызывает функции `multipleRegWrite()` для записи + * и `multipleRegSend()` для отправки данных. + */ void M3KTE::slotmultipleRegWriteAndSend() { if(!modbusDevice) @@ -1706,21 +1922,27 @@ void M3KTE::slotmultipleRegWriteAndSend() multipleRegSend(); } +/** + * @brief Отправляет команду записи нескольких регистров или катушек на устройство по Modbus. + * + * Функция создает объект QModbusDataUnit с типом регистров или катушек, в зависимости от настроек. + * Заполняет его значениями и обновляет модели данных внутреннего устройства. + * Затем инициирует асинхронную отправку запроса через `modbusDevice->sendWriteRequest()`. + * Обрабатывает результат асинхронного ответа и выводит сообщения об ошибках. + */ void M3KTE::multipleRegSend() { QModbusDataUnit *unit_tx = nullptr; - if(m_regMultipleSettings->getTypeReg()) { + if(m_regMultipleSettings->getTypeReg()) unit_tx = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, m_regMultipleSettings->getStartAdr(), m_regMultipleSettings->getCountReg()); - } else { + else unit_tx = new QModbusDataUnit(QModbusDataUnit::Coils, m_regMultipleSettings->getStartAdr(), m_regMultipleSettings->getCountReg()); - } for(unsigned i = 0; i < m_regMultipleSettings->getCountReg(); i++) { unit_tx->setValue(i, m_regMultipleSettings->getNewValue()); - if(m_regMultipleSettings->getTypeReg()) { + if(m_regMultipleSettings->getTypeReg()) Boards[m_regMultipleSettings->getBoardId()].HR[i+m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue(); - } else { + else Boards[m_regMultipleSettings->getBoardId()].coil[i+m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue(); - } } if(auto *reply = modbusDevice->sendWriteRequest(*unit_tx, Boards[m_regMultipleSettings->getBoardId()].adr)) { unsigned Adr = m_regMultipleSettings->getBoardId(); @@ -1729,100 +1951,158 @@ void M3KTE::multipleRegSend() if(reply->error() == QModbusDevice::ProtocolError) { statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)") .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr), + logError(tr("Плата %1 (ID %2)").arg(Adr + 1).arg(Boards[Adr].adr), reply->errorString(), ++Boards[Adr].error_TX, QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16)); } else if(reply->error() != QModbusDevice::NoError) { statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)"). arg(reply->errorString()).arg(reply->error(), -1, 16), 5000); - logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr), + logError(tr("Плата %1 (ID %2)").arg(Adr + 1).arg(Boards[Adr].adr), reply->errorString(), ++Boards[Adr].error_TX, QString::number(reply->error(), 16)); } reply->deleteLater(); }); - } else { + } else // broadcast replies return immediately reply->deleteLater(); - } - } else { + } else statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000); - } } +/** + * @brief Обновляет внутренние модели данных для нескольких регистров или катушек. + * + * В цикле по количеству регистров или катушек, указанных в настройках, обновляет + * значения внутренних моделей `ModbusModelHoldingReg` или `ModbusModelCoil` для соответствующих + * позиций, основываясь на типе регистров. Значения устанавливаются в новое заданное значение. + */ void M3KTE::multipleRegWrite() { for(unsigned i = 0; i < m_regMultipleSettings->getCountReg(); i++) { - if(m_regMultipleSettings->getTypeReg()) { - Boards[m_regMultipleSettings->getBoardId()].ModbusModelHoldingReg->m_holdingRegisters[i+m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue(); - } else { - Boards[m_regMultipleSettings->getBoardId()].ModbusModelCoil->m_coils[i+m_regMultipleSettings->getStartAdr()] = (bool)m_regMultipleSettings->getNewValue(); - } + if(m_regMultipleSettings->getTypeReg()) + Boards[m_regMultipleSettings->getBoardId()].ModbusModelHoldingReg->m_holdingRegisters[i + m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue(); + else + Boards[m_regMultipleSettings->getBoardId()].ModbusModelCoil->m_coils[i + m_regMultipleSettings->getStartAdr()] = (bool)m_regMultipleSettings->getNewValue(); } } +/** + * @brief Записывает значение в один котл на конкретной плате по Modbus. + * + * Проверяет наличие активного соединения и активности платы. + * Создает объект `QModbusDataUnit` для одного катушечного адреса, устанавливает значение. + * Выполняет отправку записи и обрабатывает результат асинхронно. + * + * @param boardId Идентификатор платы. + * @param coilAddress Адрес котлы, в которую нужно записать. + * @param value Значение для записи (true — включено, false — выключено). + */ void M3KTE::writeSingleCoil(int boardId, int coilAddress, bool value) { - if (!modbusDevice || !Boards[boardId].isActive) + if(!modbusDevice || !Boards[boardId].isActive) return; QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1); unit.setValue(0, value ? 1 : 0); - if (auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardId].adr)) { - if (!reply->isFinished()) { + if(auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardId].adr)) { + if(!reply->isFinished()) connect(reply, &QModbusReply::finished, this, [this, boardId, reply]() { - if (reply->error() != QModbusDevice::NoError) { - logError(tr("Плата %1 (ID %2)").arg(boardId+1).arg(Boards[boardId].adr), + if(reply->error() != QModbusDevice::NoError) + logError(tr("Плата %1 (ID %2)").arg(boardId + 1).arg(Boards[boardId].adr), reply->errorString(), ++Boards[boardId].error_TX, "Single coil write"); - } reply->deleteLater(); }); - } else { + else reply->deleteLater(); - } } } +/** + * @brief Записывает значение в один регистр (holding register) на указанной плате по Modbus. + * + * Проверяет, инициализировано ли соединение и активна ли плата. + * Создает объект `QModbusDataUnit` для одного регистра по указанному адресу и присваивает ему значение. + * Выполняет асинхронную отправку записи и обрабатывает ответ. + * + * @param boardID Идентификатор платы. + * @param regAddress Адрес регистра, в который нужно записать значение. + * @param value Значение для записи в регистр. + */ void M3KTE::writeSingleRegister(int boardID, int regAddress, quint16 value) { - if (!modbusDevice || !Boards[boardID].isActive) + if(!modbusDevice || !Boards[boardID].isActive) return; QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, regAddress, 1); unit.setValue(0, value); - if (auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardID].adr)) { - if (!reply->isFinished()) { + if(auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardID].adr)) { + if(!reply->isFinished()) connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() { - if (reply->error() != QModbusDevice::NoError) { - logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr), + if(reply->error() != QModbusDevice::NoError) + logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr), reply->errorString(), ++Boards[boardID].error_TX, "Single register write"); - } reply->deleteLater(); }); - } else { + else reply->deleteLater(); - } } } +/** + * @brief Читает состояние одного по цепочке (coil) на указанной плате по Modbus. + * + * Проверяет, инициализирован ли модуль и активна ли плата. + * Создает объект `QModbusDataUnit` для одного котла по адресу и отправляет запрос на чтение. + * Возвращает указатель на объект `QModbusReply`, который можно использовать для обработки результата асинхронно. + * + * @param boardID Идентификатор платы. + * @param coilAddress Адрес котлы (coil), состояние которой нужно прочитать. + * @return Указатель на `QModbusReply`, или `nullptr`, если модуль не инициализирован или плата не активна. + */ QModbusReply* M3KTE::readSingleCoil(int boardID, int coilAddress) { - if (!modbusDevice || !Boards[boardID].isActive) + if(!modbusDevice || !Boards[boardID].isActive) return nullptr; QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1); auto *reply = modbusDevice->sendReadRequest(unit, Boards[boardID].adr); return reply; } +/** + * @brief Выбирает позицию в дереве и таблице UI по заданному индексу. + * + * Расчет осуществляется на основе индекса, деля его на блоки, соответствующие определенным + * диапазонам элементов в интерфейсе (например, 85 элементов на плату). Затем обновляется + * выделение и прокрутка таблицы до выбранной позиции. + * + * @param index Индекс элемента, который следует выделить и прокрутить. + */ void M3KTE::selectPositionOnTree(unsigned int index) { - ui->boardSelectBox->setCurrentIndex(index/85); - int maxReg = 85 - (ui->boardSelectBox->currentIndex()/3*20); - QModelIndex selected = ui->writeValueTable->model()->index(index%maxReg + maxReg*(ui->writeTable->currentIndex()/2), 0); + ui->boardSelectBox->setCurrentIndex(index / 85); + int maxReg = 85 - (ui->boardSelectBox->currentIndex() / 3 * 20); + QModelIndex selected = ui->writeValueTable->model()->index(index % maxReg + maxReg*(ui->writeTable->currentIndex() / 2), 0); ui->writeValueTable->selectionModel()->select(selected, QItemSelectionModel::ClearAndSelect |QItemSelectionModel::Rows); ui->writeValueTable->scrollTo(selected); } +/** + * @brief Выполняет автоматический сканирование скорости передачи данных для устройств по Modbus. + * + * Эта функция перебирает стандартные скорости передачи данных (9600, 14400, 19200 и др.) + * и пытается обнаружить устройства, отвечающие на запросы по каждой скорости. + * В процессе происходит подключение к порту, отправка специальных запросов, проверка типа устройства + * и последующая синхронизация устройств, если такие были найдены. + * + * В случае успешного обнаружения устройств, результат выводится и отображается, также выполняется + * настройка устройств на выбранную скорость. + * + * Выполняет последовательные соединения, отправку запросов, обработку ответов, а также мониторинг + * пользовательского прерывания операции через диалоговое окно прогресса. + * + * @return true, если сканирование завершено успешно и все устройства синхронизированы, иначе false. + */ bool M3KTE::autoBaudRateScan() { unsigned countOfDeviceOnLine = 0; @@ -1856,9 +2136,8 @@ bool M3KTE::autoBaudRateScan() bar->setValue(i); bar->setLabelText(tr("Поиск плат... Текущая скорость: %1").arg(m_baud[i])); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]); - if(!modbusDevice->connectDevice()) { + if(!modbusDevice->connectDevice()) statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000); - } for(int tmp_adr = 1; tmp_adr < 248; tmp_adr++) { auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr); //Запрос типа устройства. @@ -1882,7 +2161,7 @@ bool M3KTE::autoBaudRateScan() bar->close(); bar->deleteLater(); return false; - } else if(!isRun) { + } else if(!isRun) //Нужна проверка типа устройства if(reply->error()==QModbusDevice::NoError) { QModbusResponse resp = reply->rawResult(); @@ -1892,21 +2171,21 @@ bool M3KTE::autoBaudRateScan() KTE[i].append(tmp_adr); } } - } } - if(countOfDeviceOnLine>0) + if(countOfDeviceOnLine > 0) resultOfScan += QString("%1 плат M3KTE работают на скорости %2.\n").arg(countOfDeviceOnLine).arg(m_baud[i]); countOfDeviceOnLine = 0; modbusDevice->disconnectDevice(); } - if(m_scanBoard->exec()==QDialog::Accepted) { - if(m_scanBoard->getCheckState()==Qt::Checked) { + 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])); + QString("Несколько устройств по адресу %1, работающих на скоростях %2 и %3.") + .arg(KTE[i].at(j)).arg(m_baud[i]).arg(m_baud[l])); return false; } } @@ -1919,9 +2198,8 @@ bool M3KTE::autoBaudRateScan() bar->setLabelText(tr("Синхронизация плат на скорости %1").arg(m_baud[i])); for(int j = 0; j < KTE[i].size(); j++) { modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]); - if(!modbusDevice->connectDevice()) { + if(!modbusDevice->connectDevice()) statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000); - } auto *reply = modbusDevice->sendWriteRequest(*_unit, KTE[i].at(j)); if(!reply) { onConnectClicked(); @@ -1938,7 +2216,7 @@ 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())); @@ -1954,16 +2232,15 @@ bool M3KTE::autoBaudRateScan() } QCoreApplication::processEvents(); } - if(subreply->error()!=QModbusDevice::NoError) { + if(subreply->error() != QModbusDevice::NoError) { onConnectClicked(); bar->close(); bar->deleteLater(); return false; } } - } else if(reply->error()!=QModbusDevice::NoError) { + } else if(reply->error() != QModbusDevice::NoError) return false; - } modbusDevice->disconnectDevice(); } } @@ -1974,10 +2251,17 @@ bool M3KTE::autoBaudRateScan() return false; } +/** + * @brief Останавливает процесс сканирования на всех платах. + * + * Эта функция перебирает все четыре устройства типа Boards и вызывает + * метод `stop()` для объекта `boardScanners`, который управляет запуском + * и остановкой процесса сканирования. После вызова все текущие сканирования + * на платах будут прекращены. + */ void M3KTE::stopScanBoard() { - for(int i = 0; i < 4; i++) { + for(int i = 0; i < 4; i++) Boards[i].boardScanners->stop(); - } return; } diff --git a/M3KTE_TERM/m3kte.h b/M3KTE_TERM/m3kte.h index 1b92fc7..903b291 100644 --- a/M3KTE_TERM/m3kte.h +++ b/M3KTE_TERM/m3kte.h @@ -59,6 +59,7 @@ private: QModbusDataUnit writeRequest() const; void changeTable(int board, int tabletype); bool event(QEvent* event); + bool deadPing(QProgressDialog *bar); bool pingNetworkDevices(); void beginScanBoards(); void stopScanBoard(); diff --git a/M3KTE_TERM/multiplesettings.cpp b/M3KTE_TERM/multiplesettings.cpp index cfe1773..c467464 100644 --- a/M3KTE_TERM/multiplesettings.cpp +++ b/M3KTE_TERM/multiplesettings.cpp @@ -25,34 +25,34 @@ void MultipleSettings::on_buttonBox_clicked(QAbstractButton *button) countReg = ui->countBox->value(); boardId = ui->boardBox->currentIndex(); emit write(); - } else if (button == ui->buttonBox->button(QDialogButtonBox::SaveAll)) { + } else if(button == ui->buttonBox->button(QDialogButtonBox::SaveAll)) { newValue = ui->regValueLine->text().toInt(nullptr, 16); typeReg = ui->regTypeBox->currentIndex(); startAdr = ui->adrBox->value(); countReg = ui->countBox->value(); boardId = ui->boardBox->currentIndex(); emit writeAndSend(); - } else {} + } } void MultipleSettings::on_regTypeBox_currentIndexChanged(int index) { short maxRange = 0; - switch (ui->boardBox->currentIndex()) { + switch(ui->boardBox->currentIndex()) { case 3: maxRange = 64; break; default: maxRange = 84; } - switch (index) { + switch(index) { case 0: case 1: ui->adrBox->setRange(0, maxRange); ui->adrBox->setValue(0); break; case 2: - ui->adrBox->setRange(85, 85+maxRange); + ui->adrBox->setRange(85, 85 + maxRange); ui->adrBox->setValue(85); break; } @@ -66,5 +66,6 @@ void MultipleSettings::on_boardBox_currentIndexChanged(int index) void MultipleSettings::on_adrBox_valueChanged(int arg1) { - ui->countBox->setRange(1, ((85-(20*(ui->boardBox->currentIndex()/3)))*(1+(ui->regTypeBox->currentIndex()/2))-arg1)); + ui->countBox->setRange(1, ((85 - (20 * (ui->boardBox->currentIndex() / 3))) + * (1 + (ui->regTypeBox->currentIndex() / 2)) - arg1)); } diff --git a/M3KTE_TERM/multiplesettings.h b/M3KTE_TERM/multiplesettings.h index a04ba97..95c4619 100644 --- a/M3KTE_TERM/multiplesettings.h +++ b/M3KTE_TERM/multiplesettings.h @@ -11,7 +11,6 @@ class MultipleSettings; class MultipleSettings : public QDialog { Q_OBJECT - public: explicit MultipleSettings(QWidget *parent = nullptr); ~MultipleSettings(); @@ -23,16 +22,11 @@ public: signals: void write(); void writeAndSend(); - private slots: void on_buttonBox_clicked(QAbstractButton *button); - void on_regTypeBox_currentIndexChanged(int index); - void on_boardBox_currentIndexChanged(int index); - void on_adrBox_valueChanged(int arg1); - private: Ui::MultipleSettings *ui; quint16 newValue = 0; diff --git a/M3KTE_TERM/parameterbox.cpp b/M3KTE_TERM/parameterbox.cpp index 57b6675..5e79ef2 100644 --- a/M3KTE_TERM/parameterbox.cpp +++ b/M3KTE_TERM/parameterbox.cpp @@ -8,7 +8,7 @@ ParameterBox::ParameterBox(QWidget *parent, pboxMode Mode, quint16 objectID) : ui->setupUi(this); boxMode = Mode; ID = objectID; - switch (boxMode) { + switch(boxMode) { case Info: ui->adrLine->setHidden(true); ui->valueBox->setHidden(true); @@ -17,7 +17,6 @@ ParameterBox::ParameterBox(QWidget *parent, pboxMode Mode, quint16 objectID) : case MTemplate: break; } - ui->objectIdLabel->setText("0x" + QString::number(ID, 16)); } @@ -29,9 +28,7 @@ ParameterBox::~ParameterBox() void ParameterBox::on_sendButton_clicked() { if(ui->valueBox->currentText().isEmpty()) - { return; - } emit writeParameter(ui->adrLine->text().toInt(), ui->valueBox->currentText().toInt(nullptr, 16)); } @@ -42,7 +39,7 @@ void ParameterBox::setData(QString data) void ParameterBox::setData(QString name, QString adr, QStringList values) { - switch (boxMode) { + switch(boxMode) { case Info: ui->nameLine->setText(name); break; diff --git a/M3KTE_TERM/parameterbox.h b/M3KTE_TERM/parameterbox.h index d1d39ec..dd6a401 100644 --- a/M3KTE_TERM/parameterbox.h +++ b/M3KTE_TERM/parameterbox.h @@ -10,7 +10,6 @@ class ParameterBox; class ParameterBox : public QWidget { Q_OBJECT - public: enum pboxMode{ Info = 0, @@ -20,10 +19,8 @@ public: Coil = 0, HR = 1 }; - explicit ParameterBox(QWidget *parent = nullptr, pboxMode Mode = Info, quint16 objectID = 0x80); ~ParameterBox(); - void setData(QString data); void setData(QString name, QString adr, QStringList values); quint16 getID(){return ID;} @@ -32,7 +29,6 @@ signals: void writeParameter(int adr, quint16 value); private slots: void on_sendButton_clicked(); - private: quint16 ID; pboxMode boxMode; diff --git a/M3KTE_TERM/parameterdevice.cpp b/M3KTE_TERM/parameterdevice.cpp index 8b731f6..0dcfc82 100644 --- a/M3KTE_TERM/parameterdevice.cpp +++ b/M3KTE_TERM/parameterdevice.cpp @@ -3,9 +3,9 @@ void sortParameterBoxesByID(QVector& parameterBoxes) { std::sort(parameterBoxes.begin(), parameterBoxes.end(), - [](ParameterBox* a, ParameterBox* b) { - return a->getID() < b->getID(); - }); + [](ParameterBox* a, ParameterBox* b) { + return a->getID() < b->getID(); + }); } ParameterDevice::ParameterDevice(QWidget *parent) : @@ -13,10 +13,6 @@ ParameterDevice::ParameterDevice(QWidget *parent) : ui(new Ui::ParameterDevice) { ui->setupUi(this); - - updateTimer = new QTimer(this); - updateTimer->setSingleShot(true); - connect(updateTimer, &QTimer::timeout, this, &ParameterDevice::sortScrollArea); } ParameterDevice::~ParameterDevice() @@ -38,46 +34,62 @@ void ParameterDevice::on_fullRadio_clicked() void ParameterDevice::on_checkButton_clicked() { - for (ParameterBox* box : parameterBoxes) { - if (box) { + for(ParameterBox* box : parameterBoxes) + if(box) box->deleteLater(); - } - } parameterBoxes.clear(); quint16 strAdr; - int cnt; + int cnt = 0; strAdr = ui->adrSpin->value(); - switch (mode) { + switch(mode) { case fullRequest: strAdr = 0x80; cnt = 128; break; - case selectiveRequest: + case selectiveRequest: cnt = ui->countSpin->value(); break; } + QElapsedTimer timer; QProgressDialog progressDialog("Обработка...", "Отмена", 0, cnt, this); progressDialog.setWindowModality(Qt::WindowModal); progressDialog.setMinimumDuration(0); // показывать сразу QEventLoop loop; connect(this, &ParameterDevice::transmitEnd, &loop, &QEventLoop::quit); - for (int i = 0; i < cnt; i ++) { + timer.start(); + for(int i = 0; i < cnt; i ++) { // Обновляем прогресс progressDialog.setValue(i); - if (progressDialog.wasCanceled()) { + if(progressDialog.wasCanceled()) break; // пользователь отменил - } QByteArray data = QByteArray::fromHex("0E04"); data.append(strAdr+i); QModbusRequest request(QModbusRequest::EncapsulatedInterfaceTransport, data); emit read(request, strAdr+i); loop.exec(); - if(errorAtTransmit) - { + if(errorAtTransmit) { errorAtTransmit = false; break; } } + qint64 elapsedNanoSeconds = timer.nsecsElapsed(); + // Вычисляем компоненты времени + qint64 totalMicroseconds = elapsedNanoSeconds / 1000; // Микросекунды + qint64 totalMilliseconds = totalMicroseconds / 1000; // Миллисекунды + qint64 totalSeconds = totalMilliseconds / 1000; // Секунды + qint64 totalMinutes = totalSeconds / 60; // Минуты + // Остатки после деления + qint64 remainingMicroseconds = totalMicroseconds % 1000; + qint64 remainingMilliseconds = totalMilliseconds % 1000; + qint64 remainingSeconds = totalSeconds % 60; + // Форматируем строку для отображения + QString timeString = QString("%1 мин %2 сек %3 мс %4 мкс") + .arg(totalMinutes) + .arg(remainingSeconds) + .arg(remainingMilliseconds) + .arg(remainingMicroseconds); + // Выводим + QMessageBox::information(this, "Общее время выполнения", timeString); progressDialog.setValue(cnt); sortParameterBoxesByID(parameterBoxes); sortScrollArea(); @@ -85,7 +97,6 @@ void ParameterDevice::on_checkButton_clicked() void ParameterDevice::setError(QString error) { - QMessageBox::information(nullptr, "Получен ответ", error); errorAtTransmit = true; emit transmitEnd(); @@ -93,14 +104,14 @@ void ParameterDevice::setError(QString error) void ParameterDevice::on_adrSpin_valueChanged(int arg1) { - ui->countSpin->setRange(1, 256-arg1); + ui->countSpin->setRange(1, 256 - arg1); } void ParameterDevice::setAnswer(QString reply, quint16 objectID) { ParameterBox *newbox = new ParameterBox(nullptr, ParameterBox::Info, objectID); newbox->setData(reply); - switch (newbox->getType()) { + switch(newbox->getType()) { case ParameterBox::Coil: connect(newbox, &ParameterBox::writeParameter, this, [this](int adr, quint16 value){ emit writeSingleCoil(adr, (bool)value); @@ -114,36 +125,20 @@ void ParameterDevice::setAnswer(QString reply, quint16 objectID) } parameterBoxes.append(newbox); emit transmitEnd(); - -// // Остановить, если уже запущен -// if (updateTimer->isActive()) { -// updateTimer->stop(); -// } -// // Запустить с задержкой 6 секунд -// updateTimer->start(6000); } void ParameterDevice::sortScrollArea() { - //sortParameterBoxesByID(parameterBoxes); - //ui->parameterBoxHubContents->layout()->deleteLater(); QLayout* pblayout = ui->parameterBoxHubContents->layout(); - if (!pblayout) { + if(!pblayout) { // Создайте новый лейаут, если его нет pblayout = new QVBoxLayout(ui->parameterBoxHubContents); ui->parameterBoxHubContents->setLayout(pblayout); } QLayoutItem *item; - while ((item = pblayout->takeAt(0)) != nullptr){ - //delete item; - } - - //ui->parameterBoxHubContents->setLayout(pblayout); - - for (int i = 0; i < parameterBoxes.count(); i++) { + while((item = pblayout->takeAt(0)) != nullptr){} + for(int i = 0; i < parameterBoxes.count(); i++) pblayout->addWidget(parameterBoxes.at(i)); - } - ui->parameterBoxHubContents->update(); ui->parameterBoxHubContents->adjustSize(); ui->scrollArea->updateGeometry(); diff --git a/M3KTE_TERM/parameterdevice.h b/M3KTE_TERM/parameterdevice.h index 5d030ac..28ebfaf 100644 --- a/M3KTE_TERM/parameterdevice.h +++ b/M3KTE_TERM/parameterdevice.h @@ -9,6 +9,7 @@ #include #include #include +#include void sortParameterBoxesByID(QVector& parameterBoxes); @@ -19,7 +20,6 @@ class ParameterDevice; class ParameterDevice : public QWidget { Q_OBJECT - public: enum requestMode{ fullRequest = 0, @@ -37,24 +37,16 @@ signals: void writeSingleCoil(int coilAddress, bool value); void writeSingleRegister(int registerAddress, quint16 value); void transmitEnd(); - private slots: void on_selectiveRadio_clicked(); - void on_fullRadio_clicked(); - void on_checkButton_clicked(); - void on_adrSpin_valueChanged(int arg1); - private: void sortScrollArea(); - private: int adr; - QTimer *updateTimer; QVectorparameterBoxes; - requestMode mode = fullRequest; Ui::ParameterDevice *ui; }; diff --git a/M3KTE_TERM/parameterworkspace.cpp b/M3KTE_TERM/parameterworkspace.cpp index 1443c5d..0fcbb1d 100644 --- a/M3KTE_TERM/parameterworkspace.cpp +++ b/M3KTE_TERM/parameterworkspace.cpp @@ -6,39 +6,38 @@ ParameterWorkspace::ParameterWorkspace(QWidget *parent) : ui(new Ui::ParameterWorkspace) { ui->setupUi(this); - } ParameterWorkspace::~ParameterWorkspace() { delete ui; } -// QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404")); -// auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr); + void ParameterWorkspace::setDeviceCount(int count) { - for(const auto& device : deviceList) - { + for(const auto& device : deviceList) { device.tab->deleteLater(); device.device->deleteLater(); } deviceList.clear(); for(int i = 0; i < ui->tabWidget->count(); i++) ui->tabWidget->removeTab(i); - for(int i = 0; i < count; i++) - { + for(int i = 0; i < count; i++) { device* _device = new device(); deviceList.append(*_device); deviceList[i].device = new ParameterDevice(); int newtab = ui->tabWidget->addTab(deviceList[i].device, tr("Device №%1").arg(i+1)); deviceList[i].tab = ui->tabWidget->widget(newtab); - connect(deviceList[i].device, &ParameterDevice::read, this, [this, i](QModbusRequest request, quint16 objectID){ + connect(deviceList[i].device, &ParameterDevice::read, this, + [this, i](QModbusRequest request, quint16 objectID){ readDeviceIdentification(deviceList[i].device, request, deviceList[i].adr, objectID); }); - connect(deviceList[i].device, &ParameterDevice::writeSingleCoil, this, [this, i](int coilAddress, bool value){ + connect(deviceList[i].device, &ParameterDevice::writeSingleCoil, this, + [this, i](int coilAddress, bool value){ writeSingleCoil(deviceList[i].adr, coilAddress, value); }); - connect(deviceList[i].device, &ParameterDevice::writeSingleRegister, this, [this, i](int registerAddress, quint16 value){ + connect(deviceList[i].device, &ParameterDevice::writeSingleRegister, this, + [this, i](int registerAddress, quint16 value){ writeSingleRegister(deviceList[i].adr, registerAddress, value); }); } @@ -46,74 +45,62 @@ void ParameterWorkspace::setDeviceCount(int count) void ParameterWorkspace::writeSingleCoil(int adr, int coilAddress, bool value) { - if (!modbusDevice && modbusDevice->state() == QModbusDevice::ConnectedState) + if(!modbusDevice && modbusDevice->state() == QModbusDevice::ConnectedState) return; QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1); unit.setValue(0, value ? 1 : 0); - if (auto *reply = modbusDevice->sendWriteRequest(unit, adr)) { - if (!reply->isFinished()) { - connect(reply, &QModbusReply::finished, this, [this, reply]() { - if (reply->error() != QModbusDevice::NoError) { - //ERROR - } + if(auto *reply = modbusDevice->sendWriteRequest(unit, adr)) { + if(!reply->isFinished()) + connect(reply, &QModbusReply::finished, this, [reply]() { + if(reply->error() != QModbusDevice::NoError) + {/*ERROR*/} reply->deleteLater(); }); - } else { + else reply->deleteLater(); - } } } void ParameterWorkspace::writeSingleRegister(int adr, int regAddress, quint16 value) { - if (!modbusDevice && modbusDevice->state() == QModbusDevice::ConnectedState) + if(!modbusDevice && modbusDevice->state() == QModbusDevice::ConnectedState) return; QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, regAddress, 1); unit.setValue(0, value); - if (auto *reply = modbusDevice->sendWriteRequest(unit, adr)) { - if (!reply->isFinished()) { - connect(reply, &QModbusReply::finished, this, [this, reply]() { - if (reply->error() != QModbusDevice::NoError) { - //ERROR - } + if(auto *reply = modbusDevice->sendWriteRequest(unit, adr)) { + if(!reply->isFinished()) + connect(reply, &QModbusReply::finished, this, [reply]() { + if(reply->error() != QModbusDevice::NoError) + {/*ERROR*/} reply->deleteLater(); }); - } else { + else reply->deleteLater(); - } } } void ParameterWorkspace::readDeviceIdentification(ParameterDevice *device, QModbusRequest request, int adr, quint16 objectID) { - if (!modbusDevice && modbusDevice->state() == QModbusDevice::ConnectedState) + if(!modbusDevice && modbusDevice->state() == QModbusDevice::ConnectedState) return; - if(auto *reply = modbusDevice->sendRawRequest(request, adr)) - { - if (!reply->isFinished()) { - connect(reply, &QModbusReply::finished, this, [this, device, reply, objectID](){ - if(reply->error() == QModbusDevice::NoError) - { + if(auto *reply = modbusDevice->sendRawRequest(request, adr)) { + if(!reply->isFinished()) { + connect(reply, &QModbusReply::finished, this, [device, reply, objectID](){ + if(reply->error() == QModbusDevice::NoError) { QModbusResponse resp = reply->rawResult(); - if(resp.data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) - { + if(resp.data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) { QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH)); device->setAnswer(result, objectID); } - } - else - { + } else { device->setError(reply->errorString()); qDebug()<<"Получен ответ:" + reply->errorString(); } reply->deleteLater(); }); } - } - else - { + } else device->setError("Unknow error"); - } } void ParameterWorkspace::updateDevice(int ID, bool status, int adr) diff --git a/M3KTE_TERM/parameterworkspace.h b/M3KTE_TERM/parameterworkspace.h index c825703..451cdce 100644 --- a/M3KTE_TERM/parameterworkspace.h +++ b/M3KTE_TERM/parameterworkspace.h @@ -24,7 +24,6 @@ class ParameterWorkspace; class ParameterWorkspace : public QWidget { Q_OBJECT - public: explicit ParameterWorkspace(QWidget *parent = nullptr); ~ParameterWorkspace(); @@ -32,12 +31,10 @@ public: void setModbusClient(QModbusClient *device){modbusDevice = device;} void setDeviceCount(int count); void updateDevice(int deviceID, bool status, int adr); - private slots: void readDeviceIdentification(ParameterDevice *board, QModbusRequest request, int adr, quint16 objectID); void writeSingleCoil(int adr, int coilAddress, bool value); void writeSingleRegister(int adr, int registerAddress, quint16 value); - private: struct device{ bool isActive = false; diff --git a/M3KTE_TERM/scanboard.h b/M3KTE_TERM/scanboard.h index 2cf10c5..7ee0de2 100644 --- a/M3KTE_TERM/scanboard.h +++ b/M3KTE_TERM/scanboard.h @@ -14,19 +14,15 @@ class ScanBoard : public QDialog public: explicit ScanBoard(QWidget *parent = nullptr); ~ScanBoard(); - Qt::CheckState getCheckState(); void showMeTheTruth(QString resultOfScan); quint16 getBaud(); private slots: void on_applyToAllBox_stateChanged(int arg1); - void on_baudRateBox_currentTextChanged(const QString &arg1); - private: Qt::CheckState checkState; quint16 baud; - Ui::ScanBoard *ui; }; diff --git a/M3KTE_TERM/settingsdialog.cpp b/M3KTE_TERM/settingsdialog.cpp index 427d469..e58e066 100644 --- a/M3KTE_TERM/settingsdialog.cpp +++ b/M3KTE_TERM/settingsdialog.cpp @@ -19,7 +19,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) : #if QT_CONFIG(modbus_serialport) m_settings.portName = ui->comBox->currentData().toString(); m_settings.parity = ui->parityCombo->currentIndex(); - if (m_settings.parity > 0) + if(m_settings.parity > 0) m_settings.parity++; m_settings.baud = ui->baudCombo->currentText().toInt(); m_settings.dataBits = ui->dataBitsCombo->currentText().toInt(); @@ -50,11 +50,10 @@ int SettingsDialog::UpdateBaud(int baud) int SettingsDialog::UpdateParity(int parity) { ui->parityCombo->setCurrentIndex(parity); - if(parity>0) { - return (m_settings.parity = ++parity); - } else { + if(parity > 0) + return (m_settings.parity = ++parity); + else return (m_settings.parity = parity); - } } int SettingsDialog::curBaud() @@ -71,7 +70,6 @@ void SettingsDialog::on_updateComBox_clicked() { ui->comBox->clear(); const auto listPorts = QSerialPortInfo::availablePorts(); - for (const auto& port: listPorts) { + for(const auto& port: listPorts) ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName())); - } } diff --git a/M3KTE_TERM/settingsdialog.h b/M3KTE_TERM/settingsdialog.h index 3716f38..b62adff 100644 --- a/M3KTE_TERM/settingsdialog.h +++ b/M3KTE_TERM/settingsdialog.h @@ -27,20 +27,15 @@ public: int responseTime = 1000; int numberOfRetries = 0; }; - explicit SettingsDialog(QWidget *parent = nullptr); ~SettingsDialog(); - Settings settings() const; - int UpdateBaud(int baud); int UpdateParity(int parity); - int curBaud(); int curParity(); private slots: void on_updateComBox_clicked(); - private: Settings m_settings; Ui::SettingsDialog *ui; diff --git a/M3KTE_TERM/writeregistermodel.cpp b/M3KTE_TERM/writeregistermodel.cpp index d7e2907..aaf057c 100644 --- a/M3KTE_TERM/writeregistermodel.cpp +++ b/M3KTE_TERM/writeregistermodel.cpp @@ -1,7 +1,5 @@ #include "writeregistermodel.h" -#include "writeregistermodel.h" - enum { NumColumn = 0, NameColumn = 1, CoilsColumn = 2, HoldingColumn = 3, ColumnCount = 5, CurrentUColumn = 4}; WriteRegisterModel::WriteRegisterModel(QObject *parent, int _tmpRC, bool _isHR) @@ -23,29 +21,29 @@ int WriteRegisterModel::columnCount(const QModelIndex &/*parent*/) const QVariant WriteRegisterModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount) + if(!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount) return QVariant(); Q_ASSERT(m_coils.count() == RowCount); Q_ASSERT(m_holdingRegisters.count() == RowCount); - if (index.column() == NumColumn && role == Qt::DisplayRole) + if(index.column() == NumColumn && role == Qt::DisplayRole) return QString::number(index.row()); - if (index.column() == NameColumn && role == Qt::DisplayRole) + if(index.column() == NameColumn && role == Qt::DisplayRole) return QString("ТЭ%1").arg(index.row()%(RowCount/(1+isHR))+1); - if (index.column() == CoilsColumn && role == Qt::CheckStateRole) // coils + if(index.column() == CoilsColumn && role == Qt::CheckStateRole) // coils return m_coils.at(index.row()) ? Qt::Checked : Qt::Unchecked; - if (index.column() == HoldingColumn && role == Qt::DisplayRole) // holding registers - return QString("%1 В").arg(QString::number((double)((double)m_holdingRegisters.at(index.row())/(double)1000), 'f', 3)); + if(index.column() == HoldingColumn && role == Qt::DisplayRole) // holding registers + return QString("%1 В").arg(QString::number((double)((double)m_holdingRegisters.at(index.row()) / (double)1000), 'f', 3)); if(index.column() == CurrentUColumn && role == Qt::DisplayRole) - return QString("%1 В").arg(QString::number((double)((double)m_currentU.at(index.row())/(double)1000), 'f', 3)); + return QString("%1 В").arg(QString::number((double)((double)m_currentU.at(index.row()) / (double)1000), 'f', 3)); return QVariant(); } QVariant WriteRegisterModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role != Qt::DisplayRole) + if(role != Qt::DisplayRole) return QVariant(); - if (orientation == Qt::Horizontal) { - switch (section) { + if(orientation == Qt::Horizontal) { + switch(section) { case NumColumn: return QStringLiteral("#Reg"); case NameColumn: @@ -65,20 +63,20 @@ QVariant WriteRegisterModel::headerData(int section, Qt::Orientation orientation bool WriteRegisterModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount) + if(!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount) return false; Q_ASSERT(m_coils.count() == RowCount); Q_ASSERT(m_holdingRegisters.count() == RowCount); - if (index.column() == CoilsColumn && role == Qt::CheckStateRole) { // coils + if(index.column() == CoilsColumn && role == Qt::CheckStateRole) { // coils auto s = static_cast(value.toUInt()); s == Qt::Checked ? m_coils.setBit(index.row()) : m_coils.clearBit(index.row()); emit dataChanged(index, index); return true; } - if (index.column() == HoldingColumn && role == Qt::EditRole) { // holding registers + if(index.column() == HoldingColumn && role == Qt::EditRole) { // holding registers bool result = false; quint16 newValue = value.toString().toUShort(&result, 10); - if (result) + if(result) m_holdingRegisters[index.row()] = newValue; emit dataChanged(index, index); return result; @@ -88,14 +86,14 @@ bool WriteRegisterModel::setData(const QModelIndex &index, const QVariant &value Qt::ItemFlags WriteRegisterModel::flags(const QModelIndex &index) const { - if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount) + if(!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount) return QAbstractTableModel::flags(index); Qt::ItemFlags flags = QAbstractTableModel::flags(index); - if ((index.row() < m_address) || (index.row() >= (m_address + m_number))) + if((index.row() < m_address) || (index.row() >= (m_address + m_number))) flags &= ~Qt::ItemIsEnabled; - if (index.column() == CoilsColumn) // coils + if(index.column() == CoilsColumn) // coils return flags | Qt::ItemIsUserCheckable; - if (index.column() == HoldingColumn) // holding registers + if(index.column() == HoldingColumn) // holding registers return flags | Qt::ItemIsEditable; return flags; } @@ -103,13 +101,11 @@ Qt::ItemFlags WriteRegisterModel::flags(const QModelIndex &index) const void WriteRegisterModel::setStartAddress(int address) { m_address = address; - //emit updateViewport(); } void WriteRegisterModel::setNumberOfValues(const QString &number) { m_number = number.toInt(); - //emit updateViewport(); } bool WriteRegisterModel::get_coil(const QModelIndex &index) diff --git a/M3KTE_TERM/writeregistermodel.h b/M3KTE_TERM/writeregistermodel.h index 867c325..8b58c21 100644 --- a/M3KTE_TERM/writeregistermodel.h +++ b/M3KTE_TERM/writeregistermodel.h @@ -14,25 +14,18 @@ public: WriteRegisterModel(QObject *parent = nullptr, int _tmpRC = 85, bool _isHR = false); bool get_coil(const QModelIndex &index); uint get_holreg(const QModelIndex &index); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - bool set_currentU(unsigned _tmpU, unsigned index); - public slots: void setStartAddress(int address); void setNumberOfValues(const QString &number); - signals: void updateViewport(); - public: int m_number = 0; int m_address = 0;