Оптимизация кода, начало работы с комментариями

This commit is contained in:
2025-12-01 17:23:24 +03:00
parent 3f1cd53e19
commit f10f3c8927
23 changed files with 914 additions and 989 deletions

View File

@@ -26,36 +26,31 @@ AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) :
m_teNumber(-1), m_teNumber(-1),
m_adcZero(0), m_adcZero(0),
m_adcOneVolt(4096), m_adcOneVolt(4096),
m_series(new QLineSeries()),
m_chart(new QChart()),
m_stableStartLine(new QLineSeries()), m_stableStartLine(new QLineSeries()),
m_stableEndLine(new QLineSeries()), m_stableEndLine(new QLineSeries()),
m_stableStartIndex(-1), m_stableStartIndex(-1),
m_stableEndIndex(-1), m_stableEndIndex(-1),
m_series(new QLineSeries()),
m_chart(new QChart()),
m_startAddress(0), m_startAddress(0),
m_registerCount(100) m_registerCount(100)
{ {
ui->setupUi(this); ui->setupUi(this);
// Настройка основного графика // Настройка основного графика
m_series->setName("АЦП данные"); m_series->setName("АЦП данные");
m_chart->addSeries(m_series); m_chart->addSeries(m_series);
// Настройка линий стабильного участка // Настройка линий стабильного участка
m_stableStartLine->setName("Начало стаб. участка"); m_stableStartLine->setName("Начало стаб. участка");
m_stableStartLine->setColor(Qt::red); m_stableStartLine->setColor(Qt::red);
m_stableStartLine->setPen(QPen(Qt::red, 2, Qt::DashLine)); m_stableStartLine->setPen(QPen(Qt::red, 2, Qt::DashLine));
m_chart->addSeries(m_stableStartLine); m_chart->addSeries(m_stableStartLine);
m_stableEndLine->setName("Конец стаб. участка"); m_stableEndLine->setName("Конец стаб. участка");
m_stableEndLine->setColor(Qt::green); m_stableEndLine->setColor(Qt::green);
m_stableEndLine->setPen(QPen(Qt::green, 2, Qt::DashLine)); m_stableEndLine->setPen(QPen(Qt::green, 2, Qt::DashLine));
m_chart->addSeries(m_stableEndLine); m_chart->addSeries(m_stableEndLine);
m_chart->setTitle("График АЦП"); m_chart->setTitle("График АЦП");
m_chart->legend()->setVisible(true); m_chart->legend()->setVisible(true);
m_chart->legend()->setAlignment(Qt::AlignTop); m_chart->legend()->setAlignment(Qt::AlignTop);
m_axisX = new QValueAxis(); m_axisX = new QValueAxis();
m_axisX->setTitleText("Отсчеты АЦП"); m_axisX->setTitleText("Отсчеты АЦП");
m_axisX->setRange(0, m_registerCount); m_axisX->setRange(0, m_registerCount);
@@ -63,7 +58,6 @@ AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) :
m_series->attachAxis(m_axisX); m_series->attachAxis(m_axisX);
m_stableStartLine->attachAxis(m_axisX); m_stableStartLine->attachAxis(m_axisX);
m_stableEndLine->attachAxis(m_axisX); m_stableEndLine->attachAxis(m_axisX);
m_axisY = new QValueAxis(); m_axisY = new QValueAxis();
m_axisY->setTitleText("Напряжение, В"); m_axisY->setTitleText("Напряжение, В");
m_axisY->setRange(-1.3, 1.3); m_axisY->setRange(-1.3, 1.3);
@@ -71,13 +65,10 @@ AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) :
m_series->attachAxis(m_axisY); m_series->attachAxis(m_axisY);
m_stableStartLine->attachAxis(m_axisY); m_stableStartLine->attachAxis(m_axisY);
m_stableEndLine->attachAxis(m_axisY); m_stableEndLine->attachAxis(m_axisY);
QChartView *chartView = new QChartView(m_chart); QChartView *chartView = new QChartView(m_chart);
chartView->setRenderHint(QPainter::Antialiasing); chartView->setRenderHint(QPainter::Antialiasing);
QVBoxLayout *layout = new QVBoxLayout(ui->plotWidget); QVBoxLayout *layout = new QVBoxLayout(ui->plotWidget);
layout->addWidget(chartView); layout->addWidget(chartView);
// Подключаем сигналы элементов управления диапазоном // Подключаем сигналы элементов управления диапазоном
connect(ui->registerCountSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), connect(ui->registerCountSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &AdcGraphDialog::on_registerCountChanged); this, &AdcGraphDialog::on_registerCountChanged);
@@ -85,21 +76,16 @@ AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) :
this, &AdcGraphDialog::on_rangeApplyClicked); this, &AdcGraphDialog::on_rangeApplyClicked);
connect(ui->teNumberSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), connect(ui->teNumberSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &AdcGraphDialog::on_teNumberChanged); this, &AdcGraphDialog::on_teNumberChanged);
connect(m_updateTimer, &QTimer::timeout, this, &AdcGraphDialog::onUpdateTimer); connect(m_updateTimer, &QTimer::timeout, this, &AdcGraphDialog::onUpdateTimer);
connect(ui->closeBtn, &QPushButton::clicked, this, &AdcGraphDialog::on_closeBtn_clicked); connect(ui->closeBtn, &QPushButton::clicked, this, &AdcGraphDialog::on_closeBtn_clicked);
} }
AdcGraphDialog::~AdcGraphDialog() AdcGraphDialog::~AdcGraphDialog()
{ {
stopGraph(); stopGraph();
delete ui; delete ui;
} }
void AdcGraphDialog::setModbusDevice(QModbusClient *device) void AdcGraphDialog::setModbusDevice(QModbusClient *device)
{ {
m_modbusDevice = device; m_modbusDevice = device;
@@ -113,26 +99,23 @@ void AdcGraphDialog::on_teNumberChanged(int value)
void AdcGraphDialog::setTENumber(int boardID, int teNumber) void AdcGraphDialog::setTENumber(int boardID, int teNumber)
{ {
if (m_boardAddress == -1) return; if(m_boardAddress == -1)
return;
m_teNumber = teNumber; m_teNumber = teNumber;
m_boardId = boardID; m_boardId = boardID;
m_boardAddress = m_boardId + 1; m_boardAddress = m_boardId + 1;
// Обновляем заголовок окна // Обновляем заголовок окна
setWindowTitle(QString("График АЦП - Плата %1, ТЭ %2 (адр %3-%4)") setWindowTitle(QString("График АЦП - Плата %1, ТЭ %2 (адр %3-%4)")
.arg(m_boardId + 1) .arg(m_boardId + 1)
.arg(m_teNumber) .arg(m_teNumber)
.arg(m_startAddress) .arg(m_startAddress)
.arg(m_startAddress + m_registerCount - 1)); .arg(m_startAddress + m_registerCount - 1));
// Записываем новый номер ТЭ в устройство // Записываем новый номер ТЭ в устройство
if(m_modbusDevice) { if(m_modbusDevice) {
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, REG_TE_NUMBER, 1); QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, REG_TE_NUMBER, 1);
unit.setValue(0, teNumber); unit.setValue(0, teNumber);
if(auto *reply = m_modbusDevice->sendWriteRequest(unit, m_boardAddress)) { if(auto *reply = m_modbusDevice->sendWriteRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [this, reply, teNumber]() { connect(reply, &QModbusReply::finished, this, [this, reply, teNumber]() {
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
qDebug() << "TE number changed to:" << teNumber; qDebug() << "TE number changed to:" << teNumber;
@@ -143,78 +126,65 @@ void AdcGraphDialog::setTENumber(int boardID, int teNumber)
} }
reply->deleteLater(); reply->deleteLater();
}); });
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} }
}
ui->teNumberSpinBox->setValue(teNumber); ui->teNumberSpinBox->setValue(teNumber);
} }
void AdcGraphDialog::readCalibrationValues() void AdcGraphDialog::readCalibrationValues()
{ {
if (!m_modbusDevice || m_boardAddress == -1) return; if(!m_modbusDevice || m_boardAddress == -1)
return;
// Читаем калибровочные значения (регистры 555 и 556) // Читаем калибровочные значения (регистры 555 и 556)
QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_ADC_ZERO, 2); QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_ADC_ZERO, 2);
if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [this, reply]() { connect(reply, &QModbusReply::finished, this, [this, reply]() {
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit result = reply->result(); const QModbusDataUnit result = reply->result();
if(result.valueCount() >= 2) { if(result.valueCount() >= 2) {
m_adcZero = result.value(0); m_adcZero = result.value(0);
m_adcOneVolt = result.value(1); m_adcOneVolt = result.value(1);
//qDebug() << "Calibration values - Zero:" << m_adcZero << "1V:" << m_adcOneVolt;
} }
} else {
//qDebug() << "Error reading calibration:" << reply->errorString();
} }
reply->deleteLater(); reply->deleteLater();
}); });
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} }
}
void AdcGraphDialog::readStableIndices() void AdcGraphDialog::readStableIndices()
{ {
if (!m_modbusDevice || m_boardAddress == -1) return; if(!m_modbusDevice || m_boardAddress == -1)
return;
// Читаем индексы стабильного участка (регистры 557 и 558) // Читаем индексы стабильного участка (регистры 557 и 558)
QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_STABLE_START, 2); QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_STABLE_START, 2);
if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) { if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onStableIndicesReady); connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onStableIndicesReady);
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} }
}
void AdcGraphDialog::onStableIndicesReady() void AdcGraphDialog::onStableIndicesReady()
{ {
auto *reply = qobject_cast<QModbusReply*>(sender()); auto *reply = qobject_cast<QModbusReply*>(sender());
if (!reply) return; if(!reply)
return;
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit result = reply->result(); const QModbusDataUnit result = reply->result();
if(result.valueCount() >= 2) { if(result.valueCount() >= 2) {
m_stableStartIndex = result.value(0); m_stableStartIndex = result.value(0);
m_stableEndIndex = result.value(1); m_stableEndIndex = result.value(1);
//qDebug() << "Stable indices updated - Start:" << m_stableStartIndex << "End:" << m_stableEndIndex;
updateStableLines(); updateStableLines();
// Обновляем статистику с новыми индексами // Обновляем статистику с новыми индексами
updateStatisticsWithStableInfo(); updateStatisticsWithStableInfo();
} }
} else {
//qDebug() << "Error reading stable indices:" << reply->errorString();
} }
reply->deleteLater(); reply->deleteLater();
} }
@@ -224,26 +194,24 @@ void AdcGraphDialog::updateStatistics()
double min = 1000, max = -1000, sum = 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(); double y = point.y();
if (y < min) min = y; if(y < min)
if (y > max) max = y; min = y;
if(y > max)
max = y;
sum += y; sum += y;
} }
double avg = sum / m_series->count(); double avg = sum / m_series->count();
ui->minLabel->setText(QString::number(min, 'f', 3) + " В"); ui->minLabel->setText(QString::number(min, 'f', 3) + " В");
ui->maxLabel->setText(QString::number(max, 'f', 3) + " В"); ui->maxLabel->setText(QString::number(max, 'f', 3) + " В");
ui->avgLabel->setText(QString::number(avg, 'f', 3) + " В"); ui->avgLabel->setText(QString::number(avg, 'f', 3) + " В");
// Обновляем информацию о стабильном участке // Обновляем информацию о стабильном участке
updateStatisticsWithStableInfo(); updateStatisticsWithStableInfo();
} }
} }
void AdcGraphDialog::updateStatisticsWithStableInfo() void AdcGraphDialog::updateStatisticsWithStableInfo()
{ {
if (m_series->count() > 0) { if(m_series->count() > 0)
// Используем абсолютные индексы в формате "начальный-конечный" // Используем абсолютные индексы в формате "начальный-конечный"
ui->samplesLabel->setText( ui->samplesLabel->setText(
QString("%1 отсч. (адр %2-%3) [стаб: %4-%5]") QString("%1 отсч. (адр %2-%3) [стаб: %4-%5]")
@@ -254,19 +222,15 @@ void AdcGraphDialog::updateStatisticsWithStableInfo()
.arg(m_stableEndIndex) // Абсолютный конечный индекс .arg(m_stableEndIndex) // Абсолютный конечный индекс
); );
} }
}
void AdcGraphDialog::updateStableLines() void AdcGraphDialog::updateStableLines()
{ {
// Очищаем предыдущие линии // Очищаем предыдущие линии
m_stableStartLine->clear(); m_stableStartLine->clear();
m_stableEndLine->clear(); m_stableEndLine->clear();
// Получаем текущий диапазон оси Y // Получаем текущий диапазон оси Y
double yMin = m_axisY->min(); double yMin = m_axisY->min();
double yMax = m_axisY->max(); 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) {
@@ -274,7 +238,6 @@ void AdcGraphDialog::updateStableLines()
m_stableStartLine->append(relativeStartIndex, yMin); m_stableStartLine->append(relativeStartIndex, yMin);
m_stableStartLine->append(relativeStartIndex, yMax); 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; int relativeEndIndex = m_stableEndIndex - m_startAddress;
@@ -288,112 +251,84 @@ void AdcGraphDialog::updateGraphRange()
// Обновляем диапазон оси X // Обновляем диапазон оси X
m_axisX->setRange(0, m_registerCount); m_axisX->setRange(0, m_registerCount);
m_axisX->setTitleText(QString("Отсчеты АЦП (%1-%2)").arg(m_startAddress).arg(m_startAddress + m_registerCount - 1)); m_axisX->setTitleText(QString("Отсчеты АЦП (%1-%2)").arg(m_startAddress).arg(m_startAddress + m_registerCount - 1));
// Сбрасываем ось Y к разумному диапазону по умолчанию // Сбрасываем ось Y к разумному диапазону по умолчанию
m_axisY->setRange(-1.2, 1.2); m_axisY->setRange(-1.2, 1.2);
// Обновляем линии стабильного участка с учетом нового диапазона // Обновляем линии стабильного участка с учетом нового диапазона
updateStableLines(); updateStableLines();
} }
void AdcGraphDialog::readAdcDataAndIndices() void AdcGraphDialog::readAdcDataAndIndices()
{ {
if (!m_modbusDevice || m_boardAddress == -1) return; if(!m_modbusDevice || m_boardAddress == -1)
return;
// Создаем один запрос для данных АЦП + индексов стабильности // Создаем один запрос для данных АЦП + индексов стабильности
// Адреса: данные АЦП (571+), индексы (557-558) // Адреса: данные АЦП (571+), индексы (557-558)
int start = m_startAddress + REG_ADC_BUFFER_START; int start = m_startAddress + REG_ADC_BUFFER_START;
int count = m_registerCount; int count = m_registerCount;
// Читаем индексы стабильности (557-558) и данные АЦП одним запросом // Читаем индексы стабильности (557-558) и данные АЦП одним запросом
QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_STABLE_START, QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_STABLE_START,
count + (start - 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(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onCombinedDataReady); connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onCombinedDataReady);
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} else {
//qDebug() << "Failed to send combined data read request";
} }
}
void AdcGraphDialog::onCombinedDataReady() void AdcGraphDialog::onCombinedDataReady()
{ {
auto *reply = qobject_cast<QModbusReply*>(sender()); auto *reply = qobject_cast<QModbusReply*>(sender());
if (!reply) return; if(!reply)
return;
if((m_adcZero == 0) || (m_adcOneVolt == 0)) if((m_adcZero == 0) || (m_adcOneVolt == 0)) {
{
readCalibrationValues(); readCalibrationValues();
return; return;
} }
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit result = reply->result(); const QModbusDataUnit result = reply->result();
// Обрабатываем индексы стабильности (первые 2 регистра) // Обрабатываем индексы стабильности (первые 2 регистра)
if(result.valueCount() >= 2) { if(result.valueCount() >= 2) {
m_stableStartIndex = result.value(0); m_stableStartIndex = result.value(0);
m_stableEndIndex = result.value(1); 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(); m_series->clear();
// Добавляем новые точки и определяем диапазон // Добавляем новые точки и определяем диапазон
double minVoltage = 1000, maxVoltage = -1000; double minVoltage = 1000, maxVoltage = -1000;
for(int i = 0; i < m_registerCount; ++i) { for(int i = 0; i < m_registerCount; ++i) {
if(adcDataStartIndex + i < result.valueCount()) { if(adcDataStartIndex + i < result.valueCount()) {
double voltage = convertAdcToVoltage(result.value(adcDataStartIndex + i)); double voltage = convertAdcToVoltage(result.value(adcDataStartIndex + i));
m_series->append(i, voltage); m_series->append(i, voltage);
// Обновляем мин/макс для автоматического масштабирования // Обновляем мин/макс для автоматического масштабирования
if (voltage < minVoltage) minVoltage = voltage; if(voltage < minVoltage)
if (voltage > maxVoltage) maxVoltage = voltage; minVoltage = voltage;
if(voltage > maxVoltage)
maxVoltage = voltage;
} }
} }
// Обновляем график и статистику // Обновляем график и статистику
updateYAxisRange(minVoltage, maxVoltage); updateYAxisRange(minVoltage, maxVoltage);
updateStableLines(); updateStableLines();
updateStatistics(); updateStatistics();
} else {
// qDebug() << "Error reading combined data:" << reply->errorString();
} }
reply->deleteLater(); reply->deleteLater();
} }
void AdcGraphDialog::readAdcBuffer() 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); 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(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onReadReady); connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onReadReady);
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} else {
// qDebug() << "Failed to send ADC buffer read request";
}
} }
void AdcGraphDialog::startGraph(int boardId, int teNumber) void AdcGraphDialog::startGraph(int boardId, int teNumber)
@@ -401,34 +336,25 @@ void AdcGraphDialog::startGraph(int boardId, int teNumber)
m_boardId = boardId; m_boardId = boardId;
m_teNumber = teNumber; m_teNumber = teNumber;
m_boardAddress = boardId + 1; m_boardAddress = boardId + 1;
// Устанавливаем начальное значение в спинбокс // Устанавливаем начальное значение в спинбокс
ui->teNumberSpinBox->setValue(teNumber); ui->teNumberSpinBox->setValue(teNumber);
setWindowTitle(QString("График АЦП - Плата %1, ТЭ %2 (адр %3-%4)") setWindowTitle(QString("График АЦП - Плата %1, ТЭ %2 (адр %3-%4)")
.arg(boardId + 1) .arg(boardId + 1)
.arg(teNumber) .arg(teNumber)
.arg(m_startAddress) .arg(m_startAddress)
.arg(m_startAddress + m_registerCount - 1)); .arg(m_startAddress + m_registerCount - 1));
// Очищаем предыдущие данные // Очищаем предыдущие данные
m_series->clear(); m_series->clear();
m_stableStartLine->clear(); m_stableStartLine->clear();
m_stableEndLine->clear(); m_stableEndLine->clear();
// Обновляем диапазон графика // Обновляем диапазон графика
updateGraphRange(); updateGraphRange();
readCalibrationValues(); readCalibrationValues();
// Записываем начальный номер ТЭ // Записываем начальный номер ТЭ
setTENumber(m_boardAddress, teNumber); setTENumber(m_boardAddress, teNumber);
m_updateTimer->start(m_timeout); m_updateTimer->start(m_timeout);
} }
void AdcGraphDialog::setTimeout(int timeout) void AdcGraphDialog::setTimeout(int timeout)
{ {
m_timeout = timeout; m_timeout = timeout;
@@ -439,17 +365,15 @@ void AdcGraphDialog::stopGraph()
m_updateTimer->stop(); m_updateTimer->stop();
m_boardId = -1; m_boardId = -1;
m_boardAddress = -1; m_boardAddress = -1;
// Отменяем все pending запросы Modbus // Отменяем все pending запросы Modbus
if (m_modbusDevice) { if(m_modbusDevice)
m_modbusDevice->disconnect(this); // Отключаем все сигналы m_modbusDevice->disconnect(this); // Отключаем все сигналы
} }
}
void AdcGraphDialog::onUpdateTimer() void AdcGraphDialog::onUpdateTimer()
{ {
if (m_boardAddress == -1) return; if(m_boardAddress == -1)
return;
// Читаем и буфер АЦП, и индексы стабильности каждый период // Читаем и буфер АЦП, и индексы стабильности каждый период
readAdcDataAndIndices(); readAdcDataAndIndices();
} }
@@ -457,54 +381,46 @@ void AdcGraphDialog::onUpdateTimer()
void AdcGraphDialog::onReadReady() void AdcGraphDialog::onReadReady()
{ {
auto *reply = qobject_cast<QModbusReply*>(sender()); auto *reply = qobject_cast<QModbusReply*>(sender());
if (!reply) return; if(!reply)
return;
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit result = reply->result(); const QModbusDataUnit result = reply->result();
// Очищаем предыдущие данные // Очищаем предыдущие данные
m_series->clear(); m_series->clear();
// Добавляем новые точки и определяем диапазон // Добавляем новые точки и определяем диапазон
double minVoltage = 1000, maxVoltage = -1000; 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)); double voltage = convertAdcToVoltage(result.value(i));
m_series->append(i, voltage); m_series->append(i, voltage);
// Обновляем мин/макс для автоматического масштабирования // Обновляем мин/макс для автоматического масштабирования
if (voltage < minVoltage) minVoltage = voltage; if(voltage < minVoltage)
if (voltage > maxVoltage) maxVoltage = voltage; minVoltage = voltage;
if(voltage > maxVoltage)
maxVoltage = voltage;
} }
// Автоматически настраиваем диапазон оси Y // Автоматически настраиваем диапазон оси Y
updateYAxisRange(minVoltage, maxVoltage); updateYAxisRange(minVoltage, maxVoltage);
// Обновляем линии стабильного участка // Обновляем линии стабильного участка
updateStableLines(); updateStableLines();
// Обновляем статистику // Обновляем статистику
if(m_series->count() > 0) { if(m_series->count() > 0) {
double min = 1000, max = -1000, sum = 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(); double y = point.y();
if (y < min) min = y; if(y < min)
if (y > max) max = y; min = y;
if(y > max)
max = y;
sum += y; sum += y;
} }
double avg = sum / m_series->count(); double avg = sum / m_series->count();
ui->minLabel->setText(QString::number(min, 'f', 3) + " В"); ui->minLabel->setText(QString::number(min, 'f', 3) + " В");
ui->maxLabel->setText(QString::number(max, 'f', 3) + " В"); ui->maxLabel->setText(QString::number(max, 'f', 3) + " В");
ui->avgLabel->setText(QString::number(avg, 'f', 3) + " В"); ui->avgLabel->setText(QString::number(avg, 'f', 3) + " В");
// Обновляем информацию о стабильном участке // Обновляем информацию о стабильном участке
updateStatisticsWithStableInfo(); updateStatisticsWithStableInfo();
} }
} else {
// qDebug() << "Error reading ADC buffer:" << reply->errorString();
} }
reply->deleteLater(); reply->deleteLater();
} }
@@ -513,66 +429,39 @@ void AdcGraphDialog::updateYAxisRange(double minVoltage, double maxVoltage)
// Добавляем запас 10% к диапазону // Добавляем запас 10% к диапазону
double range = maxVoltage - minVoltage; double range = maxVoltage - minVoltage;
double margin = range * 0.1; double margin = range * 0.1;
double yMin = minVoltage - margin; double yMin = minVoltage - margin;
double yMax = maxVoltage + 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; yMin = -1.5;
yMax = 1.5; yMax = 1.5;
}
// Ограничиваем разумными пределами // Ограничиваем разумными пределами
yMin = qMax(yMin, -5.0); // Не ниже -5В yMin = qMax(yMin, -5.0); // Не ниже -5В
yMax = qMin(yMax, 5.0); // Не выше 5В yMax = qMin(yMax, 5.0); // Не выше 5В
// Устанавливаем новый диапазон // Устанавливаем новый диапазон
m_axisY->setRange(yMin, yMax); m_axisY->setRange(yMin, yMax);
// Обновляем линии стабильного участка с новым диапазоном // Обновляем линии стабильного участка с новым диапазоном
updateStableLines(); updateStableLines();
} }
double AdcGraphDialog::convertAdcToVoltage(quint16 adcValue) 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); return (adcValue - m_adcZero) * 1.1 / (m_adcOneVolt - m_adcZero);
} }
void AdcGraphDialog::on_registerCountChanged(int value) void AdcGraphDialog::on_registerCountChanged(int value)
{ {
m_registerCount = value; m_registerCount = value;
// qDebug() << "Register count changed to:" << value;
} }
void AdcGraphDialog::on_rangeApplyClicked() void AdcGraphDialog::on_rangeApplyClicked()
{ {
// qDebug() << "Applying new range - Start:" << m_startAddress << "Count:" << m_registerCount;
updateGraphRange(); updateGraphRange();
// Немедленно обновляем данные // Немедленно обновляем данные
if (m_boardAddress != -1) { if(m_boardAddress != -1)
readAdcBuffer(); readAdcBuffer();
} }
}
void AdcGraphDialog::on_closeBtn_clicked() void AdcGraphDialog::on_closeBtn_clicked()
{ {

View File

@@ -19,21 +19,17 @@ class AdcGraphDialog;
class AdcGraphDialog : public QDialog class AdcGraphDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent = nullptr); explicit AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent = nullptr);
~AdcGraphDialog(); ~AdcGraphDialog();
void setTENumber(int boardID, int teNumber); void setTENumber(int boardID, int teNumber);
void setModbusDevice(QModbusClient *device); void setModbusDevice(QModbusClient *device);
void startGraph(int boardId, int teNumber); void startGraph(int boardId, int teNumber);
void stopGraph(); void stopGraph();
void setTimeout(int timeout); void setTimeout(int timeout);
void readyClose(); void readyClose();
signals: signals:
void dialogClosed(); void dialogClosed();
protected: protected:
void closeEvent(QCloseEvent *event) override { void closeEvent(QCloseEvent *event) override {
stopGraph(); stopGraph();
@@ -41,7 +37,6 @@ protected:
emit dialogClosed(); emit dialogClosed();
QDialog::closeEvent(event); QDialog::closeEvent(event);
} }
private slots: private slots:
void on_teNumberChanged(int value); void on_teNumberChanged(int value);
void onUpdateTimer(); void onUpdateTimer();
@@ -50,7 +45,6 @@ private slots:
void on_closeBtn_clicked(); void on_closeBtn_clicked();
void on_registerCountChanged(int value); void on_registerCountChanged(int value);
void on_rangeApplyClicked(); void on_rangeApplyClicked();
private: private:
Ui::AdcGraphDialog *ui; Ui::AdcGraphDialog *ui;
QModbusClient *m_modbusDevice; QModbusClient *m_modbusDevice;
@@ -59,27 +53,22 @@ private:
int m_boardAddress; int m_boardAddress;
int m_teNumber; int m_teNumber;
int m_timeout; int m_timeout;
// Калибровочные значения // Калибровочные значения
double m_adcZero; double m_adcZero;
double m_adcOneVolt; double m_adcOneVolt;
// Для отображения стабильного участка // Для отображения стабильного участка
QLineSeries *m_stableStartLine; QLineSeries *m_stableStartLine;
QLineSeries *m_stableEndLine; QLineSeries *m_stableEndLine;
int m_stableStartIndex; int m_stableStartIndex;
int m_stableEndIndex; int m_stableEndIndex;
// Данные графика // Данные графика
QLineSeries *m_series; QLineSeries *m_series;
QValueAxis *m_axisX; QValueAxis *m_axisX;
QValueAxis *m_axisY; QValueAxis *m_axisY;
QChart *m_chart; // Добавить указатель на chart QChart *m_chart; // Добавить указатель на chart
// Управление диапазоном регистров // Управление диапазоном регистров
int m_startAddress; int m_startAddress;
int m_registerCount; int m_registerCount;
void updateStatistics(); void updateStatistics();
void readAdcDataAndIndices(); void readAdcDataAndIndices();
void onCombinedDataReady(); void onCombinedDataReady();

