Compare commits
16 Commits
c9b44e5dab
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba0506caf7 | ||
|
|
f10f3c8927 | ||
|
|
3f1cd53e19 | ||
|
|
e402334153 | ||
|
|
9071eb4322 | ||
|
|
227deaf686 | ||
|
|
4ec595d92e | ||
|
|
a9f3d13b5f | ||
|
|
5ae694d254 | ||
|
|
c2a32e3ff5 | ||
|
|
1e3ecd0834 | ||
|
|
5b3faa798b | ||
|
|
93b4a24b8b | ||
|
|
4ae15d8c01 | ||
|
|
190f3337ed | ||
|
|
726d8d24ef |
@@ -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
|
||||||
@@ -25,29 +25,44 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
|||||||
#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 \
|
||||||
m3kte.cpp \
|
m3kte.cpp \
|
||||||
multiplesettings.cpp \
|
multiplesettings.cpp \
|
||||||
|
parameterbox.cpp \
|
||||||
|
parameterdevice.cpp \
|
||||||
|
parameterworkspace.cpp \
|
||||||
scanboard.cpp \
|
scanboard.cpp \
|
||||||
settingsdialog.cpp \
|
settingsdialog.cpp \
|
||||||
writeregistermodel.cpp
|
writeregistermodel.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
adcgraphdialog.h \
|
||||||
|
debugterminaldialog.h \
|
||||||
devicesettingsdialog.h \
|
devicesettingsdialog.h \
|
||||||
lineringer.h \
|
lineringer.h \
|
||||||
m3kte.h \
|
m3kte.h \
|
||||||
multiplesettings.h \
|
multiplesettings.h \
|
||||||
|
parameterbox.h \
|
||||||
|
parameterdevice.h \
|
||||||
|
parameterworkspace.h \
|
||||||
scanboard.h \
|
scanboard.h \
|
||||||
settingsdialog.h \
|
settingsdialog.h \
|
||||||
writeregistermodel.h
|
writeregistermodel.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
adcgraphdialog.ui \
|
||||||
|
debugTerminalDialog.ui \
|
||||||
devicesettingsdialog.ui \
|
devicesettingsdialog.ui \
|
||||||
lineringer.ui \
|
lineringer.ui \
|
||||||
m3kte.ui \
|
m3kte.ui \
|
||||||
multiplesettings.ui \
|
multiplesettings.ui \
|
||||||
|
parameterbox.ui \
|
||||||
|
parameterdevice.ui \
|
||||||
|
parameterworkspace.ui \
|
||||||
scanboard.ui \
|
scanboard.ui \
|
||||||
settingsdialog.ui
|
settingsdialog.ui
|
||||||
|
|
||||||
|
|||||||
470
M3KTE_TERM/adcgraphdialog.cpp
Normal file
470
M3KTE_TERM/adcgraphdialog.cpp
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
#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_stableStartLine(new QLineSeries()),
|
||||||
|
m_stableEndLine(new QLineSeries()),
|
||||||
|
m_stableStartIndex(-1),
|
||||||
|
m_stableEndIndex(-1),
|
||||||
|
m_series(new QLineSeries()),
|
||||||
|
m_chart(new QChart()),
|
||||||
|
m_startAddress(0),
|
||||||
|
m_registerCount(100)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
// Настройка основного графика
|
||||||
|
m_series->setName("АЦП данные");
|
||||||
|
m_chart->addSeries(m_series);
|
||||||
|
// Настройка линий стабильного участка
|
||||||
|
m_stableStartLine->setName("Начало стаб. участка");
|
||||||
|
m_stableStartLine->setColor(Qt::red);
|
||||||
|
m_stableStartLine->setPen(QPen(Qt::red, 2, Qt::DashLine));
|
||||||
|
m_chart->addSeries(m_stableStartLine);
|
||||||
|
m_stableEndLine->setName("Конец стаб. участка");
|
||||||
|
m_stableEndLine->setColor(Qt::green);
|
||||||
|
m_stableEndLine->setPen(QPen(Qt::green, 2, Qt::DashLine));
|
||||||
|
m_chart->addSeries(m_stableEndLine);
|
||||||
|
m_chart->setTitle("График АЦП");
|
||||||
|
m_chart->legend()->setVisible(true);
|
||||||
|
m_chart->legend()->setAlignment(Qt::AlignTop);
|
||||||
|
m_axisX = new QValueAxis();
|
||||||
|
m_axisX->setTitleText("Отсчеты АЦП");
|
||||||
|
m_axisX->setRange(0, m_registerCount);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
updateStableLines();
|
||||||
|
// Обновляем статистику с новыми индексами
|
||||||
|
updateStatisticsWithStableInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
|
||||||
|
if(!reply->isFinished())
|
||||||
|
connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onCombinedDataReady);
|
||||||
|
else
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// Обрабатываем данные АЦП (остальные регистры)
|
||||||
|
uint adcDataStartIndex = (m_startAddress + REG_ADC_BUFFER_START) - REG_STABLE_START;
|
||||||
|
// Очищаем предыдущие данные
|
||||||
|
m_series->clear();
|
||||||
|
// Добавляем новые точки и определяем диапазон
|
||||||
|
double minVoltage = 1000, maxVoltage = -1000;
|
||||||
|
for(int i = 0; i < m_registerCount; ++i) {
|
||||||
|
if(adcDataStartIndex + i < result.valueCount()) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdcGraphDialog::readAdcBuffer()
|
||||||
|
{
|
||||||
|
if(!m_modbusDevice || m_boardAddress == -1)
|
||||||
|
return;
|
||||||
|
// Читаем выбранный диапазон буфера АЦП
|
||||||
|
QModbusDataUnit unit(QModbusDataUnit::InputRegisters, m_startAddress+REG_ADC_BUFFER_START, m_registerCount);
|
||||||
|
if(auto *reply = m_modbusDevice->sendReadRequest(unit, m_boardAddress)) {
|
||||||
|
if(!reply->isFinished())
|
||||||
|
connect(reply, &QModbusReply::finished, this, &AdcGraphDialog::onReadReady);
|
||||||
|
else
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(uint i = 0; i < result.valueCount(); ++i) {
|
||||||
|
double voltage = convertAdcToVoltage(result.value(i));
|
||||||
|
m_series->append(i, voltage);
|
||||||
|
// Обновляем мин/макс для автоматического масштабирования
|
||||||
|
if(voltage < minVoltage)
|
||||||
|
minVoltage = voltage;
|
||||||
|
if(voltage > maxVoltage)
|
||||||
|
maxVoltage = voltage;
|
||||||
|
}
|
||||||
|
// Автоматически настраиваем диапазон оси 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
// Если диапазон слишком маленький или слишком большой, устанавливаем разумные пределы
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdcGraphDialog::on_rangeApplyClicked()
|
||||||
|
{
|
||||||
|
updateGraphRange();
|
||||||
|
// Немедленно обновляем данные
|
||||||
|
if(m_boardAddress != -1)
|
||||||
|
readAdcBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdcGraphDialog::on_closeBtn_clicked()
|
||||||
|
{
|
||||||
|
stopGraph();
|
||||||
|
reject(); // Или accept() в зависимости от логики
|
||||||
|
}
|
||||||
86
M3KTE_TERM/adcgraphdialog.h
Normal file
86
M3KTE_TERM/adcgraphdialog.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#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
|
||||||
162
M3KTE_TERM/adcgraphdialog.ui
Normal file
162
M3KTE_TERM/adcgraphdialog.ui
Normal 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>
|
||||||
796
M3KTE_TERM/debugTerminalDialog.ui
Normal file
796
M3KTE_TERM/debugTerminalDialog.ui
Normal 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>
|
||||||
790
M3KTE_TERM/debugterminaldialog.cpp
Normal file
790
M3KTE_TERM/debugterminaldialog.cpp
Normal file
@@ -0,0 +1,790 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает указатель на объект QModbusClient для отладочного терминала.
|
||||||
|
*
|
||||||
|
* Этот метод присваивает указатель на Modbus-устройство и, при наличии графического диалога
|
||||||
|
* для отображения данных АЦП, передает ему тот же объект для синхронизации.
|
||||||
|
*
|
||||||
|
* @param device Указатель на объект QModbusClient, представляющий Modbus-устройство.
|
||||||
|
*/
|
||||||
|
void DebugTerminalDialog::setModbusDevice(QModbusClient *device)
|
||||||
|
{
|
||||||
|
m_modbusDevice = device;
|
||||||
|
if(m_adcGraphDialog && device)
|
||||||
|
m_adcGraphDialog->setModbusDevice(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает режим отладки, активируя или деактивируя коили.
|
||||||
|
*
|
||||||
|
* Этот метод вызывает функцию writeCoil для нескольких адресов (0, 1, 2, 3),
|
||||||
|
* устанавливая значение enable для каждого из них. Предполагается, что эти коили
|
||||||
|
* управляют режимом отладки устройства или системы.
|
||||||
|
*
|
||||||
|
* @param enable Целое значение (например, 0 или 1), указывающее, включать или выключать режим отладки.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обрабатывает событие отображения окна диалога.
|
||||||
|
*
|
||||||
|
* Этот метод вызывается при показе окна и сначала вызывает базовую реализацию showEvent.
|
||||||
|
* Затем происходит сброс всех настроек или состояний через resetAll(), а после этого
|
||||||
|
* устанавливается значение 1 для коили, отвечающих за режим отладки, с помощью setDebugTerminalCoil(1).
|
||||||
|
*
|
||||||
|
* @param event Указатель на объект QShowEvent, содержащий информацию о событии отображения.
|
||||||
|
*/
|
||||||
|
void DebugTerminalDialog::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
QDialog::showEvent(event);
|
||||||
|
// При открытии окна записываем в коил 555 значение "1"
|
||||||
|
resetAll();
|
||||||
|
setDebugTerminalCoil(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обрабатывает событие закрытия диалогового окна.
|
||||||
|
*
|
||||||
|
* Перед закрытием окна вызывается метод setDebugTerminalCoil(0),
|
||||||
|
* который отключает режим отладки, устанавливая значение коил в 0.
|
||||||
|
* Затем вызывается базовая обработка closeEvent.
|
||||||
|
*
|
||||||
|
* @param event Указатель на объект QCloseEvent, содержащий информацию о событии закрытия.
|
||||||
|
*/
|
||||||
|
void DebugTerminalDialog::closeEvent(QCloseEvent *event)
|
||||||
|
{
|
||||||
|
// При закрытии окна записываем в коил 555 значение "0"
|
||||||
|
setDebugTerminalCoil(0);
|
||||||
|
QDialog::closeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugTerminalDialog::initializeConnections(){}
|
||||||
|
|
||||||
|
void DebugTerminalDialog::updateConnectionStatus(int boardID, bool connected)
|
||||||
|
{
|
||||||
|
// Обновляем визуальное отображение статуса соединения
|
||||||
|
// Можно изменить цвет рамки или добавить индикатор
|
||||||
|
Q_UNUSED(boardID);
|
||||||
|
Q_UNUSED(connected);
|
||||||
|
// Реализация по необходимости
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка клика по кнопкам в диалоговом окне.
|
||||||
|
*
|
||||||
|
* В зависимости от роли нажатой кнопки, выполняются соответствующие действия:
|
||||||
|
* - Если роль Reset, вызывается resetAll(), сбрасывающий настройки.
|
||||||
|
* - Если роль Accept, вызывается accept(), подтверждающий изменения.
|
||||||
|
*
|
||||||
|
* @param button Указатель на нажатую кнопку.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Открывает окно графика для отображения данных АЦП с указанной платы и канала.
|
||||||
|
*
|
||||||
|
* Этот метод уничтожает предыдущий экземпляр диалога AdcGraphDialog, если он есть,
|
||||||
|
* создает новый, связывает сигнал закрытия с установкой режима отладки в 0,
|
||||||
|
* задает интервал обновления графика, запускает отображение данных и показывает окно.
|
||||||
|
*
|
||||||
|
* @param boardID Идентификатор платы.
|
||||||
|
* @param teNumber Номер канала (или технологической единицы).
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает интервал обновления графика в миллисекундах.
|
||||||
|
*
|
||||||
|
* Этот метод задает период времени (в миллисекундах), с которым график в диалоге
|
||||||
|
* AdcGraphDialog обновляется. Если диалог открыт, вызывает его метод setTimeout.
|
||||||
|
*
|
||||||
|
* @param milliseconds Интервал обновления графика в миллисекундах.
|
||||||
|
*/
|
||||||
|
void DebugTerminalDialog::setGraphUpdateInterval(int milliseconds)
|
||||||
|
{
|
||||||
|
if(m_adcGraphDialog)
|
||||||
|
m_adcGraphDialog->setTimeout(milliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Записывает значение коила для указанной платы.
|
||||||
|
*
|
||||||
|
* Этот метод выбирает группу элементов в интерфейсе в зависимости от идентификатора платы (boardID),
|
||||||
|
* проверяет, что выбранная плата активна (enabled), и затем сообщает о смене значения коила через сигнал.
|
||||||
|
* Перед этим выводит диагностическое сообщение в лог.
|
||||||
|
*
|
||||||
|
* @param boardID Идентификатор платы (0-3).
|
||||||
|
* @param coil Номер коила, который необходимо изменить.
|
||||||
|
* @param value Новое значение для коила.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает доступность (активность) для выбранной платы.
|
||||||
|
*
|
||||||
|
* Этот метод выбирает соответствующий QGroupBox для указанной платы (boardID),
|
||||||
|
* включает или отключает его в зависимости от булевого флага active.
|
||||||
|
* Также при деактивации меняет цвет текста на серый для визуального представления.
|
||||||
|
*
|
||||||
|
* @param boardID Идентификатор платы (0-3).
|
||||||
|
* @param active Булевое значение, определяющее активность (true — активировать, false — деактивировать).
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
193
M3KTE_TERM/debugterminaldialog.h
Normal file
193
M3KTE_TERM/debugterminaldialog.h
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
#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
|
||||||
@@ -1,29 +1,23 @@
|
|||||||
#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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceSettingsDialog::~DeviceSettingsDialog()
|
DeviceSettingsDialog::~DeviceSettingsDialog()
|
||||||
@@ -77,7 +71,7 @@ unsigned short DeviceSettingsDialog::currentParity()
|
|||||||
void DeviceSettingsDialog::updateSettingsAfterConnection(unsigned tmp_speed, unsigned tmp_parity, unsigned *tmp_adr, bool *ActiveDevices)
|
void DeviceSettingsDialog::updateSettingsAfterConnection(unsigned tmp_speed, unsigned tmp_parity, unsigned *tmp_adr, bool *ActiveDevices)
|
||||||
{
|
{
|
||||||
ui->speedBox->setCurrentText(QString::number(_currentSpeed=tmp_speed, 10));
|
ui->speedBox->setCurrentText(QString::number(_currentSpeed=tmp_speed, 10));
|
||||||
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++) {
|
||||||
@@ -85,9 +79,8 @@ void DeviceSettingsDialog::updateSettingsAfterConnection(unsigned tmp_speed, uns
|
|||||||
_m_timer[i]->setEnabled(true);
|
_m_timer[i]->setEnabled(true);
|
||||||
ui->idComboBox->addItem(QString::number(i));
|
ui->idComboBox->addItem(QString::number(i));
|
||||||
_currentAdrs[i] = tmp_adr[i];
|
_currentAdrs[i] = tmp_adr[i];
|
||||||
} else {
|
} else
|
||||||
_m_timer[i]->setEnabled(false);
|
_m_timer[i]->setEnabled(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
on_idComboBox_currentIndexChanged(ui->idComboBox->currentIndex());
|
on_idComboBox_currentIndexChanged(ui->idComboBox->currentIndex());
|
||||||
}
|
}
|
||||||
@@ -105,20 +98,13 @@ 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()]);
|
||||||
break;
|
break;
|
||||||
case QDialogButtonBox::AcceptRole:
|
case QDialogButtonBox::AcceptRole:
|
||||||
@@ -131,7 +117,7 @@ void DeviceSettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
|
|||||||
|
|
||||||
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)
|
||||||
@@ -141,8 +127,13 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,8 @@ class BoardIdHasBeenChanged : public QEvent
|
|||||||
public:
|
public:
|
||||||
BoardIdHasBeenChanged(const short num, const short newId) : QEvent(QEvent::User) {_BoardNum = num; _BoardNewID = newId;}
|
BoardIdHasBeenChanged(const short num, const short newId) : QEvent(QEvent::User) {_BoardNum = num; _BoardNewID = newId;}
|
||||||
~BoardIdHasBeenChanged() {}
|
~BoardIdHasBeenChanged() {}
|
||||||
|
|
||||||
short BoardNum() const {return _BoardNum;}
|
short BoardNum() const {return _BoardNum;}
|
||||||
short BoardNewID() const {return _BoardNewID;}
|
short BoardNewID() const {return _BoardNewID;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
short _BoardNum;
|
short _BoardNum;
|
||||||
short _BoardNewID;
|
short _BoardNewID;
|
||||||
@@ -26,10 +24,8 @@ class pollStatusChange : public QEvent
|
|||||||
public:
|
public:
|
||||||
pollStatusChange(unsigned BoardID, bool Stat) : QEvent((QEvent::Type)1001) {_BoardID = BoardID; _Status = Stat;}
|
pollStatusChange(unsigned BoardID, bool Stat) : QEvent((QEvent::Type)1001) {_BoardID = BoardID; _Status = Stat;}
|
||||||
~pollStatusChange() {}
|
~pollStatusChange() {}
|
||||||
|
|
||||||
unsigned BoardID() const {return _BoardID;}
|
unsigned BoardID() const {return _BoardID;}
|
||||||
bool Status() const {return _Status;}
|
bool Status() const {return _Status;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned _BoardID;
|
unsigned _BoardID;
|
||||||
bool _Status;
|
bool _Status;
|
||||||
@@ -42,44 +38,33 @@ class DeviceSettingsDialog;
|
|||||||
class DeviceSettingsDialog : public QDialog
|
class DeviceSettingsDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DeviceSettingsDialog(QWidget *parent = nullptr);
|
explicit DeviceSettingsDialog(QWidget *parent = nullptr);
|
||||||
~DeviceSettingsDialog();
|
~DeviceSettingsDialog();
|
||||||
|
|
||||||
unsigned currentBoardTimer(unsigned short _ID);
|
unsigned currentBoardTimer(unsigned short _ID);
|
||||||
unsigned currentSpeed();
|
unsigned currentSpeed();
|
||||||
unsigned short currentParity();
|
unsigned short currentParity();
|
||||||
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();
|
void onDisconnect();
|
||||||
signals:
|
signals:
|
||||||
void parityChanged();
|
void parityChanged();
|
||||||
void speedChanged();
|
void speedChanged();
|
||||||
|
|
||||||
void firstBoardAdrHasBeenChanged();
|
void firstBoardAdrHasBeenChanged();
|
||||||
void secondBoardAdrHasBeenChanged();
|
void secondBoardAdrHasBeenChanged();
|
||||||
void thirdBoardAdrHasBeenChanged();
|
void thirdBoardAdrHasBeenChanged();
|
||||||
void fourthBoardAdrHasBeenChanged();
|
void fourthBoardAdrHasBeenChanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_buttonApplyChangeTimer_clicked();
|
void on_buttonApplyChangeTimer_clicked();
|
||||||
|
|
||||||
void on_buttonApplyChangeSpeed_clicked();
|
void on_buttonApplyChangeSpeed_clicked();
|
||||||
|
|
||||||
void on_buttonApplyChangeParity_clicked();
|
void on_buttonApplyChangeParity_clicked();
|
||||||
|
|
||||||
void on_buttonApplyChangeAdr_clicked();
|
void on_buttonApplyChangeAdr_clicked();
|
||||||
|
|
||||||
void on_idComboBox_currentIndexChanged(int index);
|
void on_idComboBox_currentIndexChanged(int index);
|
||||||
|
|
||||||
void on_buttonBox_clicked(QAbstractButton *button);
|
void on_buttonBox_clicked(QAbstractButton *button);
|
||||||
|
|
||||||
void on_buttonApplyChangePoll_clicked();
|
void on_buttonApplyChangePoll_clicked();
|
||||||
|
|
||||||
void on_idPollComboBox_currentIndexChanged(int index);
|
void on_idPollComboBox_currentIndexChanged(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSpinBox *_m_timer[4];
|
QSpinBox *_m_timer[4];
|
||||||
unsigned _currentBoardTimers[4];
|
unsigned _currentBoardTimers[4];
|
||||||
@@ -87,7 +72,6 @@ private:
|
|||||||
unsigned short _currentParity;
|
unsigned short _currentParity;
|
||||||
unsigned _currentAdrs[4];
|
unsigned _currentAdrs[4];
|
||||||
bool _currentPollStatus[4];
|
bool _currentPollStatus[4];
|
||||||
|
|
||||||
Ui::DeviceSettingsDialog *ui;
|
Ui::DeviceSettingsDialog *ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -6,52 +6,80 @@ LineRinger::LineRinger(QWidget *parent) :
|
|||||||
ui(new Ui::LineRinger)
|
ui(new Ui::LineRinger)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
const auto listPorts = QSerialPortInfo::availablePorts();
|
const auto listPorts = QSerialPortInfo::availablePorts();
|
||||||
for (const auto& port: listPorts) {
|
for(const auto& port: listPorts)
|
||||||
ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName()));
|
ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName()));
|
||||||
|
//чётность
|
||||||
|
{
|
||||||
|
ui->parityControlBox->addItem("No", QVariant(QSerialPort::NoParity));
|
||||||
|
ui->parityControlBox->addItem("Even", QVariant(QSerialPort::EvenParity));
|
||||||
|
ui->parityControlBox->addItem("Odd", QVariant(QSerialPort::OddParity));
|
||||||
|
ui->parityControlBox->addItem("Space", QVariant(QSerialPort::SpaceParity));
|
||||||
|
ui->parityControlBox->addItem("Mark", QVariant(QSerialPort::MarkParity));
|
||||||
|
}
|
||||||
|
//данные
|
||||||
|
{
|
||||||
|
ui->dataBox->addItem("Data5", QVariant(QSerialPort::Data5));
|
||||||
|
ui->dataBox->addItem("Data6", QVariant(QSerialPort::Data6));
|
||||||
|
ui->dataBox->addItem("Data7", QVariant(QSerialPort::Data7));
|
||||||
|
ui->dataBox->addItem("Data8", QVariant(QSerialPort::Data8));
|
||||||
|
ui->dataBox->setCurrentIndex(3);
|
||||||
|
}
|
||||||
|
//стопбиты
|
||||||
|
{
|
||||||
|
ui->stopBox->addItem("One", QVariant(QSerialPort::OneStop));
|
||||||
|
ui->stopBox->addItem("OneAndHalf", QVariant(QSerialPort::OneAndHalfStop));
|
||||||
|
ui->stopBox->addItem("Two", QVariant(QSerialPort::TwoStop));
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->parityControlBox->addItem("No", QVariant(QSerialPort::NoParity));
|
|
||||||
ui->parityControlBox->addItem("Even", QVariant(QSerialPort::EvenParity));
|
|
||||||
ui->parityControlBox->addItem("Odd", QVariant(QSerialPort::OddParity));
|
|
||||||
ui->parityControlBox->addItem("Space", QVariant(QSerialPort::SpaceParity));
|
|
||||||
ui->parityControlBox->addItem("Mark", QVariant(QSerialPort::MarkParity));
|
|
||||||
|
|
||||||
ui->dataBox->addItem("Data5", QVariant(QSerialPort::Data5));
|
|
||||||
ui->dataBox->addItem("Data6", QVariant(QSerialPort::Data6));
|
|
||||||
ui->dataBox->addItem("Data7", QVariant(QSerialPort::Data7));
|
|
||||||
ui->dataBox->addItem("Data8", QVariant(QSerialPort::Data8));
|
|
||||||
ui->dataBox->setCurrentIndex(3);
|
|
||||||
|
|
||||||
ui->stopBox->addItem("One", QVariant(QSerialPort::OneStop));
|
|
||||||
ui->stopBox->addItem("OneAndHalf", QVariant(QSerialPort::OneAndHalfStop));
|
|
||||||
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);
|
||||||
|
|
||||||
ui->ringButton->setEnabled(false);
|
ui->ringButton->setEnabled(false);
|
||||||
|
|
||||||
modbusDevice = new QModbusRtuSerialMaster(this);
|
modbusDevice = new QModbusRtuSerialMaster(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
LineRinger::~LineRinger()
|
LineRinger::~LineRinger()
|
||||||
{
|
{
|
||||||
if (modbusDevice->state() == QModbusDevice::ConnectedState)
|
if(modbusDevice->state() == QModbusDevice::ConnectedState)
|
||||||
on_connectButton_clicked();
|
on_connectButton_clicked();
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обновляет заголовки столбцов таблицы устройств.
|
||||||
|
*
|
||||||
|
* Этот метод устанавливает список заголовков для таблицы отображения устройств
|
||||||
|
* в интерфейсе и затем автоматически изменяет ширину колонок под содержимое.
|
||||||
|
*/
|
||||||
void LineRinger::syncColumnHeaders()
|
void LineRinger::syncColumnHeaders()
|
||||||
{
|
{
|
||||||
|
// Создаём список заголовков колонок
|
||||||
QStringList headers;
|
QStringList headers;
|
||||||
headers << "ID" << "BaudRate" << "Vendor Name" << "Product Code" << "Major Minor Revision" << "Vendor Url" << "Product Name" << "Model Name" << "User Application Name" << "Примечание";
|
headers << "ID"
|
||||||
|
<< "BaudRate"
|
||||||
|
<< "Vendor Name"
|
||||||
|
<< "Product Code"
|
||||||
|
<< "Major Minor Revision"
|
||||||
|
<< "Vendor Url"
|
||||||
|
<< "Product Name"
|
||||||
|
<< "Model Name"
|
||||||
|
<< "User Application Name"
|
||||||
|
<< "Примечание";
|
||||||
|
|
||||||
|
// Устанавливаем заголовки для таблицы
|
||||||
ui->deviceOnlineView->setHorizontalHeaderLabels(headers);
|
ui->deviceOnlineView->setHorizontalHeaderLabels(headers);
|
||||||
|
// Автоматически подгоняем ширину колонок под содержимое
|
||||||
ui->deviceOnlineView->resizeColumnsToContents();
|
ui->deviceOnlineView->resizeColumnsToContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработчик нажатия кнопки "Подключить/Отключить".
|
||||||
|
*
|
||||||
|
* Этот слот управляет подключением или отключением модбус-устройства.
|
||||||
|
* При отсутствии подключения он выполняет настройку параметров соединения,
|
||||||
|
* инициирует подключение и обновляет интерфейс в зависимости от результата.
|
||||||
|
* Если устройство уже подключено, происходит отключение и обновление интерфейса.
|
||||||
|
*/
|
||||||
void LineRinger::on_connectButton_clicked()
|
void LineRinger::on_connectButton_clicked()
|
||||||
{
|
{
|
||||||
if(!modbusDevice)
|
if(!modbusDevice)
|
||||||
@@ -71,9 +99,9 @@ void LineRinger::on_connectButton_clicked()
|
|||||||
#endif
|
#endif
|
||||||
modbusDevice->setTimeout(50);
|
modbusDevice->setTimeout(50);
|
||||||
modbusDevice->setNumberOfRetries(0);
|
modbusDevice->setNumberOfRetries(0);
|
||||||
if(!modbusDevice->connectDevice()) {
|
if(!modbusDevice->connectDevice())
|
||||||
QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения.");
|
QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения.");
|
||||||
} else {
|
else {
|
||||||
ui->connectButton->setText(tr("Отключить"));
|
ui->connectButton->setText(tr("Отключить"));
|
||||||
ui->ringButton->setEnabled(true);
|
ui->ringButton->setEnabled(true);
|
||||||
currentBaudRate = ui->baudRateBox->currentText().toUInt(nullptr, 10);
|
currentBaudRate = ui->baudRateBox->currentText().toUInt(nullptr, 10);
|
||||||
@@ -93,21 +121,20 @@ 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()));
|
||||||
@@ -129,7 +156,7 @@ LineRinger::callStatus LineRinger::lineCall()
|
|||||||
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;
|
||||||
@@ -142,17 +169,16 @@ LineRinger::callStatus LineRinger::lineCall()
|
|||||||
for(int tmp_obj = 0; tmp_obj < numOfObject; tmp_obj++) {
|
for(int tmp_obj = 0; tmp_obj < numOfObject; tmp_obj++) {
|
||||||
uint8_t objectID = result.at(0);
|
uint8_t objectID = result.at(0);
|
||||||
uint8_t lengthOfObject = result.at(1);
|
uint8_t lengthOfObject = result.at(1);
|
||||||
if(lengthOfObject>0) {
|
if(lengthOfObject > 0)
|
||||||
currentDevice.fields[objectID].clear();
|
currentDevice.fields[objectID].clear();
|
||||||
}
|
for(int i = 0; i < lengthOfObject; i++)
|
||||||
for(int i = 0; i < lengthOfObject; i++) {
|
currentDevice.fields[objectID] += QString(result.at(2 + i));
|
||||||
currentDevice.fields[objectID] += QString(result.at(2+i));
|
result.remove(0, lengthOfObject + 2);
|
||||||
}
|
|
||||||
result.remove(0, lengthOfObject+2);
|
|
||||||
}
|
}
|
||||||
auto *regularReply = modbusDevice->sendRawRequest(readDeviceRegularIdentification, tmp_adr);
|
auto *regularReply = modbusDevice->sendRawRequest(readDeviceRegularIdentification, tmp_adr);
|
||||||
if(regularReply == nullptr) {
|
if(regularReply == nullptr) {
|
||||||
QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(modbusDevice->error()).arg(modbusDevice->errorString()));
|
QMessageBox::warning(this, "Ошибка при сканировании.",
|
||||||
|
QString("%1: %2").arg(modbusDevice->error()).arg(modbusDevice->errorString()));
|
||||||
bar->close();
|
bar->close();
|
||||||
bar->deleteLater();
|
bar->deleteLater();
|
||||||
return callStatus::ERROR;
|
return callStatus::ERROR;
|
||||||
@@ -171,10 +197,6 @@ LineRinger::callStatus LineRinger::lineCall()
|
|||||||
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());
|
||||||
}
|
}
|
||||||
@@ -186,13 +208,11 @@ LineRinger::callStatus LineRinger::lineCall()
|
|||||||
if(objectID > 0x06)
|
if(objectID > 0x06)
|
||||||
continue;
|
continue;
|
||||||
uint8_t lengthOfObject = regularResult.at(1);
|
uint8_t lengthOfObject = regularResult.at(1);
|
||||||
if(lengthOfObject>0) {
|
if(lengthOfObject > 0)
|
||||||
currentDevice.fields[objectID].clear();
|
currentDevice.fields[objectID].clear();
|
||||||
}
|
for(int i = 0; i < lengthOfObject; i++)
|
||||||
for (int i = 0; i < lengthOfObject; i++) {
|
currentDevice.fields[objectID] += QString(regularResult.at(2 + i));
|
||||||
currentDevice.fields[objectID] += QString(regularResult.at(2+i));
|
regularResult.remove(0, lengthOfObject + 2);
|
||||||
}
|
|
||||||
regularResult.remove(0, lengthOfObject+2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,14 +222,12 @@ LineRinger::callStatus LineRinger::lineCall()
|
|||||||
ui->deviceOnlineView->insertRow(newRow);
|
ui->deviceOnlineView->insertRow(newRow);
|
||||||
ui->deviceOnlineView->setItem(newRow, 0, new QTableWidgetItem(QString::number(currentDevice.adr)));
|
ui->deviceOnlineView->setItem(newRow, 0, new QTableWidgetItem(QString::number(currentDevice.adr)));
|
||||||
ui->deviceOnlineView->setItem(newRow, 1, new QTableWidgetItem(QString::number(currentDevice.baudRate)));
|
ui->deviceOnlineView->setItem(newRow, 1, new QTableWidgetItem(QString::number(currentDevice.baudRate)));
|
||||||
for (int i = 0; i < 7; i++) {
|
for(int i = 0; i < 7; i++)
|
||||||
ui->deviceOnlineView->setItem(newRow, i+2, new QTableWidgetItem(currentDevice.fields[i]));
|
ui->deviceOnlineView->setItem(newRow, i + 2, new QTableWidgetItem(currentDevice.fields[i]));
|
||||||
}
|
if(reply->error()!=QModbusDevice::NoError)
|
||||||
if(reply->error()!=QModbusDevice::NoError) {
|
|
||||||
ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(QString("%1: %2").arg(reply->error()).arg(reply->errorString())));
|
ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(QString("%1: %2").arg(reply->error()).arg(reply->errorString())));
|
||||||
} else if(regularReplyError) {
|
else if(regularReplyError)
|
||||||
ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString));
|
ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString));
|
||||||
}
|
|
||||||
ui->deviceOnlineView->resizeColumnsToContents();
|
ui->deviceOnlineView->resizeColumnsToContents();
|
||||||
syncColumnHeaders();
|
syncColumnHeaders();
|
||||||
}
|
}
|
||||||
@@ -219,13 +237,23 @@ LineRinger::callStatus LineRinger::lineCall()
|
|||||||
return callStatus::NOERROR;
|
return callStatus::NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработчик нажатия кнопки "Опросить" для устройства LineRinger.
|
||||||
|
*
|
||||||
|
* Этот слот очищает текущий список устройств, обновляет интерфейс, а затем,
|
||||||
|
* в случае автоматического определения скорости передачи (isAutoBaud),
|
||||||
|
* последовательно пытается подключиться к устройствам с различными скоростями.
|
||||||
|
* В процессе поиска отображается прогресс-бар, который можно отменить.
|
||||||
|
* Если обнаружен вызываемый ответ или возникает ошибка, происходит завершение поиска.
|
||||||
|
* В случае ручного режима поиска, выполняется однократная попытка сканирования.
|
||||||
|
*/
|
||||||
void LineRinger::on_ringButton_clicked()
|
void LineRinger::on_ringButton_clicked()
|
||||||
{
|
{
|
||||||
ui->deviceOnlineView->clear();
|
ui->deviceOnlineView->clear();
|
||||||
devicesList.clear();
|
devicesList.clear();
|
||||||
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));
|
||||||
@@ -234,18 +262,16 @@ void LineRinger::on_ringButton_clicked()
|
|||||||
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()) {
|
||||||
QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения.");
|
QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения.");
|
||||||
on_connectButton_clicked();
|
on_connectButton_clicked();
|
||||||
break;
|
break;
|
||||||
@@ -253,7 +279,8 @@ void LineRinger::on_ringButton_clicked()
|
|||||||
currentBaudRate = ui->baudRateBox->itemText(i).toUInt(nullptr, 10);
|
currentBaudRate = ui->baudRateBox->itemText(i).toUInt(nullptr, 10);
|
||||||
bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate));
|
bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate));
|
||||||
if(lineCall() == callStatus::INTERRUPT) {
|
if(lineCall() == callStatus::INTERRUPT) {
|
||||||
QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count()));
|
QMessageBox::warning(this, "Уведомление",
|
||||||
|
QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count()));
|
||||||
modbusDevice->disconnectDevice();
|
modbusDevice->disconnectDevice();
|
||||||
on_connectButton_clicked();
|
on_connectButton_clicked();
|
||||||
bar->close();
|
bar->close();
|
||||||
@@ -267,9 +294,9 @@ void LineRinger::on_ringButton_clicked()
|
|||||||
on_connectButton_clicked();
|
on_connectButton_clicked();
|
||||||
} else {
|
} else {
|
||||||
ui->deviceOnlineView->setColumnHidden(1, true);
|
ui->deviceOnlineView->setColumnHidden(1, true);
|
||||||
if(lineCall() == callStatus::INTERRUPT) {
|
if(lineCall() == callStatus::INTERRUPT)
|
||||||
QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count()));
|
QMessageBox::warning(this, "Уведомление",
|
||||||
}
|
QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count()));
|
||||||
}
|
}
|
||||||
ui->timer->setTime(QTime::currentTime());
|
ui->timer->setTime(QTime::currentTime());
|
||||||
ui->timer->setDate(QDate::currentDate());
|
ui->timer->setDate(QDate::currentDate());
|
||||||
|
|||||||
@@ -16,35 +16,25 @@ class LineRinger;
|
|||||||
class LineRinger : public QWidget
|
class LineRinger : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum callStatus{
|
enum callStatus{
|
||||||
NOERROR = 0,
|
NOERROR = 0,
|
||||||
ERROR = 1,
|
ERROR = 1,
|
||||||
INTERRUPT = 2
|
INTERRUPT = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit LineRinger(QWidget *parent = nullptr);
|
explicit LineRinger(QWidget *parent = nullptr);
|
||||||
~LineRinger();
|
~LineRinger();
|
||||||
callStatus lineCall();
|
callStatus lineCall();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stopLineCall();
|
void stopLineCall();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_connectButton_clicked();
|
void on_connectButton_clicked();
|
||||||
|
|
||||||
void on_ringButton_clicked();
|
void on_ringButton_clicked();
|
||||||
|
|
||||||
void on_checkAutoBaud_stateChanged(int arg1);
|
void on_checkAutoBaud_stateChanged(int arg1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::LineRinger *ui;
|
Ui::LineRinger *ui;
|
||||||
|
|
||||||
void syncColumnHeaders();
|
void syncColumnHeaders();
|
||||||
|
struct deviceOnLine{
|
||||||
struct deviceOnLine
|
|
||||||
{
|
|
||||||
uint8_t adr;
|
uint8_t adr;
|
||||||
unsigned baudRate;
|
unsigned baudRate;
|
||||||
QString fields[7] = {"Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined"};
|
QString fields[7] = {"Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined"};
|
||||||
@@ -52,7 +42,6 @@ private:
|
|||||||
QVector<deviceOnLine>devicesList;
|
QVector<deviceOnLine>devicesList;
|
||||||
bool isAutoBaud = false;
|
bool isAutoBaud = false;
|
||||||
unsigned currentBaudRate;
|
unsigned currentBaudRate;
|
||||||
|
|
||||||
QModbusClient *modbusDevice = nullptr;
|
QModbusClient *modbusDevice = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
1781
M3KTE_TERM/m3kte.cpp
1781
M3KTE_TERM/m3kte.cpp
File diff suppressed because it is too large
Load Diff
@@ -7,14 +7,17 @@
|
|||||||
|
|
||||||
#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"
|
||||||
#include "lineringer.h"
|
#include "lineringer.h"
|
||||||
|
#include "parameterworkspace.h"
|
||||||
|
|
||||||
#include <QModbusTcpClient>
|
#include <QModbusTcpClient>
|
||||||
#include <QModbusRtuSerialMaster>
|
#include <QModbusRtuSerialMaster>
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
@@ -36,10 +39,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
|
||||||
@@ -51,87 +59,72 @@ private:
|
|||||||
QModbusDataUnit writeRequest() const;
|
QModbusDataUnit writeRequest() const;
|
||||||
void changeTable(int board, int tabletype);
|
void changeTable(int board, int tabletype);
|
||||||
bool event(QEvent* event);
|
bool event(QEvent* event);
|
||||||
|
bool deadPing(QProgressDialog *bar);
|
||||||
bool pingNetworkDevices();
|
bool pingNetworkDevices();
|
||||||
void beginScanBoards();
|
void beginScanBoards();
|
||||||
void stopScanBoard();
|
void stopScanBoard();
|
||||||
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();
|
||||||
|
|
||||||
bool autoBaudRateScan();
|
bool autoBaudRateScan();
|
||||||
|
|
||||||
void selectPositionOnTree(unsigned index);
|
void selectPositionOnTree(unsigned index);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void successAtCheckBoards();
|
void successAtCheckBoards();
|
||||||
void errorAtCheckBoards();
|
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 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 checkBoards();
|
||||||
|
|
||||||
void onSpeedUpdate();
|
void onSpeedUpdate();
|
||||||
void revertToOldSpeedAndRestart();
|
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);
|
||||||
|
void writeSingleCoil(int boardId, int coilAddress, bool value);
|
||||||
|
void writeSingleRegister(int boardId, int regAddress, quint16 value);
|
||||||
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;
|
||||||
|
ParameterWorkspace *m_parameterWorkspace = 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;
|
||||||
@@ -141,19 +134,17 @@ 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;
|
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;
|
||||||
|
|||||||
16639
M3KTE_TERM/m3kte.ui
16639
M3KTE_TERM/m3kte.ui
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -16,6 +16,15 @@ MultipleSettings::~MultipleSettings()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка нажатий кнопок в диалоговом окне настроек.
|
||||||
|
*
|
||||||
|
* В зависимости от нажатой кнопки выполняются разные действия:
|
||||||
|
* - Если нажата кнопка "Записать", сохраняются введенные параметры и вызывается сигнал write().
|
||||||
|
* - Если нажата кнопка "Записать и установить", сохраняются параметры и вызывается сигнал writeAndSend().
|
||||||
|
*
|
||||||
|
* @param button Указатель на нажатую кнопку.
|
||||||
|
*/
|
||||||
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)) {
|
||||||
@@ -25,44 +34,77 @@ void MultipleSettings::on_buttonBox_clicked(QAbstractButton *button)
|
|||||||
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 {}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка изменения выбранного типа регистра.
|
||||||
|
*
|
||||||
|
* В зависимости от выбранного типа регистра (index) и текущей выбранной платы (ui->boardBox),
|
||||||
|
* устанавливается диапазон допустимых значений для поля адреса (ui->adrBox).
|
||||||
|
* Также значение адреса сбрасывается на начальное.
|
||||||
|
*
|
||||||
|
* @param index Индекс выбранного типа регистра.
|
||||||
|
*/
|
||||||
void MultipleSettings::on_regTypeBox_currentIndexChanged(int index)
|
void MultipleSettings::on_regTypeBox_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
switch (index) {
|
short maxRange = 0;
|
||||||
|
switch(ui->boardBox->currentIndex()) {
|
||||||
|
case 3:
|
||||||
|
maxRange = 64;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
maxRange = 84;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка изменения выбранной платы в интерфейсе.
|
||||||
|
*
|
||||||
|
* Этот слот сохраняет выбранный индекс платы в переменную selectedBoard
|
||||||
|
* и обновляет диапазон адресов в зависимости от текущего типа регистра,
|
||||||
|
* вызывая обработчик on_regTypeBox_currentIndexChanged.
|
||||||
|
*
|
||||||
|
* @param 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);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка изменения значения адреса (adrBox).
|
||||||
|
*
|
||||||
|
* При изменении значения адреса (arg1) обновляется максимальный допустимый диапазон
|
||||||
|
* для количества регистров (countBox). Максимальное значение зависит от текущего
|
||||||
|
* выбранного номера платы, типа регистра и текущего адреса.
|
||||||
|
*
|
||||||
|
* Формула для расчета диапазона:
|
||||||
|
* max = (85 - (20 * (boardIndex / 3))) * (1 + (regTypeIndex / 2)) - arg1
|
||||||
|
*
|
||||||
|
* @param arg1 Новое значение адреса.
|
||||||
|
*/
|
||||||
void MultipleSettings::on_adrBox_valueChanged(int arg1)
|
void MultipleSettings::on_adrBox_valueChanged(int arg1)
|
||||||
{
|
{
|
||||||
ui->countBox->setRange(1, ((85-(20*(ui->boardBox->currentIndex()/3)))*(1+(ui->regTypeBox->currentIndex()/2))-arg1));
|
ui->countBox->setRange(1, ((85 - (20 * (ui->boardBox->currentIndex() / 3)))
|
||||||
|
* (1 + (ui->regTypeBox->currentIndex() / 2)) - arg1));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ class MultipleSettings;
|
|||||||
class MultipleSettings : public QDialog
|
class MultipleSettings : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MultipleSettings(QWidget *parent = nullptr);
|
explicit MultipleSettings(QWidget *parent = nullptr);
|
||||||
~MultipleSettings();
|
~MultipleSettings();
|
||||||
@@ -23,16 +22,11 @@ public:
|
|||||||
signals:
|
signals:
|
||||||
void write();
|
void write();
|
||||||
void writeAndSend();
|
void writeAndSend();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_buttonBox_clicked(QAbstractButton *button);
|
void on_buttonBox_clicked(QAbstractButton *button);
|
||||||
|
|
||||||
void on_regTypeBox_currentIndexChanged(int index);
|
void on_regTypeBox_currentIndexChanged(int index);
|
||||||
|
|
||||||
void on_boardBox_currentIndexChanged(int index);
|
void on_boardBox_currentIndexChanged(int index);
|
||||||
|
|
||||||
void on_adrBox_valueChanged(int arg1);
|
void on_adrBox_valueChanged(int arg1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MultipleSettings *ui;
|
Ui::MultipleSettings *ui;
|
||||||
quint16 newValue = 0;
|
quint16 newValue = 0;
|
||||||
@@ -40,6 +34,7 @@ private:
|
|||||||
unsigned countReg;
|
unsigned countReg;
|
||||||
short typeReg;
|
short typeReg;
|
||||||
short boardId;
|
short boardId;
|
||||||
|
short selectedBoard;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MULTIPLESETTINGS_H
|
#endif // MULTIPLESETTINGS_H
|
||||||
|
|||||||
78
M3KTE_TERM/parameterbox.cpp
Normal file
78
M3KTE_TERM/parameterbox.cpp
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#include "parameterbox.h"
|
||||||
|
#include "ui_parameterbox.h"
|
||||||
|
|
||||||
|
ParameterBox::ParameterBox(QWidget *parent, pboxMode Mode, quint16 objectID) :
|
||||||
|
QWidget(parent),
|
||||||
|
ui(new Ui::ParameterBox)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
boxMode = Mode;
|
||||||
|
ID = objectID;
|
||||||
|
switch(boxMode) {
|
||||||
|
case Info:
|
||||||
|
ui->adrLine->setHidden(true);
|
||||||
|
ui->valueBox->setHidden(true);
|
||||||
|
ui->sendButton->setHidden(true);
|
||||||
|
break;
|
||||||
|
case MTemplate:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ui->objectIdLabel->setText("0x" + QString::number(ID, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterBox::~ParameterBox()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработчик нажатия кнопки отправки (sendButton).
|
||||||
|
*
|
||||||
|
* При нажатии проверяется, заполнено ли выбранное значение в valueBox.
|
||||||
|
* Если значение пустое, выполнение прерывается.
|
||||||
|
* В противном случае генерируется сигнал writeParameter с текущим адресом и выбранным значением (в шестнадцатеричном формате).
|
||||||
|
*/
|
||||||
|
void ParameterBox::on_sendButton_clicked()
|
||||||
|
{
|
||||||
|
if(ui->valueBox->currentText().isEmpty())
|
||||||
|
return;
|
||||||
|
emit writeParameter(ui->adrLine->text().toInt(), ui->valueBox->currentText().toInt(nullptr, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Установка текста параметра.
|
||||||
|
*
|
||||||
|
* Этот метод устанавливает переданный текст (data) в поле для имени параметра (nameLine).
|
||||||
|
*
|
||||||
|
* @param data Текст для отображения в поле имени.
|
||||||
|
*/
|
||||||
|
void ParameterBox::setData(QString data)
|
||||||
|
{
|
||||||
|
ui->nameLine->setText(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Установка данных в параметры в зависимости от режима работы.
|
||||||
|
*
|
||||||
|
* В зависимости от текущего режима (boxMode) заполняются соответствующие элементы интерфейса:
|
||||||
|
* - При режиме Info заполняется только поле имени.
|
||||||
|
* - При режиме MTemplate заполняются поля имени, адреса и список значений.
|
||||||
|
*
|
||||||
|
* @param name Имя параметра.
|
||||||
|
* @param adr Адрес параметра.
|
||||||
|
* @param values Список значений для выбора.
|
||||||
|
*/
|
||||||
|
void ParameterBox::setData(QString name, QString adr, QStringList values)
|
||||||
|
{
|
||||||
|
switch(boxMode) {
|
||||||
|
case Info:
|
||||||
|
ui->nameLine->setText(name);
|
||||||
|
break;
|
||||||
|
case MTemplate:
|
||||||
|
ui->nameLine->setText(name);
|
||||||
|
ui->adrLine->setText(adr);
|
||||||
|
ui->valueBox->clear();
|
||||||
|
ui->valueBox->addItems(values);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
M3KTE_TERM/parameterbox.h
Normal file
39
M3KTE_TERM/parameterbox.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef PARAMETERBOX_H
|
||||||
|
#define PARAMETERBOX_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ParameterBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ParameterBox : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum pboxMode{
|
||||||
|
Info = 0,
|
||||||
|
MTemplate = 1
|
||||||
|
};
|
||||||
|
enum objectType{
|
||||||
|
Coil = 0,
|
||||||
|
HR = 1
|
||||||
|
};
|
||||||
|
explicit ParameterBox(QWidget *parent = nullptr, pboxMode Mode = Info, quint16 objectID = 0x80);
|
||||||
|
~ParameterBox();
|
||||||
|
void setData(QString data);
|
||||||
|
void setData(QString name, QString adr, QStringList values);
|
||||||
|
quint16 getID(){return ID;}
|
||||||
|
objectType getType(){return type;}
|
||||||
|
signals:
|
||||||
|
void writeParameter(int adr, quint16 value);
|
||||||
|
private slots:
|
||||||
|
void on_sendButton_clicked();
|
||||||
|
private:
|
||||||
|
quint16 ID;
|
||||||
|
pboxMode boxMode;
|
||||||
|
objectType type = HR;
|
||||||
|
Ui::ParameterBox *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PARAMETERBOX_H
|
||||||
86
M3KTE_TERM/parameterbox.ui
Normal file
86
M3KTE_TERM/parameterbox.ui
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ParameterBox</class>
|
||||||
|
<widget class="QWidget" name="ParameterBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>43</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLineEdit" name="adrLine">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QPushButton" name="sendButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>SEND</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="nameLine">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QComboBox" name="valueBox">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="editable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="objectIdLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
236
M3KTE_TERM/parameterdevice.cpp
Normal file
236
M3KTE_TERM/parameterdevice.cpp
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
#include "parameterdevice.h"
|
||||||
|
#include "ui_parameterdevice.h"
|
||||||
|
|
||||||
|
void sortParameterBoxesByID(QVector<ParameterBox*>& parameterBoxes) {
|
||||||
|
std::sort(parameterBoxes.begin(), parameterBoxes.end(),
|
||||||
|
[](ParameterBox* a, ParameterBox* b) {
|
||||||
|
return a->getID() < b->getID();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterDevice::ParameterDevice(QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
ui(new Ui::ParameterDevice)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterDevice::~ParameterDevice()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка выбора режима "Выборочный" (selectiveRadio).
|
||||||
|
*
|
||||||
|
* Включает доступность элементов управления для выбора выборочного режима
|
||||||
|
* и устанавливает режим работы на `selectiveRequest`.
|
||||||
|
*/
|
||||||
|
void ParameterDevice::on_selectiveRadio_clicked()
|
||||||
|
{
|
||||||
|
// Включение элементов для выбора выборочного режима
|
||||||
|
ui->selectiveBox->setEnabled(true);
|
||||||
|
// Установка текущего режима
|
||||||
|
mode = selectiveRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка выбора режима "Полный" (fullRadio).
|
||||||
|
*
|
||||||
|
* Выключает элементы управления для выборочного режима,
|
||||||
|
* а также устанавливает режим работы на `fullRequest`.
|
||||||
|
*/
|
||||||
|
void ParameterDevice::on_fullRadio_clicked()
|
||||||
|
{
|
||||||
|
// Отключение элементов для выборочного режима
|
||||||
|
ui->selectiveBox->setEnabled(false);
|
||||||
|
// Установка текущего режима
|
||||||
|
mode = fullRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка нажатия на кнопку checkButton.
|
||||||
|
*
|
||||||
|
* Выполняет чтение данных по определенной логике (полный или выборочный запрос),
|
||||||
|
* отображает прогресс-бар, измеряет общее время выполнения и обновляет UI.
|
||||||
|
*
|
||||||
|
* @note В процессе выполнения очищает текущие параметры, инициирует последовательное чтение данных,
|
||||||
|
* отображает прогресс, а по завершении показывает затраченное время.
|
||||||
|
*/
|
||||||
|
void ParameterDevice::on_checkButton_clicked()
|
||||||
|
{
|
||||||
|
// Очистка старых параметров
|
||||||
|
for (ParameterBox* box : parameterBoxes)
|
||||||
|
if (box)
|
||||||
|
box->deleteLater();
|
||||||
|
parameterBoxes.clear();
|
||||||
|
quint16 strAdr;
|
||||||
|
int cnt = 0;
|
||||||
|
// Установка стартового адреса
|
||||||
|
strAdr = ui->adrSpin->value();
|
||||||
|
// В зависимости от режима задаем диапазон чтения
|
||||||
|
switch (mode) {
|
||||||
|
case fullRequest:
|
||||||
|
strAdr = 0x80;
|
||||||
|
cnt = 128;
|
||||||
|
break;
|
||||||
|
case selectiveRequest:
|
||||||
|
cnt = ui->countSpin->value();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Настройка таймера для измерения времени
|
||||||
|
QElapsedTimer timer;
|
||||||
|
// Создаем диалог прогресса
|
||||||
|
QProgressDialog progressDialog("Обработка...", "Отмена", 0, cnt, this);
|
||||||
|
progressDialog.setWindowModality(Qt::WindowModal);
|
||||||
|
progressDialog.setMinimumDuration(0); // показывать сразу же
|
||||||
|
// Создаем цикл событий для ожидания завершения
|
||||||
|
QEventLoop loop;
|
||||||
|
// Соединяем сигнал завершения передачи с выходом из цикла
|
||||||
|
connect(this, &ParameterDevice::transmitEnd, &loop, &QEventLoop::quit);
|
||||||
|
// Запускаем таймер
|
||||||
|
timer.start();
|
||||||
|
// Цикл чтения данных
|
||||||
|
for (int i = 0; i < cnt; i++) {
|
||||||
|
// Обновление прогресс-бара
|
||||||
|
progressDialog.setValue(i);
|
||||||
|
if (progressDialog.wasCanceled())
|
||||||
|
break; // пользователь отменил выполнение
|
||||||
|
// Формируем запрос
|
||||||
|
QByteArray data = QByteArray::fromHex("0E04");
|
||||||
|
data.append(strAdr + i);
|
||||||
|
QModbusRequest request(QModbusRequest::EncapsulatedInterfaceTransport, data);
|
||||||
|
// Отправка запроса
|
||||||
|
emit read(request, strAdr + i);
|
||||||
|
// Ожидание завершения передачи
|
||||||
|
loop.exec();
|
||||||
|
// Проверка на ошибку
|
||||||
|
if (errorAtTransmit) {
|
||||||
|
errorAtTransmit = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Расчет затраченного времени
|
||||||
|
qint64 elapsedNanoSeconds = timer.nsecsElapsed();
|
||||||
|
// Переводим в минуты, секунды, миллисекунды, микросекунды
|
||||||
|
qint64 totalMicroseconds = elapsedNanoSeconds / 1000;
|
||||||
|
qint64 totalMilliseconds = totalMicroseconds / 1000;
|
||||||
|
qint64 totalSeconds = totalMilliseconds / 1000;
|
||||||
|
qint64 totalMinutes = totalSeconds / 60;
|
||||||
|
qint64 remainingMicroseconds = totalMicroseconds % 1000;
|
||||||
|
qint64 remainingMilliseconds = totalMilliseconds % 1000;
|
||||||
|
qint64 remainingSeconds = totalSeconds % 60;
|
||||||
|
// Формируем строку для отображения времени
|
||||||
|
QString timeString = QString("%1 мин %2 сек %3 мс %4 мкс")
|
||||||
|
.arg(totalMinutes)
|
||||||
|
.arg(remainingSeconds)
|
||||||
|
.arg(remainingMilliseconds)
|
||||||
|
.arg(remainingMicroseconds);
|
||||||
|
// Выводим сообщение с временем выполнения
|
||||||
|
QMessageBox::information(this, "Общее время выполнения", timeString);
|
||||||
|
// Устанавливаем прогресс в конец
|
||||||
|
progressDialog.setValue(cnt);
|
||||||
|
// Сортируем параметры по ID и обновляем интерфейс
|
||||||
|
sortParameterBoxesByID(parameterBoxes);
|
||||||
|
sortScrollArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка ошибки при передаче данных.
|
||||||
|
*
|
||||||
|
* Показывает информационное сообщение с текстом ошибки,
|
||||||
|
* устанавливает флаг errorAtTransmit в true,
|
||||||
|
* а затем сигнализирует о завершении передачи.
|
||||||
|
*
|
||||||
|
* @param error Текст ошибки, который будет отображен пользователю.
|
||||||
|
*/
|
||||||
|
void ParameterDevice::setError(QString error)
|
||||||
|
{
|
||||||
|
QMessageBox::information(nullptr, "Получен ответ", error);
|
||||||
|
errorAtTransmit = true;
|
||||||
|
emit transmitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработчик изменения значения спинбокса адреса (adrSpin).
|
||||||
|
*
|
||||||
|
* При изменении значения аргумента (arg1) обновляет диапазон допустимых
|
||||||
|
* значений для другого спинбокса (countSpin), чтобы сумма не превышала 256.
|
||||||
|
*
|
||||||
|
* Устанавливает диапазон: от 1 до (256 - текущего значения adrSpin).
|
||||||
|
*
|
||||||
|
* @param arg1 Новое значение адреса.
|
||||||
|
*/
|
||||||
|
void ParameterDevice::on_adrSpin_valueChanged(int arg1)
|
||||||
|
{
|
||||||
|
ui->countSpin->setRange(1, 256 - arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Установка ответа и создание нового параметра.
|
||||||
|
*
|
||||||
|
* Этот метод создает новый объект ParameterBox, устанавливает его данные,
|
||||||
|
* и в зависимости от типа параметра (Coil или HR) устанавливает соответствующие соединения.
|
||||||
|
* После этого добавляет его в список и сигнализирует о завершении передачи.
|
||||||
|
*
|
||||||
|
* @param reply Текст ответа, который отображается в параметре.
|
||||||
|
* @param objectID Идентификатор объекта, связанного с этим параметром.
|
||||||
|
*/
|
||||||
|
void ParameterDevice::setAnswer(QString reply, quint16 objectID)
|
||||||
|
{
|
||||||
|
// Создаем новый объект ParameterBox в режиме Info
|
||||||
|
ParameterBox *newbox = new ParameterBox(nullptr, ParameterBox::Info, objectID);
|
||||||
|
// Устанавливаем данные ответа в созданный параметр
|
||||||
|
newbox->setData(reply);
|
||||||
|
// В зависимости от типа параметра устанавливаем соединения
|
||||||
|
switch(newbox->getType()) {
|
||||||
|
case ParameterBox::Coil:
|
||||||
|
// Для типа Coil связываем сигнал writeParameter с выводом writeSingleCoil
|
||||||
|
connect(newbox, &ParameterBox::writeParameter, this, [this](int adr, quint16 value){
|
||||||
|
emit writeSingleCoil(adr, (bool)value);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ParameterBox::HR:
|
||||||
|
// Для типа HR связываем сигнал writeParameter с выводом writeSingleRegister
|
||||||
|
connect(newbox, &ParameterBox::writeParameter, this, [this](int adr, quint16 value){
|
||||||
|
emit writeSingleRegister(adr, value);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Добавляем созданный параметр в список
|
||||||
|
parameterBoxes.append(newbox);
|
||||||
|
// Посылаем сигнал о завершении передачи
|
||||||
|
emit transmitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Перестроение (сортировка) содержимого внутри scrollArea.
|
||||||
|
*
|
||||||
|
* Этот метод очищает текущий лейаут внутри UI элемента parameterBoxHubContents,
|
||||||
|
* затем добавляет все параметры из списка parameterBoxes обратно в лейаут.
|
||||||
|
* После этого обновляются и перерасчитываются размеры элементов интерфейса.
|
||||||
|
*/
|
||||||
|
void ParameterDevice::sortScrollArea()
|
||||||
|
{
|
||||||
|
// Получение текущего лейаута внутри parameterBoxHubContents
|
||||||
|
QLayout* pblayout = ui->parameterBoxHubContents->layout();
|
||||||
|
// Если лейаут отсутствует, создаем новый и устанавливаем его
|
||||||
|
if (!pblayout) {
|
||||||
|
pblayout = new QVBoxLayout(ui->parameterBoxHubContents);
|
||||||
|
ui->parameterBoxHubContents->setLayout(pblayout);
|
||||||
|
}
|
||||||
|
// Очистка текущих элементов из лейаута
|
||||||
|
QLayoutItem *item;
|
||||||
|
while ((item = pblayout->takeAt(0)) != nullptr) {
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
// Добавление всех параметров из списка parameterBoxes обратно в лейаут
|
||||||
|
for (int i = 0; i < parameterBoxes.count(); i++) {
|
||||||
|
pblayout->addWidget(parameterBoxes.at(i));
|
||||||
|
}
|
||||||
|
// Обновление размеров и отображения интерфейса
|
||||||
|
ui->parameterBoxHubContents->update();
|
||||||
|
ui->parameterBoxHubContents->adjustSize();
|
||||||
|
ui->scrollArea->updateGeometry();
|
||||||
|
ui->scrollArea->viewport()->update();
|
||||||
|
}
|
||||||
54
M3KTE_TERM/parameterdevice.h
Normal file
54
M3KTE_TERM/parameterdevice.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef ParameterDevice_H
|
||||||
|
#define ParameterDevice_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QModbusRequest>
|
||||||
|
#include "parameterbox.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
void sortParameterBoxesByID(QVector<ParameterBox*>& parameterBoxes);
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ParameterDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ParameterDevice : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum requestMode{
|
||||||
|
fullRequest = 0,
|
||||||
|
selectiveRequest = 1
|
||||||
|
};
|
||||||
|
void setAnswer(QString reply, quint16 objectID);
|
||||||
|
void setError(QString error);
|
||||||
|
void setAdr(int _adr){adr = _adr;}
|
||||||
|
int getAdr(){return adr;}
|
||||||
|
bool errorAtTransmit = false;
|
||||||
|
explicit ParameterDevice(QWidget *parent = nullptr);
|
||||||
|
~ParameterDevice();
|
||||||
|
signals:
|
||||||
|
void read(QModbusRequest request, quint16 objectID);
|
||||||
|
void writeSingleCoil(int coilAddress, bool value);
|
||||||
|
void writeSingleRegister(int registerAddress, quint16 value);
|
||||||
|
void transmitEnd();
|
||||||
|
private slots:
|
||||||
|
void on_selectiveRadio_clicked();
|
||||||
|
void on_fullRadio_clicked();
|
||||||
|
void on_checkButton_clicked();
|
||||||
|
void on_adrSpin_valueChanged(int arg1);
|
||||||
|
private:
|
||||||
|
void sortScrollArea();
|
||||||
|
private:
|
||||||
|
int adr;
|
||||||
|
QVector<ParameterBox*>parameterBoxes;
|
||||||
|
requestMode mode = fullRequest;
|
||||||
|
Ui::ParameterDevice *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ParameterDevice_H
|
||||||
141
M3KTE_TERM/parameterdevice.ui
Normal file
141
M3KTE_TERM/parameterdevice.ui
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ParameterDevice</class>
|
||||||
|
<widget class="QWidget" name="ParameterDevice">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>687</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Extended Objects</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QGroupBox" name="selectiveBox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QSpinBox" name="adrSpin">
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="prefix">
|
||||||
|
<string>0x</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>128</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>255</number>
|
||||||
|
</property>
|
||||||
|
<property name="displayIntegerBase">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::LeftToRight</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Start Adr:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::RightToLeft</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Count:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="countSpin">
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QRadioButton" name="selectiveRadio">
|
||||||
|
<property name="text">
|
||||||
|
<string>Selective Request</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QPushButton" name="checkButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QRadioButton" name="fullRadio">
|
||||||
|
<property name="text">
|
||||||
|
<string>Full Request</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="parameterBoxHubContents">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>380</width>
|
||||||
|
<height>450</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
193
M3KTE_TERM/parameterworkspace.cpp
Normal file
193
M3KTE_TERM/parameterworkspace.cpp
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
#include "parameterworkspace.h"
|
||||||
|
#include "ui_parameterworkspace.h"
|
||||||
|
|
||||||
|
ParameterWorkspace::ParameterWorkspace(QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
ui(new Ui::ParameterWorkspace)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterWorkspace::~ParameterWorkspace()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает количество устройств и обновляет интерфейс.
|
||||||
|
*
|
||||||
|
* Очистка текущего списка устройств и удаления соответствующих вкладок,
|
||||||
|
* затем создание новых устройств и добавление их в интерфейс.
|
||||||
|
*
|
||||||
|
* @param count Новое количество устройств.
|
||||||
|
*/
|
||||||
|
void ParameterWorkspace::setDeviceCount(int count)
|
||||||
|
{
|
||||||
|
// Удаление и очистка текущих устройств
|
||||||
|
for (const auto& device : deviceList) {
|
||||||
|
device.tab->deleteLater(); ///< Удаление вкладки устройства
|
||||||
|
device.device->deleteLater(); ///< Удаление объекта устройства
|
||||||
|
}
|
||||||
|
deviceList.clear(); ///< Очистка списка устройств
|
||||||
|
// Удаление всех вкладок из таб-виджета
|
||||||
|
for (int i = 0; i < ui->tabWidget->count(); ++i) {
|
||||||
|
ui->tabWidget->removeTab(i);
|
||||||
|
}
|
||||||
|
// Создание новых устройств
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
auto _device = new device(); ///< Создаваемое устройство
|
||||||
|
deviceList.append(*_device); ///< Добавление в список
|
||||||
|
deviceList[i].device = new ParameterDevice(); ///< Создание объекта ParameterDevice
|
||||||
|
// Добавление вкладки для устройства
|
||||||
|
int newtab = ui->tabWidget->addTab(deviceList[i].device, tr("Device №%1").arg(i + 1));
|
||||||
|
deviceList[i].tab = ui->tabWidget->widget(newtab);
|
||||||
|
// Подключение сигналов от устройства к слотам
|
||||||
|
connect(deviceList[i].device, &ParameterDevice::read, this,
|
||||||
|
[this, i](QModbusRequest request, quint16 objectID) {
|
||||||
|
readDeviceIdentification(deviceList[i].device, request, deviceList[i].adr, objectID);
|
||||||
|
});
|
||||||
|
connect(deviceList[i].device, &ParameterDevice::writeSingleCoil, this,
|
||||||
|
[this, i](int coilAddress, bool value){
|
||||||
|
writeSingleCoil(deviceList[i].adr, coilAddress, value);
|
||||||
|
});
|
||||||
|
connect(deviceList[i].device, &ParameterDevice::writeSingleRegister, this,
|
||||||
|
[this, i](int registerAddress, quint16 value){
|
||||||
|
writeSingleRegister(deviceList[i].adr, registerAddress, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Отправляет команду на изменение состояния одиночного котла по Modbus.
|
||||||
|
*
|
||||||
|
* Проверяет состояние соединения, создает запрос и отправляет его.
|
||||||
|
* Обрабатывает завершение запроса, проверяя наличие ошибок.
|
||||||
|
*
|
||||||
|
* @param adr Адрес устройства по Modbus.
|
||||||
|
* @param coilAddress Адрес катушки (котла).
|
||||||
|
* @param value Значение для установки (true — включено, false — выключено).
|
||||||
|
*/
|
||||||
|
void ParameterWorkspace::writeSingleCoil(int adr, int coilAddress, bool value)
|
||||||
|
{
|
||||||
|
// Проверка правильности состояния соединения
|
||||||
|
if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState)
|
||||||
|
return;
|
||||||
|
// Создание пакета данных для записи
|
||||||
|
QModbusDataUnit unit(QModbusDataUnit::Coils, coilAddress, 1);
|
||||||
|
unit.setValue(0, value ? 1 : 0);
|
||||||
|
// Отправка запроса
|
||||||
|
if (auto *reply = modbusDevice->sendWriteRequest(unit, adr)) {
|
||||||
|
// Обработка завершения запроса
|
||||||
|
if (!reply->isFinished()) {
|
||||||
|
connect(reply, &QModbusReply::finished, this, [reply]() {
|
||||||
|
// Проверка ошибок выполнения
|
||||||
|
if (reply->error() != QModbusDevice::NoError) {
|
||||||
|
// Обработка ошибок (можно добавить лог или сообщение)
|
||||||
|
}
|
||||||
|
reply->deleteLater(); // Очистка объекта
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Если ответ уже готов, очищаем его сразу
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Отправляет команду на запись одного регистрового значения по Modbus.
|
||||||
|
*
|
||||||
|
* Проверяет состояние соединения, создает запрос и отправляет его.
|
||||||
|
* Обрабатывает завершение запроса и возможные ошибки.
|
||||||
|
*
|
||||||
|
* @param adr Адрес устройства по Modbus.
|
||||||
|
* @param regAddress Адрес регистрового аргумента.
|
||||||
|
* @param value Значение для записи.
|
||||||
|
*/
|
||||||
|
void ParameterWorkspace::writeSingleRegister(int adr, int regAddress, quint16 value)
|
||||||
|
{
|
||||||
|
// Проверка правильности состояния соединения
|
||||||
|
if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState)
|
||||||
|
return;
|
||||||
|
// Создание пакета данных для записи
|
||||||
|
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, regAddress, 1);
|
||||||
|
unit.setValue(0, value);
|
||||||
|
// Отправка запроса
|
||||||
|
if (auto *reply = modbusDevice->sendWriteRequest(unit, adr)) {
|
||||||
|
// Обработка завершения запроса
|
||||||
|
if (!reply->isFinished()) {
|
||||||
|
connect(reply, &QModbusReply::finished, this, [reply]() {
|
||||||
|
// Проверка наличия ошибок
|
||||||
|
if (reply->error() != QModbusDevice::NoError) {
|
||||||
|
// Можно добавить лог или обработку ошибок
|
||||||
|
}
|
||||||
|
reply->deleteLater(); // Очистка объекта
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Если ответ уже готов, очищаем его сразу
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Читает идентификационную информацию устройства по Modbus.
|
||||||
|
*
|
||||||
|
* Отправляет необработанный запрос к устройству и обрабатывает ответ.
|
||||||
|
* В случае успешного ответа извлекает данные и вызывает метод `setAnswer`.
|
||||||
|
* В случае ошибки вызывает `setError` и выводит сообщение в лог.
|
||||||
|
*
|
||||||
|
* @param device Указатель на устройство, которому предназначен ответ.
|
||||||
|
* @param request Объект запроса Modbus.
|
||||||
|
* @param adr Адрес устройства по Modbus.
|
||||||
|
* @param objectID Идентификатор объекта для обработки.
|
||||||
|
*/
|
||||||
|
void ParameterWorkspace::readDeviceIdentification(ParameterDevice *device, QModbusRequest request, int adr, quint16 objectID)
|
||||||
|
{
|
||||||
|
// Проверка состояния соединения
|
||||||
|
if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState)
|
||||||
|
return;
|
||||||
|
// Отправка сырого запроса к устройству
|
||||||
|
if (auto *reply = modbusDevice->sendRawRequest(request, adr)) {
|
||||||
|
// Обработка ответа, если он не завершен
|
||||||
|
if (!reply->isFinished()) {
|
||||||
|
connect(reply, &QModbusReply::finished, this, [device, reply, objectID]() {
|
||||||
|
// Проверка ошибок
|
||||||
|
if (reply->error() == QModbusDevice::NoError) {
|
||||||
|
QModbusResponse resp = reply->rawResult();
|
||||||
|
// Проверка размера данных
|
||||||
|
if (resp.data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) {
|
||||||
|
// Удаление протокольной части данных
|
||||||
|
QByteArray data = resp.data();
|
||||||
|
data.remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH);
|
||||||
|
QString result = QString::fromUtf8(data); // или другой метод преобразования, в зависимости от формата
|
||||||
|
device->setAnswer(result, objectID);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Обработка ошибок
|
||||||
|
device->setError(reply->errorString());
|
||||||
|
qDebug() << "Получен ответ с ошибкой:" << reply->errorString();
|
||||||
|
}
|
||||||
|
reply->deleteLater(); // Очистка объекта
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Ошибка при отправке запроса
|
||||||
|
device->setError("Unknow error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обновляет параметры устройства по идентификатору.
|
||||||
|
*
|
||||||
|
* Обновляет статус активности, адрес и устанавливает новый адрес в объекте устройства.
|
||||||
|
*
|
||||||
|
* @param ID Индекс или уникальный идентификатор устройства в списке.
|
||||||
|
* @param status Новый статус активности (true/false).
|
||||||
|
* @param adr Новый адрес устройства.
|
||||||
|
*/
|
||||||
|
void ParameterWorkspace::updateDevice(int ID, bool status, int adr)
|
||||||
|
{
|
||||||
|
deviceList[ID].isActive = status;
|
||||||
|
deviceList[ID].adr = adr;
|
||||||
|
deviceList[ID].device->setAdr(adr);
|
||||||
|
}
|
||||||
50
M3KTE_TERM/parameterworkspace.h
Normal file
50
M3KTE_TERM/parameterworkspace.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef PARAMETERWORKSPACE_H
|
||||||
|
#define PARAMETERWORKSPACE_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QModbusRequest>
|
||||||
|
#include <QModbusDataUnit>
|
||||||
|
#include <QModbusTcpClient>
|
||||||
|
#include <QModbusRtuSerialMaster>
|
||||||
|
#include <QtSerialBus/qtserialbusglobal.h>
|
||||||
|
|
||||||
|
#if QT_CONFIG(modbus_serialport)
|
||||||
|
#include <QSerialPort>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "parameterdevice.h"
|
||||||
|
|
||||||
|
#define MODBUS_REQUEST_PROTOCOL_INFO_LENGTH 8
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ParameterWorkspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ParameterWorkspace : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ParameterWorkspace(QWidget *parent = nullptr);
|
||||||
|
~ParameterWorkspace();
|
||||||
|
public:
|
||||||
|
void setModbusClient(QModbusClient *device){modbusDevice = device;}
|
||||||
|
void setDeviceCount(int count);
|
||||||
|
void updateDevice(int deviceID, bool status, int adr);
|
||||||
|
private slots:
|
||||||
|
void readDeviceIdentification(ParameterDevice *board, QModbusRequest request, int adr, quint16 objectID);
|
||||||
|
void writeSingleCoil(int adr, int coilAddress, bool value);
|
||||||
|
void writeSingleRegister(int adr, int registerAddress, quint16 value);
|
||||||
|
private:
|
||||||
|
struct device{
|
||||||
|
bool isActive = false;
|
||||||
|
int adr = 1;
|
||||||
|
ParameterDevice *device = nullptr;
|
||||||
|
QWidget *tab = nullptr;
|
||||||
|
};
|
||||||
|
QVector<device> deviceList;
|
||||||
|
QModbusClient *modbusDevice = nullptr;
|
||||||
|
Ui::ParameterWorkspace *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PARAMETERWORKSPACE_H
|
||||||
31
M3KTE_TERM/parameterworkspace.ui
Normal file
31
M3KTE_TERM/parameterworkspace.ui
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ParameterWorkspace</class>
|
||||||
|
<widget class="QWidget" name="ParameterWorkspace">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>610</width>
|
||||||
|
<height>646</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="tabPosition">
|
||||||
|
<enum>QTabWidget::North</enum>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -13,26 +13,52 @@ ScanBoard::~ScanBoard()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает текущий состояние чекбокса.
|
||||||
|
* @return Текущий Qt::CheckState.
|
||||||
|
*/
|
||||||
Qt::CheckState ScanBoard::getCheckState()
|
Qt::CheckState ScanBoard::getCheckState()
|
||||||
{
|
{
|
||||||
return checkState;
|
return checkState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработчик изменения состояния чекбокса "Apply to All".
|
||||||
|
* @param arg1 Новое состояние чекбокса (целое число, преобразуемое в Qt::CheckState).
|
||||||
|
*
|
||||||
|
* Этот слот вызывается при изменении состояния чекбокса и сохраняет новое значение.
|
||||||
|
*/
|
||||||
void ScanBoard::on_applyToAllBox_stateChanged(int arg1)
|
void ScanBoard::on_applyToAllBox_stateChanged(int arg1)
|
||||||
{
|
{
|
||||||
checkState = (Qt::CheckState)arg1;
|
checkState = static_cast<Qt::CheckState>(arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Выводит результат сканирования в лог.
|
||||||
|
* @param resultOfScan Строка с результатом сканирования.
|
||||||
|
*
|
||||||
|
* Добавляет результат сканирования в лог-виджет ui->logger.
|
||||||
|
*/
|
||||||
void ScanBoard::showMeTheTruth(QString resultOfScan)
|
void ScanBoard::showMeTheTruth(QString resultOfScan)
|
||||||
{
|
{
|
||||||
ui->logger->append(resultOfScan);
|
ui->logger->append(resultOfScan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает текущий baud-скорость.
|
||||||
|
* @return Значение скорости в виде quint16.
|
||||||
|
*/
|
||||||
quint16 ScanBoard::getBaud()
|
quint16 ScanBoard::getBaud()
|
||||||
{
|
{
|
||||||
return baud;
|
return baud;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработчик изменения текста в поле выбора скорости baud.
|
||||||
|
* @param arg1 Новое значение текса в comboBox.
|
||||||
|
*
|
||||||
|
* Парсит текст в целое число и сохраняет в переменную baud.
|
||||||
|
*/
|
||||||
void ScanBoard::on_baudRateBox_currentTextChanged(const QString &arg1)
|
void ScanBoard::on_baudRateBox_currentTextChanged(const QString &arg1)
|
||||||
{
|
{
|
||||||
baud = arg1.toInt(nullptr, 10);
|
baud = arg1.toInt(nullptr, 10);
|
||||||
|
|||||||
@@ -14,19 +14,15 @@ class ScanBoard : public QDialog
|
|||||||
public:
|
public:
|
||||||
explicit ScanBoard(QWidget *parent = nullptr);
|
explicit ScanBoard(QWidget *parent = nullptr);
|
||||||
~ScanBoard();
|
~ScanBoard();
|
||||||
|
|
||||||
Qt::CheckState getCheckState();
|
Qt::CheckState getCheckState();
|
||||||
void showMeTheTruth(QString resultOfScan);
|
void showMeTheTruth(QString resultOfScan);
|
||||||
quint16 getBaud();
|
quint16 getBaud();
|
||||||
private slots:
|
private slots:
|
||||||
void on_applyToAllBox_stateChanged(int arg1);
|
void on_applyToAllBox_stateChanged(int arg1);
|
||||||
|
|
||||||
void on_baudRateBox_currentTextChanged(const QString &arg1);
|
void on_baudRateBox_currentTextChanged(const QString &arg1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Qt::CheckState checkState;
|
Qt::CheckState checkState;
|
||||||
quint16 baud;
|
quint16 baud;
|
||||||
|
|
||||||
Ui::ScanBoard *ui;
|
Ui::ScanBoard *ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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,13 +15,11 @@ 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();
|
||||||
m_settings.parity = ui->parityCombo->currentIndex();
|
m_settings.parity = ui->parityCombo->currentIndex();
|
||||||
if (m_settings.parity > 0)
|
if(m_settings.parity > 0)
|
||||||
m_settings.parity++;
|
m_settings.parity++;
|
||||||
m_settings.baud = ui->baudCombo->currentText().toInt();
|
m_settings.baud = ui->baudCombo->currentText().toInt();
|
||||||
m_settings.dataBits = ui->dataBitsCombo->currentText().toInt();
|
m_settings.dataBits = ui->dataBitsCombo->currentText().toInt();
|
||||||
@@ -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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -40,42 +36,74 @@ SettingsDialog::~SettingsDialog()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Возвращает текущие настройки.
|
||||||
|
* @return Объект настроек типа Settings.
|
||||||
|
*/
|
||||||
SettingsDialog::Settings SettingsDialog::settings() const
|
SettingsDialog::Settings SettingsDialog::settings() const
|
||||||
{
|
{
|
||||||
return m_settings;
|
return m_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обновляет индекс baud-скорости в UI и сохраняет значение в настройки.
|
||||||
|
* @param baud Индекс выбранной скорости.
|
||||||
|
* @return Новое значение baud, сохранённое в настройках.
|
||||||
|
*/
|
||||||
int SettingsDialog::UpdateBaud(int baud)
|
int SettingsDialog::UpdateBaud(int baud)
|
||||||
{
|
{
|
||||||
|
// Устанавливаем текущий индекс в comboBox
|
||||||
ui->baudCombo->setCurrentIndex(baud);
|
ui->baudCombo->setCurrentIndex(baud);
|
||||||
|
// Обновляем настройки и возвращаем новую скорость как число
|
||||||
return (m_settings.baud = ui->baudCombo->currentText().toInt());
|
return (m_settings.baud = ui->baudCombo->currentText().toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обновляет индекс паритета в UI и сохраняет значение в настройки.
|
||||||
|
* @param parity Индекс выбранного паритета.
|
||||||
|
* @return Новое значение паритета, сохранённое в настройках.
|
||||||
|
*/
|
||||||
int SettingsDialog::UpdateParity(int parity)
|
int SettingsDialog::UpdateParity(int parity)
|
||||||
{
|
{
|
||||||
|
// Устанавливаем текущий индекс
|
||||||
ui->parityCombo->setCurrentIndex(parity);
|
ui->parityCombo->setCurrentIndex(parity);
|
||||||
if(parity>0) {
|
// Если parity > 0, увеличиваем его значение перед сохранением
|
||||||
return (m_settings.parity = ++parity);
|
if (parity > 0)
|
||||||
} else {
|
return (m_settings.parity = ++parity);
|
||||||
|
else
|
||||||
return (m_settings.parity = parity);
|
return (m_settings.parity = parity);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает текущий индекс выбранной baud-скорости.
|
||||||
|
* @return Индекс выбранного элемента в comboBox.
|
||||||
|
*/
|
||||||
int SettingsDialog::curBaud()
|
int SettingsDialog::curBaud()
|
||||||
{
|
{
|
||||||
return ui->baudCombo->currentIndex();
|
return ui->baudCombo->currentIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает текущий индекс выбранного паритета.
|
||||||
|
* @return Индекс выбранного элемента в comboBox.
|
||||||
|
*/
|
||||||
int SettingsDialog::curParity()
|
int SettingsDialog::curParity()
|
||||||
{
|
{
|
||||||
return ui->parityCombo->currentIndex();
|
return ui->parityCombo->currentIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обновляет список доступных COM-портов.
|
||||||
|
*
|
||||||
|
* Этот метод вызывается при нажатии кнопки, обновляя список портов в UI.
|
||||||
|
* Он очищает текущий список и заполняет его всеми доступными портами.
|
||||||
|
*/
|
||||||
void SettingsDialog::on_updateComBox_clicked()
|
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("%1: %2").arg(port.portName(), port.manufacturer()), QVariant(port.portName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,23 +24,18 @@ 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit SettingsDialog(QWidget *parent = nullptr);
|
explicit SettingsDialog(QWidget *parent = nullptr);
|
||||||
~SettingsDialog();
|
~SettingsDialog();
|
||||||
|
|
||||||
Settings settings() const;
|
Settings settings() const;
|
||||||
|
|
||||||
int UpdateBaud(int baud);
|
int UpdateBaud(int baud);
|
||||||
int UpdateParity(int parity);
|
int UpdateParity(int parity);
|
||||||
|
|
||||||
int curBaud();
|
int curBaud();
|
||||||
int curParity();
|
int curParity();
|
||||||
private slots:
|
private slots:
|
||||||
void on_updateComBox_clicked();
|
void on_updateComBox_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Settings m_settings;
|
Settings m_settings;
|
||||||
Ui::SettingsDialog *ui;
|
Ui::SettingsDialog *ui;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#include "writeregistermodel.h"
|
#include "writeregistermodel.h"
|
||||||
|
|
||||||
#include "writeregistermodel.h"
|
|
||||||
|
|
||||||
enum { NumColumn = 0, NameColumn = 1, CoilsColumn = 2, HoldingColumn = 3, ColumnCount = 5, CurrentUColumn = 4};
|
enum { NumColumn = 0, NameColumn = 1, CoilsColumn = 2, HoldingColumn = 3, ColumnCount = 5, CurrentUColumn = 4};
|
||||||
|
|
||||||
WriteRegisterModel::WriteRegisterModel(QObject *parent, int _tmpRC, bool _isHR)
|
WriteRegisterModel::WriteRegisterModel(QObject *parent, int _tmpRC, bool _isHR)
|
||||||
@@ -21,29 +19,56 @@ int WriteRegisterModel::columnCount(const QModelIndex &/*parent*/) const
|
|||||||
return ColumnCount;
|
return ColumnCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Возвращает данные модели для отображения в представлении.
|
||||||
|
*
|
||||||
|
* В зависимости от роли и столбца возвращает соответствующее значение:
|
||||||
|
* - номер строки;
|
||||||
|
* - имя;
|
||||||
|
* - состояние чекбокса;
|
||||||
|
* - значение в Вольтах для регистров и текущего напряжения.
|
||||||
|
*
|
||||||
|
* @param index Индекс элемента модели.
|
||||||
|
* @param role Роль запрашиваемых данных.
|
||||||
|
* @return Значение данных в виде QVariant.
|
||||||
|
*/
|
||||||
QVariant WriteRegisterModel::data(const QModelIndex &index, int role) const
|
QVariant WriteRegisterModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
|
// Проверка корректности индекса
|
||||||
if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
|
if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
// Проверка соответствия размеров
|
||||||
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() == 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)));
|
||||||
|
// Обработка чекбокса
|
||||||
if (index.column() == CoilsColumn && role == Qt::CheckStateRole) // coils
|
if (index.column() == CoilsColumn && role == Qt::CheckStateRole)
|
||||||
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)
|
||||||
return QString("0x%1").arg(QString::number(m_holdingRegisters.at(index.row()), 16));
|
return QString("%1 В").arg(QString::number((double)m_holdingRegisters.at(index.row()) / 1000.0, '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)m_currentU.at(index.row()) / 1000.0, 'f', 3));
|
||||||
|
// Возврат пустого QVariant по умолчанию
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Возвращает заголовки столбцов для отображения в представлении.
|
||||||
|
*
|
||||||
|
* Обеспечивает отображение названий для горизонтальных заголовков.
|
||||||
|
*
|
||||||
|
* @param section Индекс столбца.
|
||||||
|
* @param orientation Ориентация (горизонтальная или вертикальная).
|
||||||
|
* @param role Роль данных, обычно Qt::DisplayRole.
|
||||||
|
* @return Заголовок в виде QVariant или пустой QVariant при несоответствии.
|
||||||
|
*/
|
||||||
QVariant WriteRegisterModel::headerData(int section, Qt::Orientation orientation, int role) const
|
QVariant WriteRegisterModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
{
|
{
|
||||||
if (role != Qt::DisplayRole)
|
if (role != Qt::DisplayRole)
|
||||||
@@ -67,74 +92,136 @@ QVariant WriteRegisterModel::headerData(int section, Qt::Orientation orientation
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает данные модели по индексу.
|
||||||
|
*
|
||||||
|
* Обработка для чекбоксов (CoilsColumn) и регистров (HoldingColumn).
|
||||||
|
*
|
||||||
|
* @param index Индекс элемента.
|
||||||
|
* @param value Новое значение.
|
||||||
|
* @param role Роль, определяющая тип данных (например, Qt::CheckStateRole, Qt::EditRole).
|
||||||
|
* @return true, если данные успешно установлены; иначе false.
|
||||||
|
*/
|
||||||
bool WriteRegisterModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
bool WriteRegisterModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
{
|
{
|
||||||
if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
|
// Проверяем валидность индекса и границы
|
||||||
|
if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
|
||||||
return false;
|
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) {
|
||||||
auto s = static_cast<Qt::CheckState>(value.toUInt());
|
auto state = static_cast<Qt::CheckState>(value.toUInt());
|
||||||
s == Qt::Checked ? m_coils.setBit(index.row()) : m_coils.clearBit(index.row());
|
if (state == Qt::Checked)
|
||||||
|
m_coils.setBit(index.row());
|
||||||
|
else
|
||||||
|
m_coils.clearBit(index.row());
|
||||||
emit dataChanged(index, index);
|
emit dataChanged(index, index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (index.column() == HoldingColumn && role == Qt::EditRole) { // holding registers
|
// Обработка для регистров
|
||||||
|
if (index.column() == HoldingColumn && role == Qt::EditRole) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
quint16 newValue = value.toString().toUShort(&result, 16);
|
// Преобразование QVariant в строку, затем в число
|
||||||
if (result)
|
QString valueStr = value.toString();
|
||||||
|
quint16 newValue = valueStr.toUShort(&result, 10);
|
||||||
|
if (result) {
|
||||||
m_holdingRegisters[index.row()] = newValue;
|
m_holdingRegisters[index.row()] = newValue;
|
||||||
|
emit dataChanged(index, index);
|
||||||
emit dataChanged(index, index);
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
// Если не обработано, вернуть false
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает флаги для элементов модели, определяя их поведение.
|
||||||
|
*
|
||||||
|
* @param index Индекс элемента модели.
|
||||||
|
* @return Флаги, определяющие свойства элемента.
|
||||||
|
*/
|
||||||
Qt::ItemFlags WriteRegisterModel::flags(const QModelIndex &index) const
|
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;
|
||||||
|
// Установка флага чекбокса для столбца Coils
|
||||||
if (index.column() == CoilsColumn) // coils
|
if (index.column() == CoilsColumn)
|
||||||
return flags | Qt::ItemIsUserCheckable;
|
return flags | Qt::ItemIsUserCheckable;
|
||||||
if (index.column() == HoldingColumn) // holding registers
|
// Установка флага редактируемости для столбца HoldingRegisters
|
||||||
|
if (index.column() == HoldingColumn)
|
||||||
return flags | Qt::ItemIsEditable;
|
return flags | Qt::ItemIsEditable;
|
||||||
|
// Возврат текущих флагов по умолчанию
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает начальный адрес для модели.
|
||||||
|
*
|
||||||
|
* @param address Начальный адрес.
|
||||||
|
*/
|
||||||
void WriteRegisterModel::setStartAddress(int address)
|
void WriteRegisterModel::setStartAddress(int address)
|
||||||
{
|
{
|
||||||
m_address = address;
|
m_address = address;
|
||||||
//emit updateViewport();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает число значений (величин) на основе строки.
|
||||||
|
*
|
||||||
|
* @param number Строковое представление числа.
|
||||||
|
*/
|
||||||
void WriteRegisterModel::setNumberOfValues(const QString &number)
|
void WriteRegisterModel::setNumberOfValues(const QString &number)
|
||||||
{
|
{
|
||||||
m_number = number.toInt();
|
m_number = number.toInt();
|
||||||
//emit updateViewport();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает состояние coil по индексу.
|
||||||
|
*
|
||||||
|
* @param index Индекс элемента.
|
||||||
|
* @return true, если coil активен; иначе false.
|
||||||
|
*/
|
||||||
bool WriteRegisterModel::get_coil(const QModelIndex &index)
|
bool WriteRegisterModel::get_coil(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
return m_coils.at(index.row());
|
return m_coils.at(index.row());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает значение holding register по индексу.
|
||||||
|
*
|
||||||
|
* @param index Индекс элемента.
|
||||||
|
* @return Значение регистров.
|
||||||
|
*/
|
||||||
uint WriteRegisterModel::get_holreg(const QModelIndex &index)
|
uint WriteRegisterModel::get_holreg(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
return m_holdingRegisters.at(index.row());
|
return m_holdingRegisters.at(index.row());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает текущие значения U для указанных индексов.
|
||||||
|
*
|
||||||
|
* Изначально обновляет значение в массиве m_currentU по указанному индексу.
|
||||||
|
* Если isHR установлено в true, также обновляет значение по индексу, смещённому на m_number.
|
||||||
|
*
|
||||||
|
* @param _tmpU Новое значение U.
|
||||||
|
* @param index Индекс элемента.
|
||||||
|
* @return Всегда возвращает true.
|
||||||
|
*/
|
||||||
bool WriteRegisterModel::set_currentU(unsigned _tmpU, unsigned index)
|
bool WriteRegisterModel::set_currentU(unsigned _tmpU, unsigned index)
|
||||||
{
|
{
|
||||||
|
// Установка значения для текущего индекса
|
||||||
m_currentU[index] = _tmpU;
|
m_currentU[index] = _tmpU;
|
||||||
if(isHR)
|
|
||||||
|
// Если isHR активен, обновляем также и по смещенному индексу
|
||||||
|
if (isHR)
|
||||||
m_currentU[index + m_number] = _tmpU;
|
m_currentU[index + m_number] = _tmpU;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,25 +14,18 @@ public:
|
|||||||
WriteRegisterModel(QObject *parent = nullptr, int _tmpRC = 85, bool _isHR = false);
|
WriteRegisterModel(QObject *parent = nullptr, int _tmpRC = 85, bool _isHR = false);
|
||||||
bool get_coil(const QModelIndex &index);
|
bool get_coil(const QModelIndex &index);
|
||||||
uint get_holreg(const QModelIndex &index);
|
uint get_holreg(const QModelIndex &index);
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||||
|
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
|
||||||
bool set_currentU(unsigned _tmpU, unsigned index);
|
bool set_currentU(unsigned _tmpU, unsigned index);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setStartAddress(int address);
|
void setStartAddress(int address);
|
||||||
void setNumberOfValues(const QString &number);
|
void setNumberOfValues(const QString &number);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updateViewport();
|
void updateViewport();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int m_number = 0;
|
int m_number = 0;
|
||||||
int m_address = 0;
|
int m_address = 0;
|
||||||
|
|||||||
BIN
MZKT_Test_Terminal.exe
Normal file
BIN
MZKT_Test_Terminal.exe
Normal file
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user