17 Commits

Author SHA1 Message Date
Вячеслав Штейбезандт
9071eb4322 Обновление списка ошибок 2025-10-16 09:56:36 +03:00
Вячеслав Штейбезандт
227deaf686 Исправление ошибки диапазона для записи уставок на четвёртой плате. 2025-10-16 09:23:18 +03:00
Вячеслав Штейбезандт
4ec595d92e Таймаут во время поиска плат снижен до 50 мс. 2025-10-16 09:20:54 +03:00
Вячеслав Штейбезандт
a9f3d13b5f Обновление отображения значений регистров с HEX на значения порогов.
Для быстроты ввода дробной части новые значения записывать с учётом последующего деления на 1000. (Ввод 500, Запись 0.500)
2025-10-16 09:11:58 +03:00
Вячеслав Штейбезандт
5ae694d254 Обновление алгоритма для корректного опроса четвёртой платы. 2025-10-16 08:41:49 +03:00
Вячеслав Штейбезандт
c2a32e3ff5 Добавлено отслеживание ошибок на платах в режиме отладки. 2025-10-16 08:39:30 +03:00
Вячеслав Штейбезандт
1e3ecd0834 график ацп выведен в отдельное меню и отвязан от конкретной борды 2025-10-10 18:30:40 +03:00
Вячеслав Штейбезандт
5b3faa798b фиксы графика и статической компиляции 2025-10-09 18:30:27 +03:00
Вячеслав Штейбезандт
93b4a24b8b добавлена вклада для отладочных функций
note: крашится в static компиле
2025-10-09 12:05:20 +03:00
Вячеслав Штейбезандт
4ae15d8c01 добавлен локальный статус для каждого мзктэ 2025-10-08 18:47:23 +03:00
Вячеслав Штейбезандт
190f3337ed убрана остановка опроса при ошибке платы 2025-10-08 11:31:13 +03:00
Вячеслав Штейбезандт
726d8d24ef новый алг иправлен
+ исправлен нахождение плат с костылем
+ исправлен вылет приложения при опросе 4 платы (из-за того, что в ней 65, а не 85 регистров) сделал чтобы везде было 85, просто отображатся будет 65
2025-10-08 11:11:12 +03:00
Вячеслав Штейбезандт
c9b44e5dab Изменение обработки ошибок и вывода записи в лог 2025-09-22 12:40:36 +03:00
Вячеслав Штейбезандт
14d7907d92 Отмена отслеживания папок Debug и Release 2025-09-15 13:10:16 +03:00
Вячеслав Штейбезандт
b4803e19e2 Алгоритм изменения скорости обмена данными с платами. Пока без вывода ошибок в лог. 2025-09-15 13:07:14 +03:00
Вячеслав Штейбезандт
d9f58e72e4 Обновление алгоритма смены скорости обмена - промежуточный коммит 2025-09-10 16:42:25 +03:00
Вячеслав Штейбезандт
a4cdcb7091 Снапшот перед обновлением алгоритма смены скоростей на платах 2025-09-09 16:48:21 +03:00
25 changed files with 12161 additions and 9383 deletions

3
.gitignore vendored
View File

@@ -54,3 +54,6 @@ compile_commands.json
*_qmlcache.qrc *_qmlcache.qrc
/Debug
/Release

Binary file not shown.

View File

@@ -5,7 +5,7 @@ QT += serialbus widgets
requires(qtConfig(combobox)) requires(qtConfig(combobox))
QT += serialport QT += serialport
qtConfig(modbus-serialport): QT += serialport qtConfig(modbus-serialport): QT += serialport
QT += charts
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11 CONFIG += c++11
@@ -16,8 +16,8 @@ CONFIG += c++11
# deprecated API in order to know how to port your code away from it. # deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS DEFINES += QT_DEPRECATED_WARNINGS
TEMPLATE = lib #TEMPLATE = lib
DEFINES += M3KTE_LIBRARY #DEFINES += M3KTE_LIBRARY
# You can also make your code fail to compile if it uses deprecated APIs. # You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line. # In order to do so, uncomment the following line.
@@ -25,6 +25,8 @@ DEFINES += M3KTE_LIBRARY
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \ SOURCES += \
adcgraphdialog.cpp \
debugterminaldialog.cpp \
devicesettingsdialog.cpp \ devicesettingsdialog.cpp \
lineringer.cpp \ lineringer.cpp \
main.cpp \ main.cpp \
@@ -35,6 +37,8 @@ SOURCES += \
writeregistermodel.cpp writeregistermodel.cpp
HEADERS += \ HEADERS += \
adcgraphdialog.h \
debugterminaldialog.h \
devicesettingsdialog.h \ devicesettingsdialog.h \
lineringer.h \ lineringer.h \
m3kte.h \ m3kte.h \
@@ -44,6 +48,8 @@ HEADERS += \
writeregistermodel.h writeregistermodel.h
FORMS += \ FORMS += \
adcgraphdialog.ui \
debugTerminalDialog.ui \
devicesettingsdialog.ui \ devicesettingsdialog.ui \
lineringer.ui \ lineringer.ui \
m3kte.ui \ m3kte.ui \
@@ -52,11 +58,11 @@ FORMS += \
settingsdialog.ui settingsdialog.ui
# Default rules for deployment. # Default rules for deployment.
#qnx: target.path = /tmp/$${TARGET}/bin qnx: target.path = /tmp/$${TARGET}/bin
#else: unix:!android: target.path = /opt/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin
#!isEmpty(target.path): INSTALLS += target
unix {
target.path = /usr/lib
}
!isEmpty(target.path): INSTALLS += target !isEmpty(target.path): INSTALLS += target
#unix {
# target.path = /usr/lib
#}
#!isEmpty(target.path): INSTALLS += target

View File

@@ -0,0 +1,581 @@
#include "adcgraphdialog.h"
#include "ui_adcgraphdialog.h"
#include <QModbusReply>
#include <QDebug>
#include <QMessageBox>
#include <QValueAxis>
#include <QVBoxLayout> // Добавить этот include
#include <QChartView> // Добавить этот include
// Адреса регистров для АЦП
#define REG_ADC_ZERO 555
#define REG_ADC_ONE_VOLT 556
#define REG_STABLE_START 557
#define REG_STABLE_END 558
#define REG_TE_NUMBER 564
#define REG_ADC_BUFFER_START 571
#define REG_ADC_BUFFER_END 1070
AdcGraphDialog::AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent) :
QDialog(parent),
ui(new Ui::AdcGraphDialog),
m_modbusDevice(modbusDevice),
m_updateTimer(new QTimer(this)),
m_boardId(-1),
m_boardAddress(-1),
m_teNumber(-1),
m_adcZero(0),
m_adcOneVolt(4096),
m_series(new QLineSeries()),
m_chart(new QChart()),
m_stableStartLine(new QLineSeries()),
m_stableEndLine(new QLineSeries()),
m_stableStartIndex(-1),
m_stableEndIndex(-1),
m_startAddress(0),
m_registerCount(100)
{
ui->setupUi(this);
// Настройка основного графика
m_series->setName("АЦП данные");
m_chart->addSeries(m_series);
// Настройка линий стабильного участка
m_stableStartLine->setName("Начало стаб. участка");
m_stableStartLine->setColor(Qt::red);
m_stableStartLine->setPen(QPen(Qt::red, 2, Qt::DashLine));
m_chart->addSeries(m_stableStartLine);
m_stableEndLine->setName("Конец стаб. участка");
m_stableEndLine->setColor(Qt::green);
m_stableEndLine->setPen(QPen(Qt::green, 2, Qt::DashLine));
m_chart->addSeries(m_stableEndLine);
m_chart->setTitle("График АЦП");
m_chart->legend()->setVisible(true);
m_chart->legend()->setAlignment(Qt::AlignTop);
m_axisX = new QValueAxis();
m_axisX->setTitleText("Отсчеты АЦП");
m_axisX->setRange(0, m_registerCount);
m_chart->addAxis(m_axisX, Qt::AlignBottom);
m_series->attachAxis(m_axisX);
m_stableStartLine->attachAxis(m_axisX);
m_stableEndLine->attachAxis(m_axisX);
m_axisY = new QValueAxis();
m_axisY->setTitleText("Напряжение, В");
m_axisY->setRange(-1.3, 1.3);
m_chart->addAxis(m_axisY, Qt::AlignLeft);
m_series->attachAxis(m_axisY);
m_stableStartLine->attachAxis(m_axisY);
m_stableEndLine->attachAxis(m_axisY);
QChartView *chartView = new QChartView(m_chart);
chartView->setRenderHint(QPainter::Antialiasing);
QVBoxLayout *layout = new QVBoxLayout(ui->plotWidget);
layout->addWidget(chartView);
// Подключаем сигналы элементов управления диапазоном
connect(ui->registerCountSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &AdcGraphDialog::on_registerCountChanged);
connect(ui->rangeApplyButton, &QPushButton::clicked,
this, &AdcGraphDialog::on_rangeApplyClicked);
connect(ui->teNumberSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &AdcGraphDialog::on_teNumberChanged);
connect(m_updateTimer, &QTimer::timeout, this, &AdcGraphDialog::onUpdateTimer);
connect(ui->closeBtn, &QPushButton::clicked, this, &AdcGraphDialog::on_closeBtn_clicked);
}
AdcGraphDialog::~AdcGraphDialog()
{
stopGraph();
delete ui;
}
void AdcGraphDialog::setModbusDevice(QModbusClient *device)
{
m_modbusDevice = device;
}
void AdcGraphDialog::on_teNumberChanged(int value)
{
if(m_teNumber != value)
setTENumber(m_boardId, value);
}
void AdcGraphDialog::setTENumber(int boardID, int teNumber)
{
if (m_boardAddress == -1) return;
m_teNumber = teNumber;
m_boardId = boardID;
m_boardAddress = m_boardId + 1;
// Обновляем заголовок окна
setWindowTitle(QString("График АЦП - Плата %1, ТЭ %2 (адр %3-%4)")
.arg(m_boardId + 1)
.arg(m_teNumber)
.arg(m_startAddress)
.arg(m_startAddress + m_registerCount - 1));
// Записываем новый номер ТЭ в устройство
if (m_modbusDevice) {
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, REG_TE_NUMBER, 1);
unit.setValue(0, teNumber);
if (auto *reply = m_modbusDevice->sendWriteRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, reply, teNumber]() {
if (reply->error() == QModbusDevice::NoError) {
qDebug() << "TE number changed to:" << teNumber;
// Можно обновить данные сразу после смены ТЭ
readAdcDataAndIndices();
} else {
qDebug() << "Error writing TE number:" << reply->errorString();
}
reply->deleteLater();
});
} else {
reply->deleteLater();
}
}
}
ui->teNumberSpinBox->setValue(teNumber);
}
void AdcGraphDialog::readCalibrationValues()
{
if (!m_modbusDevice || m_boardAddress == -1) return;
// Читаем калибровочные значения (регистры 555 и 556)
QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_ADC_ZERO, 2);
if (auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, reply]() {
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit result = reply->result();
if (result.valueCount() >= 2) {
m_adcZero = result.value(0);
m_adcOneVolt = result.value(1);
//qDebug() << "Calibration values - Zero:" << m_adcZero << "1V:" << m_adcOneVolt;
}
} else {
//qDebug() << "Error reading calibration:" << reply->errorString();
}
reply->deleteLater();
});
} else {
reply->deleteLater();
}
}
}
void AdcGraphDialog::readStableIndices()
{
if (!m_modbusDevice || m_boardAddress == -1) return;
// Читаем индексы стабильного участка (регистры 557 и 558)
QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_STABLE_START, 2);
if (auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onStableIndicesReady);
} else {
reply->deleteLater();
}
}
}
void AdcGraphDialog::onStableIndicesReady()
{
auto *reply = qobject_cast<QModbusReply*>(sender());
if (!reply) return;
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit result = reply->result();
if (result.valueCount() >= 2) {
m_stableStartIndex = result.value(0);
m_stableEndIndex = result.value(1);
//qDebug() << "Stable indices updated - Start:" << m_stableStartIndex << "End:" << m_stableEndIndex;
updateStableLines();
// Обновляем статистику с новыми индексами
updateStatisticsWithStableInfo();
}
} else {
//qDebug() << "Error reading stable indices:" << reply->errorString();
}
reply->deleteLater();
}
void AdcGraphDialog::updateStatistics()
{
if (m_series->count() > 0) {
double min = 1000, max = -1000, sum = 0;
for (const QPointF &point : m_series->points()) {
double y = point.y();
if (y < min) min = y;
if (y > max) max = y;
sum += y;
}
double avg = sum / m_series->count();
ui->minLabel->setText(QString::number(min, 'f', 3) + " В");
ui->maxLabel->setText(QString::number(max, 'f', 3) + " В");
ui->avgLabel->setText(QString::number(avg, 'f', 3) + " В");
// Обновляем информацию о стабильном участке
updateStatisticsWithStableInfo();
}
}
void AdcGraphDialog::updateStatisticsWithStableInfo()
{
if (m_series->count() > 0) {
// Используем абсолютные индексы в формате "начальный-конечный"
ui->samplesLabel->setText(
QString("%1 отсч. (адр %2-%3) [стаб: %4-%5]")
.arg(m_series->count())
.arg(m_startAddress)
.arg(m_startAddress + m_registerCount - 1)
.arg(m_stableStartIndex) // Абсолютный начальный индекс
.arg(m_stableEndIndex) // Абсолютный конечный индекс
);
}
}
void AdcGraphDialog::updateStableLines()
{
// Очищаем предыдущие линии
m_stableStartLine->clear();
m_stableEndLine->clear();
// Получаем текущий диапазон оси Y
double yMin = m_axisY->min();
double yMax = m_axisY->max();
// Добавляем вертикальную линию для начала стабильного участка
// Учитываем текущий диапазон отображения
if (m_stableStartIndex >= m_startAddress && m_stableStartIndex < m_startAddress + m_registerCount) {
int relativeStartIndex = m_stableStartIndex - m_startAddress;
m_stableStartLine->append(relativeStartIndex, yMin);
m_stableStartLine->append(relativeStartIndex, yMax);
}
// Добавляем вертикальную линию для конца стабильного участка
if (m_stableEndIndex >= m_startAddress && m_stableEndIndex < m_startAddress + m_registerCount) {
int relativeEndIndex = m_stableEndIndex - m_startAddress;
m_stableEndLine->append(relativeEndIndex, yMin);
m_stableEndLine->append(relativeEndIndex, yMax);
}
}
void AdcGraphDialog::updateGraphRange()
{
// Обновляем диапазон оси X
m_axisX->setRange(0, m_registerCount);
m_axisX->setTitleText(QString("Отсчеты АЦП (%1-%2)").arg(m_startAddress).arg(m_startAddress + m_registerCount - 1));
// Сбрасываем ось Y к разумному диапазону по умолчанию
m_axisY->setRange(-1.2, 1.2);
// Обновляем линии стабильного участка с учетом нового диапазона
updateStableLines();
}
void AdcGraphDialog::readAdcDataAndIndices()
{
if (!m_modbusDevice || m_boardAddress == -1) return;
// Создаем один запрос для данных АЦП + индексов стабильности
// Адреса: данные АЦП (571+), индексы (557-558)
int start = m_startAddress + REG_ADC_BUFFER_START;
int count = m_registerCount;
// Читаем индексы стабильности (557-558) и данные АЦП одним запросом
QModbusDataUnit unit(QModbusDataUnit::InputRegisters, REG_STABLE_START,
count + (start - REG_STABLE_START));
//qDebug() << "Reading combined data from address" << REG_STABLE_START << "count:" << unit.valueCount();
if (auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onCombinedDataReady);
} else {
reply->deleteLater();
}
} else {
//qDebug() << "Failed to send combined data read request";
}
}
void AdcGraphDialog::onCombinedDataReady()
{
auto *reply = qobject_cast<QModbusReply*>(sender());
if (!reply) return;
if((m_adcZero == 0) || (m_adcOneVolt == 0))
{
readCalibrationValues();
return;
}
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit result = reply->result();
// Обрабатываем индексы стабильности (первые 2 регистра)
if (result.valueCount() >= 2) {
m_stableStartIndex = result.value(0);
m_stableEndIndex = result.value(1);
//qDebug() << "Stable indices - Start:" << m_stableStartIndex << "End:" << m_stableEndIndex;
}
// Обрабатываем данные АЦП (остальные регистры)
int adcDataStartIndex = (m_startAddress + REG_ADC_BUFFER_START) - REG_STABLE_START;
// Очищаем предыдущие данные
m_series->clear();
// Добавляем новые точки и определяем диапазон
double minVoltage = 1000, maxVoltage = -1000;
for (int i = 0; i < m_registerCount; ++i) {
if (adcDataStartIndex + i < result.valueCount()) {
double voltage = convertAdcToVoltage(result.value(adcDataStartIndex + i));
m_series->append(i, voltage);
// Обновляем мин/макс для автоматического масштабирования
if (voltage < minVoltage) minVoltage = voltage;
if (voltage > maxVoltage) maxVoltage = voltage;
}
}
// Обновляем график и статистику
updateYAxisRange(minVoltage, maxVoltage);
updateStableLines();
updateStatistics();
} else {
// qDebug() << "Error reading combined data:" << reply->errorString();
}
reply->deleteLater();
}
void AdcGraphDialog::readAdcBuffer()
{
if (!m_modbusDevice || m_boardAddress == -1) return;
// Читаем выбранный диапазон буфера АЦП
QModbusDataUnit unit(QModbusDataUnit::InputRegisters, m_startAddress+REG_ADC_BUFFER_START, m_registerCount);
// qDebug() << "Reading ADC buffer from address" << m_startAddress << "count:" << m_registerCount;
if (auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onReadReady);
} else {
reply->deleteLater();
}
} else {
// qDebug() << "Failed to send ADC buffer read request";
}
}
void AdcGraphDialog::startGraph(int boardId, int teNumber)
{
m_boardId = boardId;
m_teNumber = teNumber;
m_boardAddress = boardId + 1;
// Устанавливаем начальное значение в спинбокс
ui->teNumberSpinBox->setValue(teNumber);
setWindowTitle(QString("График АЦП - Плата %1, ТЭ %2 (адр %3-%4)")
.arg(boardId + 1)
.arg(teNumber)
.arg(m_startAddress)
.arg(m_startAddress + m_registerCount - 1));
// Очищаем предыдущие данные
m_series->clear();
m_stableStartLine->clear();
m_stableEndLine->clear();
// Обновляем диапазон графика
updateGraphRange();
readCalibrationValues();
// Записываем начальный номер ТЭ
setTENumber(m_boardAddress, teNumber);
m_updateTimer->start(m_timeout);
}
void AdcGraphDialog::setTimeout(int timeout)
{
m_timeout = timeout;
}
void AdcGraphDialog::stopGraph()
{
m_updateTimer->stop();
m_boardId = -1;
m_boardAddress = -1;
// Отменяем все pending запросы Modbus
if (m_modbusDevice) {
m_modbusDevice->disconnect(this); // Отключаем все сигналы
}
}
void AdcGraphDialog::onUpdateTimer()
{
if (m_boardAddress == -1) return;
// Читаем и буфер АЦП, и индексы стабильности каждый период
readAdcDataAndIndices();
}
void AdcGraphDialog::onReadReady()
{
auto *reply = qobject_cast<QModbusReply*>(sender());
if (!reply) return;
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit result = reply->result();
// Очищаем предыдущие данные
m_series->clear();
// Добавляем новые точки и определяем диапазон
double minVoltage = 1000, maxVoltage = -1000;
for (int i = 0; i < result.valueCount(); ++i) {
double voltage = convertAdcToVoltage(result.value(i));
m_series->append(i, voltage);
// Обновляем мин/макс для автоматического масштабирования
if (voltage < minVoltage) minVoltage = voltage;
if (voltage > maxVoltage) maxVoltage = voltage;
}
// Автоматически настраиваем диапазон оси Y
updateYAxisRange(minVoltage, maxVoltage);
// Обновляем линии стабильного участка
updateStableLines();
// Обновляем статистику
if (m_series->count() > 0) {
double min = 1000, max = -1000, sum = 0;
for (const QPointF &point : m_series->points()) {
double y = point.y();
if (y < min) min = y;
if (y > max) max = y;
sum += y;
}
double avg = sum / m_series->count();
ui->minLabel->setText(QString::number(min, 'f', 3) + " В");
ui->maxLabel->setText(QString::number(max, 'f', 3) + " В");
ui->avgLabel->setText(QString::number(avg, 'f', 3) + " В");
// Обновляем информацию о стабильном участке
updateStatisticsWithStableInfo();
}
} else {
// qDebug() << "Error reading ADC buffer:" << reply->errorString();
}
reply->deleteLater();
}
void AdcGraphDialog::updateYAxisRange(double minVoltage, double maxVoltage)
{
// Добавляем запас 10% к диапазону
double range = maxVoltage - minVoltage;
double margin = range * 0.1;
double yMin = minVoltage - margin;
double yMax = maxVoltage + margin;
// Если диапазон слишком маленький или слишком большой, устанавливаем разумные пределы
// if ((range < 0.1) || ((maxVoltage > 0.5) && (minVoltage < -0.5)))
// {
// yMin = -1.5;
// yMax = 1.5;
// }
// else if(maxVoltage > 0.5) {
// yMin = -0.1;
// yMax = 1.5;
// }
// else if(minVoltage < -0.5)
// {
// yMin = -1.5;
// yMax =0.1;
// }
// else
{
yMin = -1.5;
yMax = 1.5;
}
// Ограничиваем разумными пределами
yMin = qMax(yMin, -5.0); // Не ниже -5В
yMax = qMin(yMax, 5.0); // Не выше 5В
// Устанавливаем новый диапазон
m_axisY->setRange(yMin, yMax);
// Обновляем линии стабильного участка с новым диапазоном
updateStableLines();
}
double AdcGraphDialog::convertAdcToVoltage(quint16 adcValue)
{
if (m_adcOneVolt == m_adcZero) return 0;
return (adcValue - m_adcZero) * 1.1 / (m_adcOneVolt - m_adcZero);
}
void AdcGraphDialog::on_registerCountChanged(int value)
{
m_registerCount = value;
// qDebug() << "Register count changed to:" << value;
}
void AdcGraphDialog::on_rangeApplyClicked()
{
// qDebug() << "Applying new range - Start:" << m_startAddress << "Count:" << m_registerCount;
updateGraphRange();
// Немедленно обновляем данные
if (m_boardAddress != -1) {
readAdcBuffer();
}
}
void AdcGraphDialog::on_closeBtn_clicked()
{
stopGraph();
reject(); // Или accept() в зависимости от логики
}