View File

@@ -17,23 +17,19 @@ DebugTerminalDialog::DebugTerminalDialog(QWidget *parent) :
boards[0].error5V = ui->discErr5TestChkBox_1; boards[0].error5V = ui->discErr5TestChkBox_1;
boards[0].error5VSCI = ui->discErr5VsciTestChkBox_1; boards[0].error5VSCI = ui->discErr5VsciTestChkBox_1;
boards[0].error5VA = ui->discErr5VATestChkBox_1; boards[0].error5VA = ui->discErr5VATestChkBox_1;
boards[1].error24V = ui->discErr24TestChkBox_2; boards[1].error24V = ui->discErr24TestChkBox_2;
boards[1].error5V = ui->discErr5TestChkBox_2; boards[1].error5V = ui->discErr5TestChkBox_2;
boards[1].error5VSCI = ui->discErr5VsciTestChkBox_2; boards[1].error5VSCI = ui->discErr5VsciTestChkBox_2;
boards[1].error5VA = ui->discErr5VATestChkBox_2; boards[1].error5VA = ui->discErr5VATestChkBox_2;
boards[2].error24V = ui->discErr24TestChkBox_3; boards[2].error24V = ui->discErr24TestChkBox_3;
boards[2].error5V = ui->discErr5TestChkBox_3; boards[2].error5V = ui->discErr5TestChkBox_3;
boards[2].error5VSCI = ui->discErr5VsciTestChkBox_3; boards[2].error5VSCI = ui->discErr5VsciTestChkBox_3;
boards[2].error5VA = ui->discErr5VATestChkBox_3; boards[2].error5VA = ui->discErr5VATestChkBox_3;
boards[3].error24V = ui->discErr24TestChkBox_4; boards[3].error24V = ui->discErr24TestChkBox_4;
boards[3].error5V = ui->discErr5TestChkBox_4; boards[3].error5V = ui->discErr5TestChkBox_4;
boards[3].error5VSCI = ui->discErr5VsciTestChkBox_4; boards[3].error5VSCI = ui->discErr5VsciTestChkBox_4;
boards[3].error5VA = ui->discErr5VATestChkBox_4; boards[3].error5VA = ui->discErr5VATestChkBox_4;
initializeConnections(); initializeConnections();
// Создаем AdcGraphDialog с nullptr // Создаем AdcGraphDialog с nullptr
m_adcGraphDialog = new AdcGraphDialog(nullptr, this); m_adcGraphDialog = new AdcGraphDialog(nullptr, this);
} }
@@ -50,10 +46,9 @@ void DebugTerminalDialog::setMainTerm(M3KTE* term)
void DebugTerminalDialog::setModbusDevice(QModbusClient *device) void DebugTerminalDialog::setModbusDevice(QModbusClient *device)
{ {
m_modbusDevice = device; m_modbusDevice = device;
if (m_adcGraphDialog && device) { if(m_adcGraphDialog && device)
m_adcGraphDialog->setModbusDevice(device); m_adcGraphDialog->setModbusDevice(device);
} }
}
void DebugTerminalDialog::setDebugTerminalCoil(int enable) void DebugTerminalDialog::setDebugTerminalCoil(int enable)
{ {
@@ -67,9 +62,7 @@ void DebugTerminalDialog::showEvent(QShowEvent *event)
{ {
QDialog::showEvent(event); QDialog::showEvent(event);
// При открытии окна записываем в коил 555 значение "1" // При открытии окна записываем в коил 555 значение "1"
resetAll(); resetAll();
setDebugTerminalCoil(1); setDebugTerminalCoil(1);
} }
@@ -80,76 +73,7 @@ void DebugTerminalDialog::closeEvent(QCloseEvent *event)
QDialog::closeEvent(event); QDialog::closeEvent(event);
} }
void DebugTerminalDialog::initializeConnections() 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::updateConnectionStatus(int boardID, bool connected) void DebugTerminalDialog::updateConnectionStatus(int boardID, bool connected)
{ {
@@ -572,12 +496,10 @@ void DebugTerminalDialog::openAdc(int boardID, int teNumber)
m_adcGraphDialog->deleteLater(); m_adcGraphDialog->deleteLater();
m_adcGraphDialog = nullptr; m_adcGraphDialog = nullptr;
} }
m_adcGraphDialog = new AdcGraphDialog(m_modbusDevice, this); m_adcGraphDialog = new AdcGraphDialog(m_modbusDevice, this);
connect(m_adcGraphDialog, &AdcGraphDialog::dialogClosed, this, [this]() { connect(m_adcGraphDialog, &AdcGraphDialog::dialogClosed, this, [this]() {
setDebugTerminalCoil(0); setDebugTerminalCoil(0);
}); });
setGraphUpdateInterval(1000); setGraphUpdateInterval(1000);
m_adcGraphDialog->startGraph(boardID, teNumber); m_adcGraphDialog->startGraph(boardID, teNumber);
m_adcGraphDialog->show(); m_adcGraphDialog->show();
@@ -587,10 +509,9 @@ void DebugTerminalDialog::openAdc(int boardID, int teNumber)
void DebugTerminalDialog::setGraphUpdateInterval(int milliseconds) void DebugTerminalDialog::setGraphUpdateInterval(int milliseconds)
{ {
if (m_adcGraphDialog) { if(m_adcGraphDialog)
m_adcGraphDialog->setTimeout(milliseconds); m_adcGraphDialog->setTimeout(milliseconds);
} }
}
void DebugTerminalDialog::writeCoil(int boardID, int coil, int value) void DebugTerminalDialog::writeCoil(int boardID, int coil, int value)
{ {
@@ -627,20 +548,18 @@ void DebugTerminalDialog::setBoardActive(int boardID, bool active)
if(boardGroup) { if(boardGroup) {
boardGroup->setEnabled(active); boardGroup->setEnabled(active);
// Можно добавить визуальное отличие неактивных плат // Можно добавить визуальное отличие неактивных плат
if (!active) { if(!active)
boardGroup->setStyleSheet("QGroupBox { color: gray; }"); boardGroup->setStyleSheet("QGroupBox { color: gray; }");
} else { else
boardGroup->setStyleSheet(""); // Сброс стиля boardGroup->setStyleSheet(""); // Сброс стиля
} }
} }
}
void DebugTerminalDialog::updateBoardStates(bool activeBoards[4]) void DebugTerminalDialog::updateBoardStates(bool activeBoards[4])
{ {
for (int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++)
setBoardActive(i, activeBoards[i]); setBoardActive(i, activeBoards[i]);
} }
}
void DebugTerminalDialog::resetAll() void DebugTerminalDialog::resetAll()
{ {
@@ -651,17 +570,14 @@ void DebugTerminalDialog::resetAll()
ui->resetKeyCallChkBox_1->setChecked(false); ui->resetKeyCallChkBox_1->setChecked(false);
ui->resetDefaultCallChkBox_1->setChecked(false); ui->resetDefaultCallChkBox_1->setChecked(false);
ui->getHardfaultCallChkBox_1->setChecked(false); ui->getHardfaultCallChkBox_1->setChecked(false);
ui->enableLedTestChkBox_1->setChecked(false); ui->enableLedTestChkBox_1->setChecked(false);
ui->leds_1->setEnabled(false); ui->leds_1->setEnabled(false);
ui->discs_1->setEnabled(false); ui->discs_1->setEnabled(false);
ui->discWorkTestChkBox_1->setChecked(false); ui->discWorkTestChkBox_1->setChecked(false);
// Сброс всех чекбоксов теста дискретных сигналов // Сброс всех чекбоксов теста дискретных сигналов
ui->discWorkTestChkBox_1->setChecked(false); ui->discWorkTestChkBox_1->setChecked(false);
ui->discWarnTestChkBox_1->setChecked(false); ui->discWarnTestChkBox_1->setChecked(false);
ui->discErrTestChkBox_1->setChecked(false); ui->discErrTestChkBox_1->setChecked(false);
// Сброс всех чекбоксов теста светодиодов // Сброс всех чекбоксов теста светодиодов
ui->ledWorkTestChkBox_1->setChecked(false); ui->ledWorkTestChkBox_1->setChecked(false);
ui->ledWarnTestChkBox_1->setChecked(false); ui->ledWarnTestChkBox_1->setChecked(false);
@@ -670,7 +586,6 @@ void DebugTerminalDialog::resetAll()
ui->ledVH1TestChkBox_1->setChecked(false); ui->ledVH1TestChkBox_1->setChecked(false);
ui->ledVH2TestChkBox_1->setChecked(false); ui->ledVH2TestChkBox_1->setChecked(false);
ui->ledVH3TestChkBox_1->setChecked(false); ui->ledVH3TestChkBox_1->setChecked(false);
// Сброс всех чекбоксов вызова функций // Сброс всех чекбоксов вызова функций
ui->continiusCallChkBox_2->setChecked(false); ui->continiusCallChkBox_2->setChecked(false);
ui->calibrateCallChkBox_2->setChecked(false); ui->calibrateCallChkBox_2->setChecked(false);
@@ -678,17 +593,14 @@ void DebugTerminalDialog::resetAll()
ui->resetKeyCallChkBox_2->setChecked(false); ui->resetKeyCallChkBox_2->setChecked(false);
ui->resetDefaultCallChkBox_2->setChecked(false); ui->resetDefaultCallChkBox_2->setChecked(false);
ui->getHardfaultCallChkBox_2->setChecked(false); ui->getHardfaultCallChkBox_2->setChecked(false);
ui->enableLedTestChkBox_2->setChecked(false); ui->enableLedTestChkBox_2->setChecked(false);
ui->leds_2->setEnabled(false); ui->leds_2->setEnabled(false);
ui->discs_2->setEnabled(false); ui->discs_2->setEnabled(false);
ui->discWorkTestChkBox_2->setChecked(false); ui->discWorkTestChkBox_2->setChecked(false);
// Сброс всех чекбоксов теста дискретных сигналов // Сброс всех чекбоксов теста дискретных сигналов
ui->discWorkTestChkBox_2->setChecked(false); ui->discWorkTestChkBox_2->setChecked(false);
ui->discWarnTestChkBox_2->setChecked(false); ui->discWarnTestChkBox_2->setChecked(false);
ui->discErrTestChkBox_2->setChecked(false); ui->discErrTestChkBox_2->setChecked(false);
// Сброс всех чекбоксов теста светодиодов // Сброс всех чекбоксов теста светодиодов
ui->ledWorkTestChkBox_2->setChecked(false); ui->ledWorkTestChkBox_2->setChecked(false);
ui->ledWarnTestChkBox_2->setChecked(false); ui->ledWarnTestChkBox_2->setChecked(false);
@@ -697,7 +609,6 @@ void DebugTerminalDialog::resetAll()
ui->ledVH1TestChkBox_2->setChecked(false); ui->ledVH1TestChkBox_2->setChecked(false);
ui->ledVH2TestChkBox_2->setChecked(false); ui->ledVH2TestChkBox_2->setChecked(false);
ui->ledVH3TestChkBox_2->setChecked(false); ui->ledVH3TestChkBox_2->setChecked(false);
// Сброс всех чекбоксов вызова функций // Сброс всех чекбоксов вызова функций
ui->continiusCallChkBox_3->setChecked(false); ui->continiusCallChkBox_3->setChecked(false);
ui->calibrateCallChkBox_3->setChecked(false); ui->calibrateCallChkBox_3->setChecked(false);
@@ -705,17 +616,14 @@ void DebugTerminalDialog::resetAll()
ui->resetKeyCallChkBox_3->setChecked(false); ui->resetKeyCallChkBox_3->setChecked(false);
ui->resetDefaultCallChkBox_3->setChecked(false); ui->resetDefaultCallChkBox_3->setChecked(false);
ui->getHardfaultCallChkBox_3->setChecked(false); ui->getHardfaultCallChkBox_3->setChecked(false);
ui->enableLedTestChkBox_3->setChecked(false); ui->enableLedTestChkBox_3->setChecked(false);
ui->leds_3->setEnabled(false); ui->leds_3->setEnabled(false);
ui->discs_3->setEnabled(false); ui->discs_3->setEnabled(false);
ui->discWorkTestChkBox_3->setChecked(false); ui->discWorkTestChkBox_3->setChecked(false);
// Сброс всех чекбоксов теста дискретных сигналов // Сброс всех чекбоксов теста дискретных сигналов
ui->discWorkTestChkBox_3->setChecked(false); ui->discWorkTestChkBox_3->setChecked(false);
ui->discWarnTestChkBox_3->setChecked(false); ui->discWarnTestChkBox_3->setChecked(false);
ui->discErrTestChkBox_3->setChecked(false); ui->discErrTestChkBox_3->setChecked(false);
// Сброс всех чекбоксов теста светодиодов // Сброс всех чекбоксов теста светодиодов
ui->ledWorkTestChkBox_3->setChecked(false); ui->ledWorkTestChkBox_3->setChecked(false);
ui->ledWarnTestChkBox_3->setChecked(false); ui->ledWarnTestChkBox_3->setChecked(false);
@@ -724,7 +632,6 @@ void DebugTerminalDialog::resetAll()
ui->ledVH1TestChkBox_3->setChecked(false); ui->ledVH1TestChkBox_3->setChecked(false);
ui->ledVH2TestChkBox_3->setChecked(false); ui->ledVH2TestChkBox_3->setChecked(false);
ui->ledVH3TestChkBox_3->setChecked(false); ui->ledVH3TestChkBox_3->setChecked(false);
// Сброс всех чекбоксов вызова функций // Сброс всех чекбоксов вызова функций
ui->continiusCallChkBox_4->setChecked(false); ui->continiusCallChkBox_4->setChecked(false);
ui->calibrateCallChkBox_4->setChecked(false); ui->calibrateCallChkBox_4->setChecked(false);
@@ -732,17 +639,14 @@ void DebugTerminalDialog::resetAll()
ui->resetKeyCallChkBox_4->setChecked(false); ui->resetKeyCallChkBox_4->setChecked(false);
ui->resetDefaultCallChkBox_4->setChecked(false); ui->resetDefaultCallChkBox_4->setChecked(false);
ui->getHardfaultCallChkBox_4->setChecked(false); ui->getHardfaultCallChkBox_4->setChecked(false);
ui->enableLedTestChkBox_4->setChecked(false); ui->enableLedTestChkBox_4->setChecked(false);
ui->leds_4->setEnabled(false); ui->leds_4->setEnabled(false);
ui->discs_4->setEnabled(false); ui->discs_4->setEnabled(false);
ui->discWorkTestChkBox_4->setChecked(false); ui->discWorkTestChkBox_4->setChecked(false);
// Сброс всех чекбоксов теста дискретных сигналов // Сброс всех чекбоксов теста дискретных сигналов
ui->discWorkTestChkBox_4->setChecked(false); ui->discWorkTestChkBox_4->setChecked(false);
ui->discWarnTestChkBox_4->setChecked(false); ui->discWarnTestChkBox_4->setChecked(false);
ui->discErrTestChkBox_4->setChecked(false); ui->discErrTestChkBox_4->setChecked(false);
// Сброс всех чекбоксов теста светодиодов // Сброс всех чекбоксов теста светодиодов
ui->ledWorkTestChkBox_4->setChecked(false); ui->ledWorkTestChkBox_4->setChecked(false);
ui->ledWarnTestChkBox_4->setChecked(false); ui->ledWarnTestChkBox_4->setChecked(false);
@@ -757,13 +661,10 @@ void DebugTerminalDialog::boardDebugReading(int boardID)
{ {
if(mainTerm == nullptr) if(mainTerm == nullptr)
return; return;
if(!boards[boardID].isActive) if(!boards[boardID].isActive)
return; return;
if(!this->isVisible()) if(!this->isVisible())
return; return;
QModbusReply *_24V = mainTerm->readSingleCoil(boardID, 603); QModbusReply *_24V = mainTerm->readSingleCoil(boardID, 603);
if(_24V != nullptr) if(_24V != nullptr)
connect(_24V, &QModbusReply::finished, this, [this, boardID, _24V]() { 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)); boards[boardID].error24V->setChecked(_24V->result().value(0));
_24V->deleteLater(); _24V->deleteLater();
}); });
QModbusReply *_5V = mainTerm->readSingleCoil(boardID, 604); QModbusReply *_5V = mainTerm->readSingleCoil(boardID, 604);
if(_5V != nullptr) if(_5V != nullptr)
connect(_5V, &QModbusReply::finished, this, [this, boardID, _5V]() { 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)); boards[boardID].error5V->setChecked(_5V->result().value(0));
_5V->deleteLater(); _5V->deleteLater();
}); });
QModbusReply *_5VSCI = mainTerm->readSingleCoil(boardID, 605); QModbusReply *_5VSCI = mainTerm->readSingleCoil(boardID, 605);
if(_5VSCI != nullptr) if(_5VSCI != nullptr)
connect(_5VSCI, &QModbusReply::finished, this, [this, boardID, _5VSCI]() { 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)); boards[boardID].error5VSCI->setChecked(_5VSCI->result().value(0));
_5VSCI->deleteLater(); _5VSCI->deleteLater();
}); });
QModbusReply *_5VA = mainTerm->readSingleCoil(boardID, 606); QModbusReply *_5VA = mainTerm->readSingleCoil(boardID, 606);
if(_5VA != nullptr) if(_5VA != nullptr)
connect(_5VA, &QModbusReply::finished, this, [this, boardID, _5VA]() { connect(_5VA, &QModbusReply::finished, this, [this, boardID, _5VA]() {
@@ -805,7 +703,5 @@ void DebugTerminalDialog::setScanBoardActive(bool flag, int boardID)
void DebugTerminalDialog::offAllBoard() void DebugTerminalDialog::offAllBoard()
{ {
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
{
boards[i].isActive = false; boards[i].isActive = false;
} }
}

View File

@@ -45,8 +45,6 @@ class AdcGraphDialog;
#define REGISTER_TE_NUMB 564 #define REGISTER_TE_NUMB 564
namespace Ui { namespace Ui {
class DebugTerminalDialog; class DebugTerminalDialog;
} }
@@ -54,7 +52,6 @@ class DebugTerminalDialog;
class DebugTerminalDialog : public QDialog class DebugTerminalDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DebugTerminalDialog(QWidget *parent = nullptr); explicit DebugTerminalDialog(QWidget *parent = nullptr);
~DebugTerminalDialog(); ~DebugTerminalDialog();
@@ -68,21 +65,15 @@ public:
void writeTENumber(int boardId, int teNumber); void writeTENumber(int boardId, int teNumber);
void openAdc(int boardID, int teNumber); void openAdc(int boardID, int teNumber);
void setMainTerm(M3KTE* term); void setMainTerm(M3KTE* term);
public slots: public slots:
void boardDebugReading(int boardID); void boardDebugReading(int boardID);
void setScanBoardActive(bool flag, int boardID); void setScanBoardActive(bool flag, int boardID);
void offAllBoard(); void offAllBoard();
protected: protected:
void showEvent(QShowEvent *event) override; void showEvent(QShowEvent *event) override;
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
private slots: private slots:
void on_buttonBox_clicked(QAbstractButton *button); void on_buttonBox_clicked(QAbstractButton *button);
// Плата 1 // Плата 1
void on_continiusCallChkBox_1_stateChanged(int state); void on_continiusCallChkBox_1_stateChanged(int state);
void on_calibrateCallChkBox_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_resetKeyCallChkBox_1_stateChanged(int state);
void on_resetDefaultCallChkBox_1_stateChanged(int state); void on_resetDefaultCallChkBox_1_stateChanged(int state);
void on_getHardfaultCallChkBox_1_stateChanged(int state); void on_getHardfaultCallChkBox_1_stateChanged(int state);
void on_enableLedTestChkBox_1_stateChanged(int state); void on_enableLedTestChkBox_1_stateChanged(int state);
void on_discWorkTestChkBox_1_stateChanged(int state); void on_discWorkTestChkBox_1_stateChanged(int state);
void on_discWarnTestChkBox_1_stateChanged(int state); void on_discWarnTestChkBox_1_stateChanged(int state);
void on_discErrTestChkBox_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_discErr5TestChkBox_1_stateChanged(int state);
void on_discErr5VsciTestChkBox_1_stateChanged(int state); void on_discErr5VsciTestChkBox_1_stateChanged(int state);
void on_discErr5VATestChkBox_1_stateChanged(int state); void on_discErr5VATestChkBox_1_stateChanged(int state);
void on_ledWorkTestChkBox_1_stateChanged(int state); void on_ledWorkTestChkBox_1_stateChanged(int state);
void on_ledWarnTestChkBox_1_stateChanged(int state); void on_ledWarnTestChkBox_1_stateChanged(int state);
void on_ledErrTestChkBox_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_ledVH1TestChkBox_1_stateChanged(int state);
void on_ledVH2TestChkBox_1_stateChanged(int state); void on_ledVH2TestChkBox_1_stateChanged(int state);
void on_ledVH3TestChkBox_1_stateChanged(int state); void on_ledVH3TestChkBox_1_stateChanged(int state);
// Плата 2 // Плата 2
void on_continiusCallChkBox_2_stateChanged(int state); void on_continiusCallChkBox_2_stateChanged(int state);
void on_calibrateCallChkBox_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_resetKeyCallChkBox_2_stateChanged(int state);
void on_resetDefaultCallChkBox_2_stateChanged(int state); void on_resetDefaultCallChkBox_2_stateChanged(int state);
void on_getHardfaultCallChkBox_2_stateChanged(int state); void on_getHardfaultCallChkBox_2_stateChanged(int state);
void on_enableLedTestChkBox_2_stateChanged(int state); void on_enableLedTestChkBox_2_stateChanged(int state);
void on_discWorkTestChkBox_2_stateChanged(int state); void on_discWorkTestChkBox_2_stateChanged(int state);
void on_discWarnTestChkBox_2_stateChanged(int state); void on_discWarnTestChkBox_2_stateChanged(int state);
void on_discErrTestChkBox_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_discErr5TestChkBox_2_stateChanged(int state);
void on_discErr5VsciTestChkBox_2_stateChanged(int state); void on_discErr5VsciTestChkBox_2_stateChanged(int state);
void on_discErr5VATestChkBox_2_stateChanged(int state); void on_discErr5VATestChkBox_2_stateChanged(int state);
void on_ledWorkTestChkBox_2_stateChanged(int state); void on_ledWorkTestChkBox_2_stateChanged(int state);
void on_ledWarnTestChkBox_2_stateChanged(int state); void on_ledWarnTestChkBox_2_stateChanged(int state);
void on_ledErrTestChkBox_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_ledVH1TestChkBox_2_stateChanged(int state);
void on_ledVH2TestChkBox_2_stateChanged(int state); void on_ledVH2TestChkBox_2_stateChanged(int state);
void on_ledVH3TestChkBox_2_stateChanged(int state); void on_ledVH3TestChkBox_2_stateChanged(int state);
// Плата 3 // Плата 3
void on_continiusCallChkBox_3_stateChanged(int state); void on_continiusCallChkBox_3_stateChanged(int state);
void on_calibrateCallChkBox_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_resetKeyCallChkBox_3_stateChanged(int state);
void on_resetDefaultCallChkBox_3_stateChanged(int state); void on_resetDefaultCallChkBox_3_stateChanged(int state);
void on_getHardfaultCallChkBox_3_stateChanged(int state); void on_getHardfaultCallChkBox_3_stateChanged(int state);
void on_enableLedTestChkBox_3_stateChanged(int state); void on_enableLedTestChkBox_3_stateChanged(int state);
void on_discWorkTestChkBox_3_stateChanged(int state); void on_discWorkTestChkBox_3_stateChanged(int state);
void on_discWarnTestChkBox_3_stateChanged(int state); void on_discWarnTestChkBox_3_stateChanged(int state);
void on_discErrTestChkBox_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_discErr5TestChkBox_3_stateChanged(int state);
void on_discErr5VsciTestChkBox_3_stateChanged(int state); void on_discErr5VsciTestChkBox_3_stateChanged(int state);
void on_discErr5VATestChkBox_3_stateChanged(int state); void on_discErr5VATestChkBox_3_stateChanged(int state);
void on_ledWorkTestChkBox_3_stateChanged(int state); void on_ledWorkTestChkBox_3_stateChanged(int state);
void on_ledWarnTestChkBox_3_stateChanged(int state); void on_ledWarnTestChkBox_3_stateChanged(int state);
void on_ledErrTestChkBox_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_ledVH1TestChkBox_3_stateChanged(int state);
void on_ledVH2TestChkBox_3_stateChanged(int state); void on_ledVH2TestChkBox_3_stateChanged(int state);
void on_ledVH3TestChkBox_3_stateChanged(int state); void on_ledVH3TestChkBox_3_stateChanged(int state);
// Плата 4 // Плата 4
void on_continiusCallChkBox_4_stateChanged(int state); void on_continiusCallChkBox_4_stateChanged(int state);
void on_calibrateCallChkBox_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_resetKeyCallChkBox_4_stateChanged(int state);
void on_resetDefaultCallChkBox_4_stateChanged(int state); void on_resetDefaultCallChkBox_4_stateChanged(int state);
void on_getHardfaultCallChkBox_4_stateChanged(int state); void on_getHardfaultCallChkBox_4_stateChanged(int state);
void on_enableLedTestChkBox_4_stateChanged(int state); void on_enableLedTestChkBox_4_stateChanged(int state);
void on_discWorkTestChkBox_4_stateChanged(int state); void on_discWorkTestChkBox_4_stateChanged(int state);
void on_discWarnTestChkBox_4_stateChanged(int state); void on_discWarnTestChkBox_4_stateChanged(int state);
void on_discErrTestChkBox_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_discErr5TestChkBox_4_stateChanged(int state);
void on_discErr5VsciTestChkBox_4_stateChanged(int state); void on_discErr5VsciTestChkBox_4_stateChanged(int state);
void on_discErr5VATestChkBox_4_stateChanged(int state); void on_discErr5VATestChkBox_4_stateChanged(int state);
void on_ledWorkTestChkBox_4_stateChanged(int state); void on_ledWorkTestChkBox_4_stateChanged(int state);
void on_ledWarnTestChkBox_4_stateChanged(int state); void on_ledWarnTestChkBox_4_stateChanged(int state);
void on_ledErrTestChkBox_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_ledVH1TestChkBox_4_stateChanged(int state);
void on_ledVH2TestChkBox_4_stateChanged(int state); void on_ledVH2TestChkBox_4_stateChanged(int state);
void on_ledVH3TestChkBox_4_stateChanged(int state); void on_ledVH3TestChkBox_4_stateChanged(int state);
signals: signals:
void coilValueChanged(int boardID, int coil, int value); void coilValueChanged(int boardID, int coil, int value);
void writeRegister(int boardID, int reg, int value); void writeRegister(int boardID, int reg, int value);
void readCoil(int boardID, int coil, QModbusReply *reply); void readCoil(int boardID, int coil, QModbusReply *reply);
private: private:
Ui::DebugTerminalDialog *ui; Ui::DebugTerminalDialog *ui;
QModbusClient *m_modbusDevice; // Храним указатель здесь QModbusClient *m_modbusDevice; // Храним указатель здесь
M3KTE* mainTerm = nullptr; M3KTE* mainTerm = nullptr;
// Карты для хранения состояний // Карты для хранения состояний
QMap<int, bool> m_functionCalls; // boardId -> coil -> state QMap<int, bool> m_functionCalls; // boardId -> coil -> state
QMap<int, bool> m_discreteTests; // boardId -> coil -> state QMap<int, bool> m_discreteTests; // boardId -> coil -> state
QMap<int, bool> m_ledTests; // boardId -> coil -> state QMap<int, bool> m_ledTests; // boardId -> coil -> state
// Номера ТЭ для каждой платы // Номера ТЭ для каждой платы
int m_teNumbers[4] = {0, 0, 0, 0}; int m_teNumbers[4] = {0, 0, 0, 0};
struct boardErrorLinks{ struct boardErrorLinks{
bool isActive = false; bool isActive = false;
QCheckBox* error24V = nullptr; QCheckBox* error24V = nullptr;
@@ -214,9 +184,7 @@ private:
QCheckBox* error5VA = nullptr; QCheckBox* error5VA = nullptr;
}; };
boardErrorLinks boards[4]; boardErrorLinks boards[4];
void initializeConnections(); void initializeConnections();
void writeCoil(int boardID, int coil, int value); void writeCoil(int boardID, int coil, int value);
//void readCoil(int coil); //void readCoil(int coil);
void resetAll(); void resetAll();

View File

@@ -10,18 +10,15 @@ DeviceSettingsDialog::DeviceSettingsDialog(QWidget *parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
on_buttonApplyChangeTimer_clicked(); on_buttonApplyChangeTimer_clicked();
{
_m_timer[0] = ui->spinTimerBoard_1; _m_timer[0] = ui->spinTimerBoard_1;
_m_timer[1] = ui->spinTimerBoard_2; _m_timer[1] = ui->spinTimerBoard_2;
_m_timer[2] = ui->spinTimerBoard_3; _m_timer[2] = ui->spinTimerBoard_3;
_m_timer[3] = ui->spinTimerBoard_4; _m_timer[3] = ui->spinTimerBoard_4;
}
_currentSpeed = ui->speedBox->currentText().toUInt(); _currentSpeed = ui->speedBox->currentText().toUInt();
_currentParity = ui->parityBox->currentIndex(); _currentParity = ui->parityBox->currentIndex();
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++)
_currentAdrs[i] = i+1; _currentAdrs[i] = i+1;
} }
}
DeviceSettingsDialog::~DeviceSettingsDialog() DeviceSettingsDialog::~DeviceSettingsDialog()
{ {
@@ -82,10 +79,9 @@ void DeviceSettingsDialog::updateSettingsAfterConnection(unsigned tmp_speed, uns
_m_timer[i]->setEnabled(true); _m_timer[i]->setEnabled(true);
ui->idComboBox->addItem(QString::number(i)); ui->idComboBox->addItem(QString::number(i));
_currentAdrs[i] = tmp_adr[i]; _currentAdrs[i] = tmp_adr[i];
} else { } else
_m_timer[i]->setEnabled(false); _m_timer[i]->setEnabled(false);
} }
}
on_idComboBox_currentIndexChanged(ui->idComboBox->currentIndex()); on_idComboBox_currentIndexChanged(ui->idComboBox->currentIndex());
} }
@@ -107,9 +103,8 @@ void DeviceSettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
_currentSpeed = ui->speedBox->currentText().toUInt(); _currentSpeed = ui->speedBox->currentText().toUInt();
ui->parityBox->setCurrentIndex(0); ui->parityBox->setCurrentIndex(0);
_currentParity = ui->parityBox->currentIndex(); _currentParity = ui->parityBox->currentIndex();
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++)
_currentAdrs[i] = i + 1; _currentAdrs[i] = i + 1;
}
ui->adrSpinBox->setValue(_currentAdrs[ui->idComboBox->currentIndex()]); ui->adrSpinBox->setValue(_currentAdrs[ui->idComboBox->currentIndex()]);
break; break;
case QDialogButtonBox::AcceptRole: case QDialogButtonBox::AcceptRole:

