Алгоритм изменения скорости обмена данными с платами. Пока без вывода ошибок в лог.

This commit is contained in:
Вячеслав Штейбезандт 2025-09-15 13:07:14 +03:00
parent d9f58e72e4
commit b4803e19e2
7 changed files with 176 additions and 295 deletions

Binary file not shown.

View File

@ -21,8 +21,7 @@ DeviceSettingsDialog::DeviceSettingsDialog(QWidget *parent) :
_currentParity = ui->parityBox->currentIndex(); _currentParity = ui->parityBox->currentIndex();
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{
_currentAdrs[i] = i+1; _currentAdrs[i] = i+1;
} }
} }
@ -81,16 +80,12 @@ void DeviceSettingsDialog::updateSettingsAfterConnection(unsigned tmp_speed, uns
if(tmp_parity>0) if(tmp_parity>0)
tmp_parity--; tmp_parity--;
ui->parityBox->setCurrentIndex(_currentParity = tmp_parity); ui->parityBox->setCurrentIndex(_currentParity = tmp_parity);
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{ if(ActiveDevices[i]) {
if(ActiveDevices[i])
{
_m_timer[i]->setEnabled(true); _m_timer[i]->setEnabled(true);
ui->idComboBox->addItem(QString::number(i)); ui->idComboBox->addItem(QString::number(i));
_currentAdrs[i] = tmp_adr[i]; _currentAdrs[i] = tmp_adr[i];
} } else {
else
{
_m_timer[i]->setEnabled(false); _m_timer[i]->setEnabled(false);
} }
} }
@ -121,8 +116,7 @@ void DeviceSettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
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()]);

View File