View File

@@ -0,0 +1,97 @@
#ifndef ADCGRAPHDIALOG_H
#define ADCGRAPHDIALOG_H
#include <QDialog>
#include <QTimer>
#include <QVector>
#include <QtCharts>
#include <QModbusClient>
QT_CHARTS_USE_NAMESPACE
// Forward declaration
class QModbusClient;
namespace Ui {
class AdcGraphDialog;
}
class AdcGraphDialog : public QDialog
{
Q_OBJECT
public:
explicit AdcGraphDialog(QModbusClient *modbusDevice, QWidget *parent = nullptr);
~AdcGraphDialog();
void setTENumber(int boardID, int teNumber);
void setModbusDevice(QModbusClient *device);
void startGraph(int boardId, int teNumber);
void stopGraph();
void setTimeout(int timeout);
void readyClose();
signals:
void dialogClosed();
protected:
void closeEvent(QCloseEvent *event) override {
stopGraph();
event->accept();
emit dialogClosed();
QDialog::closeEvent(event);
}
private slots:
void on_teNumberChanged(int value);
void onUpdateTimer();
void onReadReady();
void onStableIndicesReady();
void on_closeBtn_clicked();
void on_registerCountChanged(int value);
void on_rangeApplyClicked();
private:
Ui::AdcGraphDialog *ui;
QModbusClient *m_modbusDevice;
QTimer *m_updateTimer;
int m_boardId;
int m_boardAddress;
int m_teNumber;
int m_timeout;
// Калибровочные значения
double m_adcZero;
double m_adcOneVolt;
// Для отображения стабильного участка
QLineSeries *m_stableStartLine;
QLineSeries *m_stableEndLine;
int m_stableStartIndex;
int m_stableEndIndex;
// Данные графика
QLineSeries *m_series;
QValueAxis *m_axisX;
QValueAxis *m_axisY;
QChart *m_chart; // Добавить указатель на chart
// Управление диапазоном регистров
int m_startAddress;
int m_registerCount;
void updateStatistics();
void readAdcDataAndIndices();
void onCombinedDataReady();
void updateStatisticsWithStableInfo();
void updateYAxisRange(double minVoltage, double maxVoltage);
void setupRangeControls();
void updateGraphRange();
void readStableIndices();
void updateStableLines();
void readCalibrationValues();
void readAdcBuffer();
double convertAdcToVoltage(quint16 adcValue);
};
#endif // ADCGRAPHDIALOG_H

View File

@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AdcGraphDialog</class>
<widget class="QDialog" name="AdcGraphDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>График АЦП</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="rangeLayout">
<item>
<widget class="QLabel" name="registerCountLabel">
<property name="text">
<string>Количество:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="registerCountSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="rangeApplyButton">
<property name="text">
<string>Применить</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Номер ТЭ</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="teNumberSpinBox">
<property name="maximum">
<number>85</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="plotWidget" native="true"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Мин:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="minLabel">
<property name="text">
<string>0.000 В</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Макс:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="maxLabel">
<property name="text">
<string>0.000 В</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Средн:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="avgLabel">
<property name="text">
<string>0.000 В</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Сэмплов:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="samplesLabel">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="closeBtn">
<property name="text">
<string>Закрыть</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,796 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DebugTerminalDialog</class>
<widget class="QDialog" name="DebugTerminalDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1188</width>
<height>578</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="0" colspan="4">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="DbgPlate_4">
<property name="title">
<string>Плата 3</string>
</property>
<layout class="QGridLayout" name="gridLayout_25">
<item row="3" column="0">
<widget class="QGroupBox" name="leds_3">
<property name="title">
<string>Тест светодиодов</string>
</property>
<layout class="QGridLayout" name="gridLayout_13">
<item row="0" column="0">
<widget class="QCheckBox" name="ledWorkTestChkBox_3">
<property name="text">
<string>Работа</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ledWarnTestChkBox_3">
<property name="text">
<string>Предупреждение</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="ledErrTestChkBox_3">
<property name="text">
<string>Авария</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="ledConnectTestChkBox_3">
<property name="text">
<string>Связь</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="ledVH1TestChkBox_3">
<property name="text">
<string>LED VH1 (Зеленый)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="ledVH2TestChkBox_3">
<property name="text">
<string>LED VH2 (Зеленый)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="ledVH3TestChkBox_3">
<property name="text">
<string>LED VH3 (Красный)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="enableLedTestChkBox_3">
<property name="text">
<string>Тест ламп и дискретных сигналов</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_11">
<property name="title">
<string>Вызов функций</string>
</property>
<layout class="QGridLayout" name="gridLayout_11">
<item row="2" column="0">
<widget class="QCheckBox" name="pollTECallChkBox_3">
<property name="text">
<string>Опрос ТЭ</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="continiusCallChkBox_3">
<property name="text">
<string>Непрерывный вызов калибр. и опроса</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="calibrateCallChkBox_3">
<property name="text">
<string>Калибровка</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="getHardfaultCallChkBox_3">
<property name="text">
<string>Генерация HardFault</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="resetDefaultCallChkBox_3">
<property name="text">
<string>Настройки по умолчанию</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="resetKeyCallChkBox_3">
<property name="text">
<string>Сбросить все ключи</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="discs_3">
<property name="title">
<string>Тест дискретных сигналов</string>
</property>
<layout class="QGridLayout" name="gridLayout_12">
<item row="2" column="0">
<widget class="QCheckBox" name="discErrTestChkBox_3">
<property name="text">
<string>Авария</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="discErr5VsciTestChkBox_3">
<property name="text">
<string>Ошибка 5 Vsci</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="discWarnTestChkBox_3">
<property name="text">
<string>Предупреждение</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="discWorkTestChkBox_3">
<property name="text">
<string>Работа</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="discErr5TestChkBox_3">
<property name="text">
<string>Ошибка 5 В</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="discErr24TestChkBox_3">
<property name="text">
<string>Ошибка 24 В</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="discErr5VATestChkBox_3">
<property name="text">
<string>Ошибка 5 VA</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="DbgPlate_3">
<property name="title">
<string>Плата 2</string>
</property>
<layout class="QGridLayout" name="gridLayout_24">
<item row="3" column="0">
<widget class="QGroupBox" name="leds_2">
<property name="title">
<string>Тест светодиодов</string>
</property>
<layout class="QGridLayout" name="gridLayout_21">
<item row="0" column="0">
<widget class="QCheckBox" name="ledWorkTestChkBox_2">
<property name="text">
<string>Работа</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ledWarnTestChkBox_2">
<property name="text">
<string>Предупреждение</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="ledErrTestChkBox_2">
<property name="text">
<string>Авария</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="ledConnectTestChkBox_2">
<property name="text">
<string>Связь</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="ledVH1TestChkBox_2">
<property name="text">
<string>LED VH1 (Зеленый)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="ledVH2TestChkBox_2">
<property name="text">
<string>LED VH2 (Зеленый)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="ledVH3TestChkBox_2">
<property name="text">
<string>LED VH3 (Красный)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="enableLedTestChkBox_2">
<property name="text">
<string>Тест ламп и дискретных сигналов</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_21">
<property name="title">
<string>Вызов функций</string>
</property>
<layout class="QGridLayout" name="gridLayout_19">
<item row="2" column="0">
<widget class="QCheckBox" name="calibrateCallChkBox_2">
<property name="text">
<string>Калибровка</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="resetDefaultCallChkBox_2">
<property name="text">
<string>Настройки по умолчанию</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="resetKeyCallChkBox_2">
<property name="text">
<string>Сбросить все ключи</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="pollTECallChkBox_2">
<property name="text">
<string>Опрос ТЭ</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="getHardfaultCallChkBox_2">
<property name="text">
<string>Генерация HardFault</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="continiusCallChkBox_2">
<property name="text">
<string>Непрерывный вызов калибр. и опроса</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="discs_2">
<property name="title">
<string>Тест дискретных сигналов</string>
</property>
<layout class="QGridLayout" name="gridLayout_20">
<item row="2" column="1">
<widget class="QCheckBox" name="discErr5VsciTestChkBox_2">
<property name="text">
<string>Ошибка 5 Vsci</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="discErr24TestChkBox_2">
<property name="text">
<string>Ошибка 24 В</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="discWarnTestChkBox_2">
<property name="text">
<string>Предупреждение</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="discWorkTestChkBox_2">
<property name="text">
<string>Работа</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="discErr5TestChkBox_2">
<property name="text">
<string>Ошибка 5 В</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="discErrTestChkBox_2">
<property name="text">
<string>Авария</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="discErr5VATestChkBox_2">
<property name="text">
<string>Ошибка 5 VA</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="DbgPlate_1">
<property name="title">
<string>Плата 1</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Вызов функций</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="0">
<widget class="QCheckBox" name="pollTECallChkBox_1">
<property name="text">
<string>Опрос ТЭ</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="continiusCallChkBox_1">
<property name="text">
<string>Непрерывный вызов калибр. и опроса</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="calibrateCallChkBox_1">
<property name="text">
<string>Калибровка</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="getHardfaultCallChkBox_1">
<property name="text">
<string>Генерация HardFault</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="resetDefaultCallChkBox_1">
<property name="text">
<string>Настройки по умолчанию</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="resetKeyCallChkBox_1">
<property name="text">
<string>Сбросить все ключи</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="leds_1">
<property name="title">
<string>Тест светодиодов</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QCheckBox" name="ledWorkTestChkBox_1">
<property name="text">
<string>Работа</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ledWarnTestChkBox_1">
<property name="text">
<string>Предупреждение</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="ledErrTestChkBox_1">
<property name="text">
<string>Авария</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="ledConnectTestChkBox_1">
<property name="text">
<string>Связь</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="ledVH1TestChkBox_1">
<property name="text">
<string>LED VH1 (Зеленый)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="ledVH2TestChkBox_1">
<property name="text">
<string>LED VH2 (Зеленый)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="ledVH3TestChkBox_1">
<property name="text">
<string>LED VH3 (Красный)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="discs_1">
<property name="title">
<string>Тест дискретных сигналов</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1">
<widget class="QCheckBox" name="discErr5VsciTestChkBox_1">
<property name="text">
<string>Ошибка 5 Vsci</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="discErr24TestChkBox_1">
<property name="text">
<string>Ошибка 24 В</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="discWarnTestChkBox_1">
<property name="text">
<string>Предупреждение</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="discErr5TestChkBox_1">
<property name="text">
<string>Ошибка 5 В</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="discWorkTestChkBox_1">
<property name="text">
<string>Работа</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="discErrTestChkBox_1">
<property name="text">
<string>Авария</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="discErr5VATestChkBox_1">
<property name="text">
<string>Ошибка 5 VA</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="enableLedTestChkBox_1">
<property name="text">
<string>Тест ламп и дискретных сигналов</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="3">
<widget class="QGroupBox" name="DbgPlate_2">
<property name="title">
<string>Плата 4</string>
</property>
<layout class="QGridLayout" name="gridLayout_23">
<item row="2" column="0">
<widget class="QGroupBox" name="discs_4">
<property name="title">
<string>Тест дискретных сигналов</string>
</property>
<layout class="QGridLayout" name="gridLayout_16">
<item row="1" column="0">
<widget class="QCheckBox" name="discWarnTestChkBox_4">
<property name="text">
<string>Предупреждение</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="discErrTestChkBox_4">
<property name="text">
<string>Авария</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="discErr5VsciTestChkBox_4">
<property name="text">
<string>Ошибка 5 Vsci</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="discWorkTestChkBox_4">
<property name="text">
<string>Работа</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="discErr5TestChkBox_4">
<property name="text">
<string>Ошибка 5 В</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="discErr24TestChkBox_4">
<property name="text">
<string>Ошибка 24 В</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="discErr5VATestChkBox_4">
<property name="text">
<string>Ошибка 5 VA</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="leds_4">
<property name="title">
<string>Тест светодиодов</string>
</property>
<layout class="QGridLayout" name="gridLayout_17">
<item row="0" column="0">
<widget class="QCheckBox" name="ledWorkTestChkBox_4">
<property name="text">
<string>Работа</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ledWarnTestChkBox_4">
<property name="text">
<string>Предупреждение</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="ledErrTestChkBox_4">
<property name="text">
<string>Авария</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="ledConnectTestChkBox_4">
<property name="text">
<string>Связь</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="ledVH1TestChkBox_4">
<property name="text">
<string>LED VH1 (Зеленый)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="ledVH2TestChkBox_4">
<property name="text">
<string>LED VH2 (Зеленый)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="ledVH3TestChkBox_4">
<property name="text">
<string>LED VH3 (Красный)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="enableLedTestChkBox_4">
<property name="text">
<string>Тест ламп и дискретных сигналов</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_16">
<property name="title">
<string>Вызов функций</string>
</property>
<layout class="QGridLayout" name="gridLayout_15">
<item row="2" column="0">
<widget class="QCheckBox" name="pollTECallChkBox_4">
<property name="text">
<string>Опрос ТЭ</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="continiusCallChkBox_4">
<property name="text">
<string>Непрерывный вызов калибр. и опроса</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="calibrateCallChkBox_4">
<property name="text">
<string>Калибровка</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="getHardfaultCallChkBox_4">
<property name="text">
<string>Генерация HardFault</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="resetDefaultCallChkBox_4">
<property name="text">
<string>Настройки по умолчанию</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="resetKeyCallChkBox_4">
<property name="text">
<string>Сбросить все ключи</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DebugTerminalDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DebugTerminalDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,811 @@
#include "debugterminaldialog.h"
#include "ui_debugTerminalDialog.h"
#include "adcgraphdialog.h"
#include <QDebug>
#include <QShowEvent>
#include <QCloseEvent>
#include <QAbstractButton>
DebugTerminalDialog::DebugTerminalDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::DebugTerminalDialog),
m_adcGraphDialog(nullptr),
m_modbusDevice(nullptr)
{
ui->setupUi(this);
boards[0].error24V = ui->discErr24TestChkBox_1;
boards[0].error5V = ui->discErr5TestChkBox_1;
boards[0].error5VSCI = ui->discErr5VsciTestChkBox_1;
boards[0].error5VA = ui->discErr5VATestChkBox_1;
boards[1].error24V = ui->discErr24TestChkBox_2;
boards[1].error5V = ui->discErr5TestChkBox_2;
boards[1].error5VSCI = ui->discErr5VsciTestChkBox_2;
boards[1].error5VA = ui->discErr5VATestChkBox_2;
boards[2].error24V = ui->discErr24TestChkBox_3;
boards[2].error5V = ui->discErr5TestChkBox_3;
boards[2].error5VSCI = ui->discErr5VsciTestChkBox_3;
boards[2].error5VA = ui->discErr5VATestChkBox_3;
boards[3].error24V = ui->discErr24TestChkBox_4;
boards[3].error5V = ui->discErr5TestChkBox_4;
boards[3].error5VSCI = ui->discErr5VsciTestChkBox_4;
boards[3].error5VA = ui->discErr5VATestChkBox_4;
initializeConnections();
// Создаем AdcGraphDialog с nullptr
m_adcGraphDialog = new AdcGraphDialog(nullptr, this);
}
DebugTerminalDialog::~DebugTerminalDialog()
{
delete ui;
}
void DebugTerminalDialog::setMainTerm(M3KTE* term)
{
mainTerm = term;
}
void DebugTerminalDialog::setModbusDevice(QModbusClient *device)
{
m_modbusDevice = device;
if (m_adcGraphDialog && device) {
m_adcGraphDialog->setModbusDevice(device);
}
}
void DebugTerminalDialog::setDebugTerminalCoil(int enable)
{
writeCoil(0, COIL_DEBUG_MODE, enable);
writeCoil(1, COIL_DEBUG_MODE, enable);
writeCoil(2, COIL_DEBUG_MODE, enable);
writeCoil(3, COIL_DEBUG_MODE, enable);
}
void DebugTerminalDialog::showEvent(QShowEvent *event)
{
QDialog::showEvent(event);
// При открытии окна записываем в коил 555 значение "1"
resetAll();
setDebugTerminalCoil(1);
}
void DebugTerminalDialog::closeEvent(QCloseEvent *event)
{
// При закрытии окна записываем в коил 555 значение "0"
setDebugTerminalCoil(0);
QDialog::closeEvent(event);
}
void DebugTerminalDialog::initializeConnections()
{
// // Подключаем кнопки OK и RestoreDefaults
// connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &DebugTerminalDialog::on_buttonBox_clicked);
// // Подключаем все чекбоксы для платы 1
// connect(ui->continiusCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_continiusCallChkBox_1_stateChanged);
// connect(ui->calibrateCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_calibrateCallChkBox_1_stateChanged);
// connect(ui->pollTECallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_pollTECallChkBox_1_stateChanged);
// connect(ui->resetKeyCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_resetKeyCallChkBox_1_stateChanged);
// connect(ui->resetDefaultCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_resetDefaultCallChkBox_1_stateChanged);
// connect(ui->getHardfaultCallChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_getHardfaultCallChkBox_1_stateChanged);
// connect(ui->enableLedTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::enableLedTestChkBox_1_stateChanged);
// connect(ui->discWorkTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discWorkTestChkBox_1_stateChanged);
// connect(ui->discWarnTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discWarnTestChkBox_1_stateChanged);
// connect(ui->discErrTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErrTestChkBox_1_stateChanged);
// connect(ui->discErr24TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr24TestChkBox_1_stateChanged);
// ui->discErr24TestChkBox_1->setAttribute(Qt::WA_TransparentForMouseEvents, true);
// connect(ui->discErr5TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5TestChkBox_1_stateChanged);
// ui->discErr5TestChkBox_1->setAttribute(Qt::WA_TransparentForMouseEvents, true);
// connect(ui->discErr5VsciTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5VsciTestChkBox_1_stateChanged);
// ui->discErr5VsciTestChkBox_1->setAttribute(Qt::WA_TransparentForMouseEvents, true);
// connect(ui->discErr5VATestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5VATestChkBox_1_stateChanged);
// ui->discErr5VATestChkBox_1->setAttribute(Qt::WA_TransparentForMouseEvents, true);
// connect(ui->ledWorkTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledWorkTestChkBox_1_stateChanged);
// connect(ui->ledWarnTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledWarnTestChkBox_1_stateChanged);
// connect(ui->ledErrTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledErrTestChkBox_1_stateChanged);
// connect(ui->ledConnectTestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledConnectTestChkBox_1_stateChanged);
// connect(ui->ledVH1TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH1TestChkBox_1_stateChanged);
// connect(ui->ledVH2TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH2TestChkBox_1_stateChanged);
// connect(ui->ledVH3TestChkBox_1, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH3TestChkBox_1_stateChanged);
// // Подключаем все чекбоксы для платы 2
// connect(ui->continiusCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_continiusCallChkBox_2_stateChanged);
// connect(ui->calibrateCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_calibrateCallChkBox_2_stateChanged);
// connect(ui->pollTECallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_pollTECallChkBox_2_stateChanged);
// connect(ui->resetKeyCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_resetKeyCallChkBox_2_stateChanged);
// connect(ui->resetDefaultCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_resetDefaultCallChkBox_2_stateChanged);
// connect(ui->getHardfaultCallChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_getHardfaultCallChkBox_2_stateChanged);
// connect(ui->enableLedTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::enableLedTestChkBox_2_stateChanged);
// connect(ui->discWorkTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discWorkTestChkBox_2_stateChanged);
// connect(ui->discWarnTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discWarnTestChkBox_2_stateChanged);
// connect(ui->discErrTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErrTestChkBox_2_stateChanged);
// connect(ui->discErr24TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr24TestChkBox_2_stateChanged);
// ui->discErr24TestChkBox_2->setAttribute(Qt::WA_TransparentForMouseEvents, true);
// connect(ui->discErr5TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5TestChkBox_2_stateChanged);
// ui->discErr5TestChkBox_2->setAttribute(Qt::WA_TransparentForMouseEvents, true);
// connect(ui->discErr5VsciTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5VsciTestChkBox_2_stateChanged);
// ui->discErr5VsciTestChkBox_2->setAttribute(Qt::WA_TransparentForMouseEvents, true);
// connect(ui->discErr5VATestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_discErr5VATestChkBox_2_stateChanged);
// ui->discErr5VATestChkBox_2->setAttribute(Qt::WA_TransparentForMouseEvents, true);
// connect(ui->ledWorkTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledWorkTestChkBox_2_stateChanged);
// connect(ui->ledWarnTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledWarnTestChkBox_2_stateChanged);
// connect(ui->ledErrTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledErrTestChkBox_2_stateChanged);
// connect(ui->ledConnectTestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledConnectTestChkBox_2_stateChanged);
// connect(ui->ledVH1TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH1TestChkBox_2_stateChanged);
// connect(ui->ledVH2TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH2TestChkBox_2_stateChanged);
// connect(ui->ledVH3TestChkBox_2, &QCheckBox::stateChanged, this, &DebugTerminalDialog::on_ledVH3TestChkBox_2_stateChanged);
}
void DebugTerminalDialog::updateConnectionStatus(int boardID, bool connected)
{
// Обновляем визуальное отображение статуса соединения
// Можно изменить цвет рамки или добавить индикатор
Q_UNUSED(boardID);
Q_UNUSED(connected);
// Реализация по необходимости
}
void DebugTerminalDialog::on_buttonBox_clicked(QAbstractButton *button)
{
switch (ui->buttonBox->buttonRole(button)) {
case QDialogButtonBox::ResetRole:
resetAll();
break;
case QDialogButtonBox::AcceptRole:
accept();
break;
default:
break;
}
}
// Реализация слотов для вызова функций платы 1
void DebugTerminalDialog::on_continiusCallChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_CONTINUOUS_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_calibrateCallChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_CALIBRATE_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_pollTECallChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_POLL_TE_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_resetKeyCallChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_RESET_KEYS_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_resetDefaultCallChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_RESET_DEFAULT_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_getHardfaultCallChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_HARDFAULT_CALL, state == Qt::Checked ? 1 : 0);
}
// Реализация слотов для теста дискретных сигналов платы 1
void DebugTerminalDialog::on_enableLedTestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_LED_TEST_ENABLE, state == Qt::Checked ? 1 : 0);
ui->leds_1->setEnabled(state);
ui->discs_1->setEnabled(state);
}
void DebugTerminalDialog::on_discWorkTestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_DISC_WORK_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discWarnTestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_DISC_WARN_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discErrTestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_DISC_ERR_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discErr24TestChkBox_1_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5TestChkBox_1_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5VsciTestChkBox_1_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5VATestChkBox_1_stateChanged(int state){Q_UNUSED(state)}
// Реализация слотов для теста светодиодов платы 1
void DebugTerminalDialog::on_ledWorkTestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_LED_WORK_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledWarnTestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_LED_WARN_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledErrTestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_LED_ERR_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledConnectTestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_LED_CONNECT_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH1TestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_LED_VH1_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH2TestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_LED_VH2_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH3TestChkBox_1_stateChanged(int state)
{
writeCoil(0, COIL_LED_VH3_TEST, state == Qt::Checked ? 1 : 0);
}
// Реализация слотов для вызова функций платы 2
void DebugTerminalDialog::on_continiusCallChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_CONTINUOUS_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_calibrateCallChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_CALIBRATE_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_pollTECallChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_POLL_TE_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_resetKeyCallChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_RESET_KEYS_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_resetDefaultCallChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_RESET_DEFAULT_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_getHardfaultCallChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_HARDFAULT_CALL, state == Qt::Checked ? 1 : 0);
}
// Реализация слотов для теста дискретных сигналов платы 2
void DebugTerminalDialog::on_enableLedTestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_LED_TEST_ENABLE, state == Qt::Checked ? 1 : 0);
ui->leds_2->setEnabled(state);
ui->discs_2->setEnabled(state);
}
void DebugTerminalDialog::on_discWorkTestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_DISC_WORK_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discWarnTestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_DISC_WARN_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discErrTestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_DISC_ERR_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discErr24TestChkBox_2_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5TestChkBox_2_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5VsciTestChkBox_2_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5VATestChkBox_2_stateChanged(int state){Q_UNUSED(state)}
// Реализация слотов для теста светодиодов платы 2
void DebugTerminalDialog::on_ledWorkTestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_LED_WORK_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledWarnTestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_LED_WARN_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledErrTestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_LED_ERR_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledConnectTestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_LED_CONNECT_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH1TestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_LED_VH1_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH2TestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_LED_VH2_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH3TestChkBox_2_stateChanged(int state)
{
writeCoil(1, COIL_LED_VH3_TEST, state == Qt::Checked ? 1 : 0);
}
// Реализация слотов для вызова функций платы 3
void DebugTerminalDialog::on_continiusCallChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_CONTINUOUS_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_calibrateCallChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_CALIBRATE_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_pollTECallChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_POLL_TE_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_resetKeyCallChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_RESET_KEYS_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_resetDefaultCallChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_RESET_DEFAULT_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_getHardfaultCallChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_HARDFAULT_CALL, state == Qt::Checked ? 1 : 0);
}
// Реализация слотов для теста дискретных сигналов платы 3
void DebugTerminalDialog::on_enableLedTestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_LED_TEST_ENABLE, state == Qt::Checked ? 1 : 0);
ui->leds_3->setEnabled(state);
ui->discs_3->setEnabled(state);
}
void DebugTerminalDialog::on_discWorkTestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_DISC_WORK_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discWarnTestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_DISC_WARN_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discErrTestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_DISC_ERR_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discErr24TestChkBox_3_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5TestChkBox_3_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5VsciTestChkBox_3_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5VATestChkBox_3_stateChanged(int state){Q_UNUSED(state)}
// Реализация слотов для теста светодиодов платы 3
void DebugTerminalDialog::on_ledWorkTestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_LED_WORK_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledWarnTestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_LED_WARN_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledErrTestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_LED_ERR_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledConnectTestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_LED_CONNECT_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH1TestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_LED_VH1_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH2TestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_LED_VH2_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH3TestChkBox_3_stateChanged(int state)
{
writeCoil(2, COIL_LED_VH3_TEST, state == Qt::Checked ? 1 : 0);
}
// Реализация слотов для вызова функций платы 4
void DebugTerminalDialog::on_continiusCallChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_CONTINUOUS_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_calibrateCallChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_CALIBRATE_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_pollTECallChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_POLL_TE_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_resetKeyCallChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_RESET_KEYS_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_resetDefaultCallChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_RESET_DEFAULT_CALL, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_getHardfaultCallChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_HARDFAULT_CALL, state == Qt::Checked ? 1 : 0);
}
// Реализация слотов для теста дискретных сигналов платы 4
void DebugTerminalDialog::on_enableLedTestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_LED_TEST_ENABLE, state == Qt::Checked ? 1 : 0);
ui->leds_4->setEnabled(state);
ui->discs_4->setEnabled(state);
}
void DebugTerminalDialog::on_discWorkTestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_DISC_WORK_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discWarnTestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_DISC_WARN_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discErrTestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_DISC_ERR_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_discErr24TestChkBox_4_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5TestChkBox_4_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5VsciTestChkBox_4_stateChanged(int state){Q_UNUSED(state)}
void DebugTerminalDialog::on_discErr5VATestChkBox_4_stateChanged(int state){Q_UNUSED(state)}
// Реализация слотов для теста светодиодов платы 4
void DebugTerminalDialog::on_ledWorkTestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_LED_WORK_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledWarnTestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_LED_WARN_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledErrTestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_LED_ERR_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledConnectTestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_LED_CONNECT_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH1TestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_LED_VH1_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH2TestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_LED_VH2_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::on_ledVH3TestChkBox_4_stateChanged(int state)
{
writeCoil(3, COIL_LED_VH3_TEST, state == Qt::Checked ? 1 : 0);
}
void DebugTerminalDialog::openAdc(int boardID, int teNumber)
{
// Удаляем старый диалог и создаем новый
if (m_adcGraphDialog) {
m_adcGraphDialog->deleteLater();
m_adcGraphDialog = nullptr;
}
m_adcGraphDialog = new AdcGraphDialog(m_modbusDevice, this);
connect(m_adcGraphDialog, &AdcGraphDialog::dialogClosed, this, [this]() {
setDebugTerminalCoil(0);
});
setGraphUpdateInterval(1000);
m_adcGraphDialog->startGraph(boardID, teNumber);
m_adcGraphDialog->show();
m_adcGraphDialog->raise();
m_adcGraphDialog->activateWindow();
}
void DebugTerminalDialog::setGraphUpdateInterval(int milliseconds)
{
if (m_adcGraphDialog) {
m_adcGraphDialog->setTimeout(milliseconds);
}
}
void DebugTerminalDialog::writeCoil(int boardID, int coil, int value)
{
QGroupBox* boardGroup = nullptr;
switch(boardID) {
case 0: boardGroup = ui->DbgPlate_1; break; // Плата 1
case 1: boardGroup = ui->DbgPlate_2; break; // Плата 2
case 2: boardGroup = ui->DbgPlate_3; break; // Плата 3
case 3: boardGroup = ui->DbgPlate_4; break; // Плата 4
default: return;
}
if(!boardGroup->isEnabled())
return;
qDebug() << "Writing board" << boardID << "coil:" << coil << "value:" << value;
emit coilValueChanged(boardID, coil, value);
}
void DebugTerminalDialog::writeTENumber(int boardId, int teNumber)
{
m_adcGraphDialog->setTENumber(boardId, teNumber);
}
void DebugTerminalDialog::setBoardActive(int boardID, bool active)
{
// Получаем групбокс для указанной платы
QGroupBox* boardGroup = nullptr;
switch(boardID) {
case 0: boardGroup = ui->DbgPlate_1; break; // Плата 1
case 1: boardGroup = ui->DbgPlate_2; break; // Плата 2
case 2: boardGroup = ui->DbgPlate_3; break; // Плата 3
case 3: boardGroup = ui->DbgPlate_4; break; // Плата 4
default: return;
}
if (boardGroup) {
boardGroup->setEnabled(active);
// Можно добавить визуальное отличие неактивных плат
if (!active) {
boardGroup->setStyleSheet("QGroupBox { color: gray; }");
} else {
boardGroup->setStyleSheet(""); // Сброс стиля
}
}
}
void DebugTerminalDialog::updateBoardStates(bool activeBoards[4])
{
for (int i = 0; i < 4; i++) {
setBoardActive(i, activeBoards[i]);
}
}
void DebugTerminalDialog::resetAll()
{
// Сброс всех чекбоксов вызова функций
ui->continiusCallChkBox_1->setChecked(false);
ui->calibrateCallChkBox_1->setChecked(false);
ui->pollTECallChkBox_1->setChecked(false);
ui->resetKeyCallChkBox_1->setChecked(false);
ui->resetDefaultCallChkBox_1->setChecked(false);
ui->getHardfaultCallChkBox_1->setChecked(false);
ui->enableLedTestChkBox_1->setChecked(false);
ui->leds_1->setEnabled(false);
ui->discs_1->setEnabled(false);
ui->discWorkTestChkBox_1->setChecked(false);
// Сброс всех чекбоксов теста дискретных сигналов
ui->discWorkTestChkBox_1->setChecked(false);
ui->discWarnTestChkBox_1->setChecked(false);
ui->discErrTestChkBox_1->setChecked(false);
// Сброс всех чекбоксов теста светодиодов
ui->ledWorkTestChkBox_1->setChecked(false);
ui->ledWarnTestChkBox_1->setChecked(false);
ui->ledErrTestChkBox_1->setChecked(false);
ui->ledConnectTestChkBox_1->setChecked(false);
ui->ledVH1TestChkBox_1->setChecked(false);
ui->ledVH2TestChkBox_1->setChecked(false);
ui->ledVH3TestChkBox_1->setChecked(false);
// Сброс всех чекбоксов вызова функций
ui->continiusCallChkBox_2->setChecked(false);
ui->calibrateCallChkBox_2->setChecked(false);
ui->pollTECallChkBox_2->setChecked(false);
ui->resetKeyCallChkBox_2->setChecked(false);
ui->resetDefaultCallChkBox_2->setChecked(false);
ui->getHardfaultCallChkBox_2->setChecked(false);
ui->enableLedTestChkBox_2->setChecked(false);
ui->leds_2->setEnabled(false);
ui->discs_2->setEnabled(false);
ui->discWorkTestChkBox_2->setChecked(false);
// Сброс всех чекбоксов теста дискретных сигналов
ui->discWorkTestChkBox_2->setChecked(false);
ui->discWarnTestChkBox_2->setChecked(false);
ui->discErrTestChkBox_2->setChecked(false);
// Сброс всех чекбоксов теста светодиодов
ui->ledWorkTestChkBox_2->setChecked(false);
ui->ledWarnTestChkBox_2->setChecked(false);
ui->ledErrTestChkBox_2->setChecked(false);
ui->ledConnectTestChkBox_2->setChecked(false);
ui->ledVH1TestChkBox_2->setChecked(false);
ui->ledVH2TestChkBox_2->setChecked(false);
ui->ledVH3TestChkBox_2->setChecked(false);
// Сброс всех чекбоксов вызова функций
ui->continiusCallChkBox_3->setChecked(false);
ui->calibrateCallChkBox_3->setChecked(false);
ui->pollTECallChkBox_3->setChecked(false);
ui->resetKeyCallChkBox_3->setChecked(false);
ui->resetDefaultCallChkBox_3->setChecked(false);
ui->getHardfaultCallChkBox_3->setChecked(false);
ui->enableLedTestChkBox_3->setChecked(false);
ui->leds_3->setEnabled(false);
ui->discs_3->setEnabled(false);
ui->discWorkTestChkBox_3->setChecked(false);
// Сброс всех чекбоксов теста дискретных сигналов
ui->discWorkTestChkBox_3->setChecked(false);
ui->discWarnTestChkBox_3->setChecked(false);
ui->discErrTestChkBox_3->setChecked(false);
// Сброс всех чекбоксов теста светодиодов
ui->ledWorkTestChkBox_3->setChecked(false);
ui->ledWarnTestChkBox_3->setChecked(false);
ui->ledErrTestChkBox_3->setChecked(false);
ui->ledConnectTestChkBox_3->setChecked(false);
ui->ledVH1TestChkBox_3->setChecked(false);
ui->ledVH2TestChkBox_3->setChecked(false);
ui->ledVH3TestChkBox_3->setChecked(false);
// Сброс всех чекбоксов вызова функций
ui->continiusCallChkBox_4->setChecked(false);
ui->calibrateCallChkBox_4->setChecked(false);
ui->pollTECallChkBox_4->setChecked(false);
ui->resetKeyCallChkBox_4->setChecked(false);
ui->resetDefaultCallChkBox_4->setChecked(false);
ui->getHardfaultCallChkBox_4->setChecked(false);
ui->enableLedTestChkBox_4->setChecked(false);
ui->leds_4->setEnabled(false);
ui->discs_4->setEnabled(false);
ui->discWorkTestChkBox_4->setChecked(false);
// Сброс всех чекбоксов теста дискретных сигналов
ui->discWorkTestChkBox_4->setChecked(false);
ui->discWarnTestChkBox_4->setChecked(false);
ui->discErrTestChkBox_4->setChecked(false);
// Сброс всех чекбоксов теста светодиодов
ui->ledWorkTestChkBox_4->setChecked(false);
ui->ledWarnTestChkBox_4->setChecked(false);
ui->ledErrTestChkBox_4->setChecked(false);
ui->ledConnectTestChkBox_4->setChecked(false);
ui->ledVH1TestChkBox_4->setChecked(false);
ui->ledVH2TestChkBox_4->setChecked(false);
ui->ledVH3TestChkBox_4->setChecked(false);
}
void DebugTerminalDialog::boardDebugReading(int boardID)
{
if(mainTerm == nullptr)
return;
if(!boards[boardID].isActive)
return;
if(!this->isVisible())
return;
QModbusReply *_24V = mainTerm->readSingleCoil(boardID, 603);
if(_24V != nullptr)
connect(_24V, &QModbusReply::finished, this, [this, boardID, _24V]() {
if(_24V->error() == QModbusDevice::NoError)
boards[boardID].error24V->setChecked(_24V->result().value(0));
_24V->deleteLater();
});
QModbusReply *_5V = mainTerm->readSingleCoil(boardID, 604);
if(_5V != nullptr)
connect(_5V, &QModbusReply::finished, this, [this, boardID, _5V]() {
if(_5V->error() == QModbusDevice::NoError)
boards[boardID].error5V->setChecked(_5V->result().value(0));
_5V->deleteLater();
});
QModbusReply *_5VSCI = mainTerm->readSingleCoil(boardID, 605);
if(_5VSCI != nullptr)
connect(_5VSCI, &QModbusReply::finished, this, [this, boardID, _5VSCI]() {
if(_5VSCI->error() == QModbusDevice::NoError)
boards[boardID].error5VSCI->setChecked(_5VSCI->result().value(0));
_5VSCI->deleteLater();
});
QModbusReply *_5VA = mainTerm->readSingleCoil(boardID, 606);
if(_5VA != nullptr)
connect(_5VA, &QModbusReply::finished, this, [this, boardID, _5VA]() {
if(_5VA->error() == QModbusDevice::NoError)
boards[boardID].error5VA->setChecked(_5VA->result().value(0));
_5VA->deleteLater();
});
}
void DebugTerminalDialog::setScanBoardActive(bool flag, int boardID)
{
boards[boardID].isActive = flag;
}
void DebugTerminalDialog::offAllBoard()
{
for(int i = 0; i < 4; i++)
{
boards[i].isActive = false;
}
}

