добавлен локальный статус для каждого мзктэ

This commit is contained in:
Вячеслав Штейбезандт 2025-10-08 18:47:23 +03:00
parent 190f3337ed
commit 4ae15d8c01
6 changed files with 8577 additions and 8292 deletions

View File

@ -132,8 +132,13 @@ void DeviceSettingsDialog::updatePollStatus(unsigned boardID, bool status)
void DeviceSettingsDialog::on_buttonApplyChangePoll_clicked()
{
updatePollStatus(ui->idPollComboBox->currentData().toUInt(), (bool)ui->pollStatusBox->currentIndex());
pollStatusChange* _pollStatusChanged = new pollStatusChange(ui->idPollComboBox->currentData().toUInt(), _currentPollStatus[ui->idPollComboBox->currentData().toUInt()]);
sendPollCommand(ui->idPollComboBox->currentData().toUInt(), (bool)ui->pollStatusBox->currentIndex());
}
void DeviceSettingsDialog::sendPollCommand(unsigned boardID, bool status)
{
updatePollStatus(boardID, status);
pollStatusChange* _pollStatusChanged = new pollStatusChange(boardID, status);
QCoreApplication::postEvent(parent(), _pollStatusChanged);
}

View File

@ -51,6 +51,7 @@ public:
unsigned currentSpeed();
unsigned short currentParity();
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 initPollForBoard(unsigned boardID, unsigned boardAdr);
void onDisconnect();
@ -64,6 +65,7 @@ signals:
void fourthBoardAdrHasBeenChanged();
private slots:
void on_buttonApplyChangeTimer_clicked();
void on_buttonApplyChangeSpeed_clicked();

View File

@ -176,7 +176,7 @@
<item row="0" column="1">
<widget class="QSpinBox" name="adrSpinBox">
<property name="minimum">
<number>1</number>
<number>0</number>
</property>
<property name="maximum">
<number>247</number>

View File