View File

@@ -12,10 +12,8 @@ class BoardIdHasBeenChanged : public QEvent
public: public:
BoardIdHasBeenChanged(const short num, const short newId) : QEvent(QEvent::User) {_BoardNum = num; _BoardNewID = newId;} BoardIdHasBeenChanged(const short num, const short newId) : QEvent(QEvent::User) {_BoardNum = num; _BoardNewID = newId;}
~BoardIdHasBeenChanged() {} ~BoardIdHasBeenChanged() {}
short BoardNum() const {return _BoardNum;} short BoardNum() const {return _BoardNum;}
short BoardNewID() const {return _BoardNewID;} short BoardNewID() const {return _BoardNewID;}
private: private:
short _BoardNum; short _BoardNum;
short _BoardNewID; short _BoardNewID;
@@ -26,10 +24,8 @@ class pollStatusChange : public QEvent
public: public:
pollStatusChange(unsigned BoardID, bool Stat) : QEvent((QEvent::Type)1001) {_BoardID = BoardID; _Status = Stat;} pollStatusChange(unsigned BoardID, bool Stat) : QEvent((QEvent::Type)1001) {_BoardID = BoardID; _Status = Stat;}
~pollStatusChange() {} ~pollStatusChange() {}
unsigned BoardID() const {return _BoardID;} unsigned BoardID() const {return _BoardID;}
bool Status() const {return _Status;} bool Status() const {return _Status;}
private: private:
unsigned _BoardID; unsigned _BoardID;
bool _Status; bool _Status;
@@ -42,11 +38,9 @@ class DeviceSettingsDialog;
class DeviceSettingsDialog : public QDialog class DeviceSettingsDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DeviceSettingsDialog(QWidget *parent = nullptr); explicit DeviceSettingsDialog(QWidget *parent = nullptr);
~DeviceSettingsDialog(); ~DeviceSettingsDialog();
unsigned currentBoardTimer(unsigned short _ID); unsigned currentBoardTimer(unsigned short _ID);
unsigned currentSpeed(); unsigned currentSpeed();
unsigned short currentParity(); unsigned short currentParity();
@@ -58,30 +52,19 @@ public:
signals: signals:
void parityChanged(); void parityChanged();
void speedChanged(); void speedChanged();
void firstBoardAdrHasBeenChanged(); void firstBoardAdrHasBeenChanged();
void secondBoardAdrHasBeenChanged(); void secondBoardAdrHasBeenChanged();
void thirdBoardAdrHasBeenChanged(); void thirdBoardAdrHasBeenChanged();
void fourthBoardAdrHasBeenChanged(); void fourthBoardAdrHasBeenChanged();
private slots: private slots:
void on_buttonApplyChangeTimer_clicked(); void on_buttonApplyChangeTimer_clicked();
void on_buttonApplyChangeSpeed_clicked(); void on_buttonApplyChangeSpeed_clicked();
void on_buttonApplyChangeParity_clicked(); void on_buttonApplyChangeParity_clicked();
void on_buttonApplyChangeAdr_clicked(); void on_buttonApplyChangeAdr_clicked();
void on_idComboBox_currentIndexChanged(int index); void on_idComboBox_currentIndexChanged(int index);
void on_buttonBox_clicked(QAbstractButton *button); void on_buttonBox_clicked(QAbstractButton *button);
void on_buttonApplyChangePoll_clicked(); void on_buttonApplyChangePoll_clicked();
void on_idPollComboBox_currentIndexChanged(int index); void on_idPollComboBox_currentIndexChanged(int index);
private: private:
QSpinBox *_m_timer[4]; QSpinBox *_m_timer[4];
unsigned _currentBoardTimers[4]; unsigned _currentBoardTimers[4];
@@ -89,7 +72,6 @@ private:
unsigned short _currentParity; unsigned short _currentParity;
unsigned _currentAdrs[4]; unsigned _currentAdrs[4];
bool _currentPollStatus[4]; bool _currentPollStatus[4];
Ui::DeviceSettingsDialog *ui; Ui::DeviceSettingsDialog *ui;
}; };