View File

@@ -0,0 +1,225 @@
#ifndef DEBUGTERMINALDIALOG_H
#define DEBUGTERMINALDIALOG_H
#include <QDialog>
#include <QModbusClient>
#include <QAbstractButton>
#include <QCheckBox>
#include <m3kte.h>
// Forward declarations вместо include
class M3KTE;
class AdcGraphDialog;
// Дефайны для адресов коилов
#define COIL_DEBUG_MODE 555
#define COIL_CONTINUOUS_CALL 571
#define COIL_CALIBRATE_CALL 572
#define COIL_POLL_TE_CALL 573
#define COIL_RESET_KEYS_CALL 574
#define COIL_RESET_DEFAULT_CALL 576
#define COIL_HARDFAULT_CALL 586
#define COIL_LED_TEST_ENABLE 587
// Тест дискретных сигналов
#define COIL_DISC_WORK_TEST 588
#define COIL_DISC_WARN_TEST 589
#define COIL_DISC_ERR_TEST 590
// Тест светодиодов
#define COIL_LED_CONNECT_TEST 591
#define COIL_LED_WORK_TEST 592
#define COIL_LED_WARN_TEST 593
#define COIL_LED_ERR_TEST 594
#define COIL_LED_VH1_TEST 595
#define COIL_LED_VH2_TEST 596
#define COIL_LED_VH3_TEST 597
// Адреса для чтения состояний ошибок питания
#define COIL_READ_ERR_24V 600 // Чтение ошибки 24В
#define COIL_READ_ERR_5V 601 // Чтение ошибки 5В
#define COIL_READ_ERR_5VSCI 602 // Чтение ошибки 5Vsci
#define COIL_READ_ERR_5VA 603 // Чтение ошибки 5VA
#define REGISTER_TE_NUMB 564
namespace Ui {
class DebugTerminalDialog;
}
class DebugTerminalDialog : public QDialog
{
Q_OBJECT
public:
explicit DebugTerminalDialog(QWidget *parent = nullptr);
~DebugTerminalDialog();
AdcGraphDialog *m_adcGraphDialog;
void setDebugTerminalCoil(int enable);
void updateConnectionStatus(int boardId, bool connected);
void setBoardActive(int boardId, bool active);
void updateBoardStates(bool activeBoards[4]);
void setModbusDevice(QModbusClient *device);
void setGraphUpdateInterval(int milliseconds);
void writeTENumber(int boardId, int teNumber);
void openAdc(int boardID, int teNumber);
void setMainTerm(M3KTE* term);
public slots:
void boardDebugReading(int boardID);
void setScanBoardActive(bool flag, int boardID);
void offAllBoard();
protected:
void showEvent(QShowEvent *event) override;
void closeEvent(QCloseEvent *event) override;
private slots:
void on_buttonBox_clicked(QAbstractButton *button);
// Плата 1
void on_continiusCallChkBox_1_stateChanged(int state);
void on_calibrateCallChkBox_1_stateChanged(int state);
void on_pollTECallChkBox_1_stateChanged(int state);
void on_resetKeyCallChkBox_1_stateChanged(int state);
void on_resetDefaultCallChkBox_1_stateChanged(int state);
void on_getHardfaultCallChkBox_1_stateChanged(int state);
void on_enableLedTestChkBox_1_stateChanged(int state);
void on_discWorkTestChkBox_1_stateChanged(int state);
void on_discWarnTestChkBox_1_stateChanged(int state);
void on_discErrTestChkBox_1_stateChanged(int state);
void on_discErr24TestChkBox_1_stateChanged(int state);
void on_discErr5TestChkBox_1_stateChanged(int state);
void on_discErr5VsciTestChkBox_1_stateChanged(int state);
void on_discErr5VATestChkBox_1_stateChanged(int state);
void on_ledWorkTestChkBox_1_stateChanged(int state);
void on_ledWarnTestChkBox_1_stateChanged(int state);
void on_ledErrTestChkBox_1_stateChanged(int state);
void on_ledConnectTestChkBox_1_stateChanged(int state);
void on_ledVH1TestChkBox_1_stateChanged(int state);
void on_ledVH2TestChkBox_1_stateChanged(int state);
void on_ledVH3TestChkBox_1_stateChanged(int state);
// Плата 2
void on_continiusCallChkBox_2_stateChanged(int state);
void on_calibrateCallChkBox_2_stateChanged(int state);
void on_pollTECallChkBox_2_stateChanged(int state);
void on_resetKeyCallChkBox_2_stateChanged(int state);
void on_resetDefaultCallChkBox_2_stateChanged(int state);
void on_getHardfaultCallChkBox_2_stateChanged(int state);
void on_enableLedTestChkBox_2_stateChanged(int state);
void on_discWorkTestChkBox_2_stateChanged(int state);
void on_discWarnTestChkBox_2_stateChanged(int state);
void on_discErrTestChkBox_2_stateChanged(int state);
void on_discErr24TestChkBox_2_stateChanged(int state);
void on_discErr5TestChkBox_2_stateChanged(int state);
void on_discErr5VsciTestChkBox_2_stateChanged(int state);
void on_discErr5VATestChkBox_2_stateChanged(int state);
void on_ledWorkTestChkBox_2_stateChanged(int state);
void on_ledWarnTestChkBox_2_stateChanged(int state);
void on_ledErrTestChkBox_2_stateChanged(int state);
void on_ledConnectTestChkBox_2_stateChanged(int state);
void on_ledVH1TestChkBox_2_stateChanged(int state);
void on_ledVH2TestChkBox_2_stateChanged(int state);
void on_ledVH3TestChkBox_2_stateChanged(int state);
// Плата 3
void on_continiusCallChkBox_3_stateChanged(int state);
void on_calibrateCallChkBox_3_stateChanged(int state);
void on_pollTECallChkBox_3_stateChanged(int state);
void on_resetKeyCallChkBox_3_stateChanged(int state);
void on_resetDefaultCallChkBox_3_stateChanged(int state);
void on_getHardfaultCallChkBox_3_stateChanged(int state);
void on_enableLedTestChkBox_3_stateChanged(int state);
void on_discWorkTestChkBox_3_stateChanged(int state);
void on_discWarnTestChkBox_3_stateChanged(int state);
void on_discErrTestChkBox_3_stateChanged(int state);
void on_discErr24TestChkBox_3_stateChanged(int state);
void on_discErr5TestChkBox_3_stateChanged(int state);
void on_discErr5VsciTestChkBox_3_stateChanged(int state);
void on_discErr5VATestChkBox_3_stateChanged(int state);
void on_ledWorkTestChkBox_3_stateChanged(int state);
void on_ledWarnTestChkBox_3_stateChanged(int state);
void on_ledErrTestChkBox_3_stateChanged(int state);
void on_ledConnectTestChkBox_3_stateChanged(int state);
void on_ledVH1TestChkBox_3_stateChanged(int state);
void on_ledVH2TestChkBox_3_stateChanged(int state);
void on_ledVH3TestChkBox_3_stateChanged(int state);
// Плата 4
void on_continiusCallChkBox_4_stateChanged(int state);
void on_calibrateCallChkBox_4_stateChanged(int state);
void on_pollTECallChkBox_4_stateChanged(int state);
void on_resetKeyCallChkBox_4_stateChanged(int state);
void on_resetDefaultCallChkBox_4_stateChanged(int state);
void on_getHardfaultCallChkBox_4_stateChanged(int state);
void on_enableLedTestChkBox_4_stateChanged(int state);
void on_discWorkTestChkBox_4_stateChanged(int state);
void on_discWarnTestChkBox_4_stateChanged(int state);
void on_discErrTestChkBox_4_stateChanged(int state);
void on_discErr24TestChkBox_4_stateChanged(int state);
void on_discErr5TestChkBox_4_stateChanged(int state);
void on_discErr5VsciTestChkBox_4_stateChanged(int state);
void on_discErr5VATestChkBox_4_stateChanged(int state);
void on_ledWorkTestChkBox_4_stateChanged(int state);
void on_ledWarnTestChkBox_4_stateChanged(int state);
void on_ledErrTestChkBox_4_stateChanged(int state);
void on_ledConnectTestChkBox_4_stateChanged(int state);
void on_ledVH1TestChkBox_4_stateChanged(int state);
void on_ledVH2TestChkBox_4_stateChanged(int state);
void on_ledVH3TestChkBox_4_stateChanged(int state);
signals:
void coilValueChanged(int boardID, int coil, int value);
void writeRegister(int boardID, int reg, int value);
void readCoil(int boardID, int coil, QModbusReply *reply);
private:
Ui::DebugTerminalDialog *ui;
QModbusClient *m_modbusDevice; // Храним указатель здесь
M3KTE* mainTerm = nullptr;
// Карты для хранения состояний
QMap<int, bool> m_functionCalls; // boardId -> coil -> state
QMap<int, bool> m_discreteTests; // boardId -> coil -> state
QMap<int, bool> m_ledTests; // boardId -> coil -> state
// Номера ТЭ для каждой платы
int m_teNumbers[4] = {0, 0, 0, 0};
struct boardErrorLinks{
bool isActive = false;
QCheckBox* error24V = nullptr;
QCheckBox* error5V = nullptr;
QCheckBox* error5VSCI = nullptr;
QCheckBox* error5VA = nullptr;
};
boardErrorLinks boards[4];
void initializeConnections();
void writeCoil(int boardID, int coil, int value);
//void readCoil(int coil);
void resetAll();
};
#endif // DEBUGTERMINALDIALOG_H

