diff --git a/M3KTE_TERM/M3KTE_TERM.pro b/M3KTE_TERM/M3KTE_TERM.pro index ba6bb12..63e94e0 100644 --- a/M3KTE_TERM/M3KTE_TERM.pro +++ b/M3KTE_TERM/M3KTE_TERM.pro @@ -32,6 +32,9 @@ SOURCES += \ main.cpp \ m3kte.cpp \ multiplesettings.cpp \ + parameterbox.cpp \ + parameterdevice.cpp \ + parameterworkspace.cpp \ scanboard.cpp \ settingsdialog.cpp \ writeregistermodel.cpp @@ -43,6 +46,9 @@ HEADERS += \ lineringer.h \ m3kte.h \ multiplesettings.h \ + parameterbox.h \ + parameterdevice.h \ + parameterworkspace.h \ scanboard.h \ settingsdialog.h \ writeregistermodel.h @@ -54,6 +60,9 @@ FORMS += \ lineringer.ui \ m3kte.ui \ multiplesettings.ui \ + parameterbox.ui \ + parameterdevice.ui \ + parameterworkspace.ui \ scanboard.ui \ settingsdialog.ui diff --git a/M3KTE_TERM/m3kte.cpp b/M3KTE_TERM/m3kte.cpp index 07fbf10..a278d38 100644 --- a/M3KTE_TERM/m3kte.cpp +++ b/M3KTE_TERM/m3kte.cpp @@ -371,6 +371,8 @@ M3KTE::M3KTE(QWidget *parent) m_debugTerminalDialog->setMainTerm(this); m_regMultipleSettings = new MultipleSettings(this); modbusDevice = new QModbusRtuSerialMaster(this); + m_parameterWorkspace = new ParameterWorkspace(); + m_parameterWorkspace->setModbusClient(modbusDevice); m_debugTerminalDialog->setModbusDevice(modbusDevice); connect(this, &M3KTE::boardReading, m_debugTerminalDialog, &DebugTerminalDialog::boardDebugReading); m_lineRinger = new LineRinger(); @@ -382,18 +384,10 @@ M3KTE::M3KTE(QWidget *parent) Boards[1].boardScanners->setSingleShot(true); Boards[2].boardScanners->setSingleShot(true); Boards[3].boardScanners->setSingleShot(true); - connect(Boards[0].boardScanners, &QTimer::timeout, this, [this]() { - boardScan(0); - }); - connect(Boards[1].boardScanners, &QTimer::timeout, this, [this]() { - boardScan(1); - }); - connect(Boards[2].boardScanners, &QTimer::timeout, this, [this]() { - boardScan(2); - }); - connect(Boards[3].boardScanners, &QTimer::timeout, this, [this]() { - boardScan(3); - }); + connect(Boards[0].boardScanners, &QTimer::timeout, this, [this]() {boardScan(0);}); + connect(Boards[1].boardScanners, &QTimer::timeout, this, [this]() {boardScan(1);}); + connect(Boards[2].boardScanners, &QTimer::timeout, this, [this]() {boardScan(2);}); + connect(Boards[3].boardScanners, &QTimer::timeout, this, [this]() {boardScan(3);}); { Boards[0].adr = 1; Boards[1].adr = 2; @@ -459,13 +453,10 @@ M3KTE::M3KTE(QWidget *parent) 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); - }); + 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); @@ -558,6 +549,7 @@ void M3KTE::initActions() connect(m_regMultipleSettings, &MultipleSettings::writeAndSend, this, &M3KTE::slotmultipleRegWriteAndSend); connect(ui->ConnectionMenuSettings, &QAction::triggered, m_settingsDialog, &QDialog::show); connect(ui->M3kteMenuSettings, &QAction::triggered, m_deviceSettingsDialog, &QDialog::show); + connect(ui->ParameterScan, &QAction::triggered, m_parameterWorkspace, &QWidget::show); } void M3KTE::logError(const QString &errorPlace, const QString &errorString, unsigned errorCount, const QString &description) @@ -612,7 +604,9 @@ void M3KTE::onConnectClicked() } else { ui->ConnectionMenuConnect->setEnabled(false); ui->ConnectionMenuDisconnect->setEnabled(true); - if(pingNetworkDevices()) { //Опрос устройств + if(pingNetworkDevices()) //Опрос устройст + { + //m_parameterWorkspace->setDeviceCount(1); unsigned tmp_adr[4]; bool ActiveDevices[4]; for(int i = 0; i < 4; i++) { @@ -635,6 +629,7 @@ void M3KTE::onConnectClicked() ui->BSM_Accident->setEnabled(true); ui->BSM_WorkInProgress->setEnabled(true); ui->BSM_WorkInProgress->setChecked(true); + ui->ParameterScan->setEnabled(true); } } } else { @@ -677,6 +672,7 @@ void M3KTE::onConnectClicked() ui->BSM_Accident->setEnabled(false); ui->BSM_WorkInProgress->setEnabled(false); ui->M3kteRegSettings->setEnabled(false); + ui->ParameterScan->setEnabled(false); m_deviceSettingsDialog->onDisconnect(); m_debugTerminalDialog->offAllBoard(); } @@ -777,8 +773,7 @@ void M3KTE::onWriteButtonClicked() connect(reply, &QModbusReply::finished, this, [this, reply, tmp_id]() { if(reply->error() == QModbusDevice::ProtocolError) { statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)") - .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), - 5000); + .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000); logError(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr), reply->errorString(), ++Boards[tmp_id].error_TX, QString::number(reply->rawResult().exceptionCode(), 16)); @@ -1056,7 +1051,8 @@ void M3KTE::onSpeedUpdate() QPointer safeThis(this); connect(this, &M3KTE::errorAtCheckBoards, this, [safeThis]() { - if (!safeThis) return; + if (!safeThis) + return; safeThis->disconnect(safeThis, &M3KTE::errorAtCheckBoards, safeThis, nullptr); safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime); safeThis->revertToOldSpeedAndRestart(); @@ -1064,7 +1060,8 @@ void M3KTE::onSpeedUpdate() }); connect(this, &M3KTE::successAtCheckBoards, this, [safeThis]() { - if (!safeThis) return; + if (!safeThis) + return; safeThis->disconnect(safeThis, &M3KTE::successAtCheckBoards, safeThis, nullptr); safeThis->m_settingsDialog->UpdateBaud(safeThis->m_deviceSettingsDialog->currentSpeed()); safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime); @@ -1125,24 +1122,16 @@ void M3KTE::onParityUpdate() modbusDevice->setTimeout(500); QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 174, 1); switch(m_deviceSettingsDialog->currentParity()) { - case 0: //Нет контроля - unit.setValue(0, 0x000); - break; - case 1: //Четный - unit.setValue(0, 0x0400); - break; - case 2: //Нечетный - unit.setValue(0, 0x0600); - break; + case 0: unit.setValue(0, 0x000); break; //Нет контроля + case 1: unit.setValue(0, 0x0400); break;//Четный + case 2: unit.setValue(0, 0x0600); break;//Нечетный } - // Используем shared pointers вместо ссылок на стековые переменные auto totalActiveBoards = QSharedPointer::create(0); auto confirmedBoards = QSharedPointer::create(0); auto pendingBoards = QSharedPointer>::create(); auto oldParity = m_settingsDialog->curParity(); // сохраняем старую четность для отката auto newParity = m_deviceSettingsDialog->currentParity(); - // Лямбда для обработки результата auto processResult = [this, totalActiveBoards, confirmedBoards, oldParity, newParity]() { if(*confirmedBoards != *totalActiveBoards) { @@ -1152,7 +1141,6 @@ void M3KTE::onParityUpdate() modbusDevice->disconnectDevice(); modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, newParity); modbusDevice->connectDevice(); - auto errorHandler = [this, oldParity]() { disconnect(this, &M3KTE::errorAtCheckBoards, this, nullptr); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); @@ -1161,21 +1149,17 @@ void M3KTE::onParityUpdate() modbusDevice->connectDevice(); beginScanBoards(); }; - auto successHandler = [this, newParity]() { disconnect(this, &M3KTE::successAtCheckBoards, this, nullptr); m_settingsDialog->UpdateParity(newParity); modbusDevice->setTimeout(m_settingsDialog->settings().responseTime); beginScanBoards(); }; - connect(this, &M3KTE::errorAtCheckBoards, this, errorHandler); connect(this, &M3KTE::successAtCheckBoards, this, successHandler); - checkBoards(); } }; - for(int i = 0; i < 4; i++) { if(!Boards[i].isActive) continue; @@ -1184,7 +1168,6 @@ void M3KTE::onParityUpdate() if(reply) { (*totalActiveBoards)++; pendingBoards->insert(slaveAdress); - connect(reply, &QModbusReply::finished, this, [this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() { if(reply->error() == QModbusDevice::TimeoutError) { @@ -1405,6 +1388,14 @@ bool M3KTE::pingNetworkDevices() delete _unit_settings[2]; } } + int totalBoardsActive = 0; + for(int i = 0; i < 4; i++) + { + if(Boards[i].isActive) + totalBoardsActive++; + } + m_parameterWorkspace->setDeviceCount(totalBoardsActive); + modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries); beginScanBoards(); bar->deleteLater(); @@ -1413,11 +1404,13 @@ bool M3KTE::pingNetworkDevices() void M3KTE::beginScanBoards() { + int totalBoardsActive = 0; for(int i = 0; i < 4; i++) { if(Boards[i].isActive) { m_debugTerminalDialog->setScanBoardActive(true, i); m_deviceSettingsDialog->initPollForBoard(i, Boards[i].adr); boardScan(i); + m_parameterWorkspace->updateDevice(totalBoardsActive++, Boards[i].isActive, Boards[i].adr); } } return; @@ -1544,45 +1537,19 @@ void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status) } if (state) { switch (numb_err) { - case 1: - statusText += QString(" (Err 5 VD)"); - break; - case 2: - statusText += QString(" (Err 5 VA)"); - break; - case 3: - statusText += QString(" (Err 5 Vsci)"); - break; - case 4: - statusText += QString(" (Err 24 V)"); - break; - case 5: - statusText += QString(" (Hardfault)"); - break; - case 6: - statusText += QString(" (Empty Settings)"); - break; - case 7: - statusText += QString(" (ADC Error)"); - break; - case 8: - statusText += QString(" (Program Err 4)"); - break; - case 9: - statusText += QString(" (Program Err 5)"); - break; - case 10: - statusText += QString(" (EEPROM Error)"); - break; - case 11: - statusText += QString(" (Unstable discharge)"); - break; - case 12: - statusText += QString(" (RS/UART Errors)"); - break; - default: - statusText += QString(" (Program Err %1)").arg(numb_err - 4); - break; + case 1: statusText += QString(" (Err 5 VD)"); break; + case 2: statusText += QString(" (Err 5 VA)"); break; + case 3: statusText += QString(" (Err 5 Vsci)"); break; + case 4: statusText += QString(" (Err 24 V)"); break; + case 5: statusText += QString(" (Hardfault)"); break; + case 6: statusText += QString(" (Empty Settings)"); break; + case 7: statusText += QString(" (ADC Error)"); break; + case 8: statusText += QString(" (Program Err 4)"); break; + case 9: statusText += QString(" (Program Err 5)"); break; + case 10: statusText += QString(" (EEPROM Error)"); break; + case 11: statusText += QString(" (Unstable discharge)"); break; + case 12: statusText += QString(" (RS/UART Errors)"); break; + default: statusText += QString(" (Program Err %1)").arg(numb_err - 4); } } Boards[boardID].localError->setText(statusText); diff --git a/M3KTE_TERM/m3kte.h b/M3KTE_TERM/m3kte.h index ec5ac59..1b92fc7 100644 --- a/M3KTE_TERM/m3kte.h +++ b/M3KTE_TERM/m3kte.h @@ -12,6 +12,7 @@ #include "multiplesettings.h" #include "scanboard.h" #include "lineringer.h" +#include "parameterworkspace.h" #include #include @@ -65,8 +66,6 @@ private: void applySettingsFromScan(QModbusReply *reply); void multipleRegWrite(); void multipleRegSend(); - void writeSingleCoil(int boardId, int coilAddress, bool value); - void writeSingleRegister(int boardId, int regAddress, quint16 value); bool autoBaudRateScan(); void selectPositionOnTree(unsigned index); signals: @@ -95,6 +94,8 @@ public: ~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: Ui::M3KTE *ui; QTableWidget *loggerTable = nullptr; @@ -107,6 +108,7 @@ private: DebugTerminalDialog *m_debugTerminalDialog = nullptr; SettingsDialog *m_settingsDialog = nullptr; MultipleSettings *m_regMultipleSettings = nullptr; + ParameterWorkspace *m_parameterWorkspace = nullptr; ScanBoard *m_scanBoard = nullptr; LineRinger *m_lineRinger = nullptr; QGroupBox *Boards_Fields[4]; diff --git a/M3KTE_TERM/m3kte.ui b/M3KTE_TERM/m3kte.ui index 14e9956..0188642 100644 --- a/M3KTE_TERM/m3kte.ui +++ b/M3KTE_TERM/m3kte.ui @@ -14643,6 +14643,7 @@ Модули + @@ -14691,11 +14692,37 @@ Открыть + + true + + + true + Буфер АЦП + + true + + + true + + + + + false + + + false + + + false + + + Сканировать параметры + diff --git a/M3KTE_TERM/parameterbox.cpp b/M3KTE_TERM/parameterbox.cpp new file mode 100644 index 0000000..57b6675 --- /dev/null +++ b/M3KTE_TERM/parameterbox.cpp @@ -0,0 +1,56 @@ +#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; +} + +void ParameterBox::on_sendButton_clicked() +{ + if(ui->valueBox->currentText().isEmpty()) + { + return; + } + emit writeParameter(ui->adrLine->text().toInt(), ui->valueBox->currentText().toInt(nullptr, 16)); +} + +void ParameterBox::setData(QString data) +{ + ui->nameLine->setText(data); +} + +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; + } +} diff --git a/M3KTE_TERM/parameterbox.h b/M3KTE_TERM/parameterbox.h new file mode 100644 index 0000000..d1d39ec --- /dev/null +++ b/M3KTE_TERM/parameterbox.h @@ -0,0 +1,43 @@ +#ifndef PARAMETERBOX_H +#define PARAMETERBOX_H + +#include + +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 diff --git a/M3KTE_TERM/parameterbox.ui b/M3KTE_TERM/parameterbox.ui new file mode 100644 index 0000000..643fead --- /dev/null +++ b/M3KTE_TERM/parameterbox.ui @@ -0,0 +1,86 @@ + + + ParameterBox + + + + 0 + 0 + 400 + 43 + + + + + 0 + 0 + + + + Form + + + + + + + 0 + 25 + + + + true + + + + + + + + 0 + 25 + + + + SEND + + + + + + + + 0 + 25 + + + + true + + + + + + + + 0 + 25 + + + + true + + + + + + + + + + + + + + + diff --git a/M3KTE_TERM/parameterdevice.cpp b/M3KTE_TERM/parameterdevice.cpp new file mode 100644 index 0000000..8b731f6 --- /dev/null +++ b/M3KTE_TERM/parameterdevice.cpp @@ -0,0 +1,151 @@ +#include "parameterdevice.h" +#include "ui_parameterdevice.h" + +void sortParameterBoxesByID(QVector& 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); + + updateTimer = new QTimer(this); + updateTimer->setSingleShot(true); + connect(updateTimer, &QTimer::timeout, this, &ParameterDevice::sortScrollArea); +} + +ParameterDevice::~ParameterDevice() +{ + delete ui; +} + +void ParameterDevice::on_selectiveRadio_clicked() +{ + ui->selectiveBox->setEnabled(true); + mode = selectiveRequest; +} + +void ParameterDevice::on_fullRadio_clicked() +{ + ui->selectiveBox->setEnabled(false); + mode = fullRequest; +} + +void ParameterDevice::on_checkButton_clicked() +{ + for (ParameterBox* box : parameterBoxes) { + if (box) { + box->deleteLater(); + } + } + parameterBoxes.clear(); + quint16 strAdr; + int cnt; + strAdr = ui->adrSpin->value(); + switch (mode) { + case fullRequest: + strAdr = 0x80; + cnt = 128; + break; + case selectiveRequest: + cnt = ui->countSpin->value(); + break; + } + QProgressDialog progressDialog("Обработка...", "Отмена", 0, cnt, this); + progressDialog.setWindowModality(Qt::WindowModal); + progressDialog.setMinimumDuration(0); // показывать сразу + QEventLoop loop; + connect(this, &ParameterDevice::transmitEnd, &loop, &QEventLoop::quit); + 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; + } + } + progressDialog.setValue(cnt); + sortParameterBoxesByID(parameterBoxes); + sortScrollArea(); +} + +void ParameterDevice::setError(QString error) +{ + + QMessageBox::information(nullptr, "Получен ответ", error); + errorAtTransmit = true; + emit transmitEnd(); +} + +void ParameterDevice::on_adrSpin_valueChanged(int arg1) +{ + ui->countSpin->setRange(1, 256-arg1); +} + +void ParameterDevice::setAnswer(QString reply, quint16 objectID) +{ + ParameterBox *newbox = new ParameterBox(nullptr, ParameterBox::Info, objectID); + newbox->setData(reply); + switch (newbox->getType()) { + case ParameterBox::Coil: + connect(newbox, &ParameterBox::writeParameter, this, [this](int adr, quint16 value){ + emit writeSingleCoil(adr, (bool)value); + }); + break; + case ParameterBox::HR: + connect(newbox, &ParameterBox::writeParameter, this, [this](int adr, quint16 value){ + emit writeSingleRegister(adr, value); + }); + break; + } + parameterBoxes.append(newbox); + emit transmitEnd(); + +// // Остановить, если уже запущен +// if (updateTimer->isActive()) { +// updateTimer->stop(); +// } +// // Запустить с задержкой 6 секунд +// updateTimer->start(6000); +} + +void ParameterDevice::sortScrollArea() +{ + //sortParameterBoxesByID(parameterBoxes); + //ui->parameterBoxHubContents->layout()->deleteLater(); + 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; + } + + //ui->parameterBoxHubContents->setLayout(pblayout); + + 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(); +} diff --git a/M3KTE_TERM/parameterdevice.h b/M3KTE_TERM/parameterdevice.h new file mode 100644 index 0000000..5d030ac --- /dev/null +++ b/M3KTE_TERM/parameterdevice.h @@ -0,0 +1,62 @@ +#ifndef ParameterDevice_H +#define ParameterDevice_H + +#include +#include +#include "parameterbox.h" +#include +#include +#include +#include +#include + +void sortParameterBoxesByID(QVector& 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; + QTimer *updateTimer; + QVectorparameterBoxes; + + requestMode mode = fullRequest; + Ui::ParameterDevice *ui; +}; + +#endif // ParameterDevice_H diff --git a/M3KTE_TERM/parameterdevice.ui b/M3KTE_TERM/parameterdevice.ui new file mode 100644 index 0000000..7b654ae --- /dev/null +++ b/M3KTE_TERM/parameterdevice.ui @@ -0,0 +1,141 @@ + + + ParameterDevice + + + + 0 + 0 + 400 + 687 + + + + Form + + + + + + Extended Objects + + + + + + false + + + + + + false + + + false + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0x + + + 128 + + + 255 + + + 16 + + + + + + + Qt::LeftToRight + + + Start Adr: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::RightToLeft + + + Count: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Selective Request + + + + + + + Check + + + + + + + Full Request + + + true + + + + + + + + + + true + + + + + 0 + 0 + 380 + 450 + + + + + + + + + + diff --git a/M3KTE_TERM/parameterworkspace.cpp b/M3KTE_TERM/parameterworkspace.cpp new file mode 100644 index 0000000..1443c5d --- /dev/null +++ b/M3KTE_TERM/parameterworkspace.cpp @@ -0,0 +1,124 @@ +#include "parameterworkspace.h" +#include "ui_parameterworkspace.h" + +ParameterWorkspace::ParameterWorkspace(QWidget *parent) : + QWidget(parent), + ui(new Ui::ParameterWorkspace) +{ + ui->setupUi(this); + +} + +ParameterWorkspace::~ParameterWorkspace() +{ + delete ui; +} +// QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404")); +// auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr); +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++) + { + device* _device = new device(); + deviceList.append(*_device); + deviceList[i].device = new 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); + }); + } +} + +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, [this, reply]() { + if (reply->error() != QModbusDevice::NoError) { + //ERROR + } + reply->deleteLater(); + }); + } else { + reply->deleteLater(); + } + } +} + +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, [this, reply]() { + if (reply->error() != QModbusDevice::NoError) { + //ERROR + } + reply->deleteLater(); + }); + } else { + reply->deleteLater(); + } + } +} + +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, [this, device, reply, objectID](){ + if(reply->error() == QModbusDevice::NoError) + { + QModbusResponse resp = reply->rawResult(); + if(resp.data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) + { + QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH)); + device->setAnswer(result, objectID); + } + } + else + { + device->setError(reply->errorString()); + qDebug()<<"Получен ответ:" + reply->errorString(); + } + reply->deleteLater(); + }); + } + } + else + { + device->setError("Unknow error"); + } +} + +void ParameterWorkspace::updateDevice(int ID, bool status, int adr) +{ + deviceList[ID].isActive = status; + deviceList[ID].adr = adr; + deviceList[ID].device->setAdr(adr); +} diff --git a/M3KTE_TERM/parameterworkspace.h b/M3KTE_TERM/parameterworkspace.h new file mode 100644 index 0000000..c825703 --- /dev/null +++ b/M3KTE_TERM/parameterworkspace.h @@ -0,0 +1,53 @@ +#ifndef PARAMETERWORKSPACE_H +#define PARAMETERWORKSPACE_H + +#include +#include +#include +#include +#include +#include +#include + +#if QT_CONFIG(modbus_serialport) +#include +#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 deviceList; + QModbusClient *modbusDevice = nullptr; + Ui::ParameterWorkspace *ui; +}; + +#endif // PARAMETERWORKSPACE_H diff --git a/M3KTE_TERM/parameterworkspace.ui b/M3KTE_TERM/parameterworkspace.ui new file mode 100644 index 0000000..ce7e7db --- /dev/null +++ b/M3KTE_TERM/parameterworkspace.ui @@ -0,0 +1,31 @@ + + + ParameterWorkspace + + + + 0 + 0 + 610 + 646 + + + + Form + + + + + + QTabWidget::North + + + -1 + + + + + + + +