@ -8,8 +8,7 @@ LineRinger::LineRinger(QWidget *parent) :
ui->setupUi(this); ui->setupUi(this);
const auto listPorts = QSerialPortInfo::availablePorts(); const auto listPorts = QSerialPortInfo::availablePorts();
for (const auto& port: listPorts) for (const auto& port: listPorts) {
{
ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName())); ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName()));
} }
@ -55,9 +54,9 @@ void LineRinger::syncColumnHeaders()
void LineRinger::on_connectButton_clicked() void LineRinger::on_connectButton_clicked()
{ {
if (!modbusDevice) if(!modbusDevice)
return; return;
if (modbusDevice->state() != QModbusDevice::ConnectedState) { if(modbusDevice->state() != QModbusDevice::ConnectedState) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
ui->comBox->currentData().toString()); ui->comBox->currentData().toString());
#if QT_CONFIG(modbus_serialport) #if QT_CONFIG(modbus_serialport)
@ -72,7 +71,7 @@ void LineRinger::on_connectButton_clicked()
#endif #endif
modbusDevice->setTimeout(50); modbusDevice->setTimeout(50);
modbusDevice->setNumberOfRetries(0); modbusDevice->setNumberOfRetries(0);
if (!modbusDevice->connectDevice()) { if(!modbusDevice->connectDevice()) {
QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения."); QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения.");
} else { } else {
ui->connectButton->setText(tr("Отключить")); ui->connectButton->setText(tr("Отключить"));
@ -94,105 +93,84 @@ 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, [this, tmp_isRun]() {
{
*tmp_isRun = true; *tmp_isRun = true;
}); });
connect(this, &LineRinger::stopLineCall, this, [this, tmp_isRun]() connect(this, &LineRinger::stopLineCall, this, [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); //auto *reply = modbusDevice->sendReadRequest(*_unit, tmp_adr);
//Запрос типа устройства. //Запрос типа устройства.
if(reply == nullptr) if(reply == nullptr) {
{
QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1").arg(modbusDevice->errorString())); QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1").arg(modbusDevice->errorString()));
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::ERROR; return callStatus::ERROR;
} }
while(!reply->isFinished()) while(!reply->isFinished()) {
{ if(isRun) {
if(isRun)
{
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::INTERRUPT; return callStatus::INTERRUPT;
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(isRun) if(isRun) {
{
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::INTERRUPT; return callStatus::INTERRUPT;
} } else if(!isRun) {
else if (!isRun)
{
//Нужна проверка типа устройства //Нужна проверка типа устройства
if(reply->error()!=QModbusDevice::TimeoutError) if(reply->error()!=QModbusDevice::TimeoutError) {
{
deviceOnLine currentDevice; deviceOnLine currentDevice;
currentDevice.adr = tmp_adr; currentDevice.adr = tmp_adr;
currentDevice.baudRate = currentBaudRate; currentDevice.baudRate = currentBaudRate;
bool regularReplyError = false; bool regularReplyError = false;
QString regularReplyErrorString; QString regularReplyErrorString;
if(reply->error()==QModbusDevice::NoError) if(reply->error()==QModbusDevice::NoError) {
{
QModbusResponse resp = reply->rawResult(); QModbusResponse resp = reply->rawResult();
uint8_t numOfObject = resp.data().at(5); uint8_t numOfObject = resp.data().at(5);
QByteArray result = resp.data().remove(0, 6); QByteArray result = resp.data().remove(0, 6);
for(int tmp_obj = 0; tmp_obj < numOfObject; tmp_obj++) for(int tmp_obj = 0; tmp_obj < numOfObject; tmp_obj++) {
{
uint8_t objectID = result.at(0); uint8_t objectID = result.at(0);
uint8_t lengthOfObject = result.at(1); uint8_t lengthOfObject = result.at(1);
if(lengthOfObject>0) if(lengthOfObject>0) {
{
currentDevice.fields[objectID].clear(); currentDevice.fields[objectID].clear();
} }
for(int i = 0; i < lengthOfObject; i++) for(int i = 0; i < lengthOfObject; i++) {
{
currentDevice.fields[objectID] += QString(result.at(2+i)); currentDevice.fields[objectID] += QString(result.at(2+i));
} }
result.remove(0, lengthOfObject+2); result.remove(0, lengthOfObject+2);
} }
auto *regularReply = modbusDevice->sendRawRequest(readDeviceRegularIdentification, tmp_adr); auto *regularReply = modbusDevice->sendRawRequest(readDeviceRegularIdentification, tmp_adr);
if(regularReply == nullptr) if(regularReply == nullptr) {
{
QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(modbusDevice->error()).arg(modbusDevice->errorString())); QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(modbusDevice->error()).arg(modbusDevice->errorString()));
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::ERROR; return callStatus::ERROR;
} }
while(!regularReply->isFinished()) while(!regularReply->isFinished()) {
{ if(isRun) {
if(isRun)
{
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::INTERRUPT; return callStatus::INTERRUPT;
} }
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
if(isRun) if(isRun) {
{
bar->close(); bar->close();
bar->deleteLater(); bar->deleteLater();
return callStatus::INTERRUPT; return callStatus::INTERRUPT;
} } else if(!isRun) {
else if(!isRun) if(regularReply->error()!=QModbusDevice::NoError) {
{
if(regularReply->error()!=QModbusDevice::NoError)
{
// QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(regularReply->error()).arg(regularReply->errorString())); // QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(regularReply->error()).arg(regularReply->errorString()));
// bar->close(); // bar->close();
// bar->deleteLater(); // bar->deleteLater();
@ -203,14 +181,12 @@ LineRinger::callStatus LineRinger::lineCall()
QModbusResponse regularResp = regularReply->rawResult(); QModbusResponse regularResp = regularReply->rawResult();
uint8_t numOfRegularObject = regularResp.data().at(5); uint8_t numOfRegularObject = regularResp.data().at(5);
QByteArray regularResult = regularResp.data().remove(0, 6); QByteArray regularResult = regularResp.data().remove(0, 6);
for(int tmp_obj = 0; tmp_obj < numOfRegularObject; tmp_obj++) for(int tmp_obj = 0; tmp_obj < numOfRegularObject; tmp_obj++) {
{
uint8_t objectID = regularResult.at(0); uint8_t objectID = regularResult.at(0);
if(objectID > 0x06) if(objectID > 0x06)
continue; continue;
uint8_t lengthOfObject = regularResult.at(1); uint8_t lengthOfObject = regularResult.at(1);
if(lengthOfObject>0) if(lengthOfObject>0) {
{
currentDevice.fields[objectID].clear(); currentDevice.fields[objectID].clear();
} }
for (int i = 0; i < lengthOfObject; i++) { for (int i = 0; i < lengthOfObject; i++) {
@ -220,8 +196,7 @@ LineRinger::callStatus LineRinger::lineCall()
} }
} }
} }
if(!isRun) if(!isRun) {
{
devicesList.append(currentDevice); devicesList.append(currentDevice);
unsigned newRow = ui->deviceOnlineView->rowCount(); unsigned newRow = ui->deviceOnlineView->rowCount();
ui->deviceOnlineView->insertRow(newRow); ui->deviceOnlineView->insertRow(newRow);
@ -230,12 +205,9 @@ LineRinger::callStatus LineRinger::lineCall()
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
ui->deviceOnlineView->setItem(newRow, i+2, new QTableWidgetItem(currentDevice.fields[i])); ui->deviceOnlineView->setItem(newRow, i+2, new QTableWidgetItem(currentDevice.fields[i]));
} }
if(reply->error()!=QModbusDevice::NoError) if(reply->error()!=QModbusDevice::NoError) {
{
ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(QString("%1: %2").arg(reply->error()).arg(reply->errorString()))); ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(QString("%1: %2").arg(reply->error()).arg(reply->errorString())));
} } else if(regularReplyError) {
else if(regularReplyError)
{
ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString)); ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString));
} }
ui->deviceOnlineView->resizeColumnsToContents(); ui->deviceOnlineView->resizeColumnsToContents();
@ -254,16 +226,14 @@ void LineRinger::on_ringButton_clicked()
syncColumnHeaders(); syncColumnHeaders();
while(ui->deviceOnlineView->rowCount()!=0) while(ui->deviceOnlineView->rowCount()!=0)
ui->deviceOnlineView->removeRow(ui->deviceOnlineView->rowCount()-1); ui->deviceOnlineView->removeRow(ui->deviceOnlineView->rowCount()-1);
if(isAutoBaud) if(isAutoBaud) {
{
auto bar = new QProgressDialog(this); auto bar = new QProgressDialog(this);
bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate)); bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate));
bar->setRange(0, ui->baudRateBox->count()); bar->setRange(0, ui->baudRateBox->count());
bar->setAutoClose(true); bar->setAutoClose(true);
bar->setMinimumDuration(0); bar->setMinimumDuration(0);
bar->setCancelButton(nullptr); bar->setCancelButton(nullptr);
connect(bar, &QProgressDialog::canceled, this, [this]() connect(bar, &QProgressDialog::canceled, this, [this]() {
{
emit stopLineCall(); emit stopLineCall();
}); });
bar->setValue(0); bar->setValue(0);
@ -271,7 +241,6 @@ void LineRinger::on_ringButton_clicked()
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,
@ -283,8 +252,7 @@ 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();
@ -297,12 +265,9 @@ void LineRinger::on_ringButton_clicked()
modbusDevice->disconnectDevice(); modbusDevice->disconnectDevice();
} }
on_connectButton_clicked(); on_connectButton_clicked();
} } else {
else
{
ui->deviceOnlineView->setColumnHidden(1, true); ui->deviceOnlineView->setColumnHidden(1, true);
if(lineCall() == callStatus::INTERRUPT) if(lineCall() == callStatus::INTERRUPT) {
{
QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count()));
} }
} }