View File

@@ -1,28 +1,24 @@
#include "devicesettingsdialog.h" #include "devicesettingsdialog.h"
#include "ui_devicesettingsdialog.h" #include "ui_devicesettingsdialog.h"
#include <QDebug>
#include <QProcess>
#include <QCoreApplication>
DeviceSettingsDialog::DeviceSettingsDialog(QWidget *parent) : DeviceSettingsDialog::DeviceSettingsDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::DeviceSettingsDialog) ui(new Ui::DeviceSettingsDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
on_buttonApplyChangeTimer_clicked();
_currentBoardTimers[0] = ui->spinTimerBoard_1->value(); {
_currentBoardTimers[1] = ui->spinTimerBoard_2->value();
_currentBoardTimers[2] = ui->spinTimerBoard_3->value();
_currentBoardTimers[3] = ui->spinTimerBoard_4->value();
_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;
} }
} }
@@ -81,16 +77,12 @@ void DeviceSettingsDialog::updateSettingsAfterConnection(unsigned tmp_speed, uns
if(tmp_parity>0) if(tmp_parity>0)
tmp_parity--; tmp_parity--;
ui->parityBox->setCurrentIndex(_currentParity = tmp_parity); ui->parityBox->setCurrentIndex(_currentParity = tmp_parity);
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{ if(ActiveDevices[i]) {
if(ActiveDevices[i])
{
_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);
} }
} }
@@ -110,19 +102,12 @@ void DeviceSettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
ui->spinTimerBoard_2->setValue(1000); ui->spinTimerBoard_2->setValue(1000);
ui->spinTimerBoard_3->setValue(1000); ui->spinTimerBoard_3->setValue(1000);
ui->spinTimerBoard_4->setValue(1000); ui->spinTimerBoard_4->setValue(1000);
_currentBoardTimers[0] = ui->spinTimerBoard_1->value(); on_buttonApplyChangeTimer_clicked();
_currentBoardTimers[1] = ui->spinTimerBoard_2->value();
_currentBoardTimers[2] = ui->spinTimerBoard_3->value();
_currentBoardTimers[3] = ui->spinTimerBoard_4->value();
ui->speedBox->setCurrentText("31250"); ui->speedBox->setCurrentText("31250");
_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()]);
@@ -130,12 +115,14 @@ void DeviceSettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
case QDialogButtonBox::AcceptRole: case QDialogButtonBox::AcceptRole:
close(); close();
break; break;
default:
break;
} }
} }
void DeviceSettingsDialog::initPollForBoard(unsigned boardID, unsigned boardAdr) void DeviceSettingsDialog::initPollForBoard(unsigned boardID, unsigned boardAdr)
{ {
ui->idPollComboBox->addItem(QString("Плата №%1 (ID %2)").arg(boardID).arg(boardAdr), QVariant(boardID)); ui->idPollComboBox->addItem(QString("Плата №%1 (ID %2)").arg(boardID+1).arg(boardAdr), QVariant(boardID));
} }
void DeviceSettingsDialog::updatePollStatus(unsigned boardID, bool status) void DeviceSettingsDialog::updatePollStatus(unsigned boardID, bool status)
@@ -145,12 +132,24 @@ void DeviceSettingsDialog::updatePollStatus(unsigned boardID, bool status)
void DeviceSettingsDialog::on_buttonApplyChangePoll_clicked() void DeviceSettingsDialog::on_buttonApplyChangePoll_clicked()
{ {
updatePollStatus(ui->idPollComboBox->currentData().toUInt(), (bool)ui->pollStatusBox->currentIndex()); sendPollCommand(ui->idPollComboBox->currentData().toUInt(), (bool)ui->pollStatusBox->currentIndex());
pollStatusChange* _pollStatusChanged = new pollStatusChange(ui->idPollComboBox->currentData().toUInt(), _currentPollStatus[ui->idPollComboBox->currentData().toUInt()]); }
void DeviceSettingsDialog::sendPollCommand(unsigned boardID, bool status)
{
updatePollStatus(boardID, status);
pollStatusChange* _pollStatusChanged = new pollStatusChange(boardID, status);
QCoreApplication::postEvent(parent(), _pollStatusChanged); QCoreApplication::postEvent(parent(), _pollStatusChanged);
} }
void DeviceSettingsDialog::on_idPollComboBox_currentIndexChanged(int index) void DeviceSettingsDialog::on_idPollComboBox_currentIndexChanged(int index)
{ {
Q_UNUSED(index);
ui->pollStatusBox->setCurrentIndex(_currentPollStatus[ui->idPollComboBox->currentData().toUInt()]); ui->pollStatusBox->setCurrentIndex(_currentPollStatus[ui->idPollComboBox->currentData().toUInt()]);
} }
void DeviceSettingsDialog::onDisconnect()
{
ui->idComboBox->clear();
ui->idPollComboBox->clear();
}

View File

@@ -51,8 +51,10 @@ public:
unsigned currentSpeed(); unsigned currentSpeed();
unsigned short currentParity(); unsigned short currentParity();
void updateSettingsAfterConnection(unsigned tmp_speed, unsigned tmp_parity, unsigned *tmp_adr, bool *ActiveDevices); void updateSettingsAfterConnection(unsigned tmp_speed, unsigned tmp_parity, unsigned *tmp_adr, bool *ActiveDevices);
void sendPollCommand(unsigned boardID, bool status);
void updatePollStatus(unsigned boardID, bool status); void updatePollStatus(unsigned boardID, bool status);
void initPollForBoard(unsigned boardID, unsigned boardAdr); void initPollForBoard(unsigned boardID, unsigned boardAdr);
void onDisconnect();
signals: signals:
void parityChanged(); void parityChanged();
void speedChanged(); void speedChanged();
@@ -63,6 +65,7 @@ signals:
void fourthBoardAdrHasBeenChanged(); void fourthBoardAdrHasBeenChanged();
private slots: private slots:
void on_buttonApplyChangeTimer_clicked(); void on_buttonApplyChangeTimer_clicked();
void on_buttonApplyChangeSpeed_clicked(); void on_buttonApplyChangeSpeed_clicked();

View File

@@ -176,7 +176,7 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QSpinBox" name="adrSpinBox"> <widget class="QSpinBox" name="adrSpinBox">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>0</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>247</number> <number>247</number>
@@ -279,12 +279,12 @@
<widget class="QComboBox" name="pollStatusBox"> <widget class="QComboBox" name="pollStatusBox">
<item> <item>
<property name="text"> <property name="text">
<string>Вкл</string> <string>Выкл</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Выкл</string> <string>Вкл</string>
</property> </property>
</item> </item>
</widget> </widget>

View File

@@ -8,27 +8,28 @@ LineRinger::LineRinger(QWidget *parent) :
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));
ui->parityControlBox->addItem("Odd", QVariant(QSerialPort::OddParity)); ui->parityControlBox->addItem("Odd", QVariant(QSerialPort::OddParity));
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));
ui->dataBox->addItem("Data7", QVariant(QSerialPort::Data7)); ui->dataBox->addItem("Data7", QVariant(QSerialPort::Data7));
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));
ui->stopBox->addItem("Two", QVariant(QSerialPort::TwoStop)); ui->stopBox->addItem("Two", QVariant(QSerialPort::TwoStop));
}
ui->deviceOnlineView->horizontalHeader()->setVisible(true); ui->deviceOnlineView->horizontalHeader()->setVisible(true);
syncColumnHeaders(); syncColumnHeaders();
ui->deviceOnlineView->setColumnHidden(1, true); ui->deviceOnlineView->setColumnHidden(1, true);
@@ -55,9 +56,9 @@ void LineRinger::syncColumnHeaders()
void LineRinger::on_connectButton_clicked() void LineRinger::on_connectButton_clicked()
{ {
if (!modbusDevice) if(!modbusDevice)
return; return;
if (modbusDevice->state() != QModbusDevice::ConnectedState) { if(modbusDevice->state() != QModbusDevice::ConnectedState) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
ui->comBox->currentData().toString()); ui->comBox->currentData().toString());
#if QT_CONFIG(modbus_serialport) #if QT_CONFIG(modbus_serialport)
@@ -72,7 +73,7 @@ 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("Отключить"));
@@ -94,123 +95,95 @@ LineRinger::callStatus LineRinger::lineCall()
bool *tmp_isRun = &isRun; bool *tmp_isRun = &isRun;
uint tmp_adr = 1; uint tmp_adr = 1;
auto bar = new QProgressDialog(this); auto bar = new QProgressDialog(this);
connect(bar, &QProgressDialog::canceled, this, [this, tmp_isRun]() connect(bar, &QProgressDialog::canceled, this, [tmp_isRun]() {
{
*tmp_isRun = true; *tmp_isRun = true;
}); });
connect(this, &LineRinger::stopLineCall, this, [this, tmp_isRun]() connect(this, &LineRinger::stopLineCall, this, [tmp_isRun]() {
{
*tmp_isRun = true; *tmp_isRun = true;
}); });
bar->setLabelText(tr("Поиск устройств... Текущий адрес: %1").arg(tmp_adr)); bar->setLabelText(tr("Поиск устройств... Текущий адрес: %1").arg(tmp_adr));
bar->setCancelButton(nullptr); bar->setCancelButton(nullptr);
bar->setRange(1, 247); bar->setRange(1, 247);
bar->setMinimumDuration(100); bar->setMinimumDuration(100);
for(tmp_adr = 1; tmp_adr<248; tmp_adr++) for(tmp_adr = 1; tmp_adr<248; tmp_adr++) {
{
bar->setValue(tmp_adr); bar->setValue(tmp_adr);
bar->setLabelText(tr("Поиск устройств... Текущий адрес: %1/247").arg(tmp_adr)); bar->setLabelText(tr("Поиск устройств... Текущий адрес: %1/247").arg(tmp_adr));
auto *reply = modbusDevice->sendRawRequest(readDeviceBasicIdentification, tmp_adr); auto *reply = modbusDevice->sendRawRequest(readDeviceBasicIdentification, tmp_adr);
//auto *reply = modbusDevice->sendReadRequest(*_unit, tmp_adr);
//Запрос типа устройства. //Запрос типа устройства.
if(reply == nullptr) if(reply == nullptr) {
{
QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1").arg(modbusDevice->errorString())); QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1").arg(modbusDevice->errorString()));
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::ERROR; return callStatus::ERROR;
} }
while(!reply->isFinished()) while(!reply->isFinished()) {
{ if(isRun) {
if(isRun)
{
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::INTERRUPT; return callStatus::INTERRUPT;
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(isRun) if(isRun) {
{
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::INTERRUPT; return callStatus::INTERRUPT;
} } else if(!isRun) {
else if (!isRun)
{
//Нужна проверка типа устройства //Нужна проверка типа устройства
if(reply->error()!=QModbusDevice::TimeoutError) if(reply->error()!=QModbusDevice::TimeoutError) {
{
deviceOnLine currentDevice; deviceOnLine currentDevice;
currentDevice.adr = tmp_adr; currentDevice.adr = tmp_adr;
currentDevice.baudRate = currentBaudRate; currentDevice.baudRate = currentBaudRate;
bool regularReplyError = false; bool regularReplyError = false;
QString regularReplyErrorString; QString regularReplyErrorString;
if(reply->error()==QModbusDevice::NoError) if(reply->error()==QModbusDevice::NoError) {
{
QModbusResponse resp = reply->rawResult(); QModbusResponse resp = reply->rawResult();
uint8_t numOfObject = resp.data().at(5); uint8_t numOfObject = resp.data().at(5);
QByteArray result = resp.data().remove(0, 6); QByteArray result = resp.data().remove(0, 6);
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;
} }
while(!regularReply->isFinished()) while(!regularReply->isFinished()) {
{ if(isRun) {
if(isRun)
{
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::INTERRUPT; return callStatus::INTERRUPT;
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(isRun) if(isRun) {
{
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::INTERRUPT; return callStatus::INTERRUPT;
} } else if(!isRun) {
else if(!isRun) if(regularReply->error()!=QModbusDevice::NoError) {
{
if(regularReply->error()!=QModbusDevice::NoError)
{
// QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(regularReply->error()).arg(regularReply->errorString()));
// bar->close();
// bar->deleteLater();
// return callStatus::ERROR;
regularReplyError = true; regularReplyError = true;
regularReplyErrorString = QString("%1: %2").arg(regularReply->error()).arg(regularReply->errorString()); regularReplyErrorString = QString("%1: %2").arg(regularReply->error()).arg(regularReply->errorString());
} }
QModbusResponse regularResp = regularReply->rawResult(); QModbusResponse regularResp = regularReply->rawResult();
uint8_t numOfRegularObject = regularResp.data().at(5); uint8_t numOfRegularObject = regularResp.data().at(5);
QByteArray regularResult = regularResp.data().remove(0, 6); QByteArray regularResult = regularResp.data().remove(0, 6);
for(int tmp_obj = 0; tmp_obj < numOfRegularObject; tmp_obj++) for(int tmp_obj = 0; tmp_obj < numOfRegularObject; tmp_obj++) {
{
uint8_t objectID = regularResult.at(0); uint8_t objectID = regularResult.at(0);
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++) {
@@ -220,8 +193,7 @@ LineRinger::callStatus LineRinger::lineCall()
} }
} }
} }
if(!isRun) if(!isRun) {
{
devicesList.append(currentDevice); devicesList.append(currentDevice);
unsigned newRow = ui->deviceOnlineView->rowCount(); unsigned newRow = ui->deviceOnlineView->rowCount();
ui->deviceOnlineView->insertRow(newRow); ui->deviceOnlineView->insertRow(newRow);
@@ -230,12 +202,9 @@ LineRinger::callStatus LineRinger::lineCall()
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();
@@ -254,26 +223,21 @@ void LineRinger::on_ringButton_clicked()
syncColumnHeaders(); syncColumnHeaders();
while(ui->deviceOnlineView->rowCount()!=0) while(ui->deviceOnlineView->rowCount()!=0)
ui->deviceOnlineView->removeRow(ui->deviceOnlineView->rowCount()-1); ui->deviceOnlineView->removeRow(ui->deviceOnlineView->rowCount()-1);
if(isAutoBaud) if(isAutoBaud) {
{
auto bar = new QProgressDialog(this); auto bar = new QProgressDialog(this);
bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate)); bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate));
bar->setRange(0, ui->baudRateBox->count()); bar->setRange(0, ui->baudRateBox->count());
bar->setAutoClose(true); bar->setAutoClose(true);
bar->setMinimumDuration(0); bar->setMinimumDuration(0);
bar->setCancelButton(nullptr); bar->setCancelButton(nullptr);
connect(bar, &QProgressDialog::canceled, this, [this]() connect(bar, &QProgressDialog::canceled, this, [this]() {
{
emit stopLineCall(); emit stopLineCall();
}); });
bar->setValue(0); bar->setValue(0);
ui->deviceOnlineView->setColumnHidden(1, false); ui->deviceOnlineView->setColumnHidden(1, false);
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
for (int i = 0; i < ui->baudRateBox->count(); i++) { for (int i = 0; i < ui->baudRateBox->count(); i++) {
bar->setValue(i+1); bar->setValue(i+1);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
ui->baudRateBox->itemText(i).toInt(nullptr, 10)); ui->baudRateBox->itemText(i).toInt(nullptr, 10));
if (!modbusDevice->connectDevice()) { if (!modbusDevice->connectDevice()) {
@@ -282,8 +246,8 @@ void LineRinger::on_ringButton_clicked()
break; break;
} }
currentBaudRate = ui->baudRateBox->itemText(i).toUInt(nullptr, 10); currentBaudRate = ui->baudRateBox->itemText(i).toUInt(nullptr, 10);
if(lineCall() == callStatus::INTERRUPT) bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate));
{ if(lineCall() == callStatus::INTERRUPT) {
QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count()));
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
on_connectButton_clicked(); on_connectButton_clicked();
@@ -296,12 +260,9 @@ void LineRinger::on_ringButton_clicked()
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
} }
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()));
} }
} }

View File