View File

@@ -6,11 +6,10 @@ LineRinger::LineRinger(QWidget *parent) :
ui(new Ui::LineRinger) ui(new Ui::LineRinger)
{ {
ui->setupUi(this); ui->setupUi(this);
const auto listPorts = QSerialPortInfo::availablePorts(); 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->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName()));
} //чётность
{ {
ui->parityControlBox->addItem("No", QVariant(QSerialPort::NoParity)); ui->parityControlBox->addItem("No", QVariant(QSerialPort::NoParity));
ui->parityControlBox->addItem("Even", QVariant(QSerialPort::EvenParity)); 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("Space", QVariant(QSerialPort::SpaceParity));
ui->parityControlBox->addItem("Mark", QVariant(QSerialPort::MarkParity)); ui->parityControlBox->addItem("Mark", QVariant(QSerialPort::MarkParity));
} }
//данные
{ {
ui->dataBox->addItem("Data5", QVariant(QSerialPort::Data5)); ui->dataBox->addItem("Data5", QVariant(QSerialPort::Data5));
ui->dataBox->addItem("Data6", QVariant(QSerialPort::Data6)); ui->dataBox->addItem("Data6", QVariant(QSerialPort::Data6));
@@ -25,6 +25,7 @@ LineRinger::LineRinger(QWidget *parent) :
ui->dataBox->addItem("Data8", QVariant(QSerialPort::Data8)); ui->dataBox->addItem("Data8", QVariant(QSerialPort::Data8));
ui->dataBox->setCurrentIndex(3); ui->dataBox->setCurrentIndex(3);
} }
//стопбиты
{ {
ui->stopBox->addItem("One", QVariant(QSerialPort::OneStop)); ui->stopBox->addItem("One", QVariant(QSerialPort::OneStop));
ui->stopBox->addItem("OneAndHalf", QVariant(QSerialPort::OneAndHalfStop)); ui->stopBox->addItem("OneAndHalf", QVariant(QSerialPort::OneAndHalfStop));
@@ -33,9 +34,7 @@ LineRinger::LineRinger(QWidget *parent) :
ui->deviceOnlineView->horizontalHeader()->setVisible(true); ui->deviceOnlineView->horizontalHeader()->setVisible(true);
syncColumnHeaders(); syncColumnHeaders();
ui->deviceOnlineView->setColumnHidden(1, true); ui->deviceOnlineView->setColumnHidden(1, true);
ui->ringButton->setEnabled(false); ui->ringButton->setEnabled(false);
modbusDevice = new QModbusRtuSerialMaster(this); modbusDevice = new QModbusRtuSerialMaster(this);
} }
@@ -73,9 +72,9 @@ void LineRinger::on_connectButton_clicked()
#endif #endif
modbusDevice->setTimeout(50); modbusDevice->setTimeout(50);
modbusDevice->setNumberOfRetries(0); modbusDevice->setNumberOfRetries(0);
if(!modbusDevice->connectDevice()) { if(!modbusDevice->connectDevice())
QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения."); QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения.");
} else { else {
ui->connectButton->setText(tr("Отключить")); ui->connectButton->setText(tr("Отключить"));
ui->ringButton->setEnabled(true); ui->ringButton->setEnabled(true);
currentBaudRate = ui->baudRateBox->currentText().toUInt(nullptr, 10); currentBaudRate = ui->baudRateBox->currentText().toUInt(nullptr, 10);
@@ -143,17 +142,16 @@ LineRinger::callStatus LineRinger::lineCall()
for(int tmp_obj = 0; tmp_obj < numOfObject; tmp_obj++) { for(int tmp_obj = 0; tmp_obj < numOfObject; tmp_obj++) {
uint8_t objectID = result.at(0); uint8_t objectID = result.at(0);
uint8_t lengthOfObject = result.at(1); uint8_t lengthOfObject = result.at(1);
if(lengthOfObject>0) { if(lengthOfObject > 0)
currentDevice.fields[objectID].clear(); currentDevice.fields[objectID].clear();
} for(int i = 0; i < lengthOfObject; i++)
for(int i = 0; i < lengthOfObject; i++) {
currentDevice.fields[objectID] += QString(result.at(2 + i)); currentDevice.fields[objectID] += QString(result.at(2 + i));
}
result.remove(0, lengthOfObject + 2); result.remove(0, lengthOfObject + 2);
} }
auto *regularReply = modbusDevice->sendRawRequest(readDeviceRegularIdentification, tmp_adr); auto *regularReply = modbusDevice->sendRawRequest(readDeviceRegularIdentification, tmp_adr);
if(regularReply == nullptr) { 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->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::ERROR; return callStatus::ERROR;
@@ -183,12 +181,10 @@ LineRinger::callStatus LineRinger::lineCall()
if(objectID > 0x06) if(objectID > 0x06)
continue; continue;
uint8_t lengthOfObject = regularResult.at(1); uint8_t lengthOfObject = regularResult.at(1);
if(lengthOfObject>0) { if(lengthOfObject > 0)
currentDevice.fields[objectID].clear(); currentDevice.fields[objectID].clear();
} for(int i = 0; i < lengthOfObject; i++)
for (int i = 0; i < lengthOfObject; i++) {
currentDevice.fields[objectID] += QString(regularResult.at(2 + i)); currentDevice.fields[objectID] += QString(regularResult.at(2 + i));
}
regularResult.remove(0, lengthOfObject + 2); regularResult.remove(0, lengthOfObject + 2);
} }
} }
@@ -199,14 +195,12 @@ LineRinger::callStatus LineRinger::lineCall()
ui->deviceOnlineView->insertRow(newRow); ui->deviceOnlineView->insertRow(newRow);
ui->deviceOnlineView->setItem(newRow, 0, new QTableWidgetItem(QString::number(currentDevice.adr))); ui->deviceOnlineView->setItem(newRow, 0, new QTableWidgetItem(QString::number(currentDevice.adr)));
ui->deviceOnlineView->setItem(newRow, 1, new QTableWidgetItem(QString::number(currentDevice.baudRate))); ui->deviceOnlineView->setItem(newRow, 1, new QTableWidgetItem(QString::number(currentDevice.baudRate)));
for (int i = 0; i < 7; i++) { for(int i = 0; i < 7; i++)
ui->deviceOnlineView->setItem(newRow, i + 2, new QTableWidgetItem(currentDevice.fields[i])); ui->deviceOnlineView->setItem(newRow, i + 2, new QTableWidgetItem(currentDevice.fields[i]));
} if(reply->error()!=QModbusDevice::NoError)
if(reply->error()!=QModbusDevice::NoError) {
ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(QString("%1: %2").arg(reply->error()).arg(reply->errorString()))); ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(QString("%1: %2").arg(reply->error()).arg(reply->errorString())));
} else if(regularReplyError) { else if(regularReplyError)
ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString)); ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString));
}
ui->deviceOnlineView->resizeColumnsToContents(); ui->deviceOnlineView->resizeColumnsToContents();
syncColumnHeaders(); syncColumnHeaders();
} }
@@ -248,7 +242,8 @@ void LineRinger::on_ringButton_clicked()
currentBaudRate = ui->baudRateBox->itemText(i).toUInt(nullptr, 10); currentBaudRate = ui->baudRateBox->itemText(i).toUInt(nullptr, 10);
bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate)); bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate));
if(lineCall() == callStatus::INTERRUPT) { if(lineCall() == callStatus::INTERRUPT) {
QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); QMessageBox::warning(this, "Уведомление",
QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count()));
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
on_connectButton_clicked(); on_connectButton_clicked();
bar->close(); bar->close();
@@ -262,9 +257,9 @@ void LineRinger::on_ringButton_clicked()
on_connectButton_clicked(); on_connectButton_clicked();
} else { } else {
ui->deviceOnlineView->setColumnHidden(1, true); ui->deviceOnlineView->setColumnHidden(1, true);
if(lineCall() == callStatus::INTERRUPT) { if(lineCall() == callStatus::INTERRUPT)
QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); QMessageBox::warning(this, "Уведомление",
} QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count()));
} }
ui->timer->setTime(QTime::currentTime()); ui->timer->setTime(QTime::currentTime());
ui->timer->setDate(QDate::currentDate()); ui->timer->setDate(QDate::currentDate());

View File

@@ -16,35 +16,25 @@ class LineRinger;
class LineRinger : public QWidget class LineRinger : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
enum callStatus{ enum callStatus{
NOERROR = 0, NOERROR = 0,
ERROR = 1, ERROR = 1,
INTERRUPT = 2 INTERRUPT = 2
}; };
explicit LineRinger(QWidget *parent = nullptr); explicit LineRinger(QWidget *parent = nullptr);
~LineRinger(); ~LineRinger();
callStatus lineCall(); callStatus lineCall();
signals: signals:
void stopLineCall(); void stopLineCall();
private slots: private slots:
void on_connectButton_clicked(); void on_connectButton_clicked();
void on_ringButton_clicked(); void on_ringButton_clicked();
void on_checkAutoBaud_stateChanged(int arg1); void on_checkAutoBaud_stateChanged(int arg1);
private: private:
Ui::LineRinger *ui; Ui::LineRinger *ui;
void syncColumnHeaders(); void syncColumnHeaders();
struct deviceOnLine{
struct deviceOnLine
{
uint8_t adr; uint8_t adr;
unsigned baudRate; unsigned baudRate;
QString fields[7] = {"Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined"}; QString fields[7] = {"Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined"};
@@ -52,7 +42,6 @@ private:
QVector<deviceOnLine>devicesList; QVector<deviceOnLine>devicesList;
bool isAutoBaud = false; bool isAutoBaud = false;
unsigned currentBaudRate; unsigned currentBaudRate;
QModbusClient *modbusDevice = nullptr; QModbusClient *modbusDevice = nullptr;
}; };

View File