View File

@ -353,8 +353,7 @@ M3KTE::M3KTE(QWidget *parent)
ui->writeTable->addItem(tr("Exceptions"), QModbusDataUnit::Coils); ui->writeTable->addItem(tr("Exceptions"), QModbusDataUnit::Coils);
ui->writeTable->addItem(tr("Warnings"), QModbusDataUnit::HoldingRegisters); ui->writeTable->addItem(tr("Warnings"), QModbusDataUnit::HoldingRegisters);
ui->writeTable->addItem(tr("Accidents"), QModbusDataUnit::HoldingRegisters); ui->writeTable->addItem(tr("Accidents"), QModbusDataUnit::HoldingRegisters);
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{
Boards[i].ModbusModelCoil = new WriteRegisterModel(this, 85 - (i/3*20), false); Boards[i].ModbusModelCoil = new WriteRegisterModel(this, 85 - (i/3*20), false);
Boards[i].ModbusModelCoil->setStartAddress(0); Boards[i].ModbusModelCoil->setStartAddress(0);
Boards[i].ModbusModelCoil->setNumberOfValues(QString::number(85-(i/3*20))); Boards[i].ModbusModelCoil->setNumberOfValues(QString::number(85-(i/3*20)));
@ -374,20 +373,16 @@ M3KTE::M3KTE(QWidget *parent)
Boards[1].boardScanners->setSingleShot(true); Boards[1].boardScanners->setSingleShot(true);
Boards[2].boardScanners->setSingleShot(true); Boards[2].boardScanners->setSingleShot(true);
Boards[3].boardScanners->setSingleShot(true); Boards[3].boardScanners->setSingleShot(true);
connect(Boards[0].boardScanners, &QTimer::timeout, this, [this]() connect(Boards[0].boardScanners, &QTimer::timeout, this, [this]() {
{
boardScan(0); boardScan(0);
}); });
connect(Boards[1].boardScanners, &QTimer::timeout, this, [this]() connect(Boards[1].boardScanners, &QTimer::timeout, this, [this]() {
{
boardScan(1); boardScan(1);
}); });
connect(Boards[2].boardScanners, &QTimer::timeout, this, [this]() connect(Boards[2].boardScanners, &QTimer::timeout, this, [this]() {
{
boardScan(2); boardScan(2);
}); });
connect(Boards[3].boardScanners, &QTimer::timeout, this, [this]() connect(Boards[3].boardScanners, &QTimer::timeout, this, [this]() {
{
boardScan(3); boardScan(3);
}); });
Boards[0].adr = 1; Boards[0].adr = 1;
@ -426,13 +421,11 @@ M3KTE::M3KTE(QWidget *parent)
Boards[i].timerData->setText(" "); Boards[i].timerData->setText(" ");
Boards[i].timerStatus->setText(" ");; Boards[i].timerStatus->setText(" ");;
} }
for(int i = 0; i < 5; i++) for(int i = 0; i < 5; i++) {
{
ui->writeValueTable->resizeColumnToContents(i); ui->writeValueTable->resizeColumnToContents(i);
} }
QBrush tb(Qt::transparent); // Transparent brush, solid pattern QBrush tb(Qt::transparent); // Transparent brush, solid pattern
for(int i = 0; i<320; i++) for(int i = 0; i<320; i++) {
{
m_ProgressBar[i]->setTextVisible(true); m_ProgressBar[i]->setTextVisible(true);
m_ProgressBar[i]->setMinimumSize(25, 25); m_ProgressBar[i]->setMinimumSize(25, 25);
m_ProgressBar[i]->setMaximumSize(25, 25); m_ProgressBar[i]->setMaximumSize(25, 25);
@ -464,8 +457,7 @@ M3KTE::M3KTE(QWidget *parent)
M3KTE::~M3KTE() M3KTE::~M3KTE()
{ {
if(modbusDevice->state() == QModbusDevice::ConnectedState) if(modbusDevice->state() == QModbusDevice::ConnectedState) {
{
onConnectClicked(); onConnectClicked();
} }
delete ui; delete ui;
@ -521,8 +513,7 @@ void M3KTE::onConnectClicked()
} else { } else {
ui->ConnectionMenuConnect->setEnabled(false); ui->ConnectionMenuConnect->setEnabled(false);
ui->ConnectionMenuDisconnect->setEnabled(true); ui->ConnectionMenuDisconnect->setEnabled(true);
if(pingNetworkDevices()) //Опрос устройств if(pingNetworkDevices()) { //Опрос устройств
{
unsigned tmp_adr[4]; unsigned tmp_adr[4];
bool ActiveDevices[4]; bool ActiveDevices[4];
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
@ -546,13 +537,11 @@ void M3KTE::onConnectClicked()
} }
} else { } else {
QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} "; QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} ";
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{
Boards[i].boardScanners->stop(); Boards[i].boardScanners->stop();
Boards_Fields[i]->setEnabled(false); Boards_Fields[i]->setEnabled(false);
Boards[i].isActive=false; Boards[i].isActive=false;
for(int j = 0; j < (85 - (i/3*20)); j++) for(int j = 0; j < (85 - (i/3*20)); j++) {
{
Boards[i].coil[j] = false; Boards[i].coil[j] = false;
Boards[i].ModbusModelCoil->m_coils[j]=0; Boards[i].ModbusModelCoil->m_coils[j]=0;
Boards[i].ModbusModelHoldingReg->m_currentU[j]=0; Boards[i].ModbusModelHoldingReg->m_currentU[j]=0;
@ -563,8 +552,7 @@ void M3KTE::onConnectClicked()
Boards[i].timerData->setText(" ");; Boards[i].timerData->setText(" ");;
Boards[i].timerStatus->setText(" ");; Boards[i].timerStatus->setText(" ");;
} }
for(int i = 0; i < 320; i++) for(int i = 0; i < 320; i++) {
{
m_ProgressBar[i]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85))); m_ProgressBar[i]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85)));
m_ProgressBar[i]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85))); m_ProgressBar[i]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85)));
m_ProgressBar[i]->setValue(3); m_ProgressBar[i]->setValue(3);
@ -609,10 +597,8 @@ void M3KTE::onReadReady()
if(!reply) if(!reply)
return; return;
int Adr = 255; int Adr = 255;
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++) {
{ if(Boards[i].isActive && Boards[i].adr==reply->serverAddress()) {
if(Boards[i].isActive && Boards[i].adr==reply->serverAddress())
{
Adr = i; Adr = i;
break; break;
} }
@ -620,16 +606,13 @@ void M3KTE::onReadReady()
if(reply->error() == QModbusDevice::NoError) { if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result(); const QModbusDataUnit unit = reply->result();
for(int i = 0, total = int(unit.valueCount()); i < total; ++i) { for(int i = 0, total = int(unit.valueCount()); i < total; ++i) {
if(unit.registerType() == QModbusDataUnit::Coils) if(unit.registerType() == QModbusDataUnit::Coils) {
{
Boards[Adr].coil[i + unit.startAddress()] = unit.value(i); Boards[Adr].coil[i + unit.startAddress()] = unit.value(i);
if(unit.value(i)==1) if(unit.value(i)==1)
Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Checked, Qt::CheckStateRole); Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Checked, Qt::CheckStateRole);
else else
Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Unchecked, Qt::CheckStateRole); Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Unchecked, Qt::CheckStateRole);
} } else if(unit.registerType() == QModbusDataUnit::HoldingRegisters) {
else if(unit.registerType() == QModbusDataUnit::HoldingRegisters)
{
Boards[Adr].HR[i + unit.startAddress()] = unit.value(i); Boards[Adr].HR[i + unit.startAddress()] = unit.value(i);
Boards[Adr].ModbusModelHoldingReg->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 16), Qt::EditRole); Boards[Adr].ModbusModelHoldingReg->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 16), Qt::EditRole);
} }
@ -690,9 +673,7 @@ void M3KTE::onWriteButtonClicked()
{ {
Boards[ui->boardSelectBox->currentIndex()].coil[i+writeUnit.startAddress()] = Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]; Boards[ui->boardSelectBox->currentIndex()].coil[i+writeUnit.startAddress()] = Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()];
writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]); writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]);
} } else {
else
{
Boards[ui->boardSelectBox->currentIndex()].HR[i+writeUnit.startAddress()] = Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i+writeUnit.startAddress()]; Boards[ui->boardSelectBox->currentIndex()].HR[i+writeUnit.startAddress()] = Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i+writeUnit.startAddress()];
writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i + writeUnit.startAddress()]); writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i + writeUnit.startAddress()]);
} }
@ -768,8 +749,7 @@ void M3KTE::changeTable(int board, int tabletype)
} }
ui->writeValueTable->hideColumn(3); ui->writeValueTable->hideColumn(3);
ui->writeValueTable->showColumn(2); ui->writeValueTable->showColumn(2);
} } else {
else {
ui->writeValueTable->setModel(Boards[board].ModbusModelHoldingReg); ui->writeValueTable->setModel(Boards[board].ModbusModelHoldingReg);
if(tabletype==1) { if(tabletype==1) {
Boards[board].ModbusModelHoldingReg->setStartAddress(0); Boards[board].ModbusModelHoldingReg->setStartAddress(0);
@ -780,8 +760,7 @@ void M3KTE::changeTable(int board, int tabletype)
for(;i<Boards[board].ModbusModelHoldingReg->rowCount();i++) { for(;i<Boards[board].ModbusModelHoldingReg->rowCount();i++) {
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true); ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true);
} }
} } else {
else {
Boards[board].ModbusModelHoldingReg->setStartAddress(Boards[board].ModbusModelHoldingReg->rowCount()/2); Boards[board].ModbusModelHoldingReg->setStartAddress(Boards[board].ModbusModelHoldingReg->rowCount()/2);
int i = 0; int i = 0;
for(;i<Boards[board].ModbusModelHoldingReg->rowCount()/2;i++) { for(;i<Boards[board].ModbusModelHoldingReg->rowCount()/2;i++) {
@ -862,8 +841,7 @@ bool M3KTE::event(QEvent *event)
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum()); loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
reply->deleteLater(); reply->deleteLater();
} }
} } else {
else {
unsigned newRow = loggerTable->rowCount(); unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow); loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
@ -891,8 +869,7 @@ bool M3KTE::event(QEvent *event)
reply->deleteLater(); reply->deleteLater();
delete reply; delete reply;
} }
} } else {
else {
unsigned newRow = loggerTable->rowCount(); unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow); loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
@ -907,8 +884,7 @@ bool M3KTE::event(QEvent *event)
} }
m_deviceSettingsDialog->show(); m_deviceSettingsDialog->show();
return true; return true;
} } else if(event->type() == (QEvent::Type)1001) {
else if(event->type() == (QEvent::Type)1001) {
pollStatusChange* _event = static_cast<pollStatusChange*>(event); pollStatusChange* _event = static_cast<pollStatusChange*>(event);
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 170, 1); QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 170, 1);
_unit->setValue(0, _event->Status()); _unit->setValue(0, _event->Status());
@ -928,8 +904,7 @@ bool M3KTE::event(QEvent *event)
reply->deleteLater(); reply->deleteLater();
} }
}); });
} } else {
else {
unsigned newRow = loggerTable->rowCount(); unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow); loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
@ -1104,11 +1079,67 @@ void M3KTE::onSpeedUpdate()
} }
*/ */
void M3KTE::checkBoards()
{
QModbusDataUnit unitCheck(QModbusDataUnit::InputRegisters, 85, 1);
int totalActiveBoards = 0;
int confirmedBoards = 0;
QSet<int> pendingBoards;
for(int i = 0; i < 4; ++i) {
if(!Boards[i].isActive)
continue;
totalActiveBoards++;
int slaveAddress = Boards[i].adr;
QModbusReply *reply = modbusDevice->sendReadRequest(unitCheck, slaveAddress);
if(!reply) {
revertToOldSpeedAndRestart();
return;
}
pendingBoards.insert(slaveAddress);
connect(reply, &QModbusReply::finished, this, [this, reply, slaveAddress, &confirmedBoards, &pendingBoards, totalActiveBoards]() mutable {
if(reply->error() == QModbusDevice::NoError) {
// Проверяем что пришел валидный ответ
QModbusDataUnit unit = reply->result();
if(unit.valueCount() > 0) {
confirmedBoards++;
} else {
}
} else {
}
pendingBoards.remove(slaveAddress);
reply->deleteLater();
if(pendingBoards.isEmpty()) {
if(confirmedBoards != totalActiveBoards) {
emit errorAtCheckBoards();
} else {
emit successAtCheckBoards();
}
}
});
}
// Если нет ни одной активной платы — сразу запускаем сканирование
if(totalActiveBoards == 0) {
emit errorAtCheckBoards();
}
}
void M3KTE::onSpeedUpdate() void M3KTE::onSpeedUpdate()
{ {
stopScanBoard(); stopScanBoard();
modbusDevice->setTimeout(500); modbusDevice->setTimeout(500);
unsigned tmp_speed = 0;
switch(m_deviceSettingsDialog->currentSpeed()) { switch(m_deviceSettingsDialog->currentSpeed()) {
case 0: case 0:
tmp_speed = 9600; tmp_speed = 9600;
@ -1149,145 +1180,57 @@ void M3KTE::onSpeedUpdate()
beginScanBoards(); beginScanBoards();
return; return;
} }
speedChangeRequests.clear();
pendingSpeedChangeRequestsCount = 0;
for(int i = 0; i < 4; i++) {
speedChangeRequests[i].errorOccurred = false;
speedChangeRequests[i].finished = false;
speedChangeRequests[i].confirmationReceived = false;
}
for(int i = 0; i < 4; i++) {
if(!Boards[i].isActive)
continue;
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 173, 1);
unit.setValue(0, m_deviceSettingsDialog->currentSpeed());
auto *reply = modbusDevice->sendWriteRequest(unit, Boards[i].adr);
if (reply) {
SpeedChangeRequest req;
req.boardIndex = i;
speedChangeRequests.append(req);
pendingSpeedChangeRequestsCount++;
connect(reply, &QModbusReply::finished, this, [this, reply, i]() {
this->handleSpeedChangeReply(reply, i);
});
}
else
{
}
}
}
void M3KTE::handleSpeedChangeReply(QModbusReply *reply, int boardIndex)
{
auto it = std::find_if(speedChangeRequests.begin(), speedChangeRequests.end(),
[boardIndex](const SpeedChangeRequest &r) { return r.boardIndex == boardIndex; });
if (it == speedChangeRequests.end()) {
reply->deleteLater();
return;
}
// Обновление состояния
it->finished = true;
if (reply->error() != QModbusDevice::TimeoutError) {
// Произошла ошибка
it->errorOccurred = true; // флаг ошибки
}
reply->deleteLater();
// Отслеживание завершения всех запросов
pendingSpeedChangeRequestsCount--;
// Проверяем, все ли запросы завершены
if (pendingSpeedChangeRequestsCount == 0) {
// Проверяем, был ли хоть один сбой (кроме тайм-аутов)
bool hasError = false;
for (const auto &req : speedChangeRequests) {
if (req.errorOccurred) {
hasError = true;
break;
}
}
if (hasError) {
// Был сбой — отменяем переход и восстанавливаем старую скорость
// Восстановим старую скорость порта
revertToOldSpeedAndRestart();
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
beginScanBoards();
} else {
onAllSpeedChangeRepliesReceived();
}
}
}
void M3KTE::onAllSpeedChangeRepliesReceived()
{
// Переключаемся на tmp_speed
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, tmp_speed);
if (!modbusDevice->connectDevice()) {
return;
}
QModbusDataUnit unitCheck(QModbusDataUnit::InputRegisters, 85, 1);
int totalActiveBoards = 0; int totalActiveBoards = 0;
int confirmedBoards = 0; int confirmedBoards = 0;
QSet<int> pendingBoards; QSet<int> pendingBoards;
for (int i = 0; i < 4; ++i) { QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 173, 1);
if (!Boards[i].isActive) unit.setValue(0, m_deviceSettingsDialog->currentSpeed());
for(int i = 0; i < 4; i++) {
if(!Boards[i].isActive)
continue; continue;
totalActiveBoards++; int slaveAdress = Boards[i].adr;
int slaveAddress = Boards[i].adr;
QModbusReply *reply = modbusDevice->sendReadRequest(unitCheck, slaveAddress); auto *reply = modbusDevice->sendWriteRequest(unit, slaveAdress);
if (!reply) { if(reply) {
revertToOldSpeedAndRestart(); totalActiveBoards++;
return; pendingBoards.insert(slaveAdress);
} connect(reply, &QModbusReply::finished, this, [this, reply, slaveAdress, &confirmedBoards, &pendingBoards, totalActiveBoards, tmp_speed]() mutable {
if(reply->error() == QModbusDevice::TimeoutError) {
pendingBoards.insert(slaveAddress);
connect(reply, &QModbusReply::finished, this, [this, reply, slaveAddress, &confirmedBoards, &pendingBoards, totalActiveBoards]() mutable {
if (reply->error() == QModbusDevice::NoError) {
// Проверяем что пришел валидный ответ
QModbusDataUnit unit = reply->result();
if (unit.valueCount() > 0) {
confirmedBoards++; confirmedBoards++;
} else {
} }
} else { pendingBoards.remove(slaveAdress);
reply->deleteLater();
} if(pendingBoards.isEmpty()) {
if(confirmedBoards != totalActiveBoards) {
pendingBoards.remove(slaveAddress); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
reply->deleteLater(); revertToOldSpeedAndRestart();
beginScanBoards();
if (pendingBoards.isEmpty()) { } else {
if (confirmedBoards != totalActiveBoards) { // Переключаемся на tmp_speed
revertToOldSpeedAndRestart(); modbusDevice->disconnectDevice();
beginScanBoards(); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, tmp_speed);
} else { modbusDevice->connectDevice();
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); connect(this, &M3KTE::errorAtCheckBoards, this, [this](){
beginScanBoards(); disconnect(this, &M3KTE::errorAtCheckBoards, this, nullptr);
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
revertToOldSpeedAndRestart();
beginScanBoards();
});
connect(this, &M3KTE::successAtCheckBoards, this, [this](){
disconnect(this, &M3KTE::successAtCheckBoards, this, nullptr);
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
beginScanBoards();
});
checkBoards();
}
} }
} });
}); }
}
// Если нет ни одной активной платы — сразу запускаем сканирование
if (totalActiveBoards == 0) {
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
beginScanBoards();
} }
} }
@ -1362,8 +1305,7 @@ void M3KTE::onParityUpdate()
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
m_settingsDialog->curParity()); m_settingsDialog->curParity());
modbusDevice->connectDevice(); modbusDevice->connectDevice();
} } else {
else {
unsigned newRow = loggerTable->rowCount(); unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow); loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss")))); loggerTable->setItem(newRow, 0, new QTableWidgetItem((QTime::currentTime().toString("HH:mm:ss"))));
@ -1829,7 +1771,6 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID)
loggerTable->resizeColumnsToContents(); loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown()) if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum()); loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
} else { } else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)"). statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()). arg(reply->errorString()).