@@ -12,6 +12,11 @@
#include <QScrollBar> #include <QScrollBar>
#include <QTableWidget> #include <QTableWidget>
#include <QPointer>
#include <QDebug>
#include <QProcess>
#include <QCoreApplication>
#include <QThread>
QWidget* init(QWidget *parent) QWidget* init(QWidget *parent)
{ {
@@ -353,8 +358,7 @@ M3KTE::M3KTE(QWidget *parent)
ui->writeTable->addItem(tr("Exceptions"), QModbusDataUnit::Coils); ui->writeTable->addItem(tr("Exceptions"), QModbusDataUnit::Coils);
ui->writeTable->addItem(tr("Warnings"), QModbusDataUnit::HoldingRegisters); ui->writeTable->addItem(tr("Warnings"), QModbusDataUnit::HoldingRegisters);
ui->writeTable->addItem(tr("Accidents"), QModbusDataUnit::HoldingRegisters); ui->writeTable->addItem(tr("Accidents"), QModbusDataUnit::HoldingRegisters);
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{
Boards[i].ModbusModelCoil = new WriteRegisterModel(this, 85 - (i/3*20), false); Boards[i].ModbusModelCoil = new WriteRegisterModel(this, 85 - (i/3*20), false);
Boards[i].ModbusModelCoil->setStartAddress(0); Boards[i].ModbusModelCoil->setStartAddress(0);
Boards[i].ModbusModelCoil->setNumberOfValues(QString::number(85-(i/3*20))); Boards[i].ModbusModelCoil->setNumberOfValues(QString::number(85-(i/3*20)));
@@ -363,8 +367,12 @@ M3KTE::M3KTE(QWidget *parent)
Boards[i].ModbusModelHoldingReg->setNumberOfValues(QString::number(85-(i/3*20))); Boards[i].ModbusModelHoldingReg->setNumberOfValues(QString::number(85-(i/3*20)));
} }
m_deviceSettingsDialog = new DeviceSettingsDialog(this); m_deviceSettingsDialog = new DeviceSettingsDialog(this);
m_debugTerminalDialog = new DebugTerminalDialog(this);
m_debugTerminalDialog->setMainTerm(this);
m_regMultipleSettings = new MultipleSettings(this); m_regMultipleSettings = new MultipleSettings(this);
modbusDevice = new QModbusRtuSerialMaster(this); modbusDevice = new QModbusRtuSerialMaster(this);
m_debugTerminalDialog->setModbusDevice(modbusDevice);
connect(this, &M3KTE::boardReading, m_debugTerminalDialog, &DebugTerminalDialog::boardDebugReading);
m_lineRinger = new LineRinger(); m_lineRinger = new LineRinger();
Boards[0].boardScanners = new QTimer(); Boards[0].boardScanners = new QTimer();
Boards[1].boardScanners = new QTimer(); Boards[1].boardScanners = new QTimer();
@@ -374,65 +382,109 @@ M3KTE::M3KTE(QWidget *parent)
Boards[1].boardScanners->setSingleShot(true); Boards[1].boardScanners->setSingleShot(true);
Boards[2].boardScanners->setSingleShot(true); Boards[2].boardScanners->setSingleShot(true);
Boards[3].boardScanners->setSingleShot(true); Boards[3].boardScanners->setSingleShot(true);
connect(Boards[0].boardScanners, &QTimer::timeout, this, [this]() connect(Boards[0].boardScanners, &QTimer::timeout, this, [this]() {
{
boardScan(0); boardScan(0);
}); });
connect(Boards[1].boardScanners, &QTimer::timeout, this, [this]() connect(Boards[1].boardScanners, &QTimer::timeout, this, [this]() {
{
boardScan(1); boardScan(1);
}); });
connect(Boards[2].boardScanners, &QTimer::timeout, this, [this]() connect(Boards[2].boardScanners, &QTimer::timeout, this, [this]() {
{
boardScan(2); boardScan(2);
}); });
connect(Boards[3].boardScanners, &QTimer::timeout, this, [this]() connect(Boards[3].boardScanners, &QTimer::timeout, this, [this]() {
{
boardScan(3); boardScan(3);
}); });
{
Boards[0].adr = 1; Boards[0].adr = 1;
Boards[1].adr = 2; Boards[1].adr = 2;
Boards[2].adr = 3; Boards[2].adr = 3;
Boards[3].adr = 4; Boards[3].adr = 4;
//ui->M3kteMenuSettings->setEnabled(false); }
bool activeBoards[4] = {false, false, false, false};
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);
ui->BSM_WorkInProgress->setEnabled(false); ui->BSM_WorkInProgress->setEnabled(false);
initActions(); initActions();
ui->BST_On->setCheckable(false);
ui->BST_Off->setChecked(true); ui->BST_Off->setChecked(true);
ui->boardSelectBox->setCurrentIndex(0); ui->boardSelectBox->setCurrentIndex(0);
ui->writeTable->setCurrentIndex(0); ui->writeTable->setCurrentIndex(0);
changeTable(0, 0); changeTable(0, 0);
{
Boards_Fields[0] = ui->FCBoardBox; Boards_Fields[0] = ui->FCBoardBox;
Boards_Fields[1] = ui->FCBoardBox_2; Boards_Fields[1] = ui->FCBoardBox_2;
Boards_Fields[2] = ui->FCBoardBox_3; Boards_Fields[2] = ui->FCBoardBox_3;
Boards_Fields[3] = ui->FCBoardBox_4; Boards_Fields[3] = ui->FCBoardBox_4;
}
{
Boards[0].timerStatus = ui->timeStatus_1; Boards[0].timerStatus = ui->timeStatus_1;
Boards[1].timerStatus = ui->timeStatus_2; Boards[1].timerStatus = ui->timeStatus_2;
Boards[2].timerStatus = ui->timeStatus_3; Boards[2].timerStatus = ui->timeStatus_3;
Boards[3].timerStatus = ui->timeStatus_4; Boards[3].timerStatus = ui->timeStatus_4;
}
{
Boards[0].timerData = ui->timeData_1; Boards[0].timerData = ui->timeData_1;
Boards[1].timerData = ui->timeData_2; Boards[1].timerData = ui->timeData_2;
Boards[2].timerData = ui->timeData_3; Boards[2].timerData = ui->timeData_3;
Boards[3].timerData = ui->timeData_4; Boards[3].timerData = ui->timeData_4;
}
{
Boards[0].localError = ui->localErrorEdit_1;
Boards[1].localError = ui->localErrorEdit_2;
Boards[2].localError = ui->localErrorEdit_3;
Boards[3].localError = ui->localErrorEdit_4;
}
{
Boards[0].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_1;
Boards[1].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_2;
Boards[2].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_3;
Boards[3].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_4;
for (int i = 0; i < 4; i++) {
Boards[0].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_1;
Boards[1].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_2;
Boards[2].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_3;
Boards[3].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_4;
Boards[0].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_1;
Boards[1].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_2;
Boards[2].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_3;
Boards[3].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_4;
}
{ // не кликабельные чекбоксы и радиобоксы
for(int i = 0; i < 4; i++)
{
connect(Boards[i].localState[LOCAL_STATE_POLL], &QCheckBox::clicked,
this, [i, this](bool checked) {
m_deviceSettingsDialog->sendPollCommand(i, checked);
});
Boards[i].localState[LOCAL_STATE_WARN]->setAttribute(Qt::WA_TransparentForMouseEvents, true);
Boards[i].localState[LOCAL_STATE_ERR]->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
ui->BSM_Warning->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BSM_Accident->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BSM_WorkInProgress->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BST_On->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BST_Off->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
for(int i = 0; i < 4; i++) {
statusM3KTE.Warnings[i] = false; statusM3KTE.Warnings[i] = false;
statusM3KTE.Accidents[i] = false; statusM3KTE.Accidents[i] = false;
Boards_Fields[i]->setEnabled(false); Boards_Fields[i]->setEnabled(false);
Boards[i].timerData->setText(" "); Boards[i].timerData->setText(" ");
Boards[i].timerStatus->setText(" ");; Boards[i].timerStatus->setText(" ");;
Boards[i].localError->setText(" ");;
} }
for (int i = 0; i < 5; i++) for(int i = 0; i < 5; i++) {
{
ui->writeValueTable->resizeColumnToContents(i); 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);
m_ProgressBar[i]->setMinimumSize(25, 25); m_ProgressBar[i]->setMinimumSize(25, 25);
m_ProgressBar[i]->setMaximumSize(25, 25); m_ProgressBar[i]->setMaximumSize(25, 25);
@@ -447,11 +499,11 @@ M3KTE::M3KTE(QWidget *parent)
ThePhantomMenace[i]->setPalette(QPalette(tb, tb, tb, tb, tb, tb, tb, tb, tb)); ThePhantomMenace[i]->setPalette(QPalette(tb, tb, tb, tb, tb, tb, tb, tb, tb));
connect(ThePhantomMenace[i], &QPushButton::clicked, this, [this, i]() { connect(ThePhantomMenace[i], &QPushButton::clicked, this, [this, i]() {
selectPositionOnTree(i); selectPositionOnTree(i);
m_debugTerminalDialog->writeTENumber(i/85, i - (i/85)*85 + 1);
}); });
} }
connect(m_deviceSettingsDialog, &DeviceSettingsDialog::parityChanged, this, &M3KTE::onParityUpdate); connect(m_deviceSettingsDialog, &DeviceSettingsDialog::parityChanged, this, &M3KTE::onParityUpdate);
connect(m_deviceSettingsDialog, &DeviceSettingsDialog::speedChanged, this, &M3KTE::onSpeedUpdate); connect(m_deviceSettingsDialog, &DeviceSettingsDialog::speedChanged, this, &M3KTE::onSpeedUpdate);
loggerTable = new QTableWidget(ui->loggerWidget); loggerTable = new QTableWidget(ui->loggerWidget);
ui->loggerWidget->layout()->addWidget(loggerTable); ui->loggerWidget->layout()->addWidget(loggerTable);
loggerTable->setColumnCount(5); loggerTable->setColumnCount(5);
@@ -464,8 +516,7 @@ M3KTE::M3KTE(QWidget *parent)
M3KTE::~M3KTE() M3KTE::~M3KTE()
{ {
if(modbusDevice->state() == QModbusDevice::ConnectedState) if(modbusDevice->state() == QModbusDevice::ConnectedState) {
{
onConnectClicked(); onConnectClicked();
} }
delete ui; delete ui;
@@ -484,10 +535,23 @@ void M3KTE::initActions()
this, &M3KTE::onReadButtonClicked); this, &M3KTE::onReadButtonClicked);
connect(ui->writeButton, &QPushButton::clicked, connect(ui->writeButton, &QPushButton::clicked,
this, &M3KTE::onWriteButtonClicked); this, &M3KTE::onWriteButtonClicked);
connect(ui->clearLoggerBtn, &QPushButton::clicked,
this, &M3KTE::clearLogger);
connect(ui->boardSelectBox, QOverload<int>::of(&QComboBox::currentIndexChanged), connect(ui->boardSelectBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &M3KTE::onSelectedBoardChanged); this, &M3KTE::onSelectedBoardChanged);
connect(ui->writeTable, QOverload<int>::of(&QComboBox::currentIndexChanged), connect(ui->writeTable, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &M3KTE::onWriteTableChanged); this, &M3KTE::onWriteTableChanged);
connect(ui->DebugTerm, &QAction::triggered, m_debugTerminalDialog, &QWidget::show);
connect(ui->OpenADCBuff, &QAction::triggered, this, [this]() {
m_debugTerminalDialog->setDebugTerminalCoil(1);
m_debugTerminalDialog->openAdc(0, 1);
});
connect(m_debugTerminalDialog, &DebugTerminalDialog::coilValueChanged,
this, &M3KTE::writeSingleCoil);
connect(m_debugTerminalDialog, &DebugTerminalDialog::writeRegister,
this, &M3KTE::writeSingleRegister);
connect(ui->LineCall, &QAction::triggered, m_lineRinger, &QWidget::show); connect(ui->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);
@@ -496,12 +560,39 @@ void M3KTE::initActions()
connect(ui->M3kteMenuSettings, &QAction::triggered, m_deviceSettingsDialog, &QDialog::show); connect(ui->M3kteMenuSettings, &QAction::triggered, m_deviceSettingsDialog, &QDialog::show);
} }
void M3KTE::logError(const QString &errorPlace, const QString &errorString, unsigned errorCount, const QString &description)
{
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem(QTime::currentTime().toString("HH:mm:ss")));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(errorPlace));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(errorString));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(errorCount)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(description));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
}
void M3KTE::clearLogger()
{
// Проверяем, что таблица инициализирована
if (!loggerTable) {
return;
}
// Отключаем обновление UI для повышения производительности
loggerTable->setUpdatesEnabled(false);
// Очищаем все строки таблицы
loggerTable->setRowCount(0);
// Включаем обновление UI
loggerTable->setUpdatesEnabled(true);
}
void M3KTE::onConnectClicked() void M3KTE::onConnectClicked()
{ {
if (!modbusDevice) if(!modbusDevice)
return; return;
statusBar()->clearMessage(); statusBar()->clearMessage();
if (modbusDevice->state() != QModbusDevice::ConnectedState) { if(modbusDevice->state() != QModbusDevice::ConnectedState) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
m_settingsDialog->settings().portName); m_settingsDialog->settings().portName);
#if QT_CONFIG(modbus_serialport) #if QT_CONFIG(modbus_serialport)
@@ -516,27 +607,29 @@ 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()) { //Опрос устройств
{
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++) {
tmp_adr[i] = Boards[i].adr; tmp_adr[i] = Boards[i].adr;
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);
ui->boardSelectBox->setCurrentIndex(0); ui->boardSelectBox->setCurrentIndex(0);
ui->writeTable->setCurrentIndex(0); ui->writeTable->setCurrentIndex(0);
changeTable(0, 0); changeTable(0, 0);
ui->M3kteMenuSettings->setEnabled(true); ui->M3kteMenuSettings->setEnabled(true);
ui->M3kteRegSettings->setEnabled(true); ui->M3kteRegSettings->setEnabled(true);
ui->BST_Off->setCheckable(false);
ui->BST_Off->setChecked(false); ui->BST_Off->setChecked(false);
ui->BST_On->setCheckable(true);
ui->BST_On->setChecked(true); ui->BST_On->setChecked(true);
ui->BSM_Warning->setEnabled(true); ui->BSM_Warning->setEnabled(true);
ui->BSM_Accident->setEnabled(true); ui->BSM_Accident->setEnabled(true);
@@ -546,25 +639,23 @@ void M3KTE::onConnectClicked()
} }
} else { } else {
QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} "; QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} ";
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{
Boards[i].boardScanners->stop(); Boards[i].boardScanners->stop();
Boards_Fields[i]->setEnabled(false); Boards_Fields[i]->setEnabled(false);
Boards[i].isActive=false; Boards[i].isActive=false;
for(int j = 0; j < (85 - (i/3*20)); j++) for(int j = 0; j < (85 - (i/3*20)); j++) {
{
Boards[i].coil[j] = false; Boards[i].coil[j] = false;
Boards[i].ModbusModelCoil->m_coils[j]=0; Boards[i].ModbusModelCoil->m_coils[j]=0;
Boards[i].ModbusModelHoldingReg->m_currentU[j]=0; Boards[i].ModbusModelHoldingReg->m_currentU[j]=0;
Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j] = 0; Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j] = 0;
Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j + (85 - (i/3*20))] = 0; Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j + (85 - (i/3*20))] = 0;
} }
Boards_Fields[i]->setTitle(QString("Плата №%1").arg(i)); Boards_Fields[i]->setTitle(QString("Плата №%1").arg(i+1));
Boards[i].timerData->setText(" ");; Boards[i].timerData->setText(" ");;
Boards[i].timerStatus->setText(" ");; Boards[i].timerStatus->setText(" ");;
Boards[i].localError->setText(" ");;
} }
for(int i = 0; i < 320; i++) for(int i = 0; i < 320; i++) {
{
m_ProgressBar[i]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85))); m_ProgressBar[i]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85)));
m_ProgressBar[i]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85))); m_ProgressBar[i]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85)));
m_ProgressBar[i]->setValue(3); m_ProgressBar[i]->setValue(3);
@@ -575,7 +666,9 @@ void M3KTE::onConnectClicked()
ui->M3kteRegSettings->setEnabled(false); ui->M3kteRegSettings->setEnabled(false);
ui->ConnectionMenuConnect->setEnabled(true); ui->ConnectionMenuConnect->setEnabled(true);
ui->ConnectionMenuDisconnect->setEnabled(false); ui->ConnectionMenuDisconnect->setEnabled(false);
ui->BST_Off->setCheckable(true);
ui->BST_Off->setChecked(true); ui->BST_Off->setChecked(true);
ui->BST_On->setCheckable(false);
ui->BST_On->setChecked(false); ui->BST_On->setChecked(false);
ui->BSM_Warning->setChecked(false); ui->BSM_Warning->setChecked(false);
ui->BSM_Accident->setChecked(false); ui->BSM_Accident->setChecked(false);
@@ -584,16 +677,18 @@ void M3KTE::onConnectClicked()
ui->BSM_Accident->setEnabled(false); ui->BSM_Accident->setEnabled(false);
ui->BSM_WorkInProgress->setEnabled(false); ui->BSM_WorkInProgress->setEnabled(false);
ui->M3kteRegSettings->setEnabled(false); ui->M3kteRegSettings->setEnabled(false);
m_deviceSettingsDialog->onDisconnect();
m_debugTerminalDialog->offAllBoard();
} }
} }
void M3KTE::onReadButtonClicked() void M3KTE::onReadButtonClicked()
{ {
if (!modbusDevice) if(!modbusDevice)
return; return;
statusBar()->clearMessage(); statusBar()->clearMessage();
if (auto *reply = modbusDevice->sendReadRequest(readRequest(), Boards[ui->boardSelectBox->currentIndex()].adr)) { if(auto *reply = modbusDevice->sendReadRequest(readRequest(), Boards[ui->boardSelectBox->currentIndex()].adr)) {
if (!reply->isFinished()) if(!reply->isFinished())
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
@@ -605,116 +700,95 @@ void M3KTE::onReadButtonClicked()
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)
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(ui->writeValueTable->model()->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 16), Qt::EditRole); Boards[Adr].ModbusModelHoldingReg->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 10), Qt::EditRole);
} }
} }
} else if (reply->error() == QModbusDevice::ProtocolError) { switch(unit.registerType()) {
case QModbusDataUnit::Coils:
Boards[Adr].ModbusModelCoil->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 2),
ui->writeValueTable->model()->index(unit.startAddress() + unit.valueCount() -1, 2));
break;
case QModbusDataUnit::HoldingRegisters:
Boards[Adr].ModbusModelHoldingReg->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 3),
ui->writeValueTable->model()->index(unit.startAddress() + unit.valueCount() -1, 3));
break;
default:
break;
}
} else if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)"). statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()). arg(reply->errorString()).
arg(reply->rawResult().exceptionCode(), -1, 16), 5000); arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
loggerTable->insertRow(newRow); reply->errorString(), ++Boards[Adr].error_RX,
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); QString::number(reply->rawResult().exceptionCode()));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[Adr].error_RX, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString::number(reply->rawResult().exceptionCode(), 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} else { } else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)"). statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()). arg(reply->errorString()).
arg(reply->error(), -1, 16), 5000); arg(reply->error(), -1, 16), 5000);
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
loggerTable->insertRow(newRow); reply->errorString(), ++Boards[Adr].error_RX,
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); QString::number(reply->error(), 16));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[Adr].error_RX, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString::number(reply->error(), 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
reply->deleteLater(); reply->deleteLater();
} }
void M3KTE::onWriteButtonClicked() void M3KTE::onWriteButtonClicked()
{ {
if (!modbusDevice) if(!modbusDevice)
return; return;
statusBar()->clearMessage(); statusBar()->clearMessage();
QModbusDataUnit writeUnit = writeRequest(); QModbusDataUnit writeUnit = writeRequest();
QModbusDataUnit::RegisterType table = writeUnit.registerType(); QModbusDataUnit::RegisterType table = writeUnit.registerType();
for (int i = 0, total = int(writeUnit.valueCount()); i < total; ++i) { for(int i = 0, total = int(writeUnit.valueCount()); i < total; ++i) {
if (table == QModbusDataUnit::Coils) if(table == QModbusDataUnit::Coils)
{ {
Boards[ui->boardSelectBox->currentIndex()].coil[i+writeUnit.startAddress()] = Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]; Boards[ui->boardSelectBox->currentIndex()].coil[i+writeUnit.startAddress()] =
Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()];
writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]); writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]);
} } else {
else Boards[ui->boardSelectBox->currentIndex()].HR[i+writeUnit.startAddress()] =
{ Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i+writeUnit.startAddress()];
Boards[ui->boardSelectBox->currentIndex()].HR[i+writeUnit.startAddress()] = Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i+writeUnit.startAddress()];
writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i + writeUnit.startAddress()]); writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i + writeUnit.startAddress()]);
} }
} }
if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, Boards[ui->boardSelectBox->currentIndex()].adr)) { if(auto *reply = modbusDevice->sendWriteRequest(writeUnit, Boards[ui->boardSelectBox->currentIndex()].adr)) {
if (!reply->isFinished()) { if(!reply->isFinished()) {
unsigned tmp_id = ui->boardSelectBox->currentIndex(); unsigned tmp_id = ui->boardSelectBox->currentIndex();
connect(reply, &QModbusReply::finished, this, [this, reply, tmp_id]() { connect(reply, &QModbusReply::finished, this, [this, reply, tmp_id]() {
if (reply->error() == QModbusDevice::ProtocolError) { if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)") statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
5000); 5000);
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr),
loggerTable->insertRow(newRow); reply->errorString(), ++Boards[tmp_id].error_TX,
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); QString::number(reply->rawResult().exceptionCode(), 16));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr))); } else if(reply->error() != QModbusDevice::NoError) {
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[tmp_id].error_TX, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString::number(reply->rawResult().exceptionCode(), 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} else if (reply->error() != QModbusDevice::NoError) {
statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)"). statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(reply->error(), -1, 16), 5000); arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr),
loggerTable->insertRow(newRow); reply->errorString(), ++Boards[tmp_id].error_TX,
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); QString::number(reply->error()));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[tmp_id].error_TX, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString::number(reply->error(), 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
reply->deleteLater(); reply->deleteLater();
}); });
@@ -724,14 +798,7 @@ void M3KTE::onWriteButtonClicked()
} }
} else { } else {
statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000); statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
unsigned newRow = loggerTable->rowCount(); logError(tr("Терминал"), modbusDevice->errorString(), 0, "");
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Терминал")));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
} }
@@ -747,49 +814,39 @@ void M3KTE::onWriteTableChanged(int index)
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
{
ui->writeValueTable->setModel(Boards[board].ModbusModelHoldingReg); ui->writeValueTable->setModel(Boards[board].ModbusModelHoldingReg);
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);
} }
} }
@@ -816,139 +873,71 @@ QModbusDataUnit M3KTE::writeRequest() const
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); BoardIdHasBeenChanged* _event = static_cast<BoardIdHasBeenChanged*>(event);
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 172, 1); QModbusDataUnit* _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();
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())
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(!subreply->isFinished()) {
if (auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[_event->BoardNum()]._tmp_adr)) connect(subreply, &QModbusReply::finished, this, [subreply, this, _event]() {
{
if (!subreply->isFinished())
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),
unsigned newRow = loggerTable->rowCount(); subreply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
loggerTable->insertRow(newRow); "Не удалось изменить адрес устройства. [1]");
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(subreply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[_event->BoardNum()].error_adr_change, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Не удалось изменить адрес устройства."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
delete subreply; // broadcast replies return immediately delete subreply; // broadcast replies return immediately
} }
} else { } else {
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
loggerTable->insertRow(newRow); modbusDevice->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); "Не удалось изменить адрес устройства. [2]");
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[_event->BoardNum()].error_adr_change, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Не удалось изменить адрес устройства."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
} }
} } else {
else logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
{ reply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
unsigned newRow = loggerTable->rowCount(); "Не удалось изменить адрес устройства. [3]");
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[_event->BoardNum()].error_adr_change, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Не удалось изменить адрес устройства."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
} }
}); });
else else {
{ logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
unsigned newRow = loggerTable->rowCount(); reply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
loggerTable->insertRow(newRow); "Не удалось изменить адрес устройства. [4]");
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[_event->BoardNum()].error_adr_change, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Не удалось изменить адрес устройства."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
delete reply; delete reply;
} }
} } else {
else logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
{ modbusDevice->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
unsigned newRow = loggerTable->rowCount(); "Не удалось изменить адрес устройства. [5]");
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[_event->BoardNum()].error_adr_change, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Не удалось изменить адрес устройства."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
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); pollStatusChange* _event = static_cast<pollStatusChange*>(event);
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 170, 1); QModbusDataUnit* _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),
{ reply->errorString(), ++Boards[_event->BoardID()].error_cmd_change, "");
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(_event->BoardID()+1).arg(Boards[_event->BoardID()].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[_event->BoardID()].error_cmd_change, 10)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
} }
}); });
} } else {
else logError(tr("Плата %1 (ID %2)").arg(_event->BoardID()+1).arg(Boards[_event->BoardID()].adr),
{ modbusDevice->errorString(), ++Boards[_event->BoardID()].error_cmd_change, "");
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(_event->BoardID()+1).arg(Boards[_event->BoardID()].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[_event->BoardID()].error_cmd_change, 10)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
} }
return true; return true;
@@ -958,265 +947,277 @@ bool M3KTE::event(QEvent *event)
void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum) void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum)
{ {
if (!reply) if(!reply) {
{ logError(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr),
unsigned newRow = loggerTable->rowCount(); modbusDevice->errorString(), ++Boards[boardNum].error_adr_change,
loggerTable->insertRow(newRow); "Не удалось проверить изменение адреса устройства.");
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardNum].error_adr_change, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Не удалось изменить адрес устройства."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
return; return;
} }
if (reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
if(Boards[boardNum]._tmp_adr == reply->serverAddress())
{
//OK //OK
Boards[boardNum].adr = Boards[boardNum]._tmp_adr; Boards[boardNum].adr = Boards[boardNum]._tmp_adr;
reply->deleteLater(); reply->deleteLater();
} else {
logError(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr),
reply->errorString(), ++Boards[boardNum].error_adr_change,
"Ошибка при подтверждении изменения адреса устройства.");
reply->deleteLater();
}
}
void M3KTE::checkBoards()
{
QModbusDataUnit unitCheck(QModbusDataUnit::InputRegisters, 85, 1);
// Используем shared pointers вместо ссылок на стековые переменные
auto totalActiveBoards = QSharedPointer<int>::create(0);
auto confirmedBoards = QSharedPointer<int>::create(0);
auto pendingBoards = QSharedPointer<QSet<int>>::create();
for(int i = 0; i < 4; ++i) {
if(!Boards[i].isActive)
continue;
(*totalActiveBoards)++;
int slaveAddress = Boards[i].adr;
QModbusReply *reply = modbusDevice->sendReadRequest(unitCheck, slaveAddress);
if(!reply) {
revertToOldSpeedAndRestart();
return; return;
} }
//ERROR pendingBoards->insert(slaveAddress);
else{ connect(reply, &QModbusReply::finished, this,
Boards[boardNum]._tmp_adr = Boards[boardNum].adr; [this, i, reply, slaveAddress, totalActiveBoards, confirmedBoards, pendingBoards]() {
unsigned newRow = loggerTable->rowCount(); if(reply->error() == QModbusDevice::NoError) {
loggerTable->insertRow(newRow); (*confirmedBoards)++;
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); } else {
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr))); logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAddress),
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString())); reply->errorString(), ++Boards[i].error_baud_change,
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardNum].error_adr_change, 10))); "Ошибка при подтверждении изменения скорости обмена.");
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Не удалось изменить адрес устройства.")); }
loggerTable->resizeColumnsToContents(); pendingBoards->remove(slaveAddress);
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
return; if(pendingBoards->isEmpty()) {
if(*confirmedBoards != *totalActiveBoards) {
emit errorAtCheckBoards();
} else {
emit successAtCheckBoards();
} }
} }
unsigned newRow = loggerTable->rowCount(); });
loggerTable->insertRow(newRow); }
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); // Если нет ни одной активной платы
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr))); if(*totalActiveBoards == 0) {
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString())); emit errorAtCheckBoards();
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardNum].error_adr_change, 10))); }
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Не удалось изменить адрес устройства."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater();
} }
void M3KTE::onSpeedUpdate() void M3KTE::onSpeedUpdate()
{ {
stopScanBoard(); stopScanBoard();
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 173, 1); modbusDevice->setTimeout(500);
QModbusDataUnit* _unitcheck = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1); unsigned tmp_speed = 0;
_unit->setValue(0, m_deviceSettingsDialog->currentSpeed()); switch(m_deviceSettingsDialog->currentSpeed()) {
unsigned tmp_speed = m_deviceSettingsDialog->currentSpeed(); case 0: tmp_speed = 9600; break;
for (int i = 0; i < 4; i++) { case 1: tmp_speed = 14400; break;
if (!Boards[i].isActive) case 2: tmp_speed = 19200; break;
{ case 3: tmp_speed = 31250; break;
continue; case 4: tmp_speed = 38400; break;
case 5: tmp_speed = 56000; break;
case 6: tmp_speed = 57600; break;
case 7: tmp_speed = 115200; break;
} }
if (auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[i].adr))
{ if(tmp_speed == 0) {
while(!reply->isFinished()) logError(tr("Программная ошибка"), "Неожиданное значение скорости", 0,
{ "Ошибка при изменении скорости обмена.");
QCoreApplication::processEvents(); beginScanBoards();
} return;
if(reply->error()==QModbusDevice::TimeoutError)
{
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
tmp_speed);
modbusDevice->connectDevice();
if(auto *subreply = modbusDevice->sendReadRequest(*_unitcheck, Boards[i].adr))
{
while (!subreply->isFinished())
{
QCoreApplication::processEvents();
}
if(subreply->error() != QModbusDevice::NoError)
{
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(i+1).arg(Boards[i].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(subreply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[i].error_baud_change, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Ошибка при изменении скорости обмена."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
subreply->deleteLater();
} }
// Используем shared pointers вместо ссылок на стековые переменные
auto totalActiveBoards = QSharedPointer<int>::create(0);
auto confirmedBoards = QSharedPointer<int>::create(0);
auto pendingBoards = QSharedPointer<QSet<int>>::create();
auto newSpeed = tmp_speed; // копируем для захвата
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 173, 1);
unit.setValue(0, m_deviceSettingsDialog->currentSpeed());
// Лямбда для обработки результата
auto processResult = [this, totalActiveBoards, confirmedBoards, newSpeed]() {
if(*confirmedBoards != *totalActiveBoards) {
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
revertToOldSpeedAndRestart();
beginScanBoards();
} else { } else {
unsigned newRow = loggerTable->rowCount(); modbusDevice->disconnectDevice();
loggerTable->insertRow(newRow); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, newSpeed);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); modbusDevice->connectDevice();
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(i+1).arg(Boards[i].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString())); // Используем QPointer для безопасного доступа к this
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[i].error_baud_change, 10))); QPointer<M3KTE> safeThis(this);
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Ошибка при изменении скорости обмена."));
loggerTable->resizeColumnsToContents(); connect(this, &M3KTE::errorAtCheckBoards, this, [safeThis]() {
if(!loggerTable->verticalScrollBar()->isSliderDown()) if (!safeThis) return;
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum()); safeThis->disconnect(safeThis, &M3KTE::errorAtCheckBoards, safeThis, nullptr);
safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime);
safeThis->revertToOldSpeedAndRestart();
safeThis->beginScanBoards();
});
connect(this, &M3KTE::successAtCheckBoards, this, [safeThis]() {
if (!safeThis) return;
safeThis->disconnect(safeThis, &M3KTE::successAtCheckBoards, safeThis, nullptr);
safeThis->m_settingsDialog->UpdateBaud(safeThis->m_deviceSettingsDialog->currentSpeed());
safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime);
safeThis->beginScanBoards();
});
checkBoards();
} }
};
for(int i = 0; i < 4; i++) {
if(!Boards[i].isActive)
continue;
int slaveAdress = Boards[i].adr;
auto *reply = modbusDevice->sendWriteRequest(unit, slaveAdress);
if(reply) {
(*totalActiveBoards)++;
pendingBoards->insert(slaveAdress);
// Захватываем shared pointers по значению - это безопасно
connect(reply, &QModbusReply::finished, this,
[this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() {
if(reply->error() == QModbusDevice::TimeoutError) {
(*confirmedBoards)++;
} else if (reply->error() == QModbusDevice::NoError) {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress),
tr("Неожиданный ответ."), ++Boards[i].error_baud_change,
"Ошибка при изменении скорости обмена.");
} else {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress),
reply->errorString(), ++Boards[i].error_baud_change,
"Ошибка при изменении скорости обмена.");
}
pendingBoards->remove(slaveAdress);
reply->deleteLater();
if(pendingBoards->isEmpty()) {
processResult();
}
});
}
}
}
// Вспомогательная функция восстановления старой скорости
void M3KTE::revertToOldSpeedAndRestart()
{
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
m_settingsDialog->curBaud()); m_settingsDialog->curBaud());
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
modbusDevice->connectDevice(); modbusDevice->connectDevice();
}
else
{
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(i+1).arg(Boards[i].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[i].error_baud_change, 10)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Ошибка при изменении скорости обмена."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
delete reply; // broadcast replies return immediately
}
}
}
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
m_settingsDialog->UpdateBaud(tmp_speed));
modbusDevice->connectDevice();
beginScanBoards();
} }
void M3KTE::onParityUpdate() void M3KTE::onParityUpdate()
{ {
stopScanBoard(); stopScanBoard();
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 174, 1); modbusDevice->setTimeout(500);
switch (m_deviceSettingsDialog->currentParity()) QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 174, 1);
{ switch(m_deviceSettingsDialog->currentParity()) {
case 0: //Нет контроля case 0: //Нет контроля
{ unit.setValue(0, 0x000);
_unit->setValue(0, 0x000);
break; break;
}
case 1: //Четный case 1: //Четный
{ unit.setValue(0, 0x0400);
_unit->setValue(0, 0x0400);
break; break;
}
case 2: //Нечетный case 2: //Нечетный
{ unit.setValue(0, 0x0600);
_unit->setValue(0, 0x0600);
break; break;
} }
}
for (int i = 0; i < 4; i++) { // Используем shared pointers вместо ссылок на стековые переменные
if (!Boards[i].isActive) auto totalActiveBoards = QSharedPointer<int>::create(0);
{ auto confirmedBoards = QSharedPointer<int>::create(0);
continue; auto pendingBoards = QSharedPointer<QSet<int>>::create();
} auto oldParity = m_settingsDialog->curParity(); // сохраняем старую четность для отката
if(auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[i].adr)) auto newParity = m_deviceSettingsDialog->currentParity();
{
while (!reply->isFinished()) // Лямбда для обработки результата
{ auto processResult = [this, totalActiveBoards, confirmedBoards, oldParity, newParity]() {
QCoreApplication::processEvents(); if(*confirmedBoards != *totalActiveBoards) {
} modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
if(reply->error()==QModbusDevice::TimeoutError) beginScanBoards();
{
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
m_deviceSettingsDialog->currentParity());
modbusDevice->connectDevice();
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1);
if (auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[i].adr))
{
while (!subreply->isFinished())
{
QCoreApplication::processEvents();
}
if(subreply->error() != QModbusDevice::NoError)
{
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(i+1).arg(Boards[i].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(subreply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[i].error_parity_change)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Ошибка при изменении чётности платы."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
}
} else { } else {
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(i+1).arg(Boards[i].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[i].error_parity_change)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Ошибка при изменении чётности платы."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
}
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, newParity);
m_settingsDialog->curParity());
modbusDevice->connectDevice(); modbusDevice->connectDevice();
}
else auto errorHandler = [this, oldParity]() {
{ disconnect(this, &M3KTE::errorAtCheckBoards, this, nullptr);
unsigned newRow = loggerTable->rowCount(); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(i+1).arg(Boards[i].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[i].error_parity_change)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Ошибка при изменении чётности платы."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
}
}
else
{
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(i+1).arg(Boards[i].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[i].error_parity_change)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem("Ошибка при изменении чётности платы."));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
delete reply; // broadcast replies return immediately
}
}
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, oldParity);
m_settingsDialog->UpdateParity(m_deviceSettingsDialog->currentParity()));
modbusDevice->connectDevice(); modbusDevice->connectDevice();
beginScanBoards(); beginScanBoards();
};
auto successHandler = [this, newParity]() {
disconnect(this, &M3KTE::successAtCheckBoards, this, nullptr);
m_settingsDialog->UpdateParity(newParity);
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
beginScanBoards();
};
connect(this, &M3KTE::errorAtCheckBoards, this, errorHandler);
connect(this, &M3KTE::successAtCheckBoards, this, successHandler);
checkBoards();
}
};
for(int i = 0; i < 4; i++) {
if(!Boards[i].isActive)
continue;
int slaveAdress = Boards[i].adr;
auto *reply = modbusDevice->sendWriteRequest(unit, slaveAdress);
if(reply) {
(*totalActiveBoards)++;
pendingBoards->insert(slaveAdress);
connect(reply, &QModbusReply::finished, this,
[this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() {
if(reply->error() == QModbusDevice::TimeoutError) {
(*confirmedBoards)++;
} else if (reply->error() == QModbusDevice::NoError) {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress),
tr("Неожиданный ответ."), ++Boards[i].error_baud_change,
"Ошибка при изменении чётности.");
} else {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress),
reply->errorString(), ++Boards[i].error_baud_change,
"Ошибка при изменении чётности.");
}
pendingBoards->remove(slaveAdress);
reply->deleteLater();
if(pendingBoards->isEmpty()) {
processResult();
}
});
}
}
} }
bool M3KTE::pingNetworkDevices() bool M3KTE::pingNetworkDevices()
{ {
CurrentConnectedDevice = 0; CurrentConnectedDevice = 0;
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1);
int tmp_adr = 1; int tmp_adr = 1;
bool isRun = false; bool isRun = false;
bool *tmp_isRun = &isRun; bool *tmp_isRun = &isRun;
auto bar = new QProgressDialog(this); auto bar = new QProgressDialog(this);
connect(bar, &QProgressDialog::canceled, this, [this, tmp_isRun]() connect(bar, &QProgressDialog::canceled, this, [tmp_isRun]() {
{
*tmp_isRun = true; *tmp_isRun = true;
}); });
bar->setLabelText(tr("Поиск плат... Текущий адрес: %1").arg(tmp_adr)); bar->setLabelText(tr("Поиск плат... Текущий адрес: %1").arg(tmp_adr));
@@ -1225,102 +1226,112 @@ bool M3KTE::pingNetworkDevices()
bar->setMinimumDuration(100); bar->setMinimumDuration(100);
bar->setValue(CurrentConnectedDevice); bar->setValue(CurrentConnectedDevice);
modbusDevice->setNumberOfRetries(0); modbusDevice->setNumberOfRetries(0);
QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404")); QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404"));
QModbusRequest requestOfBoardID(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0401")); QModbusRequest requestOfBoardID(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0401"));
modbusDevice->setTimeout(50); modbusDevice->setTimeout(50);
for(CurrentConnectedDevice=0; CurrentConnectedDevice<4;) for(CurrentConnectedDevice=0; CurrentConnectedDevice<4;) {
{
auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr); auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr);
//auto *reply = modbusDevice->sendReadRequest(*_unit, tmp_adr);
//Запрос типа устройства. //Запрос типа устройства.
if(reply == nullptr) if(reply == nullptr) {
{
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} }
while(!reply->isFinished()) while(!reply->isFinished()) {
{ if(isRun && CurrentConnectedDevice < 1) {
if(isRun && CurrentConnectedDevice < 1)
{
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} } else if(isRun) {
else if(isRun)
{
break; break;
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(isRun && CurrentConnectedDevice < 1) if(isRun && CurrentConnectedDevice < 1) {
{
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} } else if(isRun) {
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));
//result.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(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} } else if(isRun) {
else if(isRun)
{
break; break;
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(isRun && CurrentConnectedDevice < 1) int plata_ind = 0;
if(subreply->rawResult().data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) // ответ принят
plata_ind = subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH); // парс ответа
if(plata_ind == 0) // если номер = 0 повторяем всё еще раз
{ {
qDebug() << "Reqest plata_ind again for address " << tmp_adr;
subreply = modbusDevice->sendRawRequest(requestOfBoardID, tmp_adr);
while(!subreply->isFinished()) {
if(isRun && CurrentConnectedDevice < 1) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
} else if(isRun) {
break;
}
QCoreApplication::processEvents();
}
plata_ind = subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH);
}
if(plata_ind == 0)
{
QMessageBox::warning(this, "Ошибка при сканировании сети.",
QString("Не удалось получить порядковый номер платы по адресу %1").arg(tmp_adr));
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} }
else if(isRun)
{ int board_ind = plata_ind-1;
if(isRun && CurrentConnectedDevice < 1) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
} else if(isRun) {
break; break;
} } else {
else statusBar()->showMessage(tr("Плата %1 найдена по адресу %2.").arg(board_ind).arg(tmp_adr),
{ m_settingsDialog->settings().responseTime);
//QString boardID(subreply->rawResult().data()); if(Boards[board_ind].isActive) {
//boardID.remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH); QMessageBox::warning(this, "Ошибка при сканировании сети.",
if(Boards[(int)(subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH))-1].isActive) QString("Платы по адресам %1 и %2 имеют одинаковый порядковый номер %3").arg(Boards[board_ind].adr).arg(tmp_adr).arg(plata_ind));
{
QMessageBox::warning(this, "Ошибка при сканировании сети.", QString("Платы по адресам %1 и %2 имеют одинаковый ID %3").arg(Boards[(int)subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH)].adr).arg(tmp_adr).arg((int)subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH)));
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} }
CurrentConnectedDevice++; CurrentConnectedDevice++;
Boards[(int)(subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH))-1].adr = Boards[(int)(subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH))-1]._tmp_adr = tmp_adr; Boards[board_ind].adr = Boards[board_ind]._tmp_adr = tmp_adr;
statusBar()->showMessage(tr("Плата %1 найдена по адресу %2.").arg((int)(subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH))-1).arg(tmp_adr), m_settingsDialog->settings().responseTime);
Boards[(int)(subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH))-1].isActive = true;
Boards[board_ind].isActive = true;
bar->setValue(CurrentConnectedDevice); bar->setValue(CurrentConnectedDevice);
} }
} }
@@ -1328,26 +1339,23 @@ bool M3KTE::pingNetworkDevices()
} }
tmp_adr++; tmp_adr++;
bar->setLabelText(tr("Поиск плат... Текущий адрес: %1").arg(tmp_adr)); bar->setLabelText(tr("Поиск плат... Текущий адрес: %1").arg(tmp_adr));
if(tmp_adr>=247 && (CurrentConnectedDevice<1)) if(tmp_adr>=247 && (CurrentConnectedDevice<1)) {
{
//ERROR //ERROR
//OUT OF RANGE //OUT OF RANGE
QMessageBox::warning(this, "Ошибка при сканировании сети.", QString("Выход за пределы допустимых адресов. Найдено %1 плат.").arg(CurrentConnectedDevice)); QMessageBox::warning(this, "Ошибка при сканировании сети.",
QString("Выход за пределы допустимых адресов. Найдено %1 плат.").arg(CurrentConnectedDevice));
bar->setValue(4); bar->setValue(4);
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
onConnectClicked(); onConnectClicked();
return false; return false;
} } else if(tmp_adr>=247) {
else if(tmp_adr>=247)
{
break; break;
} }
} }
isRun=false; isRun=false;
QMessageBox::warning(this, "Сканирование сети завершено.", tr("Найдено плат: %1 из 4.").arg(CurrentConnectedDevice)); QMessageBox::warning(this, "Сканирование сети завершено.", tr("Найдено плат: %1 из 4.").arg(CurrentConnectedDevice));
if(isRun) if(isRun) {
{
QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя.")); QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя."));
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
@@ -1357,60 +1365,67 @@ bool M3KTE::pingNetworkDevices()
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++) {
if(Boards[i].isActive) {
QModbusDataUnit* _unit_settings[3]; QModbusDataUnit* _unit_settings[3];
_unit_settings[0] = new QModbusDataUnit(QModbusDataUnit::Coils, 0, 85); _unit_settings[0] = new QModbusDataUnit(QModbusDataUnit::Coils, 0, 85-(i/3*20));
_unit_settings[1] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 0, 85); _unit_settings[1] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 0, 85-(i/3*20));
_unit_settings[2] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 85, 85); _unit_settings[2] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 85, 85-(i/3*20));
for(int i=0; i<4; i++)
{
if(Boards[i].isActive)
{
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(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
delete _unit_settings[0];
delete _unit_settings[1];
delete _unit_settings[2];
return false; 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(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
delete _unit_settings[0];
delete _unit_settings[1];
delete _unit_settings[2];
return false; return false;
} }
while(!reply->isFinished()) while(!reply->isFinished()) {
{ if(isRun) {
if(isRun) QMessageBox::warning(this, "Ошибка при получении текущих настроек.",
{ QString("Прерывание по запросу пользователя."));
QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя."));
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
delete _unit_settings[0];
delete _unit_settings[1];
delete _unit_settings[2];
return false; 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, "Ошибка при получении текущих настроек.",
{ QString("Таймаут при опросе устройства %1 по адресу %2").arg(i+1).arg(Boards[i].adr));
QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Таймаут при опросе устройства %1 по адресу %2").arg(i+1).arg(Boards[i].adr));
bar->setValue(CurrentConnectedDevice*3); bar->setValue(CurrentConnectedDevice*3);
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
onConnectClicked(); onConnectClicked();
delete _unit_settings[0];
delete _unit_settings[1];
delete _unit_settings[2];
return false; return false;
} }
} }
Boards_Fields[i]->setTitle(QString("Плата №%1 (ID %2)").arg(i).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];
} }
} }
modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries); modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries);
@@ -1421,9 +1436,9 @@ bool M3KTE::pingNetworkDevices()
void M3KTE::beginScanBoards() void M3KTE::beginScanBoards()
{ {
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_deviceSettingsDialog->initPollForBoard(i, Boards[i].adr); m_deviceSettingsDialog->initPollForBoard(i, Boards[i].adr);
boardScan(i); boardScan(i);
} }
@@ -1433,191 +1448,217 @@ void M3KTE::beginScanBoards()
void M3KTE::boardScan(unsigned boardID) void M3KTE::boardScan(unsigned boardID)
{ {
if (!modbusDevice) if (!modbusDevice) {
return; return;
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1); }
emit boardReading(boardID);
statusBar()->clearMessage(); statusBar()->clearMessage();
if (auto *reply = modbusDevice->sendReadRequest(*_unit, Boards[boardID].adr)) { QModbusDataUnit statusUnit(QModbusDataUnit::InputRegisters, 85, 1);
if (auto *reply = modbusDevice->sendReadRequest(statusUnit, Boards[boardID].adr)) {
Boards[boardID].timerToStatusResponse.start(); Boards[boardID].timerToStatusResponse.start();
if (!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() if (!reply->isFinished()) {
{ connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() {
if(!Boards[boardID].isActive)
return;
// Обработка ответа статуса
Boards[boardID].timerStatus->setText(QString("Status: %1 ms").arg(Boards[boardID].timerToStatusResponse.elapsed())); Boards[boardID].timerStatus->setText(QString("Status: %1 ms").arg(Boards[boardID].timerToStatusResponse.elapsed()));
if(reply->error()==QModbusDevice::NoError) {
if (reply->error() == QModbusDevice::NoError) {
statusreg StatusReg; statusreg StatusReg;
StatusReg.AllReg = reply->result().value(0); StatusReg.AllReg = reply->result().value(0);
if(StatusReg.ParsingReg.poll_allowed)
{
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
return;
}
if(StatusReg.ParsingReg.mzkte_status)
{
switch (StatusReg.ParsingReg.mzkte_error) {
case 1:
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
return;
case 2:
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
return;
case 3:
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
return;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
default:
break;
}
}
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 0, 85);
if (auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[boardID].adr)) { // Запрос полных данных
QModbusDataUnit dataUnit(QModbusDataUnit::InputRegisters, 0, 85-(boardID/3*20));
if (auto *dataReply = modbusDevice->sendReadRequest(dataUnit, Boards[boardID].adr)) {
Boards[boardID].timerToDataResponse.start(); Boards[boardID].timerToDataResponse.start();
if (!subreply->isFinished())
{ if (!dataReply->isFinished()) {
connect(subreply, &QModbusReply::finished, this, [this, boardID]() connect(dataReply, &QModbusReply::finished, this, [this, boardID, dataReply, StatusReg]() {
{ if(!Boards[boardID].isActive)
Boards[boardID].timerData->setText(QString("Data: %1 ms").arg(Boards[boardID].timerToStatusResponse.elapsed())); return;
auto subreply = qobject_cast<QModbusReply *>(sender()); Boards[boardID].timerData->setText(QString("Data: %1 ms").arg(Boards[boardID].timerToDataResponse.elapsed()));
displayResultOfScan(subreply, boardID); displayResultOfScan(dataReply, boardID, StatusReg.AllReg);
subreply->deleteLater(); dataReply->deleteLater();
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID)); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}); });
} else { } else {
// Мгновенно завершенный запрос данных
Boards[boardID].timerToDataResponse.elapsed(); Boards[boardID].timerToDataResponse.elapsed();
unsigned newRow = loggerTable->rowCount(); // shouldLog для dataReply должен определяться здесь, но используем тот же принцип
loggerTable->insertRow(newRow); if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr))); modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString())); }
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardID].error_TX))); dataReply->deleteLater();
loggerTable->resizeColumnsToContents(); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
if(!loggerTable->verticalScrollBar()->isSliderDown()) Boards[boardID].boardScanners->start(timerInterval);
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
delete subreply;
} }
} else { } else {
unsigned newRow = loggerTable->rowCount(); // Ошибка отправки запроса данных
loggerTable->insertRow(newRow); if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr))); modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardID].error_TX)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
delete subreply;
} }
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
} else { } else {
unsigned newRow = loggerTable->rowCount(); // Ошибка в ответе статуса
loggerTable->insertRow(newRow); if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr))); reply->errorString(), ++Boards[boardID].error_TX, "");
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardID].error_TX)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
reply->deleteLater();
}); });
else } else {
{ // Мгновенно завершенный запрос статуса
Boards[boardID].timerToStatusResponse.elapsed(); Boards[boardID].timerToStatusResponse.elapsed();
unsigned newRow = loggerTable->rowCount(); // Для мгновенно завершенных запросов определяем shouldLog здесь
loggerTable->insertRow(newRow); if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr))); modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString())); }
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardID].error_TX))); reply->deleteLater();
loggerTable->resizeColumnsToContents(); unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
if(!loggerTable->verticalScrollBar()->isSliderDown()) Boards[boardID].boardScanners->start(timerInterval);
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
delete reply; // broadcast replies return immediately
} }
} else { } else {
// QMessageBox::warning(this, QString("Ошибка при опросе платы #%1").arg(boardID+1), QString(tr("Read error: ") + modbusDevice->errorString())); // Ошибка отправки запроса статуса
// statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000); if (Boards[boardID].isActive) {
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
loggerTable->insertRow(newRow); modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); }
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(modbusDevice->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardID].error_TX)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
} }
void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID)
void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status)
{ {
if (!reply) if(!reply)
return; return;
if (reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result(); const QModbusDataUnit unit = reply->result();
bool W_Flag = false; bool W_Flag = false;
bool A_Flag = false; bool A_Flag = false;
if(unit.startAddress() != 0 || unit.valueCount() != 85)
{ if(unit.startAddress() != 0 || unit.valueCount() != (unsigned)(85-(boardID/3*20))) {
//ERROR logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
//QMessageBox::warning(this, QString("Ошибка при опросе платы #%1").arg(boardID), QString("Принятый ответ: Стартовый адрес %1, Количество элементов %2").arg(unit.startAddress()).arg(unit.valueCount())); "Ошибка при приёме.", ++Boards[boardID].error_RX,
unsigned newRow = loggerTable->rowCount(); tr("Принятый ответ: Стартовый адрес %1, Количество элементов %2").arg(unit.startAddress()).arg(unit.valueCount()));
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem("Ошибка при приёме."));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardID].error_RX)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString("Принятый ответ: Стартовый адрес %1, Количество элементов %2").arg(unit.startAddress()).arg(unit.valueCount())));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
return; return;
} }
statusreg StatusReg;
StatusReg.AllReg = status;
// Обрабатываем статус MZKT
QString statusText;
int state = StatusReg.ParsingReg.mzkte_status;
int numb_err = StatusReg.ParsingReg.mzkte_error;
if (state == 0) {
statusText = "Ok";
} else if (state == 1) {
statusText = "Non-Critical";
} else if (state == 2) {
statusText = "Critical";
}
if (state) {
switch (numb_err) {
case 1:
statusText += QString(" (Err 5 VD)");
break;
case 2:
statusText += QString(" (Err 5 VA)");
break;
case 3:
statusText += QString(" (Err 5 Vsci)");
break;
case 4:
statusText += QString(" (Err 24 V)");
break;
case 5:
statusText += QString(" (Hardfault)");
break;
case 6:
statusText += QString(" (Empty Settings)");
break;
case 7:
statusText += QString(" (ADC Error)");
break;
case 8:
statusText += QString(" (Program Err 4)");
break;
case 9:
statusText += QString(" (Program Err 5)");
break;
case 10:
statusText += QString(" (EEPROM Error)");
break;
case 11:
statusText += QString(" (Unstable discharge level)");
break;
case 12:
statusText += QString(" (RS/UART Errors)");
break;
default:
statusText += QString(" (Program Err %1)").arg(numb_err - 4);
break;
}
}
Boards[boardID].localError->setText(statusText);
Boards[boardID].localState[LOCAL_STATE_POLL]->setChecked(StatusReg.ParsingReg.poll_allowed);
Boards[boardID].localState[LOCAL_STATE_WARN]->setChecked(StatusReg.ParsingReg.warning);
Boards[boardID].localState[LOCAL_STATE_ERR]->setChecked(StatusReg.ParsingReg.accident);
QString W_Adr; QString W_Adr;
QString A_Adr; QString A_Adr;
for(int i = unit.startAddress(), total = int(unit.valueCount()); i < total; ++i) int total_qnt;
if(boardID == 3)
{ {
if(Boards[boardID].coil[i]==true) total_qnt = 65;
}
else
{ {
total_qnt = 85;
}
for(int i = unit.startAddress(), total = total_qnt; i < total; ++i) {
if(Boards[boardID].coil[i]==true) {
int j = 0; int j = 0;
if(Boards[boardID].HR[i + 85] > unit.value(i)) if(Boards[boardID].HR[i+85] > unit.value(i)) {
{
j = 1; j = 1;
if(j != m_ProgressBar[i+boardID*85]->value()) if(j != m_ProgressBar[i+boardID*85]->value()) {
{
A_Adr += tr("ТЭ%1 ").arg(i); A_Adr += tr("ТЭ%1 ").arg(i);
Boards[boardID].error_A++; Boards[boardID].error_A++;
} }
m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85))); m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85)));
m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85))); m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85)));
A_Flag = true; A_Flag = true;
} } else if(Boards[boardID].HR[i] > unit.value(i)) {
else if(Boards[boardID].HR[i] > unit.value(i))
{
j = 2; j = 2;
if(j != m_ProgressBar[i+boardID*85]->value()) if(j != m_ProgressBar[i+boardID*85]->value()) {
{
W_Adr += tr("ТЭ%1 ").arg(i); W_Adr += tr("ТЭ%1 ").arg(i);
Boards[boardID].error_W++; Boards[boardID].error_W++;
} }
m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85))); m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85)));
m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85))); m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85)));
W_Flag = true; W_Flag = true;
} } else {
else
{
j = 3; j = 3;
m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID+1), QString::number(i%85))); m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID+1), QString::number(i%85)));
m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID+1), QString::number(i%85))); m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID+1), QString::number(i%85)));
@@ -1625,9 +1666,7 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID)
m_ProgressBar[i+boardID*85]->setValue(j); m_ProgressBar[i+boardID*85]->setValue(j);
QString style_fc = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(j*50-50) + ", 255, 255, 100%);} "; QString style_fc = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(j*50-50) + ", 255, 255, 100%);} ";
m_ProgressBar[i+boardID*85]->setStyleSheet(style_fc); m_ProgressBar[i+boardID*85]->setStyleSheet(style_fc);
} } else {
else
{
m_ProgressBar[i+boardID*85]->setValue(3); m_ProgressBar[i+boardID*85]->setValue(3);
m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID+1), QString::number(i%85))); m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID+1), QString::number(i%85)));
m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID+1), QString::number(i%85))); m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID+1), QString::number(i%85)));
@@ -1637,88 +1676,50 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID)
Boards[boardID].ModbusModelCoil->set_currentU(unit.value(i), i); Boards[boardID].ModbusModelCoil->set_currentU(unit.value(i), i);
Boards[boardID].ModbusModelHoldingReg->set_currentU(unit.value(i), i); Boards[boardID].ModbusModelHoldingReg->set_currentU(unit.value(i), i);
} }
if(A_Flag) Boards[boardID].ModbusModelCoil->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 2),
{ ui->writeValueTable->model()->index(unit.startAddress() + total_qnt -1, 2));
Boards[boardID].ModbusModelHoldingReg->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 3),
ui->writeValueTable->model()->index(unit.startAddress() + total_qnt -1, 3));
if(A_Flag && !A_Adr.isEmpty()) {
statusM3KTE.Accidents[boardID] = true; statusM3KTE.Accidents[boardID] = true;
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
loggerTable->insertRow(newRow); "Авария", Boards[boardID].error_A, A_Adr);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); } else
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem("Авария"));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(Boards[boardID].error_A)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(A_Adr));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
}
else
statusM3KTE.Accidents[boardID] = false; statusM3KTE.Accidents[boardID] = false;
if(W_Flag) if(W_Flag && !W_Adr.isEmpty()) {
{
statusM3KTE.Warnings[boardID] = true; statusM3KTE.Warnings[boardID] = true;
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
loggerTable->insertRow(newRow); "Предупреждение", Boards[boardID].error_W, W_Adr);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); } else
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem("Предупреждение"));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(Boards[boardID].error_W)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(W_Adr));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
}
else
statusM3KTE.Warnings[boardID] = false; statusM3KTE.Warnings[boardID] = false;
ui->BSM_Warning->setChecked(false); ui->BSM_Warning->setChecked(false);
ui->BSM_Accident->setChecked(false); ui->BSM_Accident->setChecked(false);
ui->BSM_WorkInProgress->setChecked(true); ui->BSM_WorkInProgress->setChecked(true);
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{ if(statusM3KTE.Accidents[i]) {
if(statusM3KTE.Accidents[i])
{
ui->BSM_WorkInProgress->setChecked(false); ui->BSM_WorkInProgress->setChecked(false);
ui->BSM_Warning->setChecked(false); ui->BSM_Warning->setChecked(false);
ui->BSM_Accident->setChecked(true); ui->BSM_Accident->setChecked(true);
break; break;
} }
if(statusM3KTE.Warnings[i]) if(statusM3KTE.Warnings[i]) {
{
ui->BSM_WorkInProgress->setChecked(false); ui->BSM_WorkInProgress->setChecked(false);
ui->BSM_Accident->setChecked(false); ui->BSM_Accident->setChecked(false);
ui->BSM_Warning->setChecked(true); ui->BSM_Warning->setChecked(true);
} }
} }
} else if (reply->error() == QModbusDevice::ProtocolError) { } else if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)"). statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()). arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
arg(reply->rawResult().exceptionCode(), -1, 16), 5000); logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_RX,
unsigned newRow = loggerTable->rowCount(); QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16));
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardID].error_RX)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} else { } else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)"). statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()). arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
arg(reply->error(), -1, 16), 5000); logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_RX,
unsigned newRow = loggerTable->rowCount(); QString::number(reply->error(), 16));
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[boardID].error_RX)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString::number(reply->error(), 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
reply->deleteLater(); reply->deleteLater();
} }
@@ -1726,78 +1727,53 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID)
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), 16), Qt::EditRole); Boards[Adr].ModbusModelHoldingReg->setData(Boards[Adr].ModbusModelHoldingReg->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 10), Qt::EditRole);
} }
} }
} else if (reply->error() == QModbusDevice::ProtocolError) { } else if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)"). statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()). arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
arg(reply->rawResult().exceptionCode(), -1, 16), 5000); logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
unsigned newRow = loggerTable->rowCount(); reply->errorString(), ++Boards[Adr].error_RX,
loggerTable->insertRow(newRow); QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16));
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[Adr].error_RX)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} else { } else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)"). statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()). arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
arg(reply->error(), -1, 16), 5000); logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
unsigned newRow = loggerTable->rowCount(); reply->errorString(), ++Boards[Adr].error_RX,
loggerTable->insertRow(newRow); QString::number(reply->error(), 16));
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[Adr].error_RX)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString::number(reply->error(), 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
reply->deleteLater(); reply->deleteLater();
} }
void M3KTE::slotmultipleRegWrite() void M3KTE::slotmultipleRegWrite()
{ {
if (!modbusDevice) if(!modbusDevice)
return; return;
multipleRegWrite(); multipleRegWrite();
} }
void M3KTE::slotmultipleRegWriteAndSend() void M3KTE::slotmultipleRegWriteAndSend()
{ {
if (!modbusDevice) if(!modbusDevice)
return; return;
multipleRegWrite(); multipleRegWrite();
multipleRegSend(); multipleRegSend();
@@ -1806,56 +1782,35 @@ void M3KTE::slotmultipleRegWriteAndSend()
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()) {
connect(reply, &QModbusReply::finished, this, [this, reply, Adr]() { connect(reply, &QModbusReply::finished, this, [this, reply, Adr]() {
if (reply->error() == QModbusDevice::ProtocolError) { if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)") statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
5000); logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
unsigned newRow = loggerTable->rowCount(); reply->errorString(), ++Boards[Adr].error_TX,
loggerTable->insertRow(newRow); QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16));
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); } else if(reply->error() != QModbusDevice::NoError) {
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[Adr].error_TX)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} else if (reply->error() != QModbusDevice::NoError) {
statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)"). statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(reply->error(), -1, 16), 5000); arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
unsigned newRow = loggerTable->rowCount(); logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
loggerTable->insertRow(newRow); reply->errorString(), ++Boards[Adr].error_TX,
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); QString::number(reply->error(), 16));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr)));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(reply->errorString()));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(++Boards[Adr].error_TX)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(QString::number(reply->error(), 16)));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} }
reply->deleteLater(); reply->deleteLater();
}); });
@@ -1870,22 +1825,79 @@ void M3KTE::multipleRegSend()
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();
} }
} }
} }
void M3KTE::writeSingleCoil(int boardId, int coilAddress, bool value)
{
if (!modbusDevice || !Boards[boardId].isActive)
return;
QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1);
unit.setValue(0, value ? 1 : 0);
if (auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardId].adr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, boardId, reply]() {
if (reply->error() != QModbusDevice::NoError) {
logError(tr("Плата %1 (ID %2)").arg(boardId+1).arg(Boards[boardId].adr),
reply->errorString(), ++Boards[boardId].error_TX,
"Single coil write");
}
reply->deleteLater();
});
} else {
reply->deleteLater();
}
}
}
void M3KTE::writeSingleRegister(int boardID, int regAddress, quint16 value)
{
if (!modbusDevice || !Boards[boardID].isActive)
return;
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, regAddress, 1);
unit.setValue(0, value);
if (auto *reply = modbusDevice->sendWriteRequest(unit, Boards[boardID].adr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() {
if (reply->error() != QModbusDevice::NoError) {
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_TX,
"Single register write");
}
reply->deleteLater();
});
} else {
reply->deleteLater();
}
}
}
QModbusReply* M3KTE::readSingleCoil(int boardID, int coilAddress)
{
if (!modbusDevice || !Boards[boardID].isActive)
return nullptr;
QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1);
auto *reply = modbusDevice->sendReadRequest(unit, Boards[boardID].adr);
return reply;
}
void M3KTE::selectPositionOnTree(unsigned int index) void M3KTE::selectPositionOnTree(unsigned int index)
{ {
ui->boardSelectBox->setCurrentIndex(index/85); ui->boardSelectBox->setCurrentIndex(index/85);
QModelIndex selected = ui->writeValueTable->model()->index(index%85, 0); int maxReg = 85 - (ui->boardSelectBox->currentIndex()/3*20);
QModelIndex selected = ui->writeValueTable->model()->index(index%maxReg + maxReg*(ui->writeTable->currentIndex()/2), 0);
ui->writeValueTable->selectionModel()->select(selected, QItemSelectionModel::ClearAndSelect |QItemSelectionModel::Rows); ui->writeValueTable->selectionModel()->select(selected, QItemSelectionModel::ClearAndSelect |QItemSelectionModel::Rows);
ui->writeValueTable->scrollTo(selected); ui->writeValueTable->scrollTo(selected);
} }
@@ -1895,7 +1907,6 @@ bool M3KTE::autoBaudRateScan()
unsigned countOfDeviceOnLine = 0; unsigned countOfDeviceOnLine = 0;
QString resultOfScan; QString resultOfScan;
QVector<unsigned> KTE[8]; QVector<unsigned> KTE[8];
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
m_settingsDialog->settings().portName); m_settingsDialog->settings().portName);
#if QT_CONFIG(modbus_serialport) #if QT_CONFIG(modbus_serialport)
@@ -1906,53 +1917,38 @@ bool M3KTE::autoBaudRateScan()
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
m_settingsDialog->settings().stopBits); m_settingsDialog->settings().stopBits);
#endif #endif
modbusDevice->setTimeout(50); modbusDevice->setTimeout(50);
modbusDevice->setNumberOfRetries(0); modbusDevice->setNumberOfRetries(0);
uint m_baud[] = {9600, 14400, 19200, 31250, 38400, 56000, 57600, 115200}; uint m_baud[] = {9600, 14400, 19200, 31250, 38400, 56000, 57600, 115200};
bool isRun = false; bool isRun = false;
bool *tmp_isRun = &isRun; bool *tmp_isRun = &isRun;
auto bar = new QProgressDialog(this); auto bar = new QProgressDialog(this);
connect(bar, &QProgressDialog::canceled, this, [this, tmp_isRun]() connect(bar, &QProgressDialog::canceled, this, [tmp_isRun]() {
{
*tmp_isRun = true; *tmp_isRun = true;
}); });
bar->setCancelButton(nullptr); bar->setCancelButton(nullptr);
bar->setRange(0, 8); bar->setRange(0, 8);
bar->setMinimumDuration(100); bar->setMinimumDuration(100);
bar->setValue(0); bar->setValue(0);
QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404")); QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404"));
for(int i = 0; i < 8; i++) {
for(int i = 0; i < 8; i++)
{
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, modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]);
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);
//auto *reply = modbusDevice->sendReadRequest(*_unit, tmp_adr);
//Запрос типа устройства. //Запрос типа устройства.
if(reply == nullptr) if(reply == nullptr) {
{
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} }
while(!reply->isFinished()) while(!reply->isFinished()) {
{ if(isRun) {
if(isRun)
{
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
@@ -1960,23 +1956,17 @@ bool M3KTE::autoBaudRateScan()
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(isRun) if(isRun) {
{
onConnectClicked(); onConnectClicked();
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();
QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH)); QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH));
//result.remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH); if(result == QString("KTE")) {
if(result == QString("KTE"))
{
countOfDeviceOnLine++; countOfDeviceOnLine++;
KTE[i].append(tmp_adr); KTE[i].append(tmp_adr);
} }
@@ -1988,49 +1978,38 @@ bool M3KTE::autoBaudRateScan()
countOfDeviceOnLine = 0; countOfDeviceOnLine = 0;
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
} }
if(m_scanBoard->exec()==QDialog::Accepted) if(m_scanBoard->exec()==QDialog::Accepted) {
{ if(m_scanBoard->getCheckState()==Qt::Checked) {
if(m_scanBoard->getCheckState()==Qt::Checked) for(int i = 0; i < 8; i++) {
{ for(int j = 0; j < KTE[i].size(); j++) {
for(int i = 0; i < 8; i++) for(int l = i; l < 8; l++) {
{ if(KTE[l].indexOf(KTE[i].at(j))==-1) {
for (int j = 0; j < KTE[i].size(); j++) QMessageBox::warning(this, "Error",
{ QString("Несколько устройств по адресу %1, работающих на скоростях %2 и %3.").arg(KTE[i].at(j)).arg(m_baud[i]).arg(m_baud[l]));
for (int l = i; l < 8; l++) {
if(KTE[l].indexOf(KTE[i].at(j))==-1)
{
QMessageBox::warning(this, "Error", QString("Несколько устройств по адресу %1, работающих на скоростях %2 и %3.").arg(KTE[i].at(j)).arg(m_baud[i]).arg(m_baud[l]));
return false; return false;
} }
} }
} }
} }
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 173, 1); QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 173, 1);
_unit->setValue(0, m_scanBoard->getBaud()); _unit->setValue(0, m_scanBoard->getBaud());
for (int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
bar->setValue(i); bar->setValue(i);
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, if(!modbusDevice->connectDevice()) {
m_baud[i]);
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();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} }
while(!reply->isFinished()) while(!reply->isFinished()) {
{ if(isRun) {
if(isRun)
{
//dfQMessageBox::warning(this, "Ошибка при синхронизации скоростей.", QString("Прерывание по запросу пользователя."));
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
@@ -2038,20 +2017,15 @@ bool M3KTE::autoBaudRateScan()
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(reply->error()==QModbusDevice::TimeoutError) if(reply->error()==QModbusDevice::TimeoutError) {
{
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
m_settingsDialog->UpdateBaud(m_scanBoard->getBaud())); m_settingsDialog->UpdateBaud(m_scanBoard->getBaud()));
modbusDevice->connectDevice(); modbusDevice->connectDevice();
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1); QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1);
if (auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[i].adr)) if(auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[i].adr)) {
{ while(!subreply->isFinished()) {
while(!subreply->isFinished()) if(isRun) {
{
if(isRun)
{
//dfQMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя."));
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
@@ -2059,18 +2033,14 @@ bool M3KTE::autoBaudRateScan()
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(subreply->error()!=QModbusDevice::NoError) if(subreply->error()!=QModbusDevice::NoError) {
{
//QMessageBox::warning();
onConnectClicked(); onConnectClicked();
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return false; return false;
} }
} }
} } else if(reply->error()!=QModbusDevice::NoError) {
else if(reply->error()!=QModbusDevice::NoError)
{
return false; return false;
} }
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
@@ -2085,9 +2055,8 @@ bool M3KTE::autoBaudRateScan()
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

@@ -7,6 +7,7 @@
#include <QtSerialBus/QModbusDataUnit> #include <QtSerialBus/QModbusDataUnit>
#include "writeregistermodel.h" #include "writeregistermodel.h"
#include "debugterminaldialog.h"
#include "devicesettingsdialog.h" #include "devicesettingsdialog.h"
#include "multiplesettings.h" #include "multiplesettings.h"
#include "scanboard.h" #include "scanboard.h"
@@ -15,6 +16,7 @@
#include <QModbusTcpClient> #include <QModbusTcpClient>
#include <QModbusRtuSerialMaster> #include <QModbusRtuSerialMaster>
#include <QHBoxLayout>
#include <QTimer> #include <QTimer>
#include <QMessageBox> #include <QMessageBox>
#include <QProgressDialog> #include <QProgressDialog>
@@ -36,10 +38,15 @@
extern "C" __declspec(dllexport) QWidget* init(QWidget *parent); extern "C" __declspec(dllexport) QWidget* init(QWidget *parent);
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class M3KTE; class SettingsDialog;} namespace Ui { class M3KTE; class SettingsDialog; class DebugTerminalDialog;}
QT_END_NAMESPACE QT_END_NAMESPACE
#define LOCAL_STATE_POLL 0
#define LOCAL_STATE_WARN 1
#define LOCAL_STATE_ERR 2
class SettingsDialog; class SettingsDialog;
class DebugTerminalDialog;
class WriteRegisterModel; class WriteRegisterModel;
class M3KTE : public QMainWindow class M3KTE : public QMainWindow
@@ -54,76 +61,67 @@ private:
bool pingNetworkDevices(); bool pingNetworkDevices();
void beginScanBoards(); void beginScanBoards();
void stopScanBoard(); void stopScanBoard();
void displayResultOfScan(QModbusReply *reply, int boardID); void displayResultOfScan(QModbusReply *reply, int boardID, int status);
void applySettingsFromScan(QModbusReply *reply); void applySettingsFromScan(QModbusReply *reply);
void multipleRegWrite(); void multipleRegWrite();
void multipleRegSend(); void multipleRegSend();
void writeSingleCoil(int boardId, int coilAddress, bool value);
void writeSingleRegister(int boardId, int regAddress, quint16 value);
bool autoBaudRateScan(); bool autoBaudRateScan();
void selectPositionOnTree(unsigned index); void selectPositionOnTree(unsigned index);
signals:
void successAtCheckBoards();
void errorAtCheckBoards();
void boardReading(int boardID);
private slots: private slots:
void clearLogger();
void logError(const QString &errorPlace, const QString &errorString, unsigned errorCount, const QString &description);
void slotmultipleRegWrite(); void slotmultipleRegWrite();
void slotmultipleRegWriteAndSend(); void slotmultipleRegWriteAndSend();
void onConnectClicked(); void onConnectClicked();
void onReadButtonClicked(); void onReadButtonClicked();
void onReadReady(); void onReadReady();
void checkAdrChange(QModbusReply *reply, unsigned boardNum); void checkAdrChange(QModbusReply *reply, unsigned boardNum);
void onWriteButtonClicked(); void onWriteButtonClicked();
void onSelectedBoardChanged(int index); void onSelectedBoardChanged(int index);
void onWriteTableChanged(int index); void onWriteTableChanged(int index);
void checkBoards();
void onSpeedUpdate(); void onSpeedUpdate();
void revertToOldSpeedAndRestart();
void onParityUpdate(); void onParityUpdate();
void boardScan(unsigned boardID); void boardScan(unsigned boardID);
public: public:
M3KTE(QWidget *parent = nullptr); M3KTE(QWidget *parent = nullptr);
~M3KTE(); ~M3KTE();
QModbusClient* getModbusDevice() const { return modbusDevice; }
QModbusReply* readSingleCoil(int boardID, int coilAddress);
private: private:
Ui::M3KTE *ui; Ui::M3KTE *ui;
QTableWidget *loggerTable = nullptr; QTableWidget *loggerTable = nullptr;
int CurrentConnectedDevice = 0; int CurrentConnectedDevice = 0;
//int DeviceOnNetwork[4];
QProgressBar *m_ProgressBar[320]; QProgressBar *m_ProgressBar[320];
QPushButton *ThePhantomMenace[320]; QPushButton *ThePhantomMenace[320];
QModbusReply *lastRequest = nullptr; QModbusReply *lastRequest = nullptr;
QModbusClient *modbusDevice = nullptr; QModbusClient *modbusDevice = nullptr;
DeviceSettingsDialog *m_deviceSettingsDialog = nullptr; DeviceSettingsDialog *m_deviceSettingsDialog = nullptr;
DebugTerminalDialog *m_debugTerminalDialog = nullptr;
SettingsDialog *m_settingsDialog = nullptr; SettingsDialog *m_settingsDialog = nullptr;
MultipleSettings *m_regMultipleSettings = nullptr; MultipleSettings *m_regMultipleSettings = nullptr;
ScanBoard *m_scanBoard = nullptr; ScanBoard *m_scanBoard = nullptr;
LineRinger *m_lineRinger = nullptr; LineRinger *m_lineRinger = nullptr;
QGroupBox *Boards_Fields[4]; QGroupBox *Boards_Fields[4];
//WriteRegisterModel *writeModel = nullptr;
struct StatusM3KTE{ struct StatusM3KTE{
bool Warnings[4]; bool Warnings[4];
bool Accidents[4]; bool Accidents[4];
}statusM3KTE; }statusM3KTE;
unsigned error_terminal; unsigned error_terminal;
struct BoardModbusRegisters {
struct BoardModbusRegisters
{
bool isActive = false; bool isActive = false;
bool pollIsActive = true; bool pollIsActive = true;
int adr; int adr;
int _tmp_adr; int _tmp_adr;
bool coil[85]; bool coil[85];
unsigned HR[170]; unsigned HR[170];
unsigned error_W = 0; unsigned error_W = 0;
unsigned error_A = 0; unsigned error_A = 0;
unsigned error_modbus = 0; unsigned error_modbus = 0;
@@ -133,22 +131,19 @@ private:
unsigned error_TX = 0; unsigned error_TX = 0;
unsigned error_adr_change = 0; unsigned error_adr_change = 0;
unsigned error_cmd_change = 0; unsigned error_cmd_change = 0;
QLabel *timerData = nullptr; QLabel *timerData = nullptr;
QLabel *timerStatus = nullptr; QLabel *timerStatus = nullptr;
QLabel *localError = nullptr;
QCheckBox *localState[3] = {nullptr, nullptr, nullptr};
WriteRegisterModel *ModbusModelCoil; WriteRegisterModel *ModbusModelCoil;
WriteRegisterModel *ModbusModelHoldingReg; WriteRegisterModel *ModbusModelHoldingReg;
QTimer *boardScanners; QTimer *boardScanners;
bool isScan = false;
QElapsedTimer timerToStatusResponse; QElapsedTimer timerToStatusResponse;
QElapsedTimer timerToDataResponse; QElapsedTimer timerToDataResponse;
}Boards[4]; }Boards[4];
union statusreg {
union statusreg struct parsingFields {
{
struct parsingFields
{
unsigned accident:1; unsigned accident:1;
unsigned warning:1; unsigned warning:1;
unsigned poll_allowed:1; unsigned poll_allowed:1;

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
qputenv("QT_FATAL_WARNINGS", "0"); // отключает падение от ASSERT
QApplication a(argc, argv); QApplication a(argc, argv);
M3KTE w; M3KTE w;
w.show(); w.show();

View File

@@ -6,9 +6,9 @@ MultipleSettings::MultipleSettings(QWidget *parent) :
ui(new Ui::MultipleSettings) ui(new Ui::MultipleSettings)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Записать"); ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Записать");
ui->buttonBox->button(QDialogButtonBox::SaveAll)->setText("Записать и установить"); ui->buttonBox->button(QDialogButtonBox::SaveAll)->setText("Записать и установить");
selectedBoard = 0;
} }
MultipleSettings::~MultipleSettings() MultipleSettings::~MultipleSettings()
@@ -18,40 +18,41 @@ MultipleSettings::~MultipleSettings()
void MultipleSettings::on_buttonBox_clicked(QAbstractButton *button) void MultipleSettings::on_buttonBox_clicked(QAbstractButton *button)
{ {
if(button == ui->buttonBox->button(QDialogButtonBox::Ok)) if(button == ui->buttonBox->button(QDialogButtonBox::Ok)) {
{
newValue = ui->regValueLine->text().toInt(nullptr, 16); newValue = ui->regValueLine->text().toInt(nullptr, 16);
typeReg = ui->regTypeBox->currentIndex(); typeReg = ui->regTypeBox->currentIndex();
startAdr = ui->adrBox->value(); startAdr = ui->adrBox->value();
countReg = ui->countBox->value(); countReg = ui->countBox->value();
boardId = ui->boardBox->currentIndex(); boardId = ui->boardBox->currentIndex();
emit write(); emit write();
} } else if (button == ui->buttonBox->button(QDialogButtonBox::SaveAll)) {
else if (button == ui->buttonBox->button(QDialogButtonBox::SaveAll))
{
newValue = ui->regValueLine->text().toInt(nullptr, 16); newValue = ui->regValueLine->text().toInt(nullptr, 16);
typeReg = ui->regTypeBox->currentIndex(); typeReg = ui->regTypeBox->currentIndex();
startAdr = ui->adrBox->value(); startAdr = ui->adrBox->value();
countReg = ui->countBox->value(); countReg = ui->countBox->value();
boardId = ui->boardBox->currentIndex(); boardId = ui->boardBox->currentIndex();
emit writeAndSend(); emit writeAndSend();
} } else {}
else
{
}
} }
void MultipleSettings::on_regTypeBox_currentIndexChanged(int index) void MultipleSettings::on_regTypeBox_currentIndexChanged(int index)
{ {
short maxRange = 0;
switch (ui->boardBox->currentIndex()) {
case 3:
maxRange = 64;
break;
default:
maxRange = 84;
}
switch (index) { switch (index) {
case 0: case 0:
case 1: case 1:
ui->adrBox->setRange(0, 84); ui->adrBox->setRange(0, maxRange);
ui->adrBox->setValue(0); ui->adrBox->setValue(0);
break; break;
case 2: case 2:
ui->adrBox->setRange(85, 170); ui->adrBox->setRange(85, 85+maxRange);
ui->adrBox->setValue(85); ui->adrBox->setValue(85);
break; break;
} }
@@ -59,14 +60,8 @@ void MultipleSettings::on_regTypeBox_currentIndexChanged(int index)
void MultipleSettings::on_boardBox_currentIndexChanged(int index) void MultipleSettings::on_boardBox_currentIndexChanged(int index)
{ {
switch (index) { selectedBoard = index;
case 3: on_regTypeBox_currentIndexChanged(ui->regTypeBox->currentIndex());
ui->countBox->setRange(1, 65-ui->adrBox->value()+85*ui->regTypeBox->currentIndex()/2);
break;
default:
ui->countBox->setRange(1, 85-ui->adrBox->value()+85*ui->regTypeBox->currentIndex()/2);
}
} }
void MultipleSettings::on_adrBox_valueChanged(int arg1) void MultipleSettings::on_adrBox_valueChanged(int arg1)

View File

@@ -40,6 +40,7 @@ private:
unsigned countReg; unsigned countReg;
short typeReg; short typeReg;
short boardId; short boardId;
short selectedBoard;
}; };
#endif // MULTIPLESETTINGS_H #endif // MULTIPLESETTINGS_H

View File

@@ -6,7 +6,6 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
ui(new Ui::SettingsDialog) ui(new Ui::SettingsDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->parityCombo->setCurrentIndex(0); ui->parityCombo->setCurrentIndex(0);
#if QT_CONFIG(modbus_serialport) #if QT_CONFIG(modbus_serialport)
ui->baudCombo->setCurrentText(QString::number(m_settings.baud)); ui->baudCombo->setCurrentText(QString::number(m_settings.baud));
@@ -16,8 +15,6 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
#endif #endif
ui->timeoutSpinner->setValue(m_settings.responseTime); ui->timeoutSpinner->setValue(m_settings.responseTime);
ui->retriesSpinner->setValue(m_settings.numberOfRetries); ui->retriesSpinner->setValue(m_settings.numberOfRetries);
connect(ui->AcceptOrRejectButtonBox, &QDialogButtonBox::accepted, [this]() { connect(ui->AcceptOrRejectButtonBox, &QDialogButtonBox::accepted, [this]() {
#if QT_CONFIG(modbus_serialport) #if QT_CONFIG(modbus_serialport)
m_settings.portName = ui->comBox->currentData().toString(); m_settings.portName = ui->comBox->currentData().toString();
@@ -30,7 +27,6 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
#endif #endif
m_settings.responseTime = ui->timeoutSpinner->value(); m_settings.responseTime = ui->timeoutSpinner->value();
m_settings.numberOfRetries = ui->retriesSpinner->value(); m_settings.numberOfRetries = ui->retriesSpinner->value();
hide(); hide();
}); });
} }
@@ -54,11 +50,9 @@ 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);
} }
} }
@@ -77,8 +71,7 @@ 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