@ -423,12 +423,54 @@ M3KTE::M3KTE(QWidget *parent)
Boards[2].timerData = ui->timeData_3;
Boards[3].timerData = ui->timeData_4;
}
{
Boards[0].localError = ui->localErrorEdit_1;
Boards[1].localError = ui->localErrorEdit_2;
Boards[2].localError = ui->localErrorEdit_3;
Boards[3].localError = ui->localErrorEdit_4;
}
{
Boards[0].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_1;
Boards[1].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_2;
Boards[2].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_3;
Boards[3].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_4;
Boards[0].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_1;
Boards[1].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_2;
Boards[2].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_3;
Boards[3].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_4;
Boards[0].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_1;
Boards[1].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_2;
Boards[2].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_3;
Boards[3].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_4;
}
{ // не кликабельные чекбоксы и радиобоксы
for(int i = 0; i < 4; i++)
{
connect(Boards[i].localState[LOCAL_STATE_POLL], &QCheckBox::clicked,
this, [i, this](bool checked) {
m_deviceSettingsDialog->sendPollCommand(i, checked);
});
Boards[i].localState[LOCAL_STATE_WARN]->setAttribute(Qt::WA_TransparentForMouseEvents, true);
Boards[i].localState[LOCAL_STATE_ERR]->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
ui->BSM_Warning->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BSM_Accident->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BSM_WorkInProgress->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BST_On->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BST_Off->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
for(int i = 0; i < 4; i++) {
statusM3KTE.Warnings[i] = false;
statusM3KTE.Accidents[i] = false;
Boards_Fields[i]->setEnabled(false);
Boards[i].timerData->setText(" ");
Boards[i].timerStatus->setText(" ");;
Boards[i].localError->setText(" ");;
}
for(int i = 0; i < 5; i++) {
ui->writeValueTable->resizeColumnToContents(i);
@ -484,6 +526,8 @@ void M3KTE::initActions()
this, &M3KTE::onReadButtonClicked);
connect(ui->writeButton, &QPushButton::clicked,
this, &M3KTE::onWriteButtonClicked);
connect(ui->clearLoggerBtn, &QPushButton::clicked,
this, &M3KTE::clearLogger);
connect(ui->boardSelectBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &M3KTE::onSelectedBoardChanged);
connect(ui->writeTable, QOverload<int>::of(&QComboBox::currentIndexChanged),
@ -509,6 +553,19 @@ void M3KTE::logError(const QString &errorPlace, const QString &errorString, unsi
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
}
void M3KTE::clearLogger()
{
// Проверяем, что таблица инициализирована
if (!loggerTable) {
return;
}
// Отключаем обновление UI для повышения производительности
loggerTable->setUpdatesEnabled(false);
// Очищаем все строки таблицы
loggerTable->setRowCount(0);
// Включаем обновление UI
loggerTable->setUpdatesEnabled(true);
}
void M3KTE::onConnectClicked()
{
@ -575,6 +632,7 @@ void M3KTE::onConnectClicked()
Boards_Fields[i]->setTitle(QString("Плата №%1").arg(i+1));
Boards[i].timerData->setText(" ");;
Boards[i].timerStatus->setText(" ");;
Boards[i].localError->setText(" ");;
}
for(int i = 0; i < 320; i++) {
m_ProgressBar[i]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85)));
@ -1155,6 +1213,7 @@ bool M3KTE::pingNetworkDevices()
QModbusRequest requestOfBoardID(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0401"));
for(CurrentConnectedDevice=0; CurrentConnectedDevice<4;) {
modbusDevice->setTimeout(1000);
auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr);
//Запрос типа устройства.
if(reply == nullptr) {
@ -1187,6 +1246,7 @@ bool M3KTE::pingNetworkDevices()
QModbusResponse resp = reply->rawResult();
QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH));
if(result == QString("KTE")) {
modbusDevice->setTimeout(1000);
auto *subreply = modbusDevice->sendRawRequest(requestOfBoardID, tmp_adr);
while(!subreply->isFinished()) {
@ -1355,90 +1415,102 @@ void M3KTE::beginScanBoards()
void M3KTE::boardScan(unsigned boardID)
{
if(!modbusDevice)
if (!modbusDevice) {
return;
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1);
}
statusBar()->clearMessage();
if(auto *reply = modbusDevice->sendReadRequest(*_unit, Boards[boardID].adr)) {
QModbusDataUnit statusUnit(QModbusDataUnit::InputRegisters, 85, 1);
if (auto *reply = modbusDevice->sendReadRequest(statusUnit, Boards[boardID].adr)) {
Boards[boardID].timerToStatusResponse.start();
if(!reply->isFinished())
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() {
if(!Boards[boardID].isActive)
return;
// Обработка ответа статуса
Boards[boardID].timerStatus->setText(QString("Status: %1 ms").arg(Boards[boardID].timerToStatusResponse.elapsed()));
if(reply->error()==QModbusDevice::NoError) {
if (reply->error() == QModbusDevice::NoError) {
statusreg StatusReg;
StatusReg.AllReg = reply->result().value(0);
if(StatusReg.ParsingReg.poll_allowed) {
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
return;
}
if(StatusReg.ParsingReg.mzkte_status) {
switch(StatusReg.ParsingReg.mzkte_error) {
case 1:
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
return;
case 2:
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
return;
case 3:
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
return;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
default:
break;
}
}
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 0, 85);
if(auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[boardID].adr)) {
// Запрос полных данных
QModbusDataUnit dataUnit(QModbusDataUnit::InputRegisters, 0, 85);
if (auto *dataReply = modbusDevice->sendReadRequest(dataUnit, Boards[boardID].adr)) {
Boards[boardID].timerToDataResponse.start();
if(!subreply->isFinished()) {
connect(subreply, &QModbusReply::finished, this, [this, boardID]() {
Boards[boardID].timerData->setText(QString("Data: %1 ms").arg(Boards[boardID].timerToStatusResponse.elapsed()));
auto subreply = qobject_cast<QModbusReply *>(sender());
displayResultOfScan(subreply, boardID);
subreply->deleteLater();
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
if (!dataReply->isFinished()) {
connect(dataReply, &QModbusReply::finished, this, [this, boardID, dataReply, StatusReg]() {
if(!Boards[boardID].isActive)
return;
Boards[boardID].timerData->setText(QString("Data: %1 ms").arg(Boards[boardID].timerToDataResponse.elapsed()));
displayResultOfScan(dataReply, boardID, StatusReg.AllReg);
dataReply->deleteLater();
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
});
} else {
// Мгновенно завершенный запрос данных
Boards[boardID].timerToDataResponse.elapsed();
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
delete subreply;
// shouldLog для dataReply должен определяться здесь, но используем тот же принцип
if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
dataReply->deleteLater();
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
} else {
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
delete subreply;
// Ошибка отправки запроса данных
if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
} else {
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_TX, "");
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
// Ошибка в ответе статуса
if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_TX, "");
}
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
reply->deleteLater();
});
else {
} else {
// Мгновенно завершенный запрос статуса
Boards[boardID].timerToStatusResponse.elapsed();
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
delete reply; // broadcast replies return immediately
// Для мгновенно завершенных запросов определяем shouldLog здесь
if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
reply->deleteLater();
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
} else {
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
Boards[boardID].boardScanners->start(m_deviceSettingsDialog->currentBoardTimer(boardID));
// Ошибка отправки запроса статуса
if (Boards[boardID].isActive) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
}
}
void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID)
void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status)
{
if(!reply)
return;
@ -1453,6 +1525,60 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID)
reply->deleteLater();
return;
}
statusreg StatusReg;
StatusReg.AllReg = status;
// Обрабатываем статус MZKT
QString statusText;
int state = StatusReg.ParsingReg.mzkte_status;
int numb_err = StatusReg.ParsingReg.mzkte_error;
if (state == 0) {
statusText = "Ok";
} else if (state == 1) {
statusText = "Non-Critical";
} else if (state == 2) {
statusText = "Critical";
}
if (state) {
switch (numb_err) {
case 1:
statusText += QString(" (Err 5 VD)");
break;
case 2:
statusText += QString(" (Err 5 VA)");
break;
case 3:
statusText += QString(" (Err 5 Vsci)");
break;
case 4:
statusText += QString(" (Err 24 V)");
break;
case 5:
statusText += QString(" (Hardfault)");
break;
case 6:
statusText += QString(" (ADC Error)");
break;
case 7:
statusText += QString(" (UART Error)");
break;
case 8:
statusText += QString(" (Measure Error)");
break;
default:
statusText += QString(" (Program Err %1)").arg(numb_err - 4);
break;
}
}
Boards[boardID].localError->setText(statusText);
Boards[boardID].localState[LOCAL_STATE_POLL]->setChecked(StatusReg.ParsingReg.poll_allowed);
Boards[boardID].localState[LOCAL_STATE_WARN]->setChecked(StatusReg.ParsingReg.warning);
Boards[boardID].localState[LOCAL_STATE_ERR]->setChecked(StatusReg.ParsingReg.accident);
QString W_Adr;
QString A_Adr;
for(int i = unit.startAddress(), total = int(unit.valueCount()); i < total; ++i) {
@ -1498,13 +1624,13 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID)
ui->writeValueTable->model()->index(unit.startAddress() + unit.valueCount() -1, 2));
Boards[boardID].ModbusModelHoldingReg->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 3),
ui->writeValueTable->model()->index(unit.startAddress() + unit.valueCount() -1, 3));
if(A_Flag) {
if(A_Flag && !A_Adr.isEmpty()) {
statusM3KTE.Accidents[boardID] = true;
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
"Авария", Boards[boardID].error_A, A_Adr);
} else
statusM3KTE.Accidents[boardID] = false;
if(W_Flag) {
if(W_Flag && !W_Adr.isEmpty()) {
statusM3KTE.Warnings[boardID] = true;
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
"Предупреждение", Boards[boardID].error_W, W_Adr);

View File

@ -15,6 +15,7 @@
#include <QModbusTcpClient>
#include <QModbusRtuSerialMaster>
#include <QHBoxLayout>
#include <QTimer>
#include <QMessageBox>
#include <QProgressDialog>
@ -39,6 +40,10 @@ QT_BEGIN_NAMESPACE
namespace Ui { class M3KTE; class SettingsDialog;}
QT_END_NAMESPACE
#define LOCAL_STATE_POLL 0
#define LOCAL_STATE_WARN 1
#define LOCAL_STATE_ERR 2
class SettingsDialog;
class WriteRegisterModel;
@ -54,7 +59,7 @@ private:
bool pingNetworkDevices();
void beginScanBoards();
void stopScanBoard();
void displayResultOfScan(QModbusReply *reply, int boardID);
void displayResultOfScan(QModbusReply *reply, int boardID, int status);
void applySettingsFromScan(QModbusReply *reply);
void multipleRegWrite();
void multipleRegSend();
@ -64,6 +69,7 @@ signals:
void successAtCheckBoards();
void errorAtCheckBoards();
private slots:
void clearLogger();
void logError(const QString &errorPlace, const QString &errorString, unsigned errorCount, const QString &description);
void slotmultipleRegWrite();
void slotmultipleRegWriteAndSend();
@ -119,6 +125,8 @@ private:
unsigned error_cmd_change = 0;
QLabel *timerData = nullptr;
QLabel *timerStatus = nullptr;
QLabel *localError = nullptr;
QCheckBox *localState[3] = {nullptr, nullptr, nullptr};
WriteRegisterModel *ModbusModelCoil;
WriteRegisterModel *ModbusModelHoldingReg;
QTimer *boardScanners;

File diff suppressed because it is too large Load Diff