View File

@ -63,6 +63,12 @@ private:
bool autoBaudRateScan(); bool autoBaudRateScan();
void selectPositionOnTree(unsigned index); void selectPositionOnTree(unsigned index);
signals:
void successAtCheckBoards();
void errorAtCheckBoards();
private slots: private slots:
void slotmultipleRegWrite(); void slotmultipleRegWrite();
@ -79,15 +85,15 @@ private slots:
void onSelectedBoardChanged(int index); void onSelectedBoardChanged(int index);
void onWriteTableChanged(int index); void onWriteTableChanged(int index);
void checkBoards();
void onSpeedUpdate(); void onSpeedUpdate();
void revertToOldSpeedAndRestart();
void onParityUpdate(); void onParityUpdate();
void boardScan(unsigned boardID); void boardScan(unsigned boardID);
void handleSpeedChangeReply(QModbusReply *reply, int boardIndex);
void onAllSpeedChangeRepliesReceived();
void revertToOldSpeedAndRestart();
public: public:
M3KTE(QWidget *parent = nullptr); M3KTE(QWidget *parent = nullptr);
~M3KTE(); ~M3KTE();
@ -117,8 +123,7 @@ private:
unsigned error_terminal; unsigned error_terminal;
struct BoardModbusRegisters struct BoardModbusRegisters {
{
bool isActive = false; bool isActive = false;
bool pollIsActive = true; bool pollIsActive = true;
@ -150,10 +155,8 @@ private:
QElapsedTimer timerToDataResponse; QElapsedTimer timerToDataResponse;
}Boards[4]; }Boards[4];
union statusreg union statusreg {
{ struct parsingFields {
struct parsingFields
{
unsigned accident:1; unsigned accident:1;
unsigned warning:1; unsigned warning:1;
unsigned poll_allowed:1; unsigned poll_allowed:1;
@ -163,17 +166,5 @@ private:
}ParsingReg; }ParsingReg;
unsigned AllReg:16; unsigned AllReg:16;
}; };
// Структура для отслеживания состояния запроса смены скорости
struct SpeedChangeRequest {
int boardIndex;
bool errorOccurred = false;
bool finished = false;
bool confirmationReceived = false;
};
QVector<SpeedChangeRequest> speedChangeRequests;
int pendingSpeedChangeRequestsCount = 0;
int pendingConfirmationsCount = 0;
unsigned tmp_speed = 0;
}; };
#endif // M3KTE_H #endif // M3KTE_H