@@ -24,7 +24,7 @@ public:
int baud = 115200; int baud = 115200;
int dataBits = QSerialPort::Data8; int dataBits = QSerialPort::Data8;
int stopBits = QSerialPort::OneStop; int stopBits = QSerialPort::OneStop;
int responseTime = 50; int responseTime = 1000;
int numberOfRetries = 0; int numberOfRetries = 0;
}; };

View File

@@ -29,16 +29,12 @@ QVariant WriteRegisterModel::data(const QModelIndex &index, int role) const
Q_ASSERT(m_holdingRegisters.count() == RowCount); Q_ASSERT(m_holdingRegisters.count() == RowCount);
if (index.column() == NumColumn && role == Qt::DisplayRole) if (index.column() == NumColumn && role == Qt::DisplayRole)
return QString::number(index.row()); return QString::number(index.row());
if (index.column() == NameColumn && role == Qt::DisplayRole) if (index.column() == NameColumn && role == Qt::DisplayRole)
return QString("ТЭ%1").arg(index.row()%(RowCount/(1+isHR))+1); return QString("ТЭ%1").arg(index.row()%(RowCount/(1+isHR))+1);
if (index.column() == CoilsColumn && role == Qt::CheckStateRole) // coils if (index.column() == CoilsColumn && role == Qt::CheckStateRole) // coils
return m_coils.at(index.row()) ? Qt::Checked : Qt::Unchecked; return m_coils.at(index.row()) ? Qt::Checked : Qt::Unchecked;
if (index.column() == HoldingColumn && role == Qt::DisplayRole) // holding registers if (index.column() == HoldingColumn && role == Qt::DisplayRole) // holding registers
return QString("0x%1").arg(QString::number(m_holdingRegisters.at(index.row()), 16)); return QString("%1 В").arg(QString::number((double)((double)m_holdingRegisters.at(index.row())/(double)1000), 'f', 3));
if(index.column() == CurrentUColumn && role == Qt::DisplayRole) if(index.column() == CurrentUColumn && role == Qt::DisplayRole)
return QString("%1 В").arg(QString::number((double)((double)m_currentU.at(index.row())/(double)1000), 'f', 3)); return QString("%1 В").arg(QString::number((double)((double)m_currentU.at(index.row())/(double)1000), 'f', 3));
return QVariant(); return QVariant();
@@ -73,7 +69,6 @@ bool WriteRegisterModel::setData(const QModelIndex &index, const QVariant &value
return false; return false;
Q_ASSERT(m_coils.count() == RowCount); Q_ASSERT(m_coils.count() == RowCount);
Q_ASSERT(m_holdingRegisters.count() == RowCount); Q_ASSERT(m_holdingRegisters.count() == RowCount);
if (index.column() == CoilsColumn && role == Qt::CheckStateRole) { // coils if (index.column() == CoilsColumn && role == Qt::CheckStateRole) { // coils
auto s = static_cast<Qt::CheckState>(value.toUInt()); auto s = static_cast<Qt::CheckState>(value.toUInt());
s == Qt::Checked ? m_coils.setBit(index.row()) : m_coils.clearBit(index.row()); s == Qt::Checked ? m_coils.setBit(index.row()) : m_coils.clearBit(index.row());
@@ -82,10 +77,9 @@ bool WriteRegisterModel::setData(const QModelIndex &index, const QVariant &value
} }
if (index.column() == HoldingColumn && role == Qt::EditRole) { // holding registers if (index.column() == HoldingColumn && role == Qt::EditRole) { // holding registers
bool result = false; bool result = false;
quint16 newValue = value.toString().toUShort(&result, 16); quint16 newValue = value.toString().toUShort(&result, 10);
if (result) if (result)
m_holdingRegisters[index.row()] = newValue; m_holdingRegisters[index.row()] = newValue;
emit dataChanged(index, index); emit dataChanged(index, index);
return result; return result;
} }
@@ -96,16 +90,13 @@ Qt::ItemFlags WriteRegisterModel::flags(const QModelIndex &index) const
{ {
if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount) if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
return QAbstractTableModel::flags(index); return QAbstractTableModel::flags(index);
Qt::ItemFlags flags = QAbstractTableModel::flags(index); Qt::ItemFlags flags = QAbstractTableModel::flags(index);
if ((index.row() < m_address) || (index.row() >= (m_address + m_number))) if ((index.row() < m_address) || (index.row() >= (m_address + m_number)))
flags &= ~Qt::ItemIsEnabled; flags &= ~Qt::ItemIsEnabled;
if (index.column() == CoilsColumn) // coils if (index.column() == CoilsColumn) // coils
return flags | Qt::ItemIsUserCheckable; return flags | Qt::ItemIsUserCheckable;
if (index.column() == HoldingColumn) // holding registers if (index.column() == HoldingColumn) // holding registers
return flags | Qt::ItemIsEditable; return flags | Qt::ItemIsEditable;
return flags; return flags;
} }