@@ -396,7 +396,6 @@ M3KTE::M3KTE(QWidget *parent)
} }
bool activeBoards[4] = {false, false, false, false}; bool activeBoards[4] = {false, false, false, false};
m_debugTerminalDialog->updateBoardStates(activeBoards); m_debugTerminalDialog->updateBoardStates(activeBoards);
ui->M3kteRegSettings->setEnabled(false); ui->M3kteRegSettings->setEnabled(false);
ui->BSM_Warning->setEnabled(false); ui->BSM_Warning->setEnabled(false);
ui->BSM_Accident->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[2].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_3;
Boards[3].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_4; Boards[3].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_4;
Boards[0].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_1; Boards[0].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_1;
Boards[1].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_2; Boards[1].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_2;
Boards[2].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_3; 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[1].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_2;
Boards[2].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_3; Boards[2].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_3;
Boards[3].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_4; 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, connect(Boards[i].localState[LOCAL_STATE_POLL], &QCheckBox::clicked,
this, [i, this](bool checked) {m_deviceSettingsDialog->sendPollCommand(i, checked);}); this, [i, this](bool checked) {m_deviceSettingsDialog->sendPollCommand(i, checked);});
Boards[i].localState[LOCAL_STATE_WARN]->setAttribute(Qt::WA_TransparentForMouseEvents, true); 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].timerStatus->setText(" ");;
Boards[i].localError->setText(" ");; Boards[i].localError->setText(" ");;
} }
for(int i = 0; i < 5; i++) { for(int i = 0; i < 5; i++)
ui->writeValueTable->resizeColumnToContents(i); ui->writeValueTable->resizeColumnToContents(i);
}
QBrush tb(Qt::transparent); // Transparent brush, solid pattern QBrush tb(Qt::transparent); // Transparent brush, solid pattern
for(int i = 0; i < 320; i++) { for(int i = 0; i < 320; i++) {
m_ProgressBar[i]->setTextVisible(true); m_ProgressBar[i]->setTextVisible(true);
@@ -507,12 +502,17 @@ M3KTE::M3KTE(QWidget *parent)
M3KTE::~M3KTE() M3KTE::~M3KTE()
{ {
if(modbusDevice->state() == QModbusDevice::ConnectedState) { if(modbusDevice->state() == QModbusDevice::ConnectedState)
onConnectClicked(); onConnectClicked();
}
delete ui; delete ui;
} }
/**
* @brief Инициализация действий и сигналов интерфейса пользователя.
*
* Этот метод настраивает начальные состояния элементов интерфейса и соединяет
* сигналы пользовательских действий с соответствующими слотами для обработки.
*/
void M3KTE::initActions() void M3KTE::initActions()
{ {
ui->ConnectionMenuConnect->setEnabled(true); ui->ConnectionMenuConnect->setEnabled(true);
@@ -537,12 +537,10 @@ void M3KTE::initActions()
m_debugTerminalDialog->setDebugTerminalCoil(1); m_debugTerminalDialog->setDebugTerminalCoil(1);
m_debugTerminalDialog->openAdc(0, 1); m_debugTerminalDialog->openAdc(0, 1);
}); });
connect(m_debugTerminalDialog, &DebugTerminalDialog::coilValueChanged, connect(m_debugTerminalDialog, &DebugTerminalDialog::coilValueChanged,
this, &M3KTE::writeSingleCoil); this, &M3KTE::writeSingleCoil);
connect(m_debugTerminalDialog, &DebugTerminalDialog::writeRegister, connect(m_debugTerminalDialog, &DebugTerminalDialog::writeRegister,
this, &M3KTE::writeSingleRegister); this, &M3KTE::writeSingleRegister);
connect(ui->LineCall, &QAction::triggered, m_lineRinger, &QWidget::show); connect(ui->LineCall, &QAction::triggered, m_lineRinger, &QWidget::show);
connect(ui->M3kteRegSettings, &QAction::triggered, m_regMultipleSettings, &QDialog::show); connect(ui->M3kteRegSettings, &QAction::triggered, m_regMultipleSettings, &QDialog::show);
connect(m_regMultipleSettings, &MultipleSettings::write, this, &M3KTE::slotmultipleRegWrite); connect(m_regMultipleSettings, &MultipleSettings::write, this, &M3KTE::slotmultipleRegWrite);
@@ -552,6 +550,17 @@ void M3KTE::initActions()
connect(ui->ParameterScan, &QAction::triggered, m_parameterWorkspace, &QWidget::show); 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) void M3KTE::logError(const QString &errorPlace, const QString &errorString, unsigned errorCount, const QString &description)
{ {
unsigned newRow = loggerTable->rowCount(); unsigned newRow = loggerTable->rowCount();
@@ -565,12 +574,19 @@ void M3KTE::logError(const QString &errorPlace, const QString &errorString, unsi
if(!loggerTable->verticalScrollBar()->isSliderDown()) if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum()); loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
/**
* @brief Очищает содержимое таблицы логирования.
*
* Этот метод удаляет все строки из таблицы loggerTable. Перед удалением
* обновление пользовательского интерфейса временно отключается для повышения производительности.
* Если таблица не инициализирована, метод просто завершает работу.
*/
void M3KTE::clearLogger() void M3KTE::clearLogger()
{ {
// Проверяем, что таблица инициализирована // Проверяем, что таблица инициализирована
if (!loggerTable) { if(!loggerTable)
return; return;
}
// Отключаем обновление UI для повышения производительности // Отключаем обновление UI для повышения производительности
loggerTable->setUpdatesEnabled(false); loggerTable->setUpdatesEnabled(false);
// Очищаем все строки таблицы // Очищаем все строки таблицы
@@ -579,6 +595,24 @@ void M3KTE::clearLogger()
loggerTable->setUpdatesEnabled(true); loggerTable->setUpdatesEnabled(true);
} }
/**
* @brief Обработчик нажатия кнопки "Подключиться".
*
* Эта функция устанавливает соединение с устройством Modbus, если оно не подключено,
* или разрывает соединение, если уже подключено.
* В процессе подключения происходит настройка параметров соединения (порт, параллельность,
* скорость передачи и др.), а также опрос устройств для определения их состояния.
* В случае успешного подключения включаются соответствующие элементы интерфейса и
* происходит подготовка данных для дальнейшей работы.
* В случае разрыва соединения происходит сброс настроек интерфейса и отключение устройств.
*
* Основные действия:
* - Проверка актуальности объекта modbusDevice.
* - Настройка параметров соединения и попытка подключения.
* - В случае успеха — обновление интерфейса и активация элементов.
* - В случае неудачи — отображение сообщения об ошибке.
* - При уже активном соединении — отключение устройства, сброс данных и интерфейса.
*/
void M3KTE::onConnectClicked() void M3KTE::onConnectClicked()
{ {
if(!modbusDevice) if(!modbusDevice)
@@ -599,14 +633,13 @@ void M3KTE::onConnectClicked()
#endif #endif
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries); modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries);
if(!modbusDevice->connectDevice()) { if(!modbusDevice->connectDevice())
statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000); statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
} else { else {
ui->ConnectionMenuConnect->setEnabled(false); ui->ConnectionMenuConnect->setEnabled(false);
ui->ConnectionMenuDisconnect->setEnabled(true); ui->ConnectionMenuDisconnect->setEnabled(true);
if(pingNetworkDevices()) //Опрос устройст //Опрос устройст
{ if(pingNetworkDevices()) {
//m_parameterWorkspace->setDeviceCount(1);
unsigned tmp_adr[4]; unsigned tmp_adr[4];
bool ActiveDevices[4]; bool ActiveDevices[4];
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
@@ -614,7 +647,10 @@ void M3KTE::onConnectClicked()
ActiveDevices[i] = Boards[i].isActive; ActiveDevices[i] = Boards[i].isActive;
} }
ui->M3kteRegSettings->setEnabled(true); 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); m_debugTerminalDialog->updateBoardStates(ActiveDevices);
ui->boardSelectBox->setCurrentIndex(0); ui->boardSelectBox->setCurrentIndex(0);
ui->writeTable->setCurrentIndex(0); ui->writeTable->setCurrentIndex(0);
@@ -678,6 +714,13 @@ void M3KTE::onConnectClicked()
} }
} }
/**
* @brief Обработчик нажатия кнопки чтения.
*
* Этот слот вызывается при нажатии кнопки для чтения данных по протоколу Modbus.
* В случае успешного создания запроса, подключает обработчик завершения запроса.
* Если произошла ошибка при отправке запроса, выводит сообщение об ошибке в статус-бар.
*/
void M3KTE::onReadButtonClicked() void M3KTE::onReadButtonClicked()
{ {
if(!modbusDevice) if(!modbusDevice)
@@ -688,26 +731,31 @@ void M3KTE::onReadButtonClicked()
connect(reply, &QModbusReply::finished, this, &M3KTE::onReadReady); connect(reply, &QModbusReply::finished, this, &M3KTE::onReadReady);
else else
delete reply; // broadcast replies return immediately delete reply; // broadcast replies return immediately
} else { } else
statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000); statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000);
} }
}
/**
* @brief Обрабатывает завершение ответа на запрос чтения Modbus.
*
* Этот слот вызывается, когда ответ на запрос Modbus готов. Он получает указатель
* на объект QModbusReply, обрабатывает успешный ответ, обновляет состояние устройств
* и модели данных, а также выводит сообщения об ошибках при необходимости.
*/
void M3KTE::onReadReady() void M3KTE::onReadReady()
{ {
auto reply = qobject_cast<QModbusReply *>(sender()); auto reply = qobject_cast<QModbusReply *>(sender());
if(!reply) if(!reply)
return; return;
int Adr = 255; int Adr = 255;
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++)
if(Boards[i].isActive && Boards[i].adr == reply->serverAddress()) { if(Boards[i].isActive && Boards[i].adr == reply->serverAddress()) {
Adr = i; Adr = i;
break; break;
} }
}
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result(); 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) { if(unit.registerType() == QModbusDataUnit::Coils) {
Boards[Adr].coil[i + unit.startAddress()] = unit.value(i); Boards[Adr].coil[i + unit.startAddress()] = unit.value(i);
if(unit.value(i) == 1) if(unit.value(i) == 1)
@@ -718,7 +766,6 @@ void M3KTE::onReadReady()
Boards[Adr].HR[i + unit.startAddress()] = unit.value(i); 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); Boards[Adr].ModbusModelHoldingReg->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 10), Qt::EditRole);
} }
}
switch(unit.registerType()) { switch(unit.registerType()) {
case QModbusDataUnit::Coils: case QModbusDataUnit::Coils:
Boards[Adr].ModbusModelCoil->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 2), Boards[Adr].ModbusModelCoil->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 2),
@@ -749,6 +796,13 @@ void M3KTE::onReadReady()
reply->deleteLater(); reply->deleteLater();
} }
/**
* @brief Обрабатывает событие нажатия кнопки записи.
*
* Этот слот собирает данные из моделей, формирует запрос на запись по протоколу Modbus
* и отправляет его на устройство. Обрабатывает завершение запроса и отображает
* сообщения об ошибках при необходимости.
*/
void M3KTE::onWriteButtonClicked() void M3KTE::onWriteButtonClicked()
{ {
if(!modbusDevice) if(!modbusDevice)
@@ -786,34 +840,58 @@ void M3KTE::onWriteButtonClicked()
} }
reply->deleteLater(); reply->deleteLater();
}); });
} else { } else
// broadcast replies return immediately // broadcast replies return immediately
reply->deleteLater(); reply->deleteLater();
}
} else { } else {
statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000); statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
logError(tr("Терминал"), modbusDevice->errorString(), 0, ""); logError(tr("Терминал"), modbusDevice->errorString(), 0, "");
} }
} }
/**
* @brief Обрабатывает изменение выбранной платы.
*
* Этот метод вызывается при изменении выбора платы пользователем.
* Он вызывает changeTable с текущими индексами платы и таблицы.
*
* @param index Индекс выбранной платы.
*/
void M3KTE::onSelectedBoardChanged(int index) void M3KTE::onSelectedBoardChanged(int index)
{ {
changeTable(index, ui->writeTable->currentIndex()); changeTable(index, ui->writeTable->currentIndex());
} }
/**
* @brief Обрабатывает изменение выбранной таблицы.
*
* Этот метод вызывается при переключении таблицы пользователем.
* Он вызывает changeTable с текущими индексами выбранной платы и таблицы.
*
* @param index Индекс выбранной таблицы.
*/
void M3KTE::onWriteTableChanged(int index) void M3KTE::onWriteTableChanged(int index)
{ {
changeTable(ui->boardSelectBox->currentIndex(), index); changeTable(ui->boardSelectBox->currentIndex(), index);
} }
/**
* @brief Частично меняет отображаемую таблицу в зависимости от типа.
*
* В зависимости от типа таблицы (например, "Реле" или "Регистры") устанавливает
* соответствующую модель данных, скрывает или показывает строки и колонки,
* а также подгоняет ширину колонок.
*
* @param board Индекс выбранной платы.
* @param tabletype Тип таблицы (0 — Coil, 1 или другой — Holding Registers).
*/
void M3KTE::changeTable(int board, int tabletype) void M3KTE::changeTable(int board, int tabletype)
{ {
if(tabletype == 0) { if(tabletype == 0) {
ui->writeValueTable->setModel(Boards[board].ModbusModelCoil); ui->writeValueTable->setModel(Boards[board].ModbusModelCoil);
int i = 0; int i = 0;
for(;i<Boards[board].ModbusModelHoldingReg->rowCount();i++) { for(; i < Boards[board].ModbusModelHoldingReg->rowCount(); i++)
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false); ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false);
}
ui->writeValueTable->hideColumn(3); ui->writeValueTable->hideColumn(3);
ui->writeValueTable->showColumn(2); ui->writeValueTable->showColumn(2);
} else { } else {
@@ -821,30 +899,35 @@ void M3KTE::changeTable(int board, int tabletype)
if(tabletype == 1) { if(tabletype == 1) {
Boards[board].ModbusModelHoldingReg->setStartAddress(0); Boards[board].ModbusModelHoldingReg->setStartAddress(0);
int i = 0; int i = 0;
for(;i<Boards[board].ModbusModelHoldingReg->rowCount()/2;i++) { for(; i < Boards[board].ModbusModelHoldingReg->rowCount() / 2; i++)
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false); ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false);
} for(; i < Boards[board].ModbusModelHoldingReg->rowCount(); i++)
for(;i<Boards[board].ModbusModelHoldingReg->rowCount();i++) {
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true); ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true);
}
} else { } else {
Boards[board].ModbusModelHoldingReg->setStartAddress(Boards[board].ModbusModelHoldingReg->rowCount() / 2); Boards[board].ModbusModelHoldingReg->setStartAddress(Boards[board].ModbusModelHoldingReg->rowCount() / 2);
int i = 0; int i = 0;
for(;i<Boards[board].ModbusModelHoldingReg->rowCount()/2;i++) { for(; i < Boards[board].ModbusModelHoldingReg->rowCount() / 2; i++)
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true); ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true);
} for(; i < Boards[board].ModbusModelHoldingReg->rowCount(); i++)
for(;i<Boards[board].ModbusModelHoldingReg->rowCount();i++) {
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false); ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false);
} }
}
ui->writeValueTable->hideColumn(2); ui->writeValueTable->hideColumn(2);
ui->writeValueTable->showColumn(3); ui->writeValueTable->showColumn(3);
} }
for(int i = 0; i < 5; i++) { for(int i = 0; i < 5; i++)
ui->writeValueTable->resizeColumnToContents(i); ui->writeValueTable->resizeColumnToContents(i);
} }
}
/**
* @brief Создает и возвращает объект запроса чтения для Modbus.
*
* Этот метод формирует объект QModbusDataUnit в соответствии с текущими настройками интерфейса:
* - определяет тип данных (коэли или регистры) в зависимости от выбранной таблицы;
* - вычисляет стартовый адрес на основе текущего индекса таблицы;
* - определяет число записей для чтения, ограниченное диапазоном доступных данных.
*
* @return Объект QModbusDataUnit, готовый для отправки запроса чтения.
*/
QModbusDataUnit M3KTE::readRequest() const QModbusDataUnit M3KTE::readRequest() const
{ {
const auto table = const auto table =
@@ -855,6 +938,17 @@ QModbusDataUnit M3KTE::readRequest() const
return QModbusDataUnit(table, startAddress, numberOfEntries); return QModbusDataUnit(table, startAddress, numberOfEntries);
} }
/**
* @brief Создает и возвращает объект запроса записи для Modbus.
*
* Этот метод формирует объект QModbusDataUnit для отправки данных на устройство,
* основываясь на текущих настройках интерфейса:
* - определяет тип данных (например, кони или регистры) в зависимости от выбранной таблицы;
* - вычисляет стартовый адрес для записи, исходя из текущего индекса таблицы;
* - задает количество записей для записи, учитывая ограничение диапазона данных.
*
* @return Объект QModbusDataUnit, подготовленный для отправки запроса записи.
*/
QModbusDataUnit M3KTE::writeRequest() const QModbusDataUnit M3KTE::writeRequest() const
{ {
const auto table = const auto table =
@@ -865,43 +959,67 @@ QModbusDataUnit M3KTE::writeRequest() const
return QModbusDataUnit(table, startAddress, numberOfEntries); return QModbusDataUnit(table, startAddress, numberOfEntries);
} }
/**
* @brief Обрабатывает пользовательские события, связанные с изменением ID платы и её статуса.
*
* Метод переопределяет обработку событий QWidget. В зависимости от типа события:
* - При `QEvent::User` выполняется изменение ID платы через Modbus и последующая проверка.
* - При типе 1001 (кастомный тип) происходит обновление состояния платы.
*
* Логируются ошибки при неудачных операциях, осуществляется управление асинхронными запросами Modbus.
*
* @param event Указатель на событие
* @return true, если событие обработано; иначе вызывает базовый обработчик
*/
bool M3KTE::event(QEvent *event) bool M3KTE::event(QEvent *event)
{ {
if(event->type() == QEvent::User) { if(event->type() == QEvent::User) {
BoardIdHasBeenChanged* _event = static_cast<BoardIdHasBeenChanged*>(event); // Обработка пользовательского события изменения ID платы
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 172, 1); auto _event = static_cast<BoardIdHasBeenChanged*>(event);
// Создаем запрос на запись нового ID в регистр
auto *_unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 172, 1);
_unit->setValue(0, _event->BoardNewID()); _unit->setValue(0, _event->BoardNewID());
// Обновляем локально временный адрес платы
Boards[_event->BoardNum()]._tmp_adr = _event->BoardNewID(); Boards[_event->BoardNum()]._tmp_adr = _event->BoardNewID();
// Отправка запроса на изменение адреса через Modbus
if(auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[_event->BoardNum()].adr)) { 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]() { 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(auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[_event->BoardNum()]._tmp_adr)) {
if(!subreply->isFinished()) { if(!subreply->isFinished()) {
connect(subreply, &QModbusReply::finished, this, [subreply, this, _event]() { connect(subreply, &QModbusReply::finished, this, [subreply, this, _event]() {
checkAdrChange(subreply, _event->BoardNum()); checkAdrChange(subreply, _event->BoardNum());
}); });
} else { } 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),
subreply->errorString(), ++Boards[_event->BoardNum()].error_adr_change, subreply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [1]"); "Не удалось изменить адрес устройства. [1]");
reply->deleteLater(); reply->deleteLater();
delete subreply; // broadcast replies return immediately delete subreply;
} }
} else { } 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, modbusDevice->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [2]"); "Не удалось изменить адрес устройства. [2]");
reply->deleteLater(); reply->deleteLater();
} }
} else { } 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, reply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [3]"); "Не удалось изменить адрес устройства. [3]");
reply->deleteLater(); reply->deleteLater();
} }
}); });
else { } 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, reply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [4]"); "Не удалось изменить адрес устройства. [4]");
@@ -909,36 +1027,54 @@ bool M3KTE::event(QEvent *event)
delete reply; delete reply;
} }
} else { } 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, modbusDevice->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [5]"); "Не удалось изменить адрес устройства. [5]");
reply->deleteLater(); reply->deleteLater();
} }
m_deviceSettingsDialog->show(); m_deviceSettingsDialog->show();
return true; return true;
} else if(event->type() == (QEvent::Type)1001) { } else if(event->type() == (QEvent::Type)1001) {
pollStatusChange* _event = static_cast<pollStatusChange*>(event); // Обработка смены статуса плат
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 170, 1); auto _event = static_cast<pollStatusChange*>(event);
auto *_unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 170, 1);
_unit->setValue(0, _event->Status()); _unit->setValue(0, _event->Status());
// Отправка команды на изменение статуса
if(auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[_event->BoardID()].adr)) { if(auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[_event->BoardID()].adr)) {
if(!reply->isFinished()) if(!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [reply, this, _event]() { connect(reply, &QModbusReply::finished, this, [reply, this, _event]() {
if(reply->error() != QModbusDevice::NoError) { if(reply->error() != QModbusDevice::NoError) {
// Логирование ошибок
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),
reply->errorString(), ++Boards[_event->BoardID()].error_cmd_change, ""); reply->errorString(), ++Boards[_event->BoardID()].error_cmd_change, "");
reply->deleteLater(); reply->deleteLater();
} }
}); });
}
} else { } 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, ""); modbusDevice->errorString(), ++Boards[_event->BoardID()].error_cmd_change, "");
reply->deleteLater(); reply->deleteLater();
} }
return true; return true;
} }
// В случаене распознанного события вызываем дефолтный обработчик
return QWidget::event(event); return QWidget::event(event);
} }
/**
* @brief Проверяет результат изменения адреса устройства после Modbus-запроса.
*
* Анализирует ответ `reply`, обновляет текущий адрес в структуре `Boards`
* при успешной проверке. В случае ошибки логирует сообщение и увеличивает счетчик ошибок.
*
* @param reply Указатель на объект QModbusReply, содержащий ответ на запрос изменения адреса.
* @param boardNum Индекс устройства в массиве `Boards`.
*/
void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum) void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum)
{ {
if(!reply) { if(!reply) {
@@ -960,6 +1096,20 @@ void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum)
} }
} }
/**
* @brief Проверяет состояние всех активных плат через Modbus.
*
* Этот метод инициирует последовательные асинхронные чтения входных регистров (адрес 85)
* для всех активных плат, используя `QSharedPointer` для безопасного управления счётчиками и наборами.
* После завершения всех запросов генерируются сигналы:
* - `successAtCheckBoards()`, если все платы успешно подтвердили состояние,
* - `errorAtCheckBoards()`, если произошла ошибка или не все платы подтвердили.
*
* В случае неуспешной отправки запроса по плате, вызывается сигнал `errorAtCheckBoards()`,
* и выполнение метода завершается.
*
* Если активных плат не обнаружено, также генерируется сигнал `errorAtCheckBoards()`.
*/
void M3KTE::checkBoards() void M3KTE::checkBoards()
{ {
QModbusDataUnit unitCheck(QModbusDataUnit::InputRegisters, 85, 1); QModbusDataUnit unitCheck(QModbusDataUnit::InputRegisters, 85, 1);
@@ -974,36 +1124,53 @@ void M3KTE::checkBoards()
int slaveAddress = Boards[i].adr; int slaveAddress = Boards[i].adr;
QModbusReply *reply = modbusDevice->sendReadRequest(unitCheck, slaveAddress); QModbusReply *reply = modbusDevice->sendReadRequest(unitCheck, slaveAddress);
if(!reply) { if(!reply) {
revertToOldSpeedAndRestart(); emit errorAtCheckBoards();
return; return;
} }
pendingBoards->insert(slaveAddress); pendingBoards->insert(slaveAddress);
connect(reply, &QModbusReply::finished, this, connect(reply, &QModbusReply::finished, this,
[this, i, reply, slaveAddress, totalActiveBoards, confirmedBoards, pendingBoards]() { [this, i, reply, slaveAddress, totalActiveBoards, confirmedBoards, pendingBoards]() {
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError)
(*confirmedBoards)++; (*confirmedBoards)++;
} else { else
logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAddress), logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAddress),
reply->errorString(), ++Boards[i].error_baud_change, reply->errorString(), ++Boards[i].error_baud_change,
"Ошибка при подтверждении изменения скорости обмена."); "Ошибка при подтверждении изменения скорости обмена.");
}
pendingBoards->remove(slaveAddress); pendingBoards->remove(slaveAddress);
reply->deleteLater(); reply->deleteLater();
if(pendingBoards->isEmpty()) { if(pendingBoards->isEmpty()) {
if(*confirmedBoards != *totalActiveBoards) { if(*confirmedBoards != *totalActiveBoards)
emit errorAtCheckBoards(); emit errorAtCheckBoards();
} else { else
emit successAtCheckBoards(); emit successAtCheckBoards();
} }
}
}); });
} }
// Если нет ни одной активной платы // Если нет ни одной активной платы
if(*totalActiveBoards == 0) { if(*totalActiveBoards == 0)
emit errorAtCheckBoards(); emit errorAtCheckBoards();
} }
}
/**
* @brief Обновляет скорость обмена данными и проверяет ее подтверждение для устройств.
*
* Этот метод выполняет изменение скорости обмена, отправляя команды через Modbus,
* и после подтверждения повторно подключается с новой скоростью или восстанавливает предыдущие настройки при ошибках.
*
* Основные шаги:
* 1. Останавливает сканирование плат.
* 2. Устанавливает таймаут для модбас-устройства.
* 3. Определяет новую скорость исходя из текущих настроек.
* 4. Проверяет допустимость выбранной скорости.
* 5. Отправляет команды записи скорости на все активные платы.
* 6. После подтверждения всех плат — обновляет настройки соединения и перезапускает сканирование.
* 7. В случае ошибок — восстанавливает предыдущую скорость и перезапускает скан.
*
* Для синхронизации используем `QSharedPointer` для счетчиков активных и подтвержденных плат,
* а для списков активных плат — `QSharedPointer<QSet<int>>`.
*
* Лямбда `processResult` вызывается после обработки всех плат, чтобы завершить или повторить операцию в случае ошибок.
*/
void M3KTE::onSpeedUpdate() void M3KTE::onSpeedUpdate()
{ {
stopScanBoard(); stopScanBoard();
@@ -1019,23 +1186,19 @@ void M3KTE::onSpeedUpdate()
case 6: tmp_speed = 57600; break; case 6: tmp_speed = 57600; break;
case 7: tmp_speed = 115200; break; case 7: tmp_speed = 115200; break;
} }
if(tmp_speed == 0) { if(tmp_speed == 0) {
logError(tr("Программная ошибка"), "Неожиданное значение скорости", 0, logError(tr("Программная ошибка"), "Неожиданное значение скорости", 0,
"Ошибка при изменении скорости обмена."); "Ошибка при изменении скорости обмена.");
beginScanBoards(); beginScanBoards();
return; return;
} }
// Используем shared pointers вместо ссылок на стековые переменные // Используем shared pointers вместо ссылок на стековые переменные
auto totalActiveBoards = QSharedPointer<int>::create(0); auto totalActiveBoards = QSharedPointer<int>::create(0);
auto confirmedBoards = QSharedPointer<int>::create(0); auto confirmedBoards = QSharedPointer<int>::create(0);
auto pendingBoards = QSharedPointer<QSet<int>>::create(); auto pendingBoards = QSharedPointer<QSet<int>>::create();
auto newSpeed = tmp_speed; // копируем для захвата auto newSpeed = tmp_speed; // копируем для захвата
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 173, 1); QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 173, 1);
unit.setValue(0, m_deviceSettingsDialog->currentSpeed()); unit.setValue(0, m_deviceSettingsDialog->currentSpeed());
// Лямбда для обработки результата // Лямбда для обработки результата
auto processResult = [this, totalActiveBoards, confirmedBoards, newSpeed]() { auto processResult = [this, totalActiveBoards, confirmedBoards, newSpeed]() {
if(*confirmedBoards != *totalActiveBoards) { if(*confirmedBoards != *totalActiveBoards) {
@@ -1046,10 +1209,8 @@ void M3KTE::onSpeedUpdate()
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, newSpeed); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, newSpeed);
modbusDevice->connectDevice(); modbusDevice->connectDevice();
// Используем QPointer для безопасного доступа к this // Используем QPointer для безопасного доступа к this
QPointer<M3KTE> safeThis(this); QPointer<M3KTE> safeThis(this);
connect(this, &M3KTE::errorAtCheckBoards, this, [safeThis]() { connect(this, &M3KTE::errorAtCheckBoards, this, [safeThis]() {
if(!safeThis) if(!safeThis)
return; return;
@@ -1058,7 +1219,6 @@ void M3KTE::onSpeedUpdate()
safeThis->revertToOldSpeedAndRestart(); safeThis->revertToOldSpeedAndRestart();
safeThis->beginScanBoards(); safeThis->beginScanBoards();
}); });
connect(this, &M3KTE::successAtCheckBoards, this, [safeThis]() { connect(this, &M3KTE::successAtCheckBoards, this, [safeThis]() {
if(!safeThis) if(!safeThis)
return; return;
@@ -1067,11 +1227,9 @@ void M3KTE::onSpeedUpdate()
safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime); safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime);
safeThis->beginScanBoards(); safeThis->beginScanBoards();
}); });
checkBoards(); checkBoards();
} }
}; };
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
if(!Boards[i].isActive) if(!Boards[i].isActive)
continue; continue;
@@ -1080,33 +1238,35 @@ void M3KTE::onSpeedUpdate()
if(reply) { if(reply) {
(*totalActiveBoards)++; (*totalActiveBoards)++;
pendingBoards->insert(slaveAdress); pendingBoards->insert(slaveAdress);
// Захватываем shared pointers по значению - это безопасно // Захватываем shared pointers по значению - это безопасно
connect(reply, &QModbusReply::finished, this, connect(reply, &QModbusReply::finished, this,
[this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() { [this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() {
if(reply->error() == QModbusDevice::TimeoutError) { if(reply->error() == QModbusDevice::TimeoutError)
(*confirmedBoards)++; (*confirmedBoards)++;
} else if (reply->error() == QModbusDevice::NoError) { else if(reply->error() == QModbusDevice::NoError)
logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAdress), logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAdress),
tr("Неожиданный ответ."), ++Boards[i].error_baud_change, tr("Неожиданный ответ."), ++Boards[i].error_baud_change,
"Ошибка при изменении скорости обмена."); "Ошибка при изменении скорости обмена.");
} else { else
logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAdress), logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAdress),
reply->errorString(), ++Boards[i].error_baud_change, reply->errorString(), ++Boards[i].error_baud_change,
"Ошибка при изменении скорости обмена."); "Ошибка при изменении скорости обмена.");
}
pendingBoards->remove(slaveAdress); pendingBoards->remove(slaveAdress);
reply->deleteLater(); reply->deleteLater();
if(pendingBoards->isEmpty())
if(pendingBoards->isEmpty()) {
processResult(); processResult();
}
}); });
} }
} }
} }
// Вспомогательная функция восстановления старой скорости /**
* @brief Восстанавливает предыдущую скорость обмена и перезапускает соединение.
*
* Этот метод отключает текущий модбас-устройник, устанавливает скорость соединения
* в значение, сохраненное в настройках (`curBaud()`), и затем переподключается.
* Используется для возврата к исходной скорости обмена при ошибках или отмене операции.
*/
void M3KTE::revertToOldSpeedAndRestart() void M3KTE::revertToOldSpeedAndRestart()
{ {
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
@@ -1116,31 +1276,50 @@ void M3KTE::revertToOldSpeedAndRestart()
modbusDevice->connectDevice(); modbusDevice->connectDevice();
} }
/**
* @brief Обрабатывает изменение параметра четности (parity) для устройств.
*
* Отправляет запросы на изменение параметра четности на активных платах,
* затем обрабатывает результаты, при необходимости откатывая изменения.
*/
void M3KTE::onParityUpdate() void M3KTE::onParityUpdate()
{ {
// Останавливаем сканирование плат
stopScanBoard(); stopScanBoard();
modbusDevice->setTimeout(500);
// Настройка регистра для установки режима четности
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 174, 1); QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 174, 1);
switch(m_deviceSettingsDialog->currentParity()) { switch(m_deviceSettingsDialog->currentParity()) {
case 0: unit.setValue(0, 0x000); break; //Нет контроля case 0: unit.setValue(0, 0x0000); break; // Нет контроля
case 1: unit.setValue(0, 0x0400); break; // Четный case 1: unit.setValue(0, 0x0400); break; // Четный
case 2: unit.setValue(0, 0x0600); break; // Нечетный case 2: unit.setValue(0, 0x0600); break; // Нечетный
} }
// Используем shared pointers вместо ссылок на стековые переменные
// Переменные для подсчёта прогресса
auto totalActiveBoards = QSharedPointer<int>::create(0); auto totalActiveBoards = QSharedPointer<int>::create(0);
auto confirmedBoards = QSharedPointer<int>::create(0); auto confirmedBoards = QSharedPointer<int>::create(0);
auto pendingBoards = QSharedPointer<QSet<int>>::create(); auto pendingBoards = QSharedPointer<QSet<int>>::create();
auto oldParity = m_settingsDialog->curParity(); // сохраняем старую четность для отката
// Сохраняем текущий и новый параметры четности для отката при ошибках
auto oldParity = m_settingsDialog->curParity();
auto newParity = m_deviceSettingsDialog->currentParity(); auto newParity = m_deviceSettingsDialog->currentParity();
// Лямбда для обработки результата
/**
* Лямбда-функция, вызываемая по завершении всех запросов.
* Обрабатывает успешное изменение или ошибку.
*/
auto processResult = [this, totalActiveBoards, confirmedBoards, oldParity, newParity]() { auto processResult = [this, totalActiveBoards, confirmedBoards, oldParity, newParity]() {
if(*confirmedBoards != *totalActiveBoards) { if(*confirmedBoards != *totalActiveBoards) {
// Не все подтвердили — повторно запускаем скан
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
beginScanBoards(); beginScanBoards();
} else { } else {
// Все подтвердили — меняем параметры соединения
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, newParity); modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, newParity);
modbusDevice->connectDevice(); modbusDevice->connectDevice();
// Обработка ошибок и успеха при смене паритета
auto errorHandler = [this, oldParity]() { auto errorHandler = [this, oldParity]() {
disconnect(this, &M3KTE::errorAtCheckBoards, this, nullptr); disconnect(this, &M3KTE::errorAtCheckBoards, this, nullptr);
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
@@ -1149,49 +1328,96 @@ void M3KTE::onParityUpdate()
modbusDevice->connectDevice(); modbusDevice->connectDevice();
beginScanBoards(); beginScanBoards();
}; };
auto successHandler = [this, newParity]() { auto successHandler = [this, newParity]() {
disconnect(this, &M3KTE::successAtCheckBoards, this, nullptr); disconnect(this, &M3KTE::successAtCheckBoards, this, nullptr);
m_settingsDialog->UpdateParity(newParity); m_settingsDialog->UpdateParity(newParity);
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
beginScanBoards(); beginScanBoards();
}; };
// Подписка на события успеха и ошибки
connect(this, &M3KTE::errorAtCheckBoards, this, errorHandler); connect(this, &M3KTE::errorAtCheckBoards, this, errorHandler);
connect(this, &M3KTE::successAtCheckBoards, this, successHandler); connect(this, &M3KTE::successAtCheckBoards, this, successHandler);
// Запускаем повторную проверку плат
checkBoards(); checkBoards();
} }
}; };
// Отправляем запросы на каждую активную плату
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
if(!Boards[i].isActive) if(!Boards[i].isActive)
continue; 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) { if(reply) {
(*totalActiveBoards)++; (*totalActiveBoards)++;
pendingBoards->insert(slaveAdress); pendingBoards->insert(slaveAddress);
// Обработка завершения ответа
connect(reply, &QModbusReply::finished, this, connect(reply, &QModbusReply::finished, this,
[this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() { [this, i, reply, slaveAddress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() {
if(reply->error() == QModbusDevice::TimeoutError) { if(reply->error() == QModbusDevice::TimeoutError)
(*confirmedBoards)++; (*confirmedBoards)++;
} else if (reply->error() == QModbusDevice::NoError) { else if(reply->error() == QModbusDevice::NoError)
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress), logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAddress),
tr("Неожиданный ответ."), ++Boards[i].error_baud_change, tr("Неожиданный ответ."), ++Boards[i].error_baud_change,
"Ошибка при изменении чётности."); "Ошибка при изменении чётности.");
} else { else
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress), logError(tr("Плата %1 (ID %2)").arg(i + 1).arg(slaveAddress),
reply->errorString(), ++Boards[i].error_baud_change, reply->errorString(), ++Boards[i].error_baud_change,
"Ошибка при изменении чётности."); "Ошибка при изменении чётности.");
}
pendingBoards->remove(slaveAdress); // Удаляем складной ответ
pendingBoards->remove(slaveAddress);
reply->deleteLater(); reply->deleteLater();
if(pendingBoards->isEmpty()) { // Когда все ответы получены, обрабатываем результат
if(pendingBoards->isEmpty())
processResult(); 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() bool M3KTE::pingNetworkDevices()
{ {
CurrentConnectedDevice = 0; CurrentConnectedDevice = 0;
@@ -1214,80 +1440,53 @@ bool M3KTE::pingNetworkDevices()
for(CurrentConnectedDevice = 0; CurrentConnectedDevice < 4;) { for(CurrentConnectedDevice = 0; CurrentConnectedDevice < 4;) {
auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr); auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr);
//Запрос типа устройства. //Запрос типа устройства.
if(reply == nullptr) { if(reply == nullptr)
onConnectClicked(); return deadPing(bar);
bar->close();
bar->deleteLater();
return false;
}
while(!reply->isFinished()) { while(!reply->isFinished()) {
if(isRun && CurrentConnectedDevice < 1) { if(isRun && CurrentConnectedDevice < 1)
onConnectClicked(); return deadPing(bar);
bar->close(); else if(isRun)
bar->deleteLater();
return false;
} else if(isRun) {
break; break;
}
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(isRun && CurrentConnectedDevice < 1) { if(isRun && CurrentConnectedDevice < 1)
onConnectClicked(); return deadPing(bar);
bar->close(); else if(isRun)
bar->deleteLater();
return false;
} else if(isRun) {
break; break;
} else if(!isRun) { else if(!isRun) {
//Нужна проверка типа устройства //Нужна проверка типа устройства
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
QModbusResponse resp = reply->rawResult(); QModbusResponse resp = reply->rawResult();
QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH)); QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH));
if(result == QString("KTE")) { if(result == QString("KTE")) {
//modbusDevice->setTimeout(1000);
auto *subreply = modbusDevice->sendRawRequest(requestOfBoardID, tmp_adr); auto *subreply = modbusDevice->sendRawRequest(requestOfBoardID, tmp_adr);
while(!subreply->isFinished()) { while(!subreply->isFinished()) {
if(isRun && CurrentConnectedDevice < 1) { if(isRun && CurrentConnectedDevice < 1)
onConnectClicked(); return deadPing(bar);
bar->close(); else if(isRun)
bar->deleteLater();
return false;
} else if(isRun) {
break; break;
}
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
int plata_ind = 0; int plata_ind = 0;
if(subreply->rawResult().data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) // ответ принят if(subreply->rawResult().data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) // ответ принят
plata_ind = subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) - 0x30; // парс ответа plata_ind = subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) - 0x30; // парс ответа
if(plata_ind < 1 || plata_ind > 4) { if(plata_ind < 1 || plata_ind > 4) {
QMessageBox::warning(this, "Ошибка при сканировании сети.", QMessageBox::warning(this, "Ошибка при сканировании сети.",
QString("Не удалось получить порядковый номер платы по адресу %1").arg(tmp_adr)); QString("Не удалось получить порядковый номер платы по адресу %1").arg(tmp_adr));
onConnectClicked(); return deadPing(bar);
bar->close();
bar->deleteLater();
return false;
} }
int board_ind = plata_ind - 1; int board_ind = plata_ind - 1;
if(isRun && CurrentConnectedDevice < 1) { if(isRun && CurrentConnectedDevice < 1)
onConnectClicked(); return deadPing(bar);
bar->close(); else if(isRun)
bar->deleteLater();
return false;
} else if(isRun) {
break; break;
} else { else {
statusBar()->showMessage(tr("Плата %1 найдена по адресу %2.").arg(board_ind).arg(tmp_adr), statusBar()->showMessage(tr("Плата %1 найдена по адресу %2.").arg(board_ind).arg(tmp_adr),
m_settingsDialog->settings().responseTime); m_settingsDialog->settings().responseTime);
if(Boards[board_ind].isActive) { if(Boards[board_ind].isActive) {
QMessageBox::warning(this, "Ошибка при сканировании сети.", QMessageBox::warning(this, "Ошибка при сканировании сети.",
QString("Платы по адресам %1 и %2 имеют одинаковый порядковый номер %3").arg(Boards[board_ind].adr).arg(tmp_adr).arg(plata_ind)); QString("Платы по адресам %1 и %2 имеют одинаковый порядковый номер %3").arg(Boards[board_ind].adr).arg(tmp_adr).arg(plata_ind));
onConnectClicked(); return deadPing(bar);
bar->close();
bar->deleteLater();
return false;
} }
CurrentConnectedDevice++; CurrentConnectedDevice++;
Boards[board_ind].adr = Boards[board_ind]._tmp_adr = tmp_adr; Boards[board_ind].adr = Boards[board_ind]._tmp_adr = tmp_adr;
@@ -1305,128 +1504,125 @@ bool M3KTE::pingNetworkDevices()
QMessageBox::warning(this, "Ошибка при сканировании сети.", QMessageBox::warning(this, "Ошибка при сканировании сети.",
QString("Выход за пределы допустимых адресов. Найдено %1 плат.").arg(CurrentConnectedDevice)); QString("Выход за пределы допустимых адресов. Найдено %1 плат.").arg(CurrentConnectedDevice));
bar->setValue(4); bar->setValue(4);
bar->close(); return deadPing(bar);
bar->deleteLater(); } else if(tmp_adr >= 247)
onConnectClicked();
return false;
} else if(tmp_adr>=247) {
break; break;
} }
}
isRun = false; isRun = false;
QMessageBox::warning(this, "Сканирование сети завершено.", tr("Найдено плат: %1 из 4.").arg(CurrentConnectedDevice)); // Создаем QMessageBox
if(isRun) { QMessageBox msgBox;
QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя.")); msgBox.setWindowTitle("Сканирование сети завершено.");
onConnectClicked(); msgBox.setText(QString("Найдено плат: %1 из 4.").arg(CurrentConnectedDevice));
bar->close(); // Добавляем две кнопки
bar->deleteLater(); QPushButton *requestSettingsBtn = msgBox.addButton("Запросить настройки", QMessageBox::AcceptRole);
return false; QPushButton *cancelBtn = msgBox.addButton("Прервать подключение", QMessageBox::RejectRole);
} // Выполняем модальное окно и ожидаем ответ
msgBox.exec();
// Обработка нажатия
if(msgBox.clickedButton() == cancelBtn)
return deadPing(bar);
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
bar->setLabelText(tr("Считывание текущих настроек...")); bar->setLabelText(tr("Считывание текущих настроек..."));
bar->setRange(0, CurrentConnectedDevice * 3); bar->setRange(0, CurrentConnectedDevice * 3);
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
if(Boards[i].isActive) { if(Boards[i].isActive) {
QModbusDataUnit* _unit_settings[3]; QModbusDataUnit* _unit_settings[3];
_unit_settings[0] = new QModbusDataUnit(QModbusDataUnit::Coils, 0, 85-(i/3*20)); QModbusDataUnit cCoils(QModbusDataUnit::Coils, 0, 85 - (i / 3 * 20));
_unit_settings[1] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 0, 85-(i/3*20)); QModbusDataUnit wHR(QModbusDataUnit::HoldingRegisters, 0, 85 - (i / 3 * 20));
_unit_settings[2] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 85, 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); Boards_Fields[i]->setEnabled(true);
for(int j = 0; j < 3; j++) { for(int j = 0; j < 3; j++) {
bar->setValue(i * 3 + j); bar->setValue(i * 3 + j);
if(isRun) { if(isRun)
onConnectClicked(); return deadPing(bar);
bar->close();
bar->deleteLater();
delete _unit_settings[0];
delete _unit_settings[1];
delete _unit_settings[2];
return false;
}
auto *reply = modbusDevice->sendReadRequest(*_unit_settings[j], Boards[i].adr); auto *reply = modbusDevice->sendReadRequest(*_unit_settings[j], Boards[i].adr);
if(!reply) { if(!reply)
onConnectClicked(); return deadPing(bar);
bar->close();
bar->deleteLater();
delete _unit_settings[0];
delete _unit_settings[1];
delete _unit_settings[2];
return false;
}
while(!reply->isFinished()) { while(!reply->isFinished()) {
if(isRun) { if(isRun) {
QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QMessageBox::warning(this, "Ошибка при получении текущих настроек.",
QString("Прерывание по запросу пользователя.")); QString("Прерывание по запросу пользователя."));
onConnectClicked(); return deadPing(bar);
bar->close();
bar->deleteLater();
delete _unit_settings[0];
delete _unit_settings[1];
delete _unit_settings[2];
return false;
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(reply->error()==QModbusDevice::NoError) { if(reply->error()==QModbusDevice::NoError)
applySettingsFromScan(reply); applySettingsFromScan(reply);
} else { else {
QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QMessageBox::warning(this, "Ошибка при получении текущих настроек.",
QString("Таймаут при опросе устройства %1 по адресу %2").arg(i + 1).arg(Boards[i].adr)); QString("Таймаут при опросе устройства %1 по адресу %2").arg(i + 1).arg(Boards[i].adr));
bar->setValue(CurrentConnectedDevice * 3); bar->setValue(CurrentConnectedDevice * 3);
bar->close(); return deadPing(bar);
bar->deleteLater();
onConnectClicked();
delete _unit_settings[0];
delete _unit_settings[1];
delete _unit_settings[2];
return false;
} }
} }
Boards_Fields[i]->setTitle(QString("Плата №%1 (ID %2)").arg(i + 1).arg(Boards[i].adr)); 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];
} }
} }
int totalBoardsActive = 0; int totalBoardsActive = 0;
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
{
if(Boards[i].isActive) if(Boards[i].isActive)
totalBoardsActive++; totalBoardsActive++;
}
m_parameterWorkspace->setDeviceCount(totalBoardsActive); m_parameterWorkspace->setDeviceCount(totalBoardsActive);
modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries); modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries);
beginScanBoards(); beginScanBoards();
bar->deleteLater(); bar->deleteLater();
return true; return true;
} }
/**
* @brief Запускает процесс сканирования активных плат в системе.
*
* Эта функция перебирает все возможные платы (от 0 до 3), проверяет их активность,
* и для каждой активной платы инициализирует её сканирование:
* - Обновляет состояние интерфейса для отображения активных плат.
* - Инициализирует опрос настроек устройства по адресу.
* - Запускает процедуру сканирования платы.
* - Обновляет рабочее пространство параметров с информацией об активной плате.
*
* После завершения процедуры все активные платы будут обработаны, и пользователь увидит актуальное состояние.
*/
void M3KTE::beginScanBoards() void M3KTE::beginScanBoards()
{ {
int totalBoardsActive = 0; int totalBoardsActive = 0;
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++)
if(Boards[i].isActive) { if(Boards[i].isActive) {
m_debugTerminalDialog->setScanBoardActive(true, i); m_debugTerminalDialog->setScanBoardActive(true, i);
m_deviceSettingsDialog->initPollForBoard(i, Boards[i].adr); m_deviceSettingsDialog->initPollForBoard(i, Boards[i].adr);
boardScan(i); boardScan(i);
m_parameterWorkspace->updateDevice(totalBoardsActive++, Boards[i].isActive, Boards[i].adr); m_parameterWorkspace->updateDevice(totalBoardsActive++, Boards[i].isActive, Boards[i].adr);
} }
}
return; return;
} }
/**
* @brief Выполняет сканирование данных платы по Modbus.
*
* Эта функция инициирует последовательные запросы к плате с идентификатором `boardID` для получения
* статуса и полного набора данных через Modbus. Обрабатывает завершения запросов асинхронно, используя сигналы и слоты,
* измеряет время отклика, логирует ошибки и запусквает следующий цикл сканирования.
*
* Основные шаги:
* - Проверяет наличие активного Modbus-устройства.
* - Генерирует запрос чтения регистра статуса (регистры 85).
* - Обрабатывает ответ по таймеру; при успешном ответе:
* - извлекает статус регистра;
* - инициирует запрос полного набора данных (с учётом идентификатора платы);
* - обрабатывает ответ данных, вызывает функцию отображения результата,
* и перезапускает таймер следующего сканирования.
* - В случае ошибок или завершения запросов мгновенно, логирует ошибку и перезапускает цикл.
*
* @param boardID Идентификатор платы (индекс в массиве).
*/
void M3KTE::boardScan(unsigned boardID) void M3KTE::boardScan(unsigned boardID)
{ {
if (!modbusDevice) { if(!modbusDevice)
return; return;
}
emit boardReading(boardID); emit boardReading(boardID);
statusBar()->clearMessage(); statusBar()->clearMessage();
QModbusDataUnit statusUnit(QModbusDataUnit::InputRegisters, 85, 1); 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(); Boards[boardID].timerToStatusResponse.start();
if(!reply->isFinished()) { if(!reply->isFinished()) {
@@ -1456,29 +1652,26 @@ void M3KTE::boardScan(unsigned boardID)
// Мгновенно завершенный запрос данных // Мгновенно завершенный запрос данных
Boards[boardID].timerToDataResponse.elapsed(); Boards[boardID].timerToDataResponse.elapsed();
// shouldLog для dataReply должен определяться здесь, но используем тот же принцип // 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), logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, ""); modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
dataReply->deleteLater(); dataReply->deleteLater();
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval); Boards[boardID].boardScanners->start(timerInterval);
} }
} else { } 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), logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, ""); modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval); Boards[boardID].boardScanners->start(timerInterval);
} }
} else { } 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), logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_TX, ""); reply->errorString(), ++Boards[boardID].error_TX, "");
}
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval); Boards[boardID].boardScanners->start(timerInterval);
} }
@@ -1488,25 +1681,30 @@ void M3KTE::boardScan(unsigned boardID)
// Мгновенно завершенный запрос статуса // Мгновенно завершенный запрос статуса
Boards[boardID].timerToStatusResponse.elapsed(); Boards[boardID].timerToStatusResponse.elapsed();
// Для мгновенно завершенных запросов определяем shouldLog здесь // Для мгновенно завершенных запросов определяем 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), logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, ""); modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
reply->deleteLater(); reply->deleteLater();
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval); 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), logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, ""); modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
} }
}
}
/**
* @brief Обрабатывает и отображает результат сканирования Modbus-ответа.
*
* Эта функция анализирует ответ, обновляет состояние элементов пользовательского интерфейса
* и регистров, а также регистрирует ошибки и предупреждения.
*
* @param reply Указатель на объект QModbusReply, содержащий ответ.
* @param boardID Индекс платы, которую обрабатываем.
* @param status Статус регистра, полученный из устройства.
*/
void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status) void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status)
{ {
if(!reply) if(!reply)
@@ -1528,13 +1726,12 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status)
QString statusText; QString statusText;
int state = StatusReg.ParsingReg.mzkte_status; int state = StatusReg.ParsingReg.mzkte_status;
int numb_err = StatusReg.ParsingReg.mzkte_error; int numb_err = StatusReg.ParsingReg.mzkte_error;
if (state == 0) { if(state == 0)
statusText = "Ok"; statusText = "Ok";
} else if (state == 1) { else if(state == 1)
statusText = "Non-Critical"; statusText = "Non-Critical";
} else if (state == 2) { else if(state == 2)
statusText = "Critical"; statusText = "Critical";
}
if(state) { if(state) {
switch (numb_err) { switch (numb_err) {
case 1: statusText += QString(" (Err 5 VD)"); break; case 1: statusText += QString(" (Err 5 VD)"); break;
@@ -1559,11 +1756,10 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status)
QString W_Adr; QString W_Adr;
QString A_Adr; QString A_Adr;
int total_qnt; int total_qnt;
if(boardID == 3) { if(boardID == 3)
total_qnt = 65; total_qnt = 65;
} else { else
total_qnt = 85; total_qnt = 85;
}
for(int i = unit.startAddress(), total = total_qnt; i < total; ++i) { for(int i = unit.startAddress(), total = total_qnt; i < total; ++i) {
if(Boards[boardID].coil[i]==true) { if(Boards[boardID].coil[i]==true) {
int j = 0; int j = 0;
@@ -1651,25 +1847,32 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status)
reply->deleteLater(); reply->deleteLater();
} }
/**
* @brief Обрабатывает ответ Modbus и применяет настройки к платам.
*
* Эта функция проверяет ошибку ответа и, при успешном ответе,
* обновляет данные в моделях и элементах интерфейса для соответствующей платы.
* В случае ошибок отображает сообщения и регистрирует ошибки.
*
* @param reply Указатель на объект QModbusReply с ответом от устройства.
*/
void M3KTE::applySettingsFromScan(QModbusReply *reply) void M3KTE::applySettingsFromScan(QModbusReply *reply)
{ {
int Adr = 255; 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) { if(Boards[i].adr==reply->serverAddress() &&Boards[i].isActive) {
Adr = i; Adr = i;
break; break;
} }
}
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result(); 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) { if(unit.registerType() == QModbusDataUnit::Coils) {
Boards[Adr].coil[i + unit.startAddress()] = unit.value(i); 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); 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); Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Unchecked, Qt::CheckStateRole);
}
} else if(unit.registerType() == QModbusDataUnit::HoldingRegisters) { } else if(unit.registerType() == QModbusDataUnit::HoldingRegisters) {
Boards[Adr].HR[i + unit.startAddress()] = unit.value(i); 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); Boards[Adr].ModbusModelHoldingReg->setData(Boards[Adr].ModbusModelHoldingReg->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 10), Qt::EditRole);
@@ -1691,6 +1894,12 @@ void M3KTE::applySettingsFromScan(QModbusReply *reply)
reply->deleteLater(); reply->deleteLater();
} }
/**
* @brief Слот для обработки команды записи нескольких регистров.
*
* Проверяет наличие активного соединения с Modbus-устройством и
* вызывает функцию `multipleRegWrite()` для выполнения записи.
*/
void M3KTE::slotmultipleRegWrite() void M3KTE::slotmultipleRegWrite()
{ {
if(!modbusDevice) if(!modbusDevice)
@@ -1698,6 +1907,13 @@ void M3KTE::slotmultipleRegWrite()
multipleRegWrite(); multipleRegWrite();
} }
/**
* @brief Слот для записи нескольких регистров и отправки данных.
*
* Проверяет наличие активного соединения с Modbus-устройством и,
* если соединение установлено, вызывает функции `multipleRegWrite()` для записи
* и `multipleRegSend()` для отправки данных.
*/
void M3KTE::slotmultipleRegWriteAndSend() void M3KTE::slotmultipleRegWriteAndSend()
{ {
if(!modbusDevice) if(!modbusDevice)
@@ -1706,22 +1922,28 @@ void M3KTE::slotmultipleRegWriteAndSend()
multipleRegSend(); multipleRegSend();
} }
/**
* @brief Отправляет команду записи нескольких регистров или катушек на устройство по Modbus.
*
* Функция создает объект QModbusDataUnit с типом регистров или катушек, в зависимости от настроек.
* Заполняет его значениями и обновляет модели данных внутреннего устройства.
* Затем инициирует асинхронную отправку запроса через `modbusDevice->sendWriteRequest()`.
* Обрабатывает результат асинхронного ответа и выводит сообщения об ошибках.
*/
void M3KTE::multipleRegSend() void M3KTE::multipleRegSend()
{ {
QModbusDataUnit *unit_tx = nullptr; QModbusDataUnit *unit_tx = nullptr;
if(m_regMultipleSettings->getTypeReg()) { if(m_regMultipleSettings->getTypeReg())
unit_tx = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, m_regMultipleSettings->getStartAdr(), m_regMultipleSettings->getCountReg()); 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()); unit_tx = new QModbusDataUnit(QModbusDataUnit::Coils, m_regMultipleSettings->getStartAdr(), m_regMultipleSettings->getCountReg());
}
for(unsigned i = 0; i < m_regMultipleSettings->getCountReg(); i++) { for(unsigned i = 0; i < m_regMultipleSettings->getCountReg(); i++) {
unit_tx->setValue(i, m_regMultipleSettings->getNewValue()); 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(); 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(); Boards[m_regMultipleSettings->getBoardId()].coil[i+m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue();
} }
}
if(auto *reply = modbusDevice->sendWriteRequest(*unit_tx, Boards[m_regMultipleSettings->getBoardId()].adr)) { if(auto *reply = modbusDevice->sendWriteRequest(*unit_tx, Boards[m_regMultipleSettings->getBoardId()].adr)) {
unsigned Adr = m_regMultipleSettings->getBoardId(); unsigned Adr = m_regMultipleSettings->getBoardId();
if(!reply->isFinished()) { if(!reply->isFinished()) {
@@ -1741,26 +1963,41 @@ void M3KTE::multipleRegSend()
} }
reply->deleteLater(); reply->deleteLater();
}); });
} else { } else
// broadcast replies return immediately // broadcast replies return immediately
reply->deleteLater(); reply->deleteLater();
} } else
} else {
statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000); statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
} }
}
/**
* @brief Обновляет внутренние модели данных для нескольких регистров или катушек.
*
* В цикле по количеству регистров или катушек, указанных в настройках, обновляет
* значения внутренних моделей `ModbusModelHoldingReg` или `ModbusModelCoil` для соответствующих
* позиций, основываясь на типе регистров. Значения устанавливаются в новое заданное значение.
*/
void M3KTE::multipleRegWrite() void M3KTE::multipleRegWrite()
{ {
for(unsigned i = 0; i < m_regMultipleSettings->getCountReg(); i++) { for(unsigned i = 0; i < m_regMultipleSettings->getCountReg(); i++) {
if(m_regMultipleSettings->getTypeReg()) { if(m_regMultipleSettings->getTypeReg())
Boards[m_regMultipleSettings->getBoardId()].ModbusModelHoldingReg->m_holdingRegisters[i + m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue(); Boards[m_regMultipleSettings->getBoardId()].ModbusModelHoldingReg->m_holdingRegisters[i + m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue();
} else { else
Boards[m_regMultipleSettings->getBoardId()].ModbusModelCoil->m_coils[i + m_regMultipleSettings->getStartAdr()] = (bool)m_regMultipleSettings->getNewValue(); 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) void M3KTE::writeSingleCoil(int boardId, int coilAddress, bool value)
{ {
if(!modbusDevice || !Boards[boardId].isActive) if(!modbusDevice || !Boards[boardId].isActive)
@@ -1768,21 +2005,30 @@ void M3KTE::writeSingleCoil(int boardId, int coilAddress, bool value)
QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1); QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1);
unit.setValue(0, value ? 1 : 0); unit.setValue(0, value ? 1 : 0);
if(auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardId].adr)) { if(auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardId].adr)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [this, boardId, reply]() { connect(reply, &QModbusReply::finished, this, [this, boardId, reply]() {
if (reply->error() != QModbusDevice::NoError) { if(reply->error() != QModbusDevice::NoError)
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_TX, reply->errorString(), ++Boards[boardId].error_TX,
"Single coil write"); "Single coil write");
}
reply->deleteLater(); reply->deleteLater();
}); });
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} }
}
/**
* @brief Записывает значение в один регистр (holding register) на указанной плате по Modbus.
*
* Проверяет, инициализировано ли соединение и активна ли плата.
* Создает объект `QModbusDataUnit` для одного регистра по указанному адресу и присваивает ему значение.
* Выполняет асинхронную отправку записи и обрабатывает ответ.
*
* @param boardID Идентификатор платы.
* @param regAddress Адрес регистра, в который нужно записать значение.
* @param value Значение для записи в регистр.
*/
void M3KTE::writeSingleRegister(int boardID, int regAddress, quint16 value) void M3KTE::writeSingleRegister(int boardID, int regAddress, quint16 value)
{ {
if(!modbusDevice || !Boards[boardID].isActive) if(!modbusDevice || !Boards[boardID].isActive)
@@ -1790,21 +2036,30 @@ void M3KTE::writeSingleRegister(int boardID, int regAddress, quint16 value)
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, regAddress, 1); QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, regAddress, 1);
unit.setValue(0, value); unit.setValue(0, value);
if(auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardID].adr)) { if(auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardID].adr)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() { connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() {
if (reply->error() != QModbusDevice::NoError) { if(reply->error() != QModbusDevice::NoError)
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_TX, reply->errorString(), ++Boards[boardID].error_TX,
"Single register write"); "Single register write");
}
reply->deleteLater(); reply->deleteLater();
}); });
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} }
}
/**
* @brief Читает состояние одного по цепочке (coil) на указанной плате по Modbus.
*
* Проверяет, инициализирован ли модуль и активна ли плата.
* Создает объект `QModbusDataUnit` для одного котла по адресу и отправляет запрос на чтение.
* Возвращает указатель на объект `QModbusReply`, который можно использовать для обработки результата асинхронно.
*
* @param boardID Идентификатор платы.
* @param coilAddress Адрес котлы (coil), состояние которой нужно прочитать.
* @return Указатель на `QModbusReply`, или `nullptr`, если модуль не инициализирован или плата не активна.
*/
QModbusReply* M3KTE::readSingleCoil(int boardID, int coilAddress) QModbusReply* M3KTE::readSingleCoil(int boardID, int coilAddress)
{ {
if(!modbusDevice || !Boards[boardID].isActive) if(!modbusDevice || !Boards[boardID].isActive)
@@ -1814,6 +2069,15 @@ QModbusReply* M3KTE::readSingleCoil(int boardID, int coilAddress)
return reply; return reply;
} }
/**
* @brief Выбирает позицию в дереве и таблице UI по заданному индексу.
*
* Расчет осуществляется на основе индекса, деля его на блоки, соответствующие определенным
* диапазонам элементов в интерфейсе (например, 85 элементов на плату). Затем обновляется
* выделение и прокрутка таблицы до выбранной позиции.
*
* @param index Индекс элемента, который следует выделить и прокрутить.
*/
void M3KTE::selectPositionOnTree(unsigned int index) void M3KTE::selectPositionOnTree(unsigned int index)
{ {
ui->boardSelectBox->setCurrentIndex(index / 85); ui->boardSelectBox->setCurrentIndex(index / 85);
@@ -1823,6 +2087,22 @@ void M3KTE::selectPositionOnTree(unsigned int index)
ui->writeValueTable->scrollTo(selected); ui->writeValueTable->scrollTo(selected);
} }
/**
* @brief Выполняет автоматический сканирование скорости передачи данных для устройств по Modbus.
*
* Эта функция перебирает стандартные скорости передачи данных (9600, 14400, 19200 и др.)
* и пытается обнаружить устройства, отвечающие на запросы по каждой скорости.
* В процессе происходит подключение к порту, отправка специальных запросов, проверка типа устройства
* и последующая синхронизация устройств, если такие были найдены.
*
* В случае успешного обнаружения устройств, результат выводится и отображается, также выполняется
* настройка устройств на выбранную скорость.
*
* Выполняет последовательные соединения, отправку запросов, обработку ответов, а также мониторинг
* пользовательского прерывания операции через диалоговое окно прогресса.
*
* @return true, если сканирование завершено успешно и все устройства синхронизированы, иначе false.
*/
bool M3KTE::autoBaudRateScan() bool M3KTE::autoBaudRateScan()
{ {
unsigned countOfDeviceOnLine = 0; unsigned countOfDeviceOnLine = 0;
@@ -1856,9 +2136,8 @@ bool M3KTE::autoBaudRateScan()
bar->setValue(i); bar->setValue(i);
bar->setLabelText(tr("Поиск плат... Текущая скорость: %1").arg(m_baud[i])); bar->setLabelText(tr("Поиск плат... Текущая скорость: %1").arg(m_baud[i]));
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]);
if(!modbusDevice->connectDevice()) { if(!modbusDevice->connectDevice())
statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000); statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
}
for(int tmp_adr = 1; tmp_adr < 248; tmp_adr++) { for(int tmp_adr = 1; tmp_adr < 248; tmp_adr++) {
auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr); auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr);
//Запрос типа устройства. //Запрос типа устройства.
@@ -1882,7 +2161,7 @@ bool M3KTE::autoBaudRateScan()
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} else if(!isRun) { } else if(!isRun)
//Нужна проверка типа устройства //Нужна проверка типа устройства
if(reply->error()==QModbusDevice::NoError) { if(reply->error()==QModbusDevice::NoError) {
QModbusResponse resp = reply->rawResult(); QModbusResponse resp = reply->rawResult();
@@ -1893,7 +2172,6 @@ bool M3KTE::autoBaudRateScan()
} }
} }
} }
}
if(countOfDeviceOnLine > 0) if(countOfDeviceOnLine > 0)
resultOfScan += QString("%1 плат M3KTE работают на скорости %2.\n").arg(countOfDeviceOnLine).arg(m_baud[i]); resultOfScan += QString("%1 плат M3KTE работают на скорости %2.\n").arg(countOfDeviceOnLine).arg(m_baud[i]);
countOfDeviceOnLine = 0; countOfDeviceOnLine = 0;
@@ -1906,7 +2184,8 @@ bool M3KTE::autoBaudRateScan()
for(int l = i; l < 8; l++) { 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", 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; return false;
} }
} }
@@ -1919,9 +2198,8 @@ bool M3KTE::autoBaudRateScan()
bar->setLabelText(tr("Синхронизация плат на скорости %1").arg(m_baud[i])); bar->setLabelText(tr("Синхронизация плат на скорости %1").arg(m_baud[i]));
for(int j = 0; j < KTE[i].size(); j++) { for(int j = 0; j < KTE[i].size(); j++) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]);
if(!modbusDevice->connectDevice()) { if(!modbusDevice->connectDevice())
statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000); statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
}
auto *reply = modbusDevice->sendWriteRequest(*_unit, KTE[i].at(j)); auto *reply = modbusDevice->sendWriteRequest(*_unit, KTE[i].at(j));
if(!reply) { if(!reply) {
onConnectClicked(); onConnectClicked();
@@ -1961,9 +2239,8 @@ bool M3KTE::autoBaudRateScan()
return false; return false;
} }
} }
} else if(reply->error()!=QModbusDevice::NoError) { } else if(reply->error() != QModbusDevice::NoError)
return false; return false;
}
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
} }
} }
@@ -1974,10 +2251,17 @@ bool M3KTE::autoBaudRateScan()
return false; return false;
} }
/**
* @brief Останавливает процесс сканирования на всех платах.
*
* Эта функция перебирает все четыре устройства типа Boards и вызывает
* метод `stop()` для объекта `boardScanners`, который управляет запуском
* и остановкой процесса сканирования. После вызова все текущие сканирования
* на платах будут прекращены.
*/
void M3KTE::stopScanBoard() void M3KTE::stopScanBoard()
{ {
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++)
Boards[i].boardScanners->stop(); Boards[i].boardScanners->stop();
}
return; return;
} }