View File

@ -18,28 +18,21 @@ MultipleSettings::~MultipleSettings()
void MultipleSettings::on_buttonBox_clicked(QAbstractButton *button) void MultipleSettings::on_buttonBox_clicked(QAbstractButton *button)
{ {
if(button == ui->buttonBox->button(QDialogButtonBox::Ok)) if(button == ui->buttonBox->button(QDialogButtonBox::Ok)) {
{
newValue = ui->regValueLine->text().toInt(nullptr, 16); newValue = ui->regValueLine->text().toInt(nullptr, 16);
typeReg = ui->regTypeBox->currentIndex(); typeReg = ui->regTypeBox->currentIndex();
startAdr = ui->adrBox->value(); startAdr = ui->adrBox->value();
countReg = ui->countBox->value(); countReg = ui->countBox->value();
boardId = ui->boardBox->currentIndex(); boardId = ui->boardBox->currentIndex();
emit write(); emit write();
} } else if (button == ui->buttonBox->button(QDialogButtonBox::SaveAll)) {
else if (button == ui->buttonBox->button(QDialogButtonBox::SaveAll))
{
newValue = ui->regValueLine->text().toInt(nullptr, 16); newValue = ui->regValueLine->text().toInt(nullptr, 16);
typeReg = ui->regTypeBox->currentIndex(); typeReg = ui->regTypeBox->currentIndex();
startAdr = ui->adrBox->value(); startAdr = ui->adrBox->value();
countReg = ui->countBox->value(); countReg = ui->countBox->value();
boardId = ui->boardBox->currentIndex(); boardId = ui->boardBox->currentIndex();
emit writeAndSend(); emit writeAndSend();
} } else {}
else
{
}
} }
void MultipleSettings::on_regTypeBox_currentIndexChanged(int index) void MultipleSettings::on_regTypeBox_currentIndexChanged(int index)

View File

@ -54,11 +54,9 @@ int SettingsDialog::UpdateBaud(int baud)
int SettingsDialog::UpdateParity(int parity) int SettingsDialog::UpdateParity(int parity)
{ {
ui->parityCombo->setCurrentIndex(parity); ui->parityCombo->setCurrentIndex(parity);
if(parity>0) if(parity>0) {
{
return (m_settings.parity = ++parity); return (m_settings.parity = ++parity);
} } else {
else {
return (m_settings.parity = parity); return (m_settings.parity = parity);
} }
} }
@ -77,8 +75,7 @@ void SettingsDialog::on_updateComBox_clicked()
{ {
ui->comBox->clear(); ui->comBox->clear();
const auto listPorts = QSerialPortInfo::availablePorts(); const auto listPorts = QSerialPortInfo::availablePorts();
for (const auto& port: listPorts) for (const auto& port: listPorts) {
{
ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName())); ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName()));
} }
} }