BIN
MZKT_Test_Terminal.exe Normal file

Binary file not shown.

21
Release/.qmake.stash Normal file
View File

@@ -0,0 +1,21 @@
QMAKE_CXX.QT_COMPILER_STDCXX = 201402L
QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 7
QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 3
QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 0
QMAKE_CXX.COMPILER_MACROS = \
QT_COMPILER_STDCXX \
QMAKE_GCC_MAJOR_VERSION \
QMAKE_GCC_MINOR_VERSION \
QMAKE_GCC_PATCH_VERSION
QMAKE_CXX.INCDIRS = \
C:/Qt/Qt5.14.2/Tools/mingw730_32/lib/gcc/i686-w64-mingw32/7.3.0/include/c++ \
C:/Qt/Qt5.14.2/Tools/mingw730_32/lib/gcc/i686-w64-mingw32/7.3.0/include/c++/i686-w64-mingw32 \
C:/Qt/Qt5.14.2/Tools/mingw730_32/lib/gcc/i686-w64-mingw32/7.3.0/include/c++/backward \
C:/Qt/Qt5.14.2/Tools/mingw730_32/lib/gcc/i686-w64-mingw32/7.3.0/include \
C:/Qt/Qt5.14.2/Tools/mingw730_32/lib/gcc/i686-w64-mingw32/7.3.0/include-fixed \
C:/Qt/Qt5.14.2/Tools/mingw730_32/i686-w64-mingw32/include
QMAKE_CXX.LIBDIRS = \
C:/Qt/Qt5.14.2/Tools/mingw730_32/lib/gcc/i686-w64-mingw32/7.3.0 \
C:/Qt/Qt5.14.2/Tools/mingw730_32/lib/gcc \
C:/Qt/Qt5.14.2/Tools/mingw730_32/i686-w64-mingw32/lib \
C:/Qt/Qt5.14.2/Tools/mingw730_32/lib

Binary file not shown.