View File

@@ -59,6 +59,7 @@ private:
QModbusDataUnit writeRequest() const; QModbusDataUnit writeRequest() const;
void changeTable(int board, int tabletype); void changeTable(int board, int tabletype);
bool event(QEvent* event); bool event(QEvent* event);
bool deadPing(QProgressDialog *bar);
bool pingNetworkDevices(); bool pingNetworkDevices();
void beginScanBoards(); void beginScanBoards();
void stopScanBoard(); void stopScanBoard();

View File

@@ -32,7 +32,7 @@ void MultipleSettings::on_buttonBox_clicked(QAbstractButton *button)
countReg = ui->countBox->value(); countReg = ui->countBox->value();
boardId = ui->boardBox->currentIndex(); boardId = ui->boardBox->currentIndex();
emit writeAndSend(); emit writeAndSend();
} else {} }
} }
void MultipleSettings::on_regTypeBox_currentIndexChanged(int index) void MultipleSettings::on_regTypeBox_currentIndexChanged(int index)
@@ -66,5 +66,6 @@ void MultipleSettings::on_boardBox_currentIndexChanged(int index)
void MultipleSettings::on_adrBox_valueChanged(int arg1) 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));
} }

View File

@@ -11,7 +11,6 @@ class MultipleSettings;
class MultipleSettings : public QDialog class MultipleSettings : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MultipleSettings(QWidget *parent = nullptr); explicit MultipleSettings(QWidget *parent = nullptr);
~MultipleSettings(); ~MultipleSettings();
@@ -23,16 +22,11 @@ public:
signals: signals:
void write(); void write();
void writeAndSend(); void writeAndSend();
private slots: private slots:
void on_buttonBox_clicked(QAbstractButton *button); void on_buttonBox_clicked(QAbstractButton *button);
void on_regTypeBox_currentIndexChanged(int index); void on_regTypeBox_currentIndexChanged(int index);
void on_boardBox_currentIndexChanged(int index); void on_boardBox_currentIndexChanged(int index);
void on_adrBox_valueChanged(int arg1); void on_adrBox_valueChanged(int arg1);
private: private:
Ui::MultipleSettings *ui; Ui::MultipleSettings *ui;
quint16 newValue = 0; quint16 newValue = 0;

View File

@@ -17,7 +17,6 @@ ParameterBox::ParameterBox(QWidget *parent, pboxMode Mode, quint16 objectID) :
case MTemplate: case MTemplate:
break; break;
} }
ui->objectIdLabel->setText("0x" + QString::number(ID, 16)); ui->objectIdLabel->setText("0x" + QString::number(ID, 16));
} }
@@ -29,9 +28,7 @@ ParameterBox::~ParameterBox()
void ParameterBox::on_sendButton_clicked() void ParameterBox::on_sendButton_clicked()
{ {
if(ui->valueBox->currentText().isEmpty()) if(ui->valueBox->currentText().isEmpty())
{
return; return;
}
emit writeParameter(ui->adrLine->text().toInt(), ui->valueBox->currentText().toInt(nullptr, 16)); emit writeParameter(ui->adrLine->text().toInt(), ui->valueBox->currentText().toInt(nullptr, 16));
} }

View File

@@ -10,7 +10,6 @@ class ParameterBox;
class ParameterBox : public QWidget class ParameterBox : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
enum pboxMode{ enum pboxMode{
Info = 0, Info = 0,
@@ -20,10 +19,8 @@ public:
Coil = 0, Coil = 0,
HR = 1 HR = 1
}; };
explicit ParameterBox(QWidget *parent = nullptr, pboxMode Mode = Info, quint16 objectID = 0x80); explicit ParameterBox(QWidget *parent = nullptr, pboxMode Mode = Info, quint16 objectID = 0x80);
~ParameterBox(); ~ParameterBox();
void setData(QString data); void setData(QString data);
void setData(QString name, QString adr, QStringList values); void setData(QString name, QString adr, QStringList values);
quint16 getID(){return ID;} quint16 getID(){return ID;}
@@ -32,7 +29,6 @@ signals:
void writeParameter(int adr, quint16 value); void writeParameter(int adr, quint16 value);
private slots: private slots:
void on_sendButton_clicked(); void on_sendButton_clicked();
private: private:
quint16 ID; quint16 ID;
pboxMode boxMode; pboxMode boxMode;

View File

@@ -13,10 +13,6 @@ ParameterDevice::ParameterDevice(QWidget *parent) :
ui(new Ui::ParameterDevice) ui(new Ui::ParameterDevice)
{ {
ui->setupUi(this); ui->setupUi(this);
updateTimer = new QTimer(this);
updateTimer->setSingleShot(true);
connect(updateTimer, &QTimer::timeout, this, &ParameterDevice::sortScrollArea);
} }
ParameterDevice::~ParameterDevice() ParameterDevice::~ParameterDevice()
@@ -38,14 +34,12 @@ void ParameterDevice::on_fullRadio_clicked()
void ParameterDevice::on_checkButton_clicked() void ParameterDevice::on_checkButton_clicked()
{ {
for (ParameterBox* box : parameterBoxes) { for(ParameterBox* box : parameterBoxes)
if (box) { if(box)
box->deleteLater(); box->deleteLater();
}
}
parameterBoxes.clear(); parameterBoxes.clear();
quint16 strAdr; quint16 strAdr;
int cnt; int cnt = 0;
strAdr = ui->adrSpin->value(); strAdr = ui->adrSpin->value();
switch(mode) { switch(mode) {
case fullRequest: case fullRequest:
@@ -56,28 +50,46 @@ void ParameterDevice::on_checkButton_clicked()
cnt = ui->countSpin->value(); cnt = ui->countSpin->value();
break; break;
} }
QElapsedTimer timer;
QProgressDialog progressDialog("Обработка...", "Отмена", 0, cnt, this); QProgressDialog progressDialog("Обработка...", "Отмена", 0, cnt, this);
progressDialog.setWindowModality(Qt::WindowModal); progressDialog.setWindowModality(Qt::WindowModal);
progressDialog.setMinimumDuration(0); // показывать сразу progressDialog.setMinimumDuration(0); // показывать сразу
QEventLoop loop; QEventLoop loop;
connect(this, &ParameterDevice::transmitEnd, &loop, &QEventLoop::quit); connect(this, &ParameterDevice::transmitEnd, &loop, &QEventLoop::quit);
timer.start();
for(int i = 0; i < cnt; i ++) { for(int i = 0; i < cnt; i ++) {
// Обновляем прогресс // Обновляем прогресс
progressDialog.setValue(i); progressDialog.setValue(i);
if (progressDialog.wasCanceled()) { if(progressDialog.wasCanceled())
break; // пользователь отменил break; // пользователь отменил
}
QByteArray data = QByteArray::fromHex("0E04"); QByteArray data = QByteArray::fromHex("0E04");
data.append(strAdr+i); data.append(strAdr+i);
QModbusRequest request(QModbusRequest::EncapsulatedInterfaceTransport, data); QModbusRequest request(QModbusRequest::EncapsulatedInterfaceTransport, data);
emit read(request, strAdr+i); emit read(request, strAdr+i);
loop.exec(); loop.exec();
if(errorAtTransmit) if(errorAtTransmit) {
{
errorAtTransmit = false; errorAtTransmit = false;
break; 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); progressDialog.setValue(cnt);
sortParameterBoxesByID(parameterBoxes); sortParameterBoxesByID(parameterBoxes);
sortScrollArea(); sortScrollArea();
@@ -85,7 +97,6 @@ void ParameterDevice::on_checkButton_clicked()
void ParameterDevice::setError(QString error) void ParameterDevice::setError(QString error)
{ {
QMessageBox::information(nullptr, "Получен ответ", error); QMessageBox::information(nullptr, "Получен ответ", error);
errorAtTransmit = true; errorAtTransmit = true;
emit transmitEnd(); emit transmitEnd();
@@ -114,19 +125,10 @@ void ParameterDevice::setAnswer(QString reply, quint16 objectID)
} }
parameterBoxes.append(newbox); parameterBoxes.append(newbox);
emit transmitEnd(); emit transmitEnd();
// // Остановить, если уже запущен
// if (updateTimer->isActive()) {
// updateTimer->stop();
// }
// // Запустить с задержкой 6 секунд
// updateTimer->start(6000);
} }
void ParameterDevice::sortScrollArea() void ParameterDevice::sortScrollArea()
{ {
//sortParameterBoxesByID(parameterBoxes);
//ui->parameterBoxHubContents->layout()->deleteLater();
QLayout* pblayout = ui->parameterBoxHubContents->layout(); QLayout* pblayout = ui->parameterBoxHubContents->layout();
if(!pblayout) { if(!pblayout) {
// Создайте новый лейаут, если его нет // Создайте новый лейаут, если его нет
@@ -134,16 +136,9 @@ void ParameterDevice::sortScrollArea()
ui->parameterBoxHubContents->setLayout(pblayout); ui->parameterBoxHubContents->setLayout(pblayout);
} }
QLayoutItem *item; QLayoutItem *item;
while ((item = pblayout->takeAt(0)) != nullptr){ while((item = pblayout->takeAt(0)) != nullptr){}
//delete item; for(int i = 0; i < parameterBoxes.count(); i++)
}
//ui->parameterBoxHubContents->setLayout(pblayout);
for (int i = 0; i < parameterBoxes.count(); i++) {
pblayout->addWidget(parameterBoxes.at(i)); pblayout->addWidget(parameterBoxes.at(i));
}
ui->parameterBoxHubContents->update(); ui->parameterBoxHubContents->update();
ui->parameterBoxHubContents->adjustSize(); ui->parameterBoxHubContents->adjustSize();
ui->scrollArea->updateGeometry(); ui->scrollArea->updateGeometry();

View File

@@ -9,6 +9,7 @@
#include <QTimer> #include <QTimer>
#include <QMessageBox> #include <QMessageBox>
#include <QProgressDialog> #include <QProgressDialog>
#include <QElapsedTimer>
void sortParameterBoxesByID(QVector<ParameterBox*>& parameterBoxes); void sortParameterBoxesByID(QVector<ParameterBox*>& parameterBoxes);
@@ -19,7 +20,6 @@ class ParameterDevice;
class ParameterDevice : public QWidget class ParameterDevice : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
enum requestMode{ enum requestMode{
fullRequest = 0, fullRequest = 0,
@@ -37,24 +37,16 @@ signals:
void writeSingleCoil(int coilAddress, bool value); void writeSingleCoil(int coilAddress, bool value);
void writeSingleRegister(int registerAddress, quint16 value); void writeSingleRegister(int registerAddress, quint16 value);
void transmitEnd(); void transmitEnd();
private slots: private slots:
void on_selectiveRadio_clicked(); void on_selectiveRadio_clicked();
void on_fullRadio_clicked(); void on_fullRadio_clicked();
void on_checkButton_clicked(); void on_checkButton_clicked();
void on_adrSpin_valueChanged(int arg1); void on_adrSpin_valueChanged(int arg1);
private: private:
void sortScrollArea(); void sortScrollArea();
private: private:
int adr; int adr;
QTimer *updateTimer;
QVector<ParameterBox*>parameterBoxes; QVector<ParameterBox*>parameterBoxes;
requestMode mode = fullRequest; requestMode mode = fullRequest;
Ui::ParameterDevice *ui; Ui::ParameterDevice *ui;
}; };

View File

@@ -6,39 +6,38 @@ ParameterWorkspace::ParameterWorkspace(QWidget *parent) :
ui(new Ui::ParameterWorkspace) ui(new Ui::ParameterWorkspace)
{ {
ui->setupUi(this); ui->setupUi(this);
} }
ParameterWorkspace::~ParameterWorkspace() ParameterWorkspace::~ParameterWorkspace()
{ {
delete ui; delete ui;
} }
// QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404"));
// auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr);
void ParameterWorkspace::setDeviceCount(int count) void ParameterWorkspace::setDeviceCount(int count)
{ {
for(const auto& device : deviceList) for(const auto& device : deviceList) {
{
device.tab->deleteLater(); device.tab->deleteLater();
device.device->deleteLater(); device.device->deleteLater();
} }
deviceList.clear(); deviceList.clear();
for(int i = 0; i < ui->tabWidget->count(); i++) for(int i = 0; i < ui->tabWidget->count(); i++)
ui->tabWidget->removeTab(i); ui->tabWidget->removeTab(i);
for(int i = 0; i < count; i++) for(int i = 0; i < count; i++) {
{
device* _device = new device(); device* _device = new device();
deviceList.append(*_device); deviceList.append(*_device);
deviceList[i].device = new ParameterDevice(); deviceList[i].device = new ParameterDevice();
int newtab = ui->tabWidget->addTab(deviceList[i].device, tr("Device №%1").arg(i+1)); int newtab = ui->tabWidget->addTab(deviceList[i].device, tr("Device №%1").arg(i+1));
deviceList[i].tab = ui->tabWidget->widget(newtab); 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); 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); 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); writeSingleRegister(deviceList[i].adr, registerAddress, value);
}); });
} }
@@ -51,18 +50,16 @@ void ParameterWorkspace::writeSingleCoil(int adr, int coilAddress, bool value)
QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1); QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1);
unit.setValue(0, value ? 1 : 0); unit.setValue(0, value ? 1 : 0);
if(auto *reply = modbusDevice->sendWriteRequest(unit, adr)) { if(auto *reply = modbusDevice->sendWriteRequest(unit, adr)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [this, reply]() { connect(reply, &QModbusReply::finished, this, [reply]() {
if (reply->error() != QModbusDevice::NoError) { if(reply->error() != QModbusDevice::NoError)
//ERROR {/*ERROR*/}
}
reply->deleteLater(); reply->deleteLater();
}); });
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} }
}
void ParameterWorkspace::writeSingleRegister(int adr, int regAddress, quint16 value) void ParameterWorkspace::writeSingleRegister(int adr, int regAddress, quint16 value)
{ {
@@ -71,50 +68,40 @@ void ParameterWorkspace::writeSingleRegister(int adr, int regAddress, quint16 va
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, regAddress, 1); QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, regAddress, 1);
unit.setValue(0, value); unit.setValue(0, value);
if(auto *reply = modbusDevice->sendWriteRequest(unit, adr)) { if(auto *reply = modbusDevice->sendWriteRequest(unit, adr)) {
if (!reply->isFinished()) { if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [this, reply]() { connect(reply, &QModbusReply::finished, this, [reply]() {
if (reply->error() != QModbusDevice::NoError) { if(reply->error() != QModbusDevice::NoError)
//ERROR {/*ERROR*/}
}
reply->deleteLater(); reply->deleteLater();
}); });
} else { else
reply->deleteLater(); reply->deleteLater();
} }
} }
}
void ParameterWorkspace::readDeviceIdentification(ParameterDevice *device, QModbusRequest request, int adr, quint16 objectID) void ParameterWorkspace::readDeviceIdentification(ParameterDevice *device, QModbusRequest request, int adr, quint16 objectID)
{ {
if(!modbusDevice && modbusDevice->state() == QModbusDevice::ConnectedState) if(!modbusDevice && modbusDevice->state() == QModbusDevice::ConnectedState)
return; return;
if(auto *reply = modbusDevice->sendRawRequest(request, adr)) if(auto *reply = modbusDevice->sendRawRequest(request, adr)) {
{
if(!reply->isFinished()) { if(!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, device, reply, objectID](){ connect(reply, &QModbusReply::finished, this, [device, reply, objectID](){
if(reply->error() == QModbusDevice::NoError) if(reply->error() == QModbusDevice::NoError) {
{
QModbusResponse resp = reply->rawResult(); 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)); QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH));
device->setAnswer(result, objectID); device->setAnswer(result, objectID);
} }
} } else {
else
{
device->setError(reply->errorString()); device->setError(reply->errorString());
qDebug()<<"Получен ответ:" + reply->errorString(); qDebug()<<"Получен ответ:" + reply->errorString();
} }
reply->deleteLater(); reply->deleteLater();
}); });
} }
} } else
else
{
device->setError("Unknow error"); device->setError("Unknow error");
} }
}
void ParameterWorkspace::updateDevice(int ID, bool status, int adr) void ParameterWorkspace::updateDevice(int ID, bool status, int adr)
{ {

View File

@@ -24,7 +24,6 @@ class ParameterWorkspace;
class ParameterWorkspace : public QWidget class ParameterWorkspace : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ParameterWorkspace(QWidget *parent = nullptr); explicit ParameterWorkspace(QWidget *parent = nullptr);
~ParameterWorkspace(); ~ParameterWorkspace();
@@ -32,12 +31,10 @@ public:
void setModbusClient(QModbusClient *device){modbusDevice = device;} void setModbusClient(QModbusClient *device){modbusDevice = device;}
void setDeviceCount(int count); void setDeviceCount(int count);
void updateDevice(int deviceID, bool status, int adr); void updateDevice(int deviceID, bool status, int adr);
private slots: private slots:
void readDeviceIdentification(ParameterDevice *board, QModbusRequest request, int adr, quint16 objectID); void readDeviceIdentification(ParameterDevice *board, QModbusRequest request, int adr, quint16 objectID);
void writeSingleCoil(int adr, int coilAddress, bool value); void writeSingleCoil(int adr, int coilAddress, bool value);
void writeSingleRegister(int adr, int registerAddress, quint16 value); void writeSingleRegister(int adr, int registerAddress, quint16 value);
private: private:
struct device{ struct device{
bool isActive = false; bool isActive = false;

View File

@@ -14,19 +14,15 @@ class ScanBoard : public QDialog
public: public:
explicit ScanBoard(QWidget *parent = nullptr); explicit ScanBoard(QWidget *parent = nullptr);
~ScanBoard(); ~ScanBoard();
Qt::CheckState getCheckState(); Qt::CheckState getCheckState();
void showMeTheTruth(QString resultOfScan); void showMeTheTruth(QString resultOfScan);
quint16 getBaud(); quint16 getBaud();
private slots: private slots:
void on_applyToAllBox_stateChanged(int arg1); void on_applyToAllBox_stateChanged(int arg1);
void on_baudRateBox_currentTextChanged(const QString &arg1); void on_baudRateBox_currentTextChanged(const QString &arg1);
private: private:
Qt::CheckState checkState; Qt::CheckState checkState;
quint16 baud; quint16 baud;
Ui::ScanBoard *ui; Ui::ScanBoard *ui;
}; };

View File

@@ -50,12 +50,11 @@ int SettingsDialog::UpdateBaud(int baud)
int SettingsDialog::UpdateParity(int parity) int SettingsDialog::UpdateParity(int parity)
{ {
ui->parityCombo->setCurrentIndex(parity); ui->parityCombo->setCurrentIndex(parity);
if(parity>0) { if(parity > 0)
return (m_settings.parity = ++parity); return (m_settings.parity = ++parity);
} else { else
return (m_settings.parity = parity); return (m_settings.parity = parity);
} }
}
int SettingsDialog::curBaud() int SettingsDialog::curBaud()
{ {
@@ -71,7 +70,6 @@ void SettingsDialog::on_updateComBox_clicked()
{ {
ui->comBox->clear(); ui->comBox->clear();
const auto listPorts = QSerialPortInfo::availablePorts(); 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->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName()));
} }
}

View File

@@ -27,20 +27,15 @@ public:
int responseTime = 1000; int responseTime = 1000;
int numberOfRetries = 0; int numberOfRetries = 0;
}; };
explicit SettingsDialog(QWidget *parent = nullptr); explicit SettingsDialog(QWidget *parent = nullptr);
~SettingsDialog(); ~SettingsDialog();
Settings settings() const; Settings settings() const;
int UpdateBaud(int baud); int UpdateBaud(int baud);
int UpdateParity(int parity); int UpdateParity(int parity);
int curBaud(); int curBaud();
int curParity(); int curParity();
private slots: private slots:
void on_updateComBox_clicked(); void on_updateComBox_clicked();
private: private:
Settings m_settings; Settings m_settings;
Ui::SettingsDialog *ui; Ui::SettingsDialog *ui;

View File

@@ -1,7 +1,5 @@
#include "writeregistermodel.h" #include "writeregistermodel.h"
#include "writeregistermodel.h"
enum { NumColumn = 0, NameColumn = 1, CoilsColumn = 2, HoldingColumn = 3, ColumnCount = 5, CurrentUColumn = 4}; enum { NumColumn = 0, NameColumn = 1, CoilsColumn = 2, HoldingColumn = 3, ColumnCount = 5, CurrentUColumn = 4};
WriteRegisterModel::WriteRegisterModel(QObject *parent, int _tmpRC, bool _isHR) WriteRegisterModel::WriteRegisterModel(QObject *parent, int _tmpRC, bool _isHR)
@@ -103,13 +101,11 @@ Qt::ItemFlags WriteRegisterModel::flags(const QModelIndex &index) const
void WriteRegisterModel::setStartAddress(int address) void WriteRegisterModel::setStartAddress(int address)
{ {
m_address = address; m_address = address;
//emit updateViewport();
} }
void WriteRegisterModel::setNumberOfValues(const QString &number) void WriteRegisterModel::setNumberOfValues(const QString &number)
{ {
m_number = number.toInt(); m_number = number.toInt();
//emit updateViewport();
} }
bool WriteRegisterModel::get_coil(const QModelIndex &index) bool WriteRegisterModel::get_coil(const QModelIndex &index)

View File

@@ -14,25 +14,18 @@ public:
WriteRegisterModel(QObject *parent = nullptr, int _tmpRC = 85, bool _isHR = false); WriteRegisterModel(QObject *parent = nullptr, int _tmpRC = 85, bool _isHR = false);
bool get_coil(const QModelIndex &index); bool get_coil(const QModelIndex &index);
uint get_holreg(const QModelIndex &index); uint get_holreg(const QModelIndex &index);
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(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 data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool setData(const QModelIndex &index, const QVariant &value, int role) override;
Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;
bool set_currentU(unsigned _tmpU, unsigned index); bool set_currentU(unsigned _tmpU, unsigned index);
public slots: public slots:
void setStartAddress(int address); void setStartAddress(int address);
void setNumberOfValues(const QString &number); void setNumberOfValues(const QString &number);
signals: signals:
void updateViewport(); void updateViewport();
public: public:
int m_number = 0; int m_number = 0;
int m_address = 0; int m_address